From 0e370118032f3ce168df382af941011e20e1b549 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Wed, 19 Feb 2020 17:56:47 +0100 Subject: [PATCH] FEM: constraint tie, get the faces data in writer base class --- src/Mod/Fem/femmesh/meshtools.py | 75 +++++++++++++++++++ src/Mod/Fem/femsolver/calculix/writer.py | 50 ++++--------- src/Mod/Fem/femsolver/writerbase.py | 26 +++++++ .../Fem/femtest/data/ccx/constraint_tie.inp | 12 +-- 4 files changed, 121 insertions(+), 42 deletions(-) diff --git a/src/Mod/Fem/femmesh/meshtools.py b/src/Mod/Fem/femmesh/meshtools.py index d2b5ce6567..bd6c07c287 100644 --- a/src/Mod/Fem/femmesh/meshtools.py +++ b/src/Mod/Fem/femmesh/meshtools.py @@ -1737,6 +1737,81 @@ def get_contact_obj_faces( return [slave_faces, master_faces] +# ***** tie faces **************************************************************************** +def get_tie_obj_faces( + femmesh, + femelement_table, + femnodes_ele_table, + femobj +): + # see comment get_contact_obj_faces + # solid mesh is same as contact, but face mesh is not allowed for tie + # TODO get rid of duplicate code for contact and tie + + slave_faces, master_faces = [], [] + + tie_obj = femobj["Object"] + if len(tie_obj.References) == 1 and len(tie_obj.References[0][1]) == 2: + # [(, ('Face7', 'Face3'))] + # refs are merged because they are on the same doc obj + # but only one element face for each contact face (Gui, TaskPael tie) + ref_obj = tie_obj.References[0][0] + ref_ele = tie_obj.References[0][1] + slave_ref = (ref_obj, (ref_ele[0],)) # the comma is needed! + master_ref = (ref_obj, (ref_ele[1],)) # the comma is needed! + elif ( + len(tie_obj.References) == 2 + and len(tie_obj.References[0][1]) == 1 + and len(tie_obj.References[1][1]) == 1 + ): + # [(, ('Face3',)), (, ('Face7',))] + # refs are on different objects + # but only one element face for each contact face (Gui, TaskPael tie) + slave_ref = tie_obj.References[0] + master_ref = tie_obj.References[1] + else: + FreeCAD.Console.PrintError( + "Not valid (example: only master or slave defined) " + "or not supported reference shape elements, contact face combination " + "(example: multiple element faces per master or slave\n" + ) + + FreeCAD.Console.PrintLog("Slave: {}, {}\n".format(slave_ref[0].Name, slave_ref)) + FreeCAD.Console.PrintLog("Master: {}, {}\n".format(master_ref[0].Name, master_ref)) + + if is_solid_femmesh(femmesh): + # get the nodes, sorted and duplicates removed + slaveface_nds = sorted(list(set(get_femnodes_by_refshape(femmesh, slave_ref)))) + masterface_nds = sorted(list(set(get_femnodes_by_refshape(femmesh, master_ref)))) + # FreeCAD.Console.PrintLog("slaveface_nds: {}\n".format(slaveface_nds)) + # FreeCAD.Console.PrintLog("masterface_nds: {}\n".format(slaveface_nds)) + + # fill the bit_pattern_dict and search for the faces + slave_bit_pattern_dict = get_bit_pattern_dict( + femelement_table, + femnodes_ele_table, + slaveface_nds + ) + master_bit_pattern_dict = get_bit_pattern_dict( + femelement_table, + femnodes_ele_table, + masterface_nds + ) + + # get the faces ids + slave_faces = get_ccxelement_faces_from_binary_search(slave_bit_pattern_dict) + master_faces = get_ccxelement_faces_from_binary_search(master_bit_pattern_dict) + + elif is_face_femmesh(femmesh): + FreeCAD.Console.PrintError( + "Shell mesh is not allowed for constraint tie.\n" + ) + + FreeCAD.Console.PrintLog("slave_faces: {}\n".format(slave_faces)) + FreeCAD.Console.PrintLog("master_faces: {}\n".format(master_faces)) + return [slave_faces, master_faces] + + # ************************************************************************************************ # ***** groups *********************************************************************************** def get_mesh_group_elements( diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 1a2846f7df..8087f56d78 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -591,44 +591,24 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write("{},S{}\n".format(i[0], i[1])) def write_surfaces_constraints_tie(self, f): - # get surface nodes and write them to file + # get faces + self.get_constraints_tie_faces() + # write faces to file f.write("\n***********************************************************\n") f.write("** Surfaces for tie constraint\n") f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - obj = 0 for femobj in self.tie_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] tie_obj = femobj["Object"] f.write("** " + tie_obj.Label + "\n") - cnt = 0 - obj = obj + 1 - for o, elem_tup in tie_obj.References: - for elem in elem_tup: - ref_shape = o.Shape.getElement(elem) - cnt = cnt + 1 - if ref_shape.ShapeType == "Face": - if cnt == 1: - name = "TIE_DEP" + str(obj) - else: - name = "TIE_IND" + str(obj) - f.write("*SURFACE, NAME=" + name + "\n") - - 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(tie_obj.Label, 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(tie_obj.Label, name) - ) + # 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_node_sets_constraints_transform(self, f): # get nodes @@ -1065,19 +1045,17 @@ class FemInputWriterCcx(writerbase.FemInputWriter): f.write("\n***********************************************************\n") f.write("** Tie Constraints\n") f.write("** written by {} function\n".format(sys._getframe().f_code.co_name)) - obj = 0 for femobj in self.tie_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] - obj = obj + 1 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, obj) + .format(tolerance, tie_obj.Name) ) - ind_surf = "TIE_IND" + str(obj) - dep_surf = "TIE_DEP" + str(obj) + ind_surf = "TIE_IND" + tie_obj.Name + dep_surf = "TIE_DEP" + tie_obj.Name f.write("{},{}\n".format(dep_surf, ind_surf)) def write_constraints_planerotation(self, f): diff --git a/src/Mod/Fem/femsolver/writerbase.py b/src/Mod/Fem/femsolver/writerbase.py index f080a57004..eeeda4e2a4 100644 --- a/src/Mod/Fem/femsolver/writerbase.py +++ b/src/Mod/Fem/femsolver/writerbase.py @@ -339,6 +339,32 @@ class FemInputWriter(): # FreeCAD.Console.PrintLog("{}\n".format(femobj["ContactSlaveFaces"])) # FreeCAD.Console.PrintLog("{}\n".format(femobj["ContactMasterFaces"])) + def get_constraints_tie_faces(self): + if not self.femnodes_mesh: + self.femnodes_mesh = self.femmesh.Nodes + if not self.femelement_table: + self.femelement_table = meshtools.get_femelement_table(self.femmesh) + if not self.femnodes_ele_table: + self.femnodes_ele_table = meshtools.get_femnodes_ele_table( + self.femnodes_mesh, + self.femelement_table + ) + + for femobj in self.tie_objects: + # femobj --> dict, FreeCAD document object is femobj["Object"] + print_obj_info(femobj["Object"]) + slave_faces, master_faces = meshtools.get_tie_obj_faces( + self.femmesh, + self.femelement_table, + self.femnodes_ele_table, femobj + ) + # [ele_id, ele_face_id], [ele_id, ele_face_id], ...] + # whereas the ele_face_id might be ccx specific + femobj["TieSlaveFaces"] = slave_faces + femobj["TieMasterFaces"] = master_faces + # FreeCAD.Console.PrintLog("{}\n".format(femobj["ContactSlaveFaces"])) + # FreeCAD.Console.PrintLog("{}\n".format(femobj["ContactMasterFaces"])) + def get_element_geometry2D_elements(self): # get element ids and write them into the objects FreeCAD.Console.PrintMessage("Shell thicknesses\n") diff --git a/src/Mod/Fem/femtest/data/ccx/constraint_tie.inp b/src/Mod/Fem/femtest/data/ccx/constraint_tie.inp index 945ec8c505..a4d8614ab1 100644 --- a/src/Mod/Fem/femtest/data/ccx/constraint_tie.inp +++ b/src/Mod/Fem/femtest/data/ccx/constraint_tie.inp @@ -18547,7 +18547,7 @@ Evolumes ** Surfaces for tie constraint ** written by write_surfaces_constraints_tie function ** ConstraintTie -*SURFACE, NAME=TIE_DEP1 +*SURFACE, NAME=TIE_DEPConstraintTie 4834,S1 4835,S1 4890,S1 @@ -18570,7 +18570,7 @@ Evolumes 9637,S1 9877,S1 10493,S2 -*SURFACE, NAME=TIE_IND1 +*SURFACE, NAME=TIE_INDConstraintTie 4687,S4 5445,S3 5759,S4 @@ -18613,8 +18613,8 @@ Evolumes ** Tie Constraints ** written by write_constraints_tie function ** ConstraintTie -*TIE, POSITION TOLERANCE=25, ADJUST=NO, NAME=TIE1 -TIE_DEP1,TIE_IND1 +*TIE, POSITION TOLERANCE=25, ADJUST=NO, NAME=TIEConstraintTie +TIE_DEPConstraintTie,TIE_INDConstraintTie *********************************************************** ** At least one step is needed to run an CalculiX analysis of FreeCAD @@ -18665,8 +18665,8 @@ RF *********************************************************** ** CalculiX Input file ** written by write_footer function -** written by --> FreeCAD 0.19.19475 (Git) -** written on --> Tue Feb 4 16:49:27 2020 +** written by --> FreeCAD 0.19.19481 (Git) +** written on --> Wed Feb 5 08:55:37 2020 ** file name --> ** analysis name --> Analysis **