freecad-cam/Mod/Fem/femsolver/writerbase.py
2026-02-01 01:59:24 +01:00

244 lines
10 KiB
Python

# ***************************************************************************
# * Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM solver writer base object"
__author__ = "Bernd Hahnebach"
__url__ = "https://www.freecad.org"
## \addtogroup FEM
# @{
import os
from os.path import join
import FreeCAD
from femmesh import meshsetsgetter
class FemInputWriter:
def __init__(
self, analysis_obj, solver_obj, mesh_obj, member, dir_name=None, mat_geo_sets=None
):
# class attributes from parameter values
self.analysis = analysis_obj
self.solver_obj = solver_obj
self.mesh_object = mesh_obj
self.member = member
# more attributes
self.analysis_type = self.solver_obj.AnalysisType
self.document = self.analysis.Document
# working dir
# if dir_name was not given or if it exists but is not empty: create a temporary dir
# Purpose: makes sure the analysis can be run even on wired situation
make_tmp_dir = False
if dir_name is None:
FreeCAD.Console.PrintWarning(
"Error: The working_dir in base input file writer class was not set. "
"A temporary directory is used.\n"
)
make_tmp_dir = True
elif not os.path.isdir(dir_name):
FreeCAD.Console.PrintWarning(
"Error: The working_dir: '{}' given to "
"base input file writer class does not exist. "
"A temporary directory is used.\n".format(dir_name)
)
make_tmp_dir = True
if make_tmp_dir is True:
from tempfile import mkdtemp
dir_name = mkdtemp(prefix="fcfem_")
FreeCAD.Console.PrintWarning(
f"The working directory '{dir_name}' was created and will be used."
)
self.dir_name = dir_name
# new class attributes
self.fc_ver = FreeCAD.Version()
self.ccx_nall = "Nall"
self.ccx_eall = "Eall"
self.ccx_evolumes = "Evolumes"
self.ccx_efaces = "Efaces"
self.ccx_eedges = "Eedges"
self.mat_geo_sets = mat_geo_sets
if self.mesh_object:
self.femmesh = self.mesh_object.FemMesh
else:
FreeCAD.Console.PrintWarning(
"No finite element mesh object was given to the writer class. "
"In rare cases this might not be an error. "
)
# *************************************************
# deprecated, leave for compatibility reasons
# if these are calculated here they are calculated twice :-(
self.femnodes_mesh = {}
self.femelement_table = {}
self.constraint_conflict_nodes = []
self.femnodes_ele_table = {}
self.femelements_edges_only = []
self.femelements_faces_only = []
self.femelement_volumes_table = {}
self.femelement_faces_table = {}
self.femelement_edges_table = {}
self.femelement_count_test = True
# deprecated, leave for compatibility reasons
# do not add new objects
# only the ones which exists on 0.19 release are kept
# materials
self.material_objects = member.mats_linear
self.material_nonlinear_objects = member.mats_nonlinear
# geometries
self.beamsection_objects = member.geos_beamsection
self.beamrotation_objects = member.geos_beamrotation
self.fluidsection_objects = member.geos_fluidsection
self.shellthickness_objects = member.geos_shellthickness
# constraints
self.contact_objects = member.cons_contact
self.displacement_objects = member.cons_displacement
self.fixed_objects = member.cons_fixed
self.force_objects = member.cons_force
self.heatflux_objects = member.cons_heatflux
self.initialtemperature_objects = member.cons_initialtemperature
self.planerotation_objects = member.cons_planerotation
self.pressure_objects = member.cons_pressure
self.selfweight_objects = member.cons_selfweight
self.temperature_objects = member.cons_temperature
self.tie_objects = member.cons_tie
self.transform_objects = member.cons_transform
# meshdatagetter, for compatibility, same with all getter methods
self.meshdatagetter = meshsetsgetter.MeshSetsGetter(
self.analysis,
self.solver_obj,
self.mesh_object,
self.member,
)
# ********************************************************************************************
# ********************************************************************************************
# generic writer for constraints mesh sets and constraints property data
# write constraint node sets, constraint face sets, constraint element sets
def write_constraints_meshsets(self, f, femobjs, con_module):
if not femobjs:
return
analysis_types = con_module.get_analysis_types()
if analysis_types != "all" and self.analysis_type not in analysis_types:
return
def constraint_sets_loop_writing(the_file, femobjs, write_before, write_after):
if write_before != "":
the_file.write(write_before)
for femobj in femobjs:
# femobj --> dict, FreeCAD document object is femobj["Object"]
the_obj = femobj["Object"]
the_file.write(f"** {the_obj.Label}\n")
con_module.write_meshdata_constraint(the_file, femobj, the_obj, self)
if write_after != "":
the_file.write(write_after)
write_before = con_module.get_before_write_meshdata_constraint()
write_after = con_module.get_after_write_meshdata_constraint()
# write sets to file
write_name = con_module.get_sets_name()
f.write("\n{}\n".format(59 * "*"))
f.write("** {}\n".format(write_name.replace("_", " ")))
if self.split_inpfile is True:
file_name_split = f"{self.mesh_name}_{write_name}.inp"
f.write(f"*INCLUDE,INPUT={file_name_split}\n")
inpfile_split = open(join(self.dir_name, file_name_split), "w")
constraint_sets_loop_writing(inpfile_split, femobjs, write_before, write_after)
inpfile_split.close()
else:
constraint_sets_loop_writing(f, femobjs, write_before, write_after)
# write constraint property data
def write_constraints_propdata(self, f, femobjs, con_module):
if not femobjs:
return
analysis_types = con_module.get_analysis_types()
if analysis_types != "all" and self.analysis_type not in analysis_types:
return
write_before = con_module.get_before_write_constraint()
write_after = con_module.get_after_write_constraint()
# write constraint to file
f.write("\n{}\n".format(59 * "*"))
f.write(f"** {con_module.get_constraint_title()}\n")
if write_before != "":
f.write(write_before)
for femobj in femobjs:
# femobj --> dict, FreeCAD document object is femobj["Object"]
the_obj = femobj["Object"]
f.write(f"** {the_obj.Label}\n")
con_module.write_constraint(f, femobj, the_obj, self)
if write_after != "":
f.write(write_after)
# ********************************************************************************************
# deprecated, do not add new constraints
# only the ones which exists on 0.19 release are kept
def get_constraints_fixed_nodes(self):
self.meshdatagetter.get_constraints_fixed_nodes()
def get_constraints_displacement_nodes(self):
self.meshdatagetter.get_constraints_displacement_nodes()
def get_constraints_planerotation_nodes(self):
self.meshdatagetter.get_constraints_planerotation_nodes()
def get_constraints_transform_nodes(self):
self.meshdatagetter.get_constraints_transform_nodes()
def get_constraints_temperature_nodes(self):
self.meshdatagetter.get_constraints_temperature_nodes()
def get_constraints_fluidsection_nodes(self):
self.meshdatagetter.get_constraints_fluidsection_nodes()
def get_constraints_force_nodeloads(self):
self.meshdatagetter.get_constraints_force_nodeloads()
def get_constraints_pressure_faces(self):
self.meshdatagetter.get_constraints_pressure_faces()
def get_constraints_contact_faces(self):
self.meshdatagetter.get_constraints_contact_faces()
def get_constraints_tie_faces(self):
self.meshdatagetter.get_constraints_tie_faces()
def get_constraints_heatflux_faces(self):
self.meshdatagetter.get_constraints_heatflux_faces()
## @}