From 3fcdef5ca0fc08d78a66bd52d6385ea73815232f Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 12:13:23 +0200 Subject: [PATCH 1/6] FEM: calculix writer, use obj name as unique identifier for constraint section print --- src/Mod/Fem/femsolver/calculix/writer.py | 14 ++++---------- .../data/calculix/constraint_sectionprint.inp | 4 ++-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 7df2fca43d..7acea2e9f8 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -636,25 +636,21 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # into get_constraints_sectionprint_faces method def write_surfacefaces_constraints_sectionprint(self, f): # get surface nodes and write them to file - obj = 0 for femobj in self.sectionprint_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] sectionprint_obj = femobj["Object"] f.write("** " + sectionprint_obj.Label + "\n") - obj = obj + 1 for o, elem_tup in sectionprint_obj.References: for elem in elem_tup: ref_shape = o.Shape.getElement(elem) if ref_shape.ShapeType == "Face": - name = "SECTIONFACE" + str(obj) - f.write("*SURFACE, NAME=" + name + "\n") - + f.write("*SURFACE, NAME=SECTIONFACE{}\n".format(sectionprint_obj.Name)) v = self.mesh_object.FemMesh.getccxVolumesByFace(ref_shape) if len(v) > 0: # volume elements found FreeCAD.Console.PrintLog( "{}, surface {}, {} touching volume elements found\n" - .format(sectionprint_obj.Label, name, len(v)) + .format(sectionprint_obj.Label, sectionprint_obj.Name, len(v)) ) for i in v: f.write("{},S{}\n".format(i[0], i[1])) @@ -663,7 +659,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): FreeCAD.Console.PrintError( "{}, surface {}, Error: " "No volume elements found!\n" - .format(sectionprint_obj.Label, name) + .format(sectionprint_obj.Label, sectionprint_obj.Name) ) f.write("** Error: empty list\n") @@ -676,15 +672,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write("\n***********************************************************\n") f.write("** SectionPrint Constraints\n") f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - obj = 0 for femobj in self.sectionprint_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] - obj = obj + 1 sectionprint_obj = femobj["Object"] f.write("** {}\n".format(sectionprint_obj.Label)) f.write( "*SECTION PRINT, SURFACE=SECTIONFACE{}, NAME=SECTIONPRINT{}\n" - .format(obj, obj) + .format(sectionprint_obj.Name, sectionprint_obj.Name) ) f.write("SOF, SOM, SOAREA\n") diff --git a/src/Mod/Fem/femtest/data/calculix/constraint_sectionprint.inp b/src/Mod/Fem/femtest/data/calculix/constraint_sectionprint.inp index 074f7bade4..937740938d 100644 --- a/src/Mod/Fem/femtest/data/calculix/constraint_sectionprint.inp +++ b/src/Mod/Fem/femtest/data/calculix/constraint_sectionprint.inp @@ -3359,7 +3359,7 @@ Evolumes ** constraints sectionprint surface sets ** written by write_surfaces_constraints_sectionprint function ** ConstraintSectionPrint -*SURFACE, NAME=SECTIONFACE1 +*SURFACE, NAME=SECTIONFACEConstraintSectionPrint 811,S4 872,S2 880,S1 @@ -3425,7 +3425,7 @@ ConstraintFixed,3 ** SectionPrint Constraints ** written by write_constraints_sectionprint function ** ConstraintSectionPrint -*SECTION PRINT, SURFACE=SECTIONFACE1, NAME=SECTIONPRINT1 +*SECTION PRINT, SURFACE=SECTIONFACEConstraintSectionPrint, NAME=SECTIONPRINTConstraintSectionPrint SOF, SOM, SOAREA *********************************************************** From 78a11b8f42246d2bbd2d3d096dd1aecdc8401150 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 07:45:21 +0200 Subject: [PATCH 2/6] FEM: calculix writer, improve contraint set writer --- src/Mod/Fem/femsolver/calculix/writer.py | 355 +++++++++++------------ 1 file changed, 163 insertions(+), 192 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 7acea2e9f8..2f7e19b5e2 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -275,6 +275,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): write_name, sets_writer_method, caller_method_name="", + write_before="", + write_after="", ): if not femobjs: return @@ -285,6 +287,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # get the sets sets_getter_method() + # write sets to file f.write("\n{}\n".format(59 * "*")) f.write("** {}\n".format(write_name.replace("_", " "))) f.write("** written by {} function\n".format(caller_method_name)) @@ -294,10 +297,26 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write("** {}\n".format(write_name.replace("_", " "))) f.write("*INCLUDE,INPUT={}\n".format(file_name_split)) inpfile_split = open(join(self.dir_name, file_name_split), "w") - sets_writer_method(inpfile_split) + 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("** " + the_obj.Label + "\n") + sets_writer_method(inpfile_split, femobj, the_obj) + if write_after != "": + f.write(write_after) inpfile_split.close() else: - sets_writer_method(f) + 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("** " + the_obj.Label + "\n") + sets_writer_method(f, femobj, the_obj) + if write_after != "": + f.write(write_after) # ******************************************************************************************** # constraints fixed @@ -312,26 +331,21 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_fixed(self, f): - # write nodes to file - for femobj in self.fixed_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - fix_obj = femobj["Object"] - f.write("** " + fix_obj.Label + "\n") - if self.femmesh.Volumes \ - and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): - if len(femobj["NodesSolid"]) > 0: - f.write("*NSET,NSET=" + fix_obj.Name + "Solid\n") - for n in femobj["NodesSolid"]: - f.write(str(n) + ",\n") - if len(femobj["NodesFaceEdge"]) > 0: - f.write("*NSET,NSET=" + fix_obj.Name + "FaceEdge\n") - for n in femobj["NodesFaceEdge"]: - f.write(str(n) + ",\n") - else: - f.write("*NSET,NSET=" + fix_obj.Name + "\n") - for n in femobj["Nodes"]: + def write_node_sets_nodes_constraints_fixed(self, f, femobj, fix_obj): + if self.femmesh.Volumes \ + and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): + if len(femobj["NodesSolid"]) > 0: + f.write("*NSET,NSET=" + fix_obj.Name + "Solid\n") + for n in femobj["NodesSolid"]: f.write(str(n) + ",\n") + if len(femobj["NodesFaceEdge"]) > 0: + f.write("*NSET,NSET=" + fix_obj.Name + "FaceEdge\n") + for n in femobj["NodesFaceEdge"]: + f.write(str(n) + ",\n") + else: + f.write("*NSET,NSET=" + fix_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write(str(n) + ",\n") def write_constraints_fixed(self, f): if not self.fixed_objects: @@ -387,15 +401,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_displacement(self, f): - # write nodes to file - for femobj in self.displacement_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - disp_obj = femobj["Object"] - f.write("** " + disp_obj.Label + "\n") - f.write("*NSET,NSET=" + disp_obj.Name + "\n") - for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + def write_node_sets_nodes_constraints_displacement(self, f femobj, disp_obj): + f.write("*NSET,NSET=" + disp_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write(str(n) + ",\n") def write_constraints_displacement(self, f): if not self.displacement_objects: @@ -453,7 +462,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_planerotation(self, f): + def write_node_sets_nodes_constraints_planerotation(self, f, femobj, fric_obj): # write nodes to file if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes @@ -464,36 +473,32 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # constraints displacement can't share same nodes. # Thus call write_node_sets_constraints_planerotation has to be # after constraint fixed and constraint displacement - for femobj in self.planerotation_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - l_nodes = femobj["Nodes"] - fric_obj = femobj["Object"] - f.write("** " + fric_obj.Label + "\n") - f.write("*NSET,NSET=" + fric_obj.Name + "\n") - # Code to extract nodes and coordinates on the PlaneRotation support face - nodes_coords = [] - for node in l_nodes: - nodes_coords.append(( - node, - self.femnodes_mesh[node].x, - self.femnodes_mesh[node].y, - self.femnodes_mesh[node].z - )) - node_planerotation = meshtools.get_three_non_colinear_nodes(nodes_coords) - for i in range(len(l_nodes)): - if l_nodes[i] not in node_planerotation: - node_planerotation.append(l_nodes[i]) - MPC_nodes = [] - for i in range(len(node_planerotation)): - cnt = 0 - for j in range(len(self.constraint_conflict_nodes)): - if node_planerotation[i] == self.constraint_conflict_nodes[j]: - cnt = cnt + 1 - if cnt == 0: - MPC = node_planerotation[i] - MPC_nodes.append(MPC) - for i in range(len(MPC_nodes)): - f.write(str(MPC_nodes[i]) + ",\n") + l_nodes = femobj["Nodes"] + f.write("*NSET,NSET=" + fric_obj.Name + "\n") + # Code to extract nodes and coordinates on the PlaneRotation support face + nodes_coords = [] + for node in l_nodes: + nodes_coords.append(( + node, + self.femnodes_mesh[node].x, + self.femnodes_mesh[node].y, + self.femnodes_mesh[node].z + )) + node_planerotation = meshtools.get_three_non_colinear_nodes(nodes_coords) + for i in range(len(l_nodes)): + if l_nodes[i] not in node_planerotation: + node_planerotation.append(l_nodes[i]) + MPC_nodes = [] + for i in range(len(node_planerotation)): + cnt = 0 + for j in range(len(self.constraint_conflict_nodes)): + if node_planerotation[i] == self.constraint_conflict_nodes[j]: + cnt = cnt + 1 + if cnt == 0: + MPC = node_planerotation[i] + MPC_nodes.append(MPC) + for i in range(len(MPC_nodes)): + f.write(str(MPC_nodes[i]) + ",\n") def write_constraints_planerotation(self, f): if not self.planerotation_objects: @@ -524,20 +529,15 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_surfacefaces_constraints_contact(self, f): - # write faces to file - for femobj in self.contact_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - contact_obj = femobj["Object"] - f.write("** " + contact_obj.Label + "\n") - # slave DEP - f.write("*SURFACE, NAME=DEP{}\n".format(contact_obj.Name)) - for i in femobj["ContactSlaveFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - # master IND - f.write("*SURFACE, NAME=IND{}\n".format(contact_obj.Name)) - for i in femobj["ContactMasterFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) + def write_surfacefaces_constraints_contact(self, f, femobj, contact_obj): + # slave DEP + f.write("*SURFACE, NAME=DEP{}\n".format(contact_obj.Name)) + for i in femobj["ContactSlaveFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + # master IND + f.write("*SURFACE, NAME=IND{}\n".format(contact_obj.Name)) + for i in femobj["ContactMasterFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) def write_constraints_contact(self, f): if not self.contact_objects: @@ -582,20 +582,15 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_surfacefaces_constraints_tie(self, f): - # write faces to file - for femobj in self.tie_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - tie_obj = femobj["Object"] - f.write("** " + tie_obj.Label + "\n") - # slave DEP - f.write("*SURFACE, NAME=TIE_DEP{}\n".format(tie_obj.Name)) - for i in femobj["TieSlaveFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - # master IND - f.write("*SURFACE, NAME=TIE_IND{}\n".format(tie_obj.Name)) - for i in femobj["TieMasterFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) + def write_surfacefaces_constraints_tie(self, f, femobj, tie_obj): + # slave DEP + f.write("*SURFACE, NAME=TIE_DEP{}\n".format(tie_obj.Name)) + for i in femobj["TieSlaveFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + # master IND + f.write("*SURFACE, NAME=TIE_IND{}\n".format(tie_obj.Name)) + for i in femobj["TieMasterFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) def write_constraints_tie(self, f): if not self.tie_objects: @@ -634,7 +629,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # TODO move code parts from this method to base writer module # into get_constraints_sectionprint_faces method - def write_surfacefaces_constraints_sectionprint(self, f): + def write_surfacefaces_constraints_sectionprint(self, f, femobj, sectionprint_obj): # get surface nodes and write them to file for femobj in self.sectionprint_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] @@ -695,18 +690,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_transform(self, f): - # write nodes to file - for femobj in self.transform_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - trans_obj = femobj["Object"] - f.write("** " + trans_obj.Label + "\n") - if trans_obj.TransformType == "Rectangular": - f.write("*NSET,NSET=Rect" + trans_obj.Name + "\n") - elif trans_obj.TransformType == "Cylindrical": - f.write("*NSET,NSET=Cylin" + trans_obj.Name + "\n") - for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + def write_node_sets_nodes_constraints_transform(self, f, femobj, trans_obj): + if trans_obj.TransformType == "Rectangular": + f.write("*NSET,NSET=Rect" + trans_obj.Name + "\n") + elif trans_obj.TransformType == "Cylindrical": + f.write("*NSET,NSET=Cylin" + trans_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write(str(n) + ",\n") def write_constraints_transform(self, f): if not self.transform_objects: @@ -757,15 +747,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_temperature(self, f): - # write nodes to file - for femobj in self.temperature_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - temp_obj = femobj["Object"] - f.write("** " + temp_obj.Label + "\n") - f.write("*NSET,NSET=" + temp_obj.Name + "\n") - for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + def write_node_sets_nodes_constraints_temperature(self, f, femobj, temp_obj): + f.write("*NSET,NSET=" + temp_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write(str(n) + ",\n") def write_constraints_temperature(self, f): if not self.temperature_objects: @@ -858,28 +843,23 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_nodeloads_constraints_force(self, f): - # write node loads to file - f.write("*CLOAD\n") - for femobj in self.force_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - f.write("** " + femobj["Object"].Label + "\n") - direction_vec = femobj["Object"].DirectionVector - for ref_shape in femobj["NodeLoadTable"]: - f.write("** " + ref_shape[0] + "\n") - for n in sorted(ref_shape[1]): - node_load = ref_shape[1][n] - if (direction_vec.x != 0.0): - v1 = "{:.13E}".format(direction_vec.x * node_load) - f.write(str(n) + ",1," + v1 + "\n") - if (direction_vec.y != 0.0): - v2 = "{:.13E}".format(direction_vec.y * node_load) - f.write(str(n) + ",2," + v2 + "\n") - if (direction_vec.z != 0.0): - v3 = "{:.13E}".format(direction_vec.z * node_load) - f.write(str(n) + ",3," + v3 + "\n") - f.write("\n") + def write_nodeloads_constraints_force(self, f, femobj, force_obj): + direction_vec = femobj["Object"].DirectionVector + for ref_shape in femobj["NodeLoadTable"]: + f.write("** " + ref_shape[0] + "\n") + for n in sorted(ref_shape[1]): + node_load = ref_shape[1][n] + if (direction_vec.x != 0.0): + v1 = "{:.13E}".format(direction_vec.x * node_load) + f.write(str(n) + ",1," + v1 + "\n") + if (direction_vec.y != 0.0): + v2 = "{:.13E}".format(direction_vec.y * node_load) + f.write(str(n) + ",2," + v2 + "\n") + if (direction_vec.z != 0.0): + v3 = "{:.13E}".format(direction_vec.z * node_load) + f.write(str(n) + ",3," + v3 + "\n") f.write("\n") + f.write("\n") # ******************************************************************************************** # constraints pressure @@ -894,30 +874,25 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_faceloads_constraints_pressure(self, f): - # write face loads to file - for femobj in self.pressure_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - prs_obj = femobj["Object"] - f.write("** " + prs_obj.Label + "\n") - rev = -1 if prs_obj.Reversed else 1 - f.write("*DLOAD\n") - for ref_shape in femobj["PressureFaces"]: - # the loop is needed for compatibility reason - # in deprecated method get_pressure_obj_faces_depreciated - # the face ids where per ref_shape - f.write("** " + ref_shape[0] + "\n") - for face, fno in ref_shape[1]: - if fno > 0: # solid mesh face - f.write("{},P{},{}\n".format(face, fno, rev * prs_obj.Pressure)) - # on shell mesh face: fno == 0 - # normal of element face == face normal - elif fno == 0: - f.write("{},P,{}\n".format(face, rev * prs_obj.Pressure)) - # on shell mesh face: fno == -1 - # normal of element face opposite direction face normal - elif fno == -1: - f.write("{},P,{}\n".format(face, -1 * rev * prs_obj.Pressure)) + def write_faceloads_constraints_pressure(self, f, femobj, prs_obj): + rev = -1 if prs_obj.Reversed else 1 + f.write("*DLOAD\n") + for ref_shape in femobj["PressureFaces"]: + # the loop is needed for compatibility reason + # in deprecated method get_pressure_obj_faces_depreciated + # the face ids where per ref_shape + f.write("** " + ref_shape[0] + "\n") + for face, fno in ref_shape[1]: + if fno > 0: # solid mesh face + f.write("{},P{},{}\n".format(face, fno, rev * prs_obj.Pressure)) + # on shell mesh face: fno == 0 + # normal of element face == face normal + elif fno == 0: + f.write("{},P,{}\n".format(face, rev * prs_obj.Pressure)) + # on shell mesh face: fno == -1 + # normal of element face opposite direction face normal + elif fno == -1: + f.write("{},P,{}\n".format(face, -1 * rev * prs_obj.Pressure)) # ******************************************************************************************** # constraints heatflux @@ -934,42 +909,38 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # TODO move code parts from this method to base writer module # into get_constraints_heatflux_faces method - def write_faceheatflux_constraints_heatflux(self, f): - # write heat flux faces to file - for hfobj in self.heatflux_objects: - heatflux_obj = hfobj["Object"] - f.write("** " + heatflux_obj.Label + "\n") - if heatflux_obj.ConstraintType == "Convection": - f.write("*FILM\n") - for o, elem_tup in heatflux_obj.References: - for elem in elem_tup: - ho = o.Shape.getElement(elem) - if ho.ShapeType == "Face": - v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) - f.write("** Heat flux on face {}\n".format(elem)) - for i in v: - # SvdW: add factor to force heatflux to units system of t/mm/s/K - # OvG: Only write out the VolumeIDs linked to a particular face - f.write("{},F{},{},{}\n".format( - i[0], - i[1], - heatflux_obj.AmbientTemp, - heatflux_obj.FilmCoef * 0.001 - )) - elif heatflux_obj.ConstraintType == "DFlux": - f.write("*DFLUX\n") - for o, elem_tup in heatflux_obj.References: - for elem in elem_tup: - ho = o.Shape.getElement(elem) - if ho.ShapeType == "Face": - v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) - f.write("** Heat flux on face {}\n".format(elem)) - for i in v: - f.write("{},S{},{}\n".format( - i[0], - i[1], - heatflux_obj.DFlux * 0.001 - )) + def write_faceheatflux_constraints_heatflux(self, f, femobj, heatflux_obj): + if heatflux_obj.ConstraintType == "Convection": + f.write("*FILM\n") + for o, elem_tup in heatflux_obj.References: + for elem in elem_tup: + ho = o.Shape.getElement(elem) + if ho.ShapeType == "Face": + v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) + f.write("** Heat flux on face {}\n".format(elem)) + for i in v: + # SvdW: add factor to force heatflux to units system of t/mm/s/K + # OvG: Only write out the VolumeIDs linked to a particular face + f.write("{},F{},{},{}\n".format( + i[0], + i[1], + heatflux_obj.AmbientTemp, + heatflux_obj.FilmCoef * 0.001 + )) + elif heatflux_obj.ConstraintType == "DFlux": + f.write("*DFLUX\n") + for o, elem_tup in heatflux_obj.References: + for elem in elem_tup: + ho = o.Shape.getElement(elem) + if ho.ShapeType == "Face": + v = self.mesh_object.FemMesh.getccxVolumesByFace(ho) + f.write("** Heat flux on face {}\n".format(elem)) + for i in v: + f.write("{},S{},{}\n".format( + i[0], + i[1], + heatflux_obj.DFlux * 0.001 + )) # ******************************************************************************************** # constraints fluidsection From 05465a53fe5fcd9c0059df9d8fa480495e4449fd Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 07:48:20 +0200 Subject: [PATCH 3/6] FEM: calculix writer, add generic constraint data writer --- src/Mod/Fem/femsolver/calculix/writer.py | 514 ++++++++++++----------- 1 file changed, 265 insertions(+), 249 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 2f7e19b5e2..1fc9b3e638 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -318,6 +318,39 @@ class FemInputWriterCcx(writerbase.FemInputWriter): if write_after != "": f.write(write_after) + # ******************************************************************************************** + # write constraint data + def write_constraints_data( + self, + f, + femobjs, + analysis_types, + constraint_title_name, + constraint_writer_method, + caller_method_name="", + write_before="", + write_after="", + ): + if not femobjs: + return + + if analysis_types != "all" and self.analysis_type not in analysis_types: + return + + # write constraint to file + f.write("\n{}\n".format(59 * "*")) + f.write("** {}\n".format(constraint_title_name)) + f.write("** written by {} function\n".format(caller_method_name)) + 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("** {}\n".format(the_obj.Label)) + constraint_writer_method(f, femobj, the_obj) + if write_after != "": + f.write(write_after) + # ******************************************************************************************** # constraints fixed def write_node_sets_constraints_fixed(self, f): @@ -331,6 +364,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_fixed(self, f): + self.write_constraints_data( + f, + femobjs=self.fixed_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="Fixed Constraints", + constraint_writer_method=self.constraint_fixed_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_node_sets_nodes_constraints_fixed(self, f, femobj, fix_obj): if self.femmesh.Volumes \ and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): @@ -347,46 +390,34 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for n in femobj["Nodes"]: f.write(str(n) + ",\n") - def write_constraints_fixed(self, f): - if not self.fixed_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Fixed Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.fixed_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - f.write("** " + femobj["Object"].Label + "\n") - fix_obj_name = femobj["Object"].Name - if self.femmesh.Volumes \ - and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): - if len(femobj["NodesSolid"]) > 0: - f.write("*BOUNDARY\n") - f.write(fix_obj_name + "Solid" + ",1\n") - f.write(fix_obj_name + "Solid" + ",2\n") - f.write(fix_obj_name + "Solid" + ",3\n") - f.write("\n") - if len(femobj["NodesFaceEdge"]) > 0: - f.write("*BOUNDARY\n") - f.write(fix_obj_name + "FaceEdge" + ",1\n") - f.write(fix_obj_name + "FaceEdge" + ",2\n") - f.write(fix_obj_name + "FaceEdge" + ",3\n") - f.write(fix_obj_name + "FaceEdge" + ",4\n") - f.write(fix_obj_name + "FaceEdge" + ",5\n") - f.write(fix_obj_name + "FaceEdge" + ",6\n") - f.write("\n") - else: + def constraint_fixed_writer(self, f, femobj, fix_obj): + if self.femmesh.Volumes \ + and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): + if len(femobj["NodesSolid"]) > 0: f.write("*BOUNDARY\n") - f.write(fix_obj_name + ",1\n") - f.write(fix_obj_name + ",2\n") - f.write(fix_obj_name + ",3\n") - if self.beamsection_objects or self.shellthickness_objects: - f.write(fix_obj_name + ",4\n") - f.write(fix_obj_name + ",5\n") - f.write(fix_obj_name + ",6\n") + f.write(fix_obj.Name + "Solid" + ",1\n") + f.write(fix_obj.Name + "Solid" + ",2\n") + f.write(fix_obj.Name + "Solid" + ",3\n") f.write("\n") + if len(femobj["NodesFaceEdge"]) > 0: + f.write("*BOUNDARY\n") + f.write(fix_obj.Name + "FaceEdge" + ",1\n") + f.write(fix_obj.Name + "FaceEdge" + ",2\n") + f.write(fix_obj.Name + "FaceEdge" + ",3\n") + f.write(fix_obj.Name + "FaceEdge" + ",4\n") + f.write(fix_obj.Name + "FaceEdge" + ",5\n") + f.write(fix_obj.Name + "FaceEdge" + ",6\n") + f.write("\n") + else: + f.write("*BOUNDARY\n") + f.write(fix_obj.Name + ",1\n") + f.write(fix_obj.Name + ",2\n") + f.write(fix_obj.Name + ",3\n") + if self.beamsection_objects or self.shellthickness_objects: + f.write(fix_obj.Name + ",4\n") + f.write(fix_obj.Name + ",5\n") + f.write(fix_obj.Name + ",6\n") + f.write("\n") # ******************************************************************************************** # constraints displacement @@ -401,53 +432,52 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_displacement(self, f femobj, disp_obj): + def write_constraints_displacement(self, f): + self.write_constraints_data( + f, + femobjs=self.displacement_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="Displacement constraint applied", + constraint_writer_method=self.constraint_displacement_writer, + caller_method_name=sys._getframe().f_code.co_name, + write_after="\n", + ) + + def write_node_sets_nodes_constraints_displacement(self, f, femobj, disp_obj): f.write("*NSET,NSET=" + disp_obj.Name + "\n") for n in femobj["Nodes"]: f.write(str(n) + ",\n") - def write_constraints_displacement(self, f): - if not self.displacement_objects: - return - # write for all analysis types + def constraint_displacement_writer(self, f, femobj, disp_obj): + disp_obj_name = disp_obj.Name + f.write("*BOUNDARY\n") + if disp_obj.xFix: + f.write(disp_obj_name + ",1\n") + elif not disp_obj.xFree: + f.write(disp_obj_name + ",1,1," + str(disp_obj.xDisplacement) + "\n") + if disp_obj.yFix: + f.write(disp_obj_name + ",2\n") + elif not disp_obj.yFree: + f.write(disp_obj_name + ",2,2," + str(disp_obj.yDisplacement) + "\n") + if disp_obj.zFix: + f.write(disp_obj_name + ",3\n") + elif not disp_obj.zFree: + f.write(disp_obj_name + ",3,3," + str(disp_obj.zDisplacement) + "\n") - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Displacement constraint applied\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.displacement_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - f.write("** " + femobj["Object"].Label + "\n") - disp_obj = femobj["Object"] - disp_obj_name = disp_obj.Name - f.write("*BOUNDARY\n") - if disp_obj.xFix: - f.write(disp_obj_name + ",1\n") - elif not disp_obj.xFree: - f.write(disp_obj_name + ",1,1," + str(disp_obj.xDisplacement) + "\n") - if disp_obj.yFix: - f.write(disp_obj_name + ",2\n") - elif not disp_obj.yFree: - f.write(disp_obj_name + ",2,2," + str(disp_obj.yDisplacement) + "\n") - if disp_obj.zFix: - f.write(disp_obj_name + ",3\n") - elif not disp_obj.zFree: - f.write(disp_obj_name + ",3,3," + str(disp_obj.zDisplacement) + "\n") + if self.beamsection_objects or self.shellthickness_objects: + if disp_obj.rotxFix: + f.write(disp_obj_name + ",4\n") + elif not disp_obj.rotxFree: + f.write(disp_obj_name + ",4,4," + str(disp_obj.xRotation) + "\n") + if disp_obj.rotyFix: + f.write(disp_obj_name + ",5\n") + elif not disp_obj.rotyFree: + f.write(disp_obj_name + ",5,5," + str(disp_obj.yRotation) + "\n") + if disp_obj.rotzFix: + f.write(disp_obj_name + ",6\n") + elif not disp_obj.rotzFree: + f.write(disp_obj_name + ",6,6," + str(disp_obj.zRotation) + "\n") - if self.beamsection_objects or self.shellthickness_objects: - if disp_obj.rotxFix: - f.write(disp_obj_name + ",4\n") - elif not disp_obj.rotxFree: - f.write(disp_obj_name + ",4,4," + str(disp_obj.xRotation) + "\n") - if disp_obj.rotyFix: - f.write(disp_obj_name + ",5\n") - elif not disp_obj.rotyFree: - f.write(disp_obj_name + ",5,5," + str(disp_obj.yRotation) + "\n") - if disp_obj.rotzFix: - f.write(disp_obj_name + ",6\n") - elif not disp_obj.rotzFree: - f.write(disp_obj_name + ",6,6," + str(disp_obj.zRotation) + "\n") - f.write("\n") # ******************************************************************************************** # constraints planerotation @@ -462,6 +492,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_planerotation(self, f): + self.write_constraints_data( + f, + femobjs=self.planerotation_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="PlaneRotation Constraints", + constraint_writer_method=self.constraint_planerotation_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_node_sets_nodes_constraints_planerotation(self, f, femobj, fric_obj): # write nodes to file if not self.femnodes_mesh: @@ -500,21 +540,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for i in range(len(MPC_nodes)): f.write(str(MPC_nodes[i]) + ",\n") - def write_constraints_planerotation(self, f): - if not self.planerotation_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** PlaneRotation Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.planerotation_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - f.write("** " + femobj["Object"].Label + "\n") - fric_obj_name = femobj["Object"].Name - f.write("*MPC\n") - f.write("PLANE," + fric_obj_name + "\n") + def constraint_planerotation_writer(self, f, femobj, fric_obj): + f.write("*MPC\n") + f.write("PLANE," + fric_obj.Name + "\n") # ******************************************************************************************** # constraints contact @@ -529,6 +557,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_contact(self, f): + self.write_constraints_data( + f, + femobjs=self.contact_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="Contact Constraints", + constraint_writer_method=self.constraint_contact_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_surfacefaces_constraints_contact(self, f, femobj, contact_obj): # slave DEP f.write("*SURFACE, NAME=DEP{}\n".format(contact_obj.Name)) @@ -539,35 +577,23 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for i in femobj["ContactMasterFaces"]: f.write("{},S{}\n".format(i[0], i[1])) - def write_constraints_contact(self, f): - if not self.contact_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Contact Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.contact_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - contact_obj = femobj["Object"] - f.write("** " + contact_obj.Label + "\n") - f.write( - "*CONTACT PAIR, INTERACTION=INT{},TYPE=SURFACE TO SURFACE\n" - .format(contact_obj.Name) - ) - ind_surf = "IND" + contact_obj.Name - dep_surf = "DEP" + contact_obj.Name - f.write(dep_surf + "," + ind_surf + "\n") - f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) - f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") - slope = contact_obj.Slope - f.write(str(slope) + " \n") - friction = contact_obj.Friction - if friction > 0: - f.write("*FRICTION \n") - stick = (slope / 10.0) - f.write(str(friction) + ", " + str(stick) + " \n") + def constraint_contact_writer(self, f, femobj, contact_obj): + f.write( + "*CONTACT PAIR, INTERACTION=INT{},TYPE=SURFACE TO SURFACE\n" + .format(contact_obj.Name) + ) + ind_surf = "IND" + contact_obj.Name + dep_surf = "DEP" + contact_obj.Name + f.write(dep_surf + "," + ind_surf + "\n") + f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) + f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") + slope = contact_obj.Slope + f.write(str(slope) + " \n") + friction = contact_obj.Friction + if friction > 0: + f.write("*FRICTION \n") + stick = (slope / 10.0) + f.write(str(friction) + ", " + str(stick) + " \n") # ******************************************************************************************** # constraints tie @@ -582,6 +608,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_tie(self, f): + self.write_constraints_data( + f, + femobjs=self.tie_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="Tie Constraints", + constraint_writer_method=self.constraint_tie_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_surfacefaces_constraints_tie(self, f, femobj, tie_obj): # slave DEP f.write("*SURFACE, NAME=TIE_DEP{}\n".format(tie_obj.Name)) @@ -592,27 +628,15 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for i in femobj["TieMasterFaces"]: f.write("{},S{}\n".format(i[0], i[1])) - def write_constraints_tie(self, f): - if not self.tie_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Tie Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.tie_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - tie_obj = femobj["Object"] - f.write("** {}\n".format(tie_obj.Label)) - tolerance = str(tie_obj.Tolerance.getValueAs("mm")).rstrip() - f.write( - "*TIE, POSITION TOLERANCE={}, ADJUST=NO, NAME=TIE{}\n" - .format(tolerance, tie_obj.Name) - ) - ind_surf = "TIE_IND" + tie_obj.Name - dep_surf = "TIE_DEP" + tie_obj.Name - f.write("{},{}\n".format(dep_surf, ind_surf)) + def constraint_tie_writer(self, f, femobj, tie_obj): + tolerance = str(tie_obj.Tolerance.getValueAs("mm")).rstrip() + f.write( + "*TIE, POSITION TOLERANCE={}, ADJUST=NO, NAME=TIE{}\n" + .format(tolerance, tie_obj.Name) + ) + ind_surf = "TIE_IND" + tie_obj.Name + dep_surf = "TIE_DEP" + tie_obj.Name + f.write("{},{}\n".format(dep_surf, ind_surf)) # ******************************************************************************************** # constraints sectionprint @@ -627,55 +651,48 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_sectionprint(self, f): + self.write_constraints_data( + f, + femobjs=self.sectionprint_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="SectionPrint Constraints", + constraint_writer_method=self.constraint_sectionprint_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + # TODO move code parts from this method to base writer module # into get_constraints_sectionprint_faces method def write_surfacefaces_constraints_sectionprint(self, f, femobj, sectionprint_obj): - # get surface nodes and write them to file - for femobj in self.sectionprint_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - sectionprint_obj = femobj["Object"] - f.write("** " + sectionprint_obj.Label + "\n") - for o, elem_tup in sectionprint_obj.References: - for elem in elem_tup: - ref_shape = o.Shape.getElement(elem) - if ref_shape.ShapeType == "Face": - f.write("*SURFACE, NAME=SECTIONFACE{}\n".format(sectionprint_obj.Name)) - v = self.mesh_object.FemMesh.getccxVolumesByFace(ref_shape) - if len(v) > 0: - # volume elements found - FreeCAD.Console.PrintLog( - "{}, surface {}, {} touching volume elements found\n" - .format(sectionprint_obj.Label, sectionprint_obj.Name, len(v)) - ) - for i in v: - f.write("{},S{}\n".format(i[0], i[1])) - else: - # no volume elements found, shell elements not allowed - FreeCAD.Console.PrintError( - "{}, surface {}, Error: " - "No volume elements found!\n" - .format(sectionprint_obj.Label, sectionprint_obj.Name) - ) - f.write("** Error: empty list\n") + for o, elem_tup in sectionprint_obj.References: + for elem in elem_tup: + ref_shape = o.Shape.getElement(elem) + if ref_shape.ShapeType == "Face": + f.write("*SURFACE, NAME=SECTIONFACE{}\n".format(sectionprint_obj.Name)) + v = self.mesh_object.FemMesh.getccxVolumesByFace(ref_shape) + if len(v) > 0: + # volume elements found + FreeCAD.Console.PrintLog( + "{}, surface {}, {} touching volume elements found\n" + .format(sectionprint_obj.Label, sectionprint_obj.Name, len(v)) + ) + for i in v: + f.write("{},S{}\n".format(i[0], i[1])) + else: + # no volume elements found, shell elements not allowed + FreeCAD.Console.PrintError( + "{}, surface {}, Error: " + "No volume elements found!\n" + .format(sectionprint_obj.Label, sectionprint_obj.Name) + ) + f.write("** Error: empty list\n") - def write_constraints_sectionprint(self, f): - if not self.sectionprint_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** SectionPrint Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for femobj in self.sectionprint_objects: - # femobj --> dict, FreeCAD document object is femobj["Object"] - sectionprint_obj = femobj["Object"] - f.write("** {}\n".format(sectionprint_obj.Label)) - f.write( - "*SECTION PRINT, SURFACE=SECTIONFACE{}, NAME=SECTIONPRINT{}\n" - .format(sectionprint_obj.Name, sectionprint_obj.Name) - ) - f.write("SOF, SOM, SOAREA\n") + def constraint_sectionprint_writer(self, f, femobj, sectionprint_obj): + f.write( + "*SECTION PRINT, SURFACE=SECTIONFACE{}, NAME=SECTIONPRINT{}\n" + .format(sectionprint_obj.Name, sectionprint_obj.Name) + ) + f.write("SOF, SOM, SOAREA\n") # ******************************************************************************************** # constraints transform @@ -690,6 +707,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_transform(self, f): + self.write_constraints_data( + f, + femobjs=self.transform_objects, + analysis_types="all", # write for all analysis types + constraint_title_name="Transform Constraints", + constraint_writer_method=self.constraint_transform_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_node_sets_nodes_constraints_transform(self, f, femobj, trans_obj): if trans_obj.TransformType == "Rectangular": f.write("*NSET,NSET=Rect" + trans_obj.Name + "\n") @@ -698,41 +725,31 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for n in femobj["Nodes"]: f.write(str(n) + ",\n") - def write_constraints_transform(self, f): - if not self.transform_objects: - return - # write for all analysis types - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Transform Constraints\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for trans_object in self.transform_objects: - trans_obj = trans_object["Object"] - trans_name = "" - trans_type = "" - if trans_obj.TransformType == "Rectangular": - trans_name = "Rect" - trans_type = "R" - coords = geomtools.get_rectangular_coords(trans_obj) - elif trans_obj.TransformType == "Cylindrical": - trans_name = "Cylin" - trans_type = "C" - coords = geomtools.get_cylindrical_coords(trans_obj) - f.write("** {}\n".format(trans_obj.Label)) - f.write("*TRANSFORM, NSET={}{}, TYPE={}\n".format( - trans_name, - trans_obj.Name, - trans_type, - )) - f.write("{:f},{:f},{:f},{:f},{:f},{:f}\n".format( - coords[0], - coords[1], - coords[2], - coords[3], - coords[4], - coords[5], - )) + def constraint_transform_writer(self, f, femobj, trans_obj): + trans_name = "" + trans_type = "" + if trans_obj.TransformType == "Rectangular": + trans_name = "Rect" + trans_type = "R" + coords = geomtools.get_rectangular_coords(trans_obj) + elif trans_obj.TransformType == "Cylindrical": + trans_name = "Cylin" + trans_type = "C" + coords = geomtools.get_cylindrical_coords(trans_obj) + f.write("** {}\n".format(trans_obj.Label)) + f.write("*TRANSFORM, NSET={}{}, TYPE={}\n".format( + trans_name, + trans_obj.Name, + trans_type, + )) + f.write("{:f},{:f},{:f},{:f},{:f},{:f}\n".format( + coords[0], + coords[1], + coords[2], + coords[3], + coords[4], + coords[5], + )) # ******************************************************************************************** # constraints temperature @@ -747,36 +764,34 @@ class FemInputWriterCcx(writerbase.FemInputWriter): caller_method_name=sys._getframe().f_code.co_name, ) + def write_constraints_temperature(self, f): + self.write_constraints_data( + f, + femobjs=self.temperature_objects, + analysis_types=["thermomech"], + constraint_title_name="Fixed temperature constraint applied", + constraint_writer_method=self.constraint_temperature_writer, + caller_method_name=sys._getframe().f_code.co_name, + ) + def write_node_sets_nodes_constraints_temperature(self, f, femobj, temp_obj): f.write("*NSET,NSET=" + temp_obj.Name + "\n") for n in femobj["Nodes"]: f.write(str(n) + ",\n") - def write_constraints_temperature(self, f): - if not self.temperature_objects: - return - if not self.analysis_type == "thermomech": - return - - # write constraint to file - f.write("\n***********************************************************\n") - f.write("** Fixed temperature constraint applied\n") - f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - for ftobj in self.temperature_objects: - fixedtemp_obj = ftobj["Object"] - f.write("** " + fixedtemp_obj.Label + "\n") - NumberOfNodes = len(ftobj["Nodes"]) - if fixedtemp_obj.ConstraintType == "Temperature": - f.write("*BOUNDARY\n") - f.write("{},11,11,{}\n".format(fixedtemp_obj.Name, fixedtemp_obj.Temperature)) - f.write("\n") - elif fixedtemp_obj.ConstraintType == "CFlux": - f.write("*CFLUX\n") - f.write("{},11,{}\n".format( - fixedtemp_obj.Name, - fixedtemp_obj.CFlux * 0.001 / NumberOfNodes - )) - f.write("\n") + def constraint_temperature_writer(self, f, femobj, fixedtemp_obj): + NumberOfNodes = len(femobj["Nodes"]) + if fixedtemp_obj.ConstraintType == "Temperature": + f.write("*BOUNDARY\n") + f.write("{},11,11,{}\n".format(fixedtemp_obj.Name, fixedtemp_obj.Temperature)) + f.write("\n") + elif fixedtemp_obj.ConstraintType == "CFlux": + f.write("*CFLUX\n") + f.write("{},11,{}\n".format( + fixedtemp_obj.Name, + fixedtemp_obj.CFlux * 0.001 / NumberOfNodes + )) + f.write("\n") # ******************************************************************************************** # constraints initialtemperature @@ -841,6 +856,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): write_name="constraints_force_node_loads", sets_writer_method=self.write_nodeloads_constraints_force, caller_method_name=sys._getframe().f_code.co_name, + write_before="*CLOAD\n" ) def write_nodeloads_constraints_force(self, f, femobj, force_obj): From 7f01e989dbfdba087bcd998853da40fccb6ac5c8 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 13:19:14 +0200 Subject: [PATCH 4/6] FEM: calculix writer, code formating --- src/Mod/Fem/femsolver/calculix/writer.py | 90 ++++++++++++------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 1fc9b3e638..d9c395aa8c 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -302,7 +302,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for femobj in femobjs: # femobj --> dict, FreeCAD document object is femobj["Object"] the_obj = femobj["Object"] - f.write("** " + the_obj.Label + "\n") + f.write("** {}\n".format(the_obj.Label)) sets_writer_method(inpfile_split, femobj, the_obj) if write_after != "": f.write(write_after) @@ -313,7 +313,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): for femobj in femobjs: # femobj --> dict, FreeCAD document object is femobj["Object"] the_obj = femobj["Object"] - f.write("** " + the_obj.Label + "\n") + f.write("** {}\n".format(the_obj.Label)) sets_writer_method(f, femobj, the_obj) if write_after != "": f.write(write_after) @@ -378,17 +378,17 @@ class FemInputWriterCcx(writerbase.FemInputWriter): if self.femmesh.Volumes \ and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): if len(femobj["NodesSolid"]) > 0: - f.write("*NSET,NSET=" + fix_obj.Name + "Solid\n") + f.write("*NSET,NSET={}Solid\n".format(fix_obj.Name)) for n in femobj["NodesSolid"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) if len(femobj["NodesFaceEdge"]) > 0: - f.write("*NSET,NSET=" + fix_obj.Name + "FaceEdge\n") + f.write("*NSET,NSET={}FaceEdge\n".format(fix_obj.Name)) for n in femobj["NodesFaceEdge"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) else: f.write("*NSET,NSET=" + fix_obj.Name + "\n") for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) def constraint_fixed_writer(self, f, femobj, fix_obj): if self.femmesh.Volumes \ @@ -444,40 +444,38 @@ class FemInputWriterCcx(writerbase.FemInputWriter): ) def write_node_sets_nodes_constraints_displacement(self, f, femobj, disp_obj): - f.write("*NSET,NSET=" + disp_obj.Name + "\n") + f.write("*NSET,NSET={}\n".format(disp_obj.Name)) for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) def constraint_displacement_writer(self, f, femobj, disp_obj): - disp_obj_name = disp_obj.Name f.write("*BOUNDARY\n") if disp_obj.xFix: - f.write(disp_obj_name + ",1\n") + f.write("{},1\n".format(disp_obj.Name)) elif not disp_obj.xFree: - f.write(disp_obj_name + ",1,1," + str(disp_obj.xDisplacement) + "\n") + f.write("{},1,1,{}\n".format(disp_obj.Name, disp_obj.xDisplacement)) if disp_obj.yFix: - f.write(disp_obj_name + ",2\n") + f.write("{},2\n".format(disp_obj.Name)) elif not disp_obj.yFree: - f.write(disp_obj_name + ",2,2," + str(disp_obj.yDisplacement) + "\n") + f.write("{},2,2,{}\n".format(disp_obj.Name, disp_obj.yDisplacement)) if disp_obj.zFix: - f.write(disp_obj_name + ",3\n") + f.write("{},3\n".format(disp_obj.Name)) elif not disp_obj.zFree: - f.write(disp_obj_name + ",3,3," + str(disp_obj.zDisplacement) + "\n") + f.write("{},3,3,{}\n".format(disp_obj.Name, disp_obj.zDisplacement)) if self.beamsection_objects or self.shellthickness_objects: if disp_obj.rotxFix: - f.write(disp_obj_name + ",4\n") + f.write("{},4\n".format(disp_obj.Name)) elif not disp_obj.rotxFree: - f.write(disp_obj_name + ",4,4," + str(disp_obj.xRotation) + "\n") + f.write("{},4,4,{}\n".format(disp_obj.Name, disp_obj.xRotation)) if disp_obj.rotyFix: - f.write(disp_obj_name + ",5\n") + f.write("{},5\n".format(disp_obj.Name)) elif not disp_obj.rotyFree: - f.write(disp_obj_name + ",5,5," + str(disp_obj.yRotation) + "\n") + f.write("{},5,5,{}\n".format(disp_obj.Name, disp_obj.yRotation)) if disp_obj.rotzFix: - f.write(disp_obj_name + ",6\n") + f.write("{},6\n".format(disp_obj.Name)) elif not disp_obj.rotzFree: - f.write(disp_obj_name + ",6,6," + str(disp_obj.zRotation) + "\n") - + f.write("{},6,6,{}\n".format(disp_obj.Name, disp_obj.zRotation)) # ******************************************************************************************** # constraints planerotation @@ -514,7 +512,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # Thus call write_node_sets_constraints_planerotation has to be # after constraint fixed and constraint displacement l_nodes = femobj["Nodes"] - f.write("*NSET,NSET=" + fric_obj.Name + "\n") + f.write("*NSET,NSET={}\n".format(fric_obj.Name)) # Code to extract nodes and coordinates on the PlaneRotation support face nodes_coords = [] for node in l_nodes: @@ -538,11 +536,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): MPC = node_planerotation[i] MPC_nodes.append(MPC) for i in range(len(MPC_nodes)): - f.write(str(MPC_nodes[i]) + ",\n") + f.write("{},\n".format(MPC_nodes[i])) def constraint_planerotation_writer(self, f, femobj, fric_obj): f.write("*MPC\n") - f.write("PLANE," + fric_obj.Name + "\n") + f.write("PLANE,{}\n".format(fric_obj.Name)) # ******************************************************************************************** # constraints contact @@ -584,16 +582,16 @@ class FemInputWriterCcx(writerbase.FemInputWriter): ) ind_surf = "IND" + contact_obj.Name dep_surf = "DEP" + contact_obj.Name - f.write(dep_surf + "," + ind_surf + "\n") + f.write("{},{}\n".format(dep_surf, ind_surf)) f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") slope = contact_obj.Slope - f.write(str(slope) + " \n") + f.write("{} \n".format(slope)) friction = contact_obj.Friction if friction > 0: f.write("*FRICTION \n") stick = (slope / 10.0) - f.write(str(friction) + ", " + str(stick) + " \n") + f.write("{}, {} \n".format(friction, stick)) # ******************************************************************************************** # constraints tie @@ -634,8 +632,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter): "*TIE, POSITION TOLERANCE={}, ADJUST=NO, NAME=TIE{}\n" .format(tolerance, tie_obj.Name) ) - ind_surf = "TIE_IND" + tie_obj.Name - dep_surf = "TIE_DEP" + tie_obj.Name + ind_surf = "TIE_IND{}".format(tie_obj.Name) + dep_surf = "TIE_DEP{}".format(tie_obj.Name) f.write("{},{}\n".format(dep_surf, ind_surf)) # ******************************************************************************************** @@ -719,11 +717,11 @@ class FemInputWriterCcx(writerbase.FemInputWriter): def write_node_sets_nodes_constraints_transform(self, f, femobj, trans_obj): if trans_obj.TransformType == "Rectangular": - f.write("*NSET,NSET=Rect" + trans_obj.Name + "\n") + f.write("*NSET,NSET=Rect{}\n".format(trans_obj.Name)) elif trans_obj.TransformType == "Cylindrical": - f.write("*NSET,NSET=Cylin" + trans_obj.Name + "\n") + f.write("*NSET,NSET=Cylin{}\n".format(trans_obj.Name)) for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) def constraint_transform_writer(self, f, femobj, trans_obj): trans_name = "" @@ -775,21 +773,21 @@ class FemInputWriterCcx(writerbase.FemInputWriter): ) def write_node_sets_nodes_constraints_temperature(self, f, femobj, temp_obj): - f.write("*NSET,NSET=" + temp_obj.Name + "\n") + f.write("*NSET,NSET={}\n".format(temp_obj.Name)) for n in femobj["Nodes"]: - f.write(str(n) + ",\n") + f.write("{},\n".format(n)) - def constraint_temperature_writer(self, f, femobj, fixedtemp_obj): + def constraint_temperature_writer(self, f, femobj, temp_obj): NumberOfNodes = len(femobj["Nodes"]) - if fixedtemp_obj.ConstraintType == "Temperature": + if temp_obj.ConstraintType == "Temperature": f.write("*BOUNDARY\n") - f.write("{},11,11,{}\n".format(fixedtemp_obj.Name, fixedtemp_obj.Temperature)) + f.write("{},11,11,{}\n".format(temp_obj.Name, temp_obj.Temperature)) f.write("\n") - elif fixedtemp_obj.ConstraintType == "CFlux": + elif temp_obj.ConstraintType == "CFlux": f.write("*CFLUX\n") f.write("{},11,{}\n".format( - fixedtemp_obj.Name, - fixedtemp_obj.CFlux * 0.001 / NumberOfNodes + temp_obj.Name, + temp_obj.CFlux * 0.001 / NumberOfNodes )) f.write("\n") @@ -867,13 +865,13 @@ class FemInputWriterCcx(writerbase.FemInputWriter): node_load = ref_shape[1][n] if (direction_vec.x != 0.0): v1 = "{:.13E}".format(direction_vec.x * node_load) - f.write(str(n) + ",1," + v1 + "\n") + f.write("{},1,{}\n".format(n, v1)) if (direction_vec.y != 0.0): v2 = "{:.13E}".format(direction_vec.y * node_load) - f.write(str(n) + ",2," + v2 + "\n") + f.write("{},2,{}\n".format(n, v2)) if (direction_vec.z != 0.0): v3 = "{:.13E}".format(direction_vec.z * node_load) - f.write(str(n) + ",3," + v3 + "\n") + f.write("{},3,{}\n".format(n, v3)) f.write("\n") f.write("\n") @@ -1065,7 +1063,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): ) if self.solver_obj.IterationsThermoMechMaximum: if self.analysis_type == "thermomech": - step += ", INC=" + str(self.solver_obj.IterationsThermoMechMaximum) + step += ", INC={}".format(self.solver_obj.IterationsThermoMechMaximum) elif ( self.analysis_type == "static" or self.analysis_type == "frequency" From ec55cb6b779bd8d670c77c1061f86ae430e323d7 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 14:24:43 +0200 Subject: [PATCH 5/6] FEM: calculix writer, generic node set writer, get rid of duplicate code --- src/Mod/Fem/femsolver/calculix/writer.py | 31 ++++++++++-------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index d9c395aa8c..59d0b19861 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -278,6 +278,17 @@ class FemInputWriterCcx(writerbase.FemInputWriter): write_before="", write_after="", ): + def constraint_sets_loop_writing(the_file, femobjs, write_before, write_after): + 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("** {}\n".format(the_obj.Label)) + sets_writer_method(the_file, femobj, the_obj) + if write_after != "": + f.write(write_after) + if not femobjs: return @@ -297,26 +308,10 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write("** {}\n".format(write_name.replace("_", " "))) f.write("*INCLUDE,INPUT={}\n".format(file_name_split)) inpfile_split = open(join(self.dir_name, file_name_split), "w") - 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("** {}\n".format(the_obj.Label)) - sets_writer_method(inpfile_split, femobj, the_obj) - if write_after != "": - f.write(write_after) + constraint_sets_loop_writing(inpfile_split, femobjs, write_before, write_after) inpfile_split.close() else: - 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("** {}\n".format(the_obj.Label)) - sets_writer_method(f, femobj, the_obj) - if write_after != "": - f.write(write_after) + constraint_sets_loop_writing(f, femobjs, write_before, write_after) # ******************************************************************************************** # write constraint data From f1db4bc83e8946991008dfccaae6af92d51a4347 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 6 Jul 2021 14:54:40 +0200 Subject: [PATCH 6/6] FEM: calculix writer, get rid of two times the word head --- src/Mod/Fem/femsolver/calculix/writer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 59d0b19861..83fd35b893 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -1935,8 +1935,8 @@ def liquid_section_def(obj, section_type): section_geo = "" for i in range(len(obj.PumpFlowRate)): flow_rate = str(obj.PumpFlowRate[i]) - head = str(obj.PumpHeadLoss[i]) - section_geo = section_geo + flow_rate + "," + head + "," + top = str(obj.PumpHeadLoss[i]) + section_geo = section_geo + flow_rate + "," + top + "," section_geo = section_geo + "\n" return section_geo else: