# *************************************************************************** # * Copyright (c) 2016 Bernd Hahnebach * # * * # * 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 self.electrostatic_objects = member.cons_electrostatic self.electricchargedensity_objects = member.cons_electricchargedensity # 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() ## @}