def get_material_elements(self): # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites FreeCAD.Console.PrintMessage('Materials\n') if self.femmesh.Volumes: # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges, # there we have to check of some geometric objects all_found = False if self.femmesh.GroupCount: all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects) FreeCAD.Console.PrintMessage(all_found) FreeCAD.Console.PrintMessage('\n') if all_found is False: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # we're going to use the binary search for get_femelements_by_femnodes() # thus we need the parameter values self.femnodes_ele_table if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femnodes_ele_table: self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table) if self.shellthickness_objects: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) if self.beamsection_objects or self.fluidsection_objects: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
def get_material_elements(self): # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites print("Materials") if self.femmesh.Volumes: # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges, # there we have to check of some geometric objects all_found = False if self.femmesh.GroupCount: all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects) print(all_found) if all_found is False: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # we're going to use the binary search for get_femelements_by_femnodes() # thus we need the parameter values self.femnodes_ele_table if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femnodes_ele_table: self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table) if self.shellthickness_objects: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) if self.beamsection_objects or self.fluidsection_objects: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
def get_solid_element_sets(self, femobjs): # get element ids and write them into the femobj all_found = False if self.femmesh.GroupCount: all_found = meshtools.get_femelement_sets_from_group_data( self.femmesh, femobjs) FreeCAD.Console.PrintMessage(all_found) FreeCAD.Console.PrintMessage("\n") if all_found is False: if not self.femelement_table: self.femelement_table = meshtools.get_femelement_table( self.femmesh) # we're going to use the binary search for get_femelements_by_femnodes() # thus we need the parameter values self.femnodes_ele_table if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femnodes_ele_table: self.femnodes_ele_table = meshtools.get_femnodes_ele_table( self.femnodes_mesh, self.femelement_table) control = meshtools.get_femelement_sets(self.femmesh, self.femelement_table, femobjs, self.femnodes_ele_table) # we only need to set it, if it is still True if (self.femelement_count_test is True) and (control is False): self.femelement_count_test = False
def get_z88_element_type(femmesh, femelement_table=None): import femmesh.meshtools as FemMeshTools if not femmesh: print("Error: No femmesh!") if not femelement_table: print("We need to get the femelement_table first!") femelement_table = FemMeshTools.get_femelement_table(femmesh) # in some cases lowest key in femelement_table is not [1] for elem in sorted(femelement_table): elem_length = len(femelement_table[elem]) FreeCAD.Console.PrintLog('node count of first element: ' + str(elem_length) + '\n') break # break after the first elem if FemMeshTools.is_solid_femmesh(femmesh): if femmesh.TetraCount == femmesh.VolumeCount: if elem_length == 4: return 17 elif elem_length == 10: return 16 else: print('Tetra with neither 4 nor 10 nodes') elif femmesh.HexaCount == femmesh.VolumeCount: if elem_length == 8: return 1 elif elem_length == 20: return 10 else: print('Hexa with neither 8 nor 20 nodes') return 0 else: print('no tetra, no hexa or Mixed Volume Elements') elif FemMeshTools.is_face_femmesh(femmesh): if femmesh.TriangleCount == femmesh.FaceCount: if elem_length == 3: print('tria3mesh, not supported by z88') return 0 elif elem_length == 6: return 24 else: print('Tria with neither 3 nor 6 nodes') return 0 elif femmesh.QuadrangleCount == femmesh.FaceCount: if elem_length == 4: print('quad4mesh, not supported by z88') return 0 elif elem_length == 8: return 23 else: print('Quad with neither 4 nor 8 nodes') return 0 else: print('no tria, no quad') return 0 elif FemMeshTools.is_edge_femmesh(femmesh): print('Edge femmesh will be exported as 3D truss element nr 4') return 4 else: print('Neither edge nor face nor solid femmesh') return 0 return 0
def get_constraints_force_nodeloads(self): # check shape type of reference shape for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] FreeCAD.Console.PrintMessage("Constraint force:" + ' ' + femobj['Object'].Name + '\n') frc_obj = femobj['Object'] if femobj['RefShapeType'] == 'Vertex': # print("load on vertices --> we do not need the femelement_table and femnodes_mesh for node load calculation") pass elif femobj['RefShapeType'] == 'Face' and FemMeshTools.is_solid_femmesh(self.femmesh) and not FemMeshTools.has_no_face_data(self.femmesh): # print("solid_mesh with face data --> we do not need the femelement_table but we need the femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes else: # print("mesh without needed data --> we need the femelement_table and femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # get node loads FreeCAD.Console.PrintMessage(" Finite element mesh nodes will be retrieved by searching the appropriate nodes in the finite element mesh.\n") FreeCAD.Console.PrintMessage(" The appropriate finite element mesh node load values will be calculated according to the finite element definition.\n") for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] frc_obj = femobj['Object'] if frc_obj.Force == 0: FreeCAD.Console.PrintMessage(' Warning --> Force = 0\n') if femobj['RefShapeType'] == 'Vertex': # point load on vertieces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_vertex_nodeload_table(self.femmesh, frc_obj) elif femobj['RefShapeType'] == 'Edge': # line load on edges femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_edge_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) elif femobj['RefShapeType'] == 'Face': # area load on faces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_face_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj)
def get_constraints_force_nodeloads(self): # check shape type of reference shape for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] FreeCAD.Console.PrintMessage("Constraint force: " + femobj['Object'].Name + '\n') frc_obj = femobj['Object'] if femobj['RefShapeType'] == 'Vertex': # print("load on vertices --> we do not need the femelement_table and femnodes_mesh for node load calculation") pass elif femobj['RefShapeType'] == 'Face' and FemMeshTools.is_solid_femmesh(self.femmesh) and not FemMeshTools.has_no_face_data(self.femmesh): # print("solid_mesh with face data --> we do not need the femelement_table but we need the femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes else: # print("mesh without needed data --> we need the femelement_table and femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # get node loads for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] frc_obj = femobj['Object'] if frc_obj.Force == 0: FreeCAD.Console.PrintMessage(' Warning --> Force = 0\n') if femobj['RefShapeType'] == 'Vertex': # point load on vertieces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_vertex_nodeload_table(self.femmesh, frc_obj) elif femobj['RefShapeType'] == 'Edge': # line load on edges femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_edge_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) elif femobj['RefShapeType'] == 'Face': # area load on faces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_face_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj)
def get_material_elements(self): # it only works if either Volumes or Shellthicknesses or Beamsections are in the material objects # it means it does not work for mixed meshes and multiple materials, this is checked in check_prerequisites # the femelement_table is only calculated for the highest dimension in get_femelement_table FreeCAD.Console.PrintMessage('Materials\n') if self.femmesh.Volumes: # we only could do this for volumes, if a mesh contains volumes we're going to use them in the analysis # but a mesh could contain the element faces of the volumes as faces and the edges of the faces as edges, # there we have to check of some geometric objects all_found = False if self.femmesh.GroupCount: all_found = FemMeshTools.get_femelement_sets_from_group_data(self.femmesh, self.material_objects) FreeCAD.Console.PrintMessage(all_found) FreeCAD.Console.PrintMessage('\n') if all_found is False: if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # we're going to use the binary search for get_femelements_by_femnodes() # thus we need the parameter values self.femnodes_ele_table if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femnodes_ele_table: self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) control = FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table) if (self.femelement_count_test is True) and (control is False): # we only need to set it, if it is still True self.femelement_count_test = False if self.shellthickness_objects: if not self.femelement_faces_table: self.femelement_faces_table = FemMeshTools.get_femelement_faces_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_faces_table, self.material_objects) if self.beamsection_objects or self.fluidsection_objects: if not self.femelement_edges_table: self.femelement_edges_table = FemMeshTools.get_femelement_edges_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_edges_table, self.material_objects)
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ... ''' # depreciated version # get the faces and face numbers for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces_depreciated(self.femmesh, femobj) # print(femobj['PressureFaces']) ''' if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) if not self.femnodes_ele_table: self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table) for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] FreeCAD.Console.PrintMessage("Constraint pressure: " + femobj['Object'].Name + '\n') pressure_faces = FemMeshTools.get_pressure_obj_faces(self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj) # print(len(pressure_faces)) femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load', pressure_faces)] FreeCAD.Console.PrintMessage(femobj['PressureFaces']) FreeCAD.Console.PrintMessage('\n')
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads() # it applies here too. Mhh it applies to all constraints ... """ # depreciated version # get the faces and face numbers for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] femobj["PressureFaces"] = meshtools.get_pressure_obj_faces_depreciated( self.femmesh, femobj ) # print(femobj["PressureFaces"]) """ 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.pressure_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] FreeCAD.Console.PrintMessage("Constraint pressure: " + femobj["Object"].Name + "\n") pressure_faces = meshtools.get_pressure_obj_faces( self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj) femobj["PressureFaces"] = [(femobj["Object"].Name + ": face load", pressure_faces)] FreeCAD.Console.PrintLog("{}\n".format(femobj["PressureFaces"]))
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ... ''' # depreciated version # get the faces and face numbers for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces_depreciated(self.femmesh, femobj) # print(femobj['PressureFaces']) ''' if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table( self.femmesh) if not self.femnodes_ele_table: self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table( self.femnodes_mesh, self.femelement_table) for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] print("Constraint pressure: " + femobj['Object'].Name) pressure_faces = FemMeshTools.get_pressure_obj_faces( self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj) # print(len(pressure_faces)) femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load', pressure_faces)] print(femobj['PressureFaces'])
def add_mesh(f, model, mystran_writer): # needed basic data if not mystran_writer.femnodes_mesh: mystran_writer.femnodes_mesh = mystran_writer.femmesh.Nodes if not mystran_writer.femelement_table: mystran_writer.femelement_table = meshtools.get_femelement_table( mystran_writer.femmesh) mesh_eletype = exportNastranMesh.get_export_element_type( mystran_writer.femmesh, mystran_writer.femelement_table) # get the pynas code mesh_pynas_code = exportNastranMesh.get_pynastran_mesh( mystran_writer.femnodes_mesh, mystran_writer.femelement_table, mesh_eletype) # print(mesh_pynas_code) # write the pyNastran code f.write(mesh_pynas_code) # execute pyNastran code to add grid to the model # print(model.get_bdf_stats()) exec(mesh_pynas_code) # print(model.get_bdf_stats()) return model
def export(objectslist, filename): "called when freecad exports a file" if len(objectslist) != 1: FreeCAD.Console.PrintError( "This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): FreeCAD.Console.PrintError("No FEM mesh object selected.\n") return femnodes_mesh = obj.FemMesh.Nodes femelement_table = meshtools.get_femelement_table(obj.FemMesh) if meshtools.is_solid_femmesh(obj.FemMesh): fem_mesh_type = "Solid" elif meshtools.is_face_femmesh(obj.FemMesh): fem_mesh_type = "Face" elif meshtools.is_edge_femmesh(obj.FemMesh): fem_mesh_type = "Edge" else: FreeCAD.Console.PrintError( "Export of this FEM mesh to Python not supported.\n") return f = pyopen(filename, "w") write_python_mesh_to_file(femnodes_mesh, femelement_table, fem_mesh_type, f) f.close()
def get_z88_element_type(femmesh, femelement_table=None): if not femmesh: Console.PrintError("Error: No femmesh.\n") if not femelement_table: Console.PrintError("The femelement_table need to be calculated.\n") femelement_table = meshtools.get_femelement_table(femmesh) # in some cases lowest key in femelement_table is not [1] for elem in sorted(femelement_table): elem_length = len(femelement_table[elem]) Console.PrintLog( "Node count of first element: {}\n".format(elem_length)) break # break after the first elem if meshtools.is_solid_femmesh(femmesh): if femmesh.TetraCount == femmesh.VolumeCount: if elem_length == 4: return 17 elif elem_length == 10: return 16 else: Console.PrintMessage("Tetra with neither 4 nor 10 nodes.\n") elif femmesh.HexaCount == femmesh.VolumeCount: if elem_length == 8: return 1 elif elem_length == 20: return 10 else: Console.PrintError("Hexa with neither 8 nor 20 nodes.\n") return 0 else: Console.PrintError("no tetra, no hexa or Mixed Volume Elements.\n") elif meshtools.is_face_femmesh(femmesh): if femmesh.TriangleCount == femmesh.FaceCount: if elem_length == 3: Console.PrintError("tria3mesh, not supported by Z88.\n") return 0 elif elem_length == 6: return 24 else: Console.PrintError("Tria with neither 3 nor 6 nodes.\n") return 0 elif femmesh.QuadrangleCount == femmesh.FaceCount: if elem_length == 4: Console.PrintError("quad4mesh, not supported by Z88.\n") return 0 elif elem_length == 8: return 23 else: Console.PrintError("Quad with neither 4 nor 8 nodes.\n") return 0 else: Console.PrintError("no tria, no quad\n") return 0 elif meshtools.is_edge_femmesh(femmesh): Console.PrintMessage( "Edge femmesh will be exported as 3D truss element nr 4.\n") return 4 else: Console.PrintError("Neither edge nor face nor solid femmesh.\n") return 0 return 0
def get_constraints_force_nodeloads(self): # check shape type of reference shape for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] print("Constraint force: " + femobj['Object'].Name) frc_obj = femobj['Object'] if femobj['RefShapeType'] == 'Vertex': # print("load on vertices --> we do not need the femelement_table and femnodes_mesh for node load calculation") pass elif femobj['RefShapeType'] == 'Face' and FemMeshTools.is_solid_femmesh(self.femmesh) and not FemMeshTools.has_no_face_data(self.femmesh): # print("solid_mesh with face data --> we do not need the femelement_table but we need the femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes else: # print("mesh without needed data --> we need the femelement_table and femnodes_mesh for node load calculation") if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) # get node loads for femobj in self.force_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] frc_obj = femobj['Object'] if frc_obj.Force == 0: print(' Warning --> Force = 0') if femobj['RefShapeType'] == 'Vertex': # point load on vertieces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_vertex_nodeload_table(self.femmesh, frc_obj) elif femobj['RefShapeType'] == 'Edge': # line load on edges femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_edge_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) elif femobj['RefShapeType'] == 'Face': # area load on faces femobj['NodeLoadTable'] = FemMeshTools.get_force_obj_face_nodeload_table(self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj)
def get_z88_element_type(femmesh, femelement_table=None): import femmesh.meshtools as FemMeshTools if not femmesh: print("Error: No femmesh!") if not femelement_table: print("We need to get the femelement_table first!") femelement_table = FemMeshTools.get_femelement_table(femmesh) # in some cases lowest key in femelement_table is not [1] for elem in sorted(femelement_table): elem_length = len(femelement_table[elem]) print(elem_length) break # break after the first elem if FemMeshTools.is_solid_femmesh(femmesh): if femmesh.TetraCount == femmesh.VolumeCount: if elem_length == 4: return 17 elif elem_length == 10: return 16 else: print('Tetra with neither 4 nor 10 nodes') elif femmesh.HexaCount == femmesh.VolumeCount: if elem_length == 8: return 1 elif elem_length == 20: return 10 else: print('Hexa with neither 8 nor 20 nodes') return 0 else: print('no tetra, no hexa or Mixed Volume Elements') elif FemMeshTools.is_face_femmesh(femmesh): if femmesh.TriangleCount == femmesh.FaceCount: if elem_length == 3: print('tria3mesh, not supported by z88') return 0 elif elem_length == 6: return 24 else: print('Tria with neither 3 nor 6 nodes') return 0 elif femmesh.QuadrangleCount == femmesh.FaceCount: if elem_length == 4: print('quad4mesh, not supported by z88') return 0 elif elem_length == 8: return 23 else: print('Quad with neither 4 nor 8 nodes') return 0 else: print('no tria, no quad') return 0 elif FemMeshTools.is_edge_femmesh(femmesh): print('Edge femmesh will be exported as 3D truss element nr 4') return 4 else: print('Neither edge nor face nor solid femmesh') return 0 return 0
def get_element_geometry2D_elements(self): # get element ids and write them into the objects print("Shell thicknesses") if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table( self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.shellthickness_objects)
def get_element_fluid1D_elements(self): # get element ids and write them into the objects print("Fluid sections") if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table( self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.fluidsection_objects)
def get_constraints_force_nodeloads(self): if not self.member.cons_force: return # check shape type of reference shape for femobj in self.member.cons_force: # femobj --> dict, FreeCAD document object is femobj["Object"] print_obj_info(femobj["Object"], log=True) if femobj["RefShapeType"] == "Vertex": FreeCAD.Console.PrintLog( " load on vertices --> The femelement_table " "and femnodes_mesh are not needed for node load calculation.\n" ) elif femobj["RefShapeType"] == "Face" \ and meshtools.is_solid_femmesh(self.femmesh) \ and not meshtools.has_no_face_data(self.femmesh): FreeCAD.Console.PrintLog( " solid_mesh with face data --> The femelement_table is not " "needed but the femnodes_mesh is needed for node load calculation.\n" ) if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes else: FreeCAD.Console.PrintLog( " mesh without needed data --> The femelement_table " "and femnodes_mesh are not needed for node load calculation.\n" ) 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) # get node loads FreeCAD.Console.PrintLog( " Finite element mesh nodes will be retrieved by searching " "the appropriate nodes in the finite element mesh.\n") FreeCAD.Console.PrintLog( " The appropriate finite element mesh node load values will " "be calculated according to the finite element definition.\n") for femobj in self.member.cons_force: # femobj --> dict, FreeCAD document object is femobj["Object"] frc_obj = femobj["Object"] print_obj_info(frc_obj) if frc_obj.Force == 0: FreeCAD.Console.PrintMessage(" Warning --> Force = 0\n") if femobj["RefShapeType"] == "Vertex": # point load on vertices femobj[ "NodeLoadTable"] = meshtools.get_force_obj_vertex_nodeload_table( self.femmesh, frc_obj) elif femobj["RefShapeType"] == "Edge": # line load on edges femobj[ "NodeLoadTable"] = meshtools.get_force_obj_edge_nodeload_table( self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj) elif femobj["RefShapeType"] == "Face": # area load on faces femobj[ "NodeLoadTable"] = meshtools.get_force_obj_face_nodeload_table( self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj)
def write_z88_mesh(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) self.element_count = len(self.femelement_table) mesh_file_path = self.file_name + "i1.txt" f = open(mesh_file_path, "w") importZ88Mesh.write_z88_mesh_to_file(self.femnodes_mesh, self.femelement_table, self.z88_element_type, f) f.close()
def write(fem_mesh, filename): '''directly write a FemMesh to a Z88 mesh file format fem_mesh: a FemMesh''' if not fem_mesh.isDerivedFrom("Fem::FemMesh"): FreeCAD.Console.PrintError("Not a FemMesh was given as parameter.\n") return femnodes_mesh = fem_mesh.Nodes import femmesh.meshtools as FemMeshTools femelement_table = FemMeshTools.get_femelement_table(fem_mesh) z88_element_type = get_z88_element_type(fem_mesh, femelement_table) f = pyopen(filename, "w") write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f) f.close()
def write(fem_mesh, filename): """directly write a FemMesh to a Z88 mesh file format fem_mesh: a FemMesh""" if not fem_mesh.isDerivedFrom("Fem::FemMesh"): Console.PrintError("Not a FemMesh was given as parameter.\n") return femnodes_mesh = fem_mesh.Nodes femelement_table = meshtools.get_femelement_table(fem_mesh) z88_element_type = get_z88_element_type(fem_mesh, femelement_table) f = pyopen(filename, "w") write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f) f.close()
def export(objectslist, filename): "called when freecad exports a file" if len(objectslist) != 1: FreeCAD.Console.PrintError("This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): FreeCAD.Console.PrintError("No FEM mesh object selected.\n") return femnodes_mesh = obj.FemMesh.Nodes import femmesh.meshtools as FemMeshTools femelement_table = FemMeshTools.get_femelement_table(obj.FemMesh) z88_element_type = get_z88_element_type(obj.FemMesh, femelement_table) f = pyopen(filename, "wb") write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f) f.close()
def export(objectslist, filename): "called when freecad exports a file" if len(objectslist) != 1: Console.PrintError("This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): Console.PrintError("No FEM mesh object selected.\n") return femnodes_mesh = obj.FemMesh.Nodes femelement_table = meshtools.get_femelement_table(obj.FemMesh) z88_element_type = get_z88_element_type(obj.FemMesh, femelement_table) f = pyopen(filename, "w") write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f) f.close()
def write_z88_input(self): if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table( self.femmesh) self.element_count = len(self.femelement_table) self.set_z88_elparam() self.write_z88_mesh() self.write_z88_contraints() self.write_z88_face_loads() self.write_z88_materials() self.write_z88_elements_properties() self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() return self.dir_name
def write_z88_input(self): timestart = time.clock() if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) self.element_count = len(self.femelement_table) self.set_z88_elparam() self.write_z88_mesh() self.write_z88_contraints() self.write_z88_face_loads() self.write_z88_materials() self.write_z88_elements_properties() self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() print("Writing time input file: " + str(time.clock() - timestart) + ' \n') return self.dir_name
def write_z88_input(self): timestart = time.clock() if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) self.element_count = len(self.femelement_table) self.set_z88_elparam() self.write_z88_mesh() self.write_z88_contraints() self.write_z88_face_loads() self.write_z88_materials() self.write_z88_elements_properties() self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() FreeCAD.Console.PrintMessage("Writing time input file: " + str(time.clock() - timestart) + ' \n\n') return self.dir_name
def write_z88_input(self): timestart = time.clock() if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) self.element_count = len(self.femelement_table) self.set_z88_elparam() self.write_z88_mesh() self.write_z88_contraints() self.write_z88_face_loads() self.write_z88_materials() self.write_z88_elements_properties() self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() writing_time_string = "Writing time input file: " + str(round((time.clock() - timestart), 2)) + " seconds" FreeCAD.Console.PrintMessage(writing_time_string + ' \n\n') return self.dir_name
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
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads() # it applies here too. Mhh it applies to all constraints ... """ # depreciated version # get the faces and face numbers for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] femobj["PressureFaces"] = meshtools.get_pressure_obj_faces_depreciated( self.femmesh, femobj ) # print(femobj["PressureFaces"]) """ 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.pressure_objects: # femobj --> dict, FreeCAD document object is femobj["Object"] print_obj_info(femobj["Object"]) pressure_faces = meshtools.get_pressure_obj_faces( self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj ) # the data model is for compatibility reason with depreciated version # get_pressure_obj_faces_depreciated returns the face ids in a tuple per ref_shape # some_string was the reference_shape_element_string in depreciated method # [(some_string, [ele_id, ele_face_id], [ele_id, ele_face_id], ...])] some_string = "{}: face load".format(femobj["Object"].Name) femobj["PressureFaces"] = [(some_string, pressure_faces)] FreeCAD.Console.PrintLog("{}\n".format(femobj["PressureFaces"]))
def get_constraints_contact_faces(self): if not self.member.cons_contact: return 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.member.cons_contact: # femobj --> dict, FreeCAD document object is femobj["Object"] print_obj_info(femobj["Object"]) contact_slave_faces, contact_master_faces = meshtools.get_contact_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["ContactSlaveFaces"] = contact_slave_faces femobj["ContactMasterFaces"] = contact_master_faces
def write(fem_mesh, filename): """directly write a FemMesh to a pyNastran mesh file format fem_mesh: a FemMesh""" if not fem_mesh.isDerivedFrom("Fem::FemMesh"): Console.PrintError("Not a FemMesh was given as parameter.\n") return femnodes_mesh = fem_mesh.Nodes femelement_table = meshtools.get_femelement_table(fem_mesh) export_element_type = get_export_element_type(fem_mesh, femelement_table) model = BDF() mesh_pynas_code = get_pynastran_mesh(femnodes_mesh, femelement_table, export_element_type) mesh_pynas_code += missing_code_pnynasmesh # pynas file basefilename = filename[:len(filename) - 4] # TODO basename is more failsafe pynasf = open(basefilename + ".py", "w") pynasf.write("# written by FreeCAD\n\n\n") pynasf.write("from pyNastran.bdf.bdf import BDF\n") pynasf.write("model = BDF()\n\n\n") pynasf.write(mesh_pynas_code) pynasf.write("model.write_bdf('{}', enddata=True)\n".format(basefilename + "_pyNas.bdf")) pynasf.close() # execute pyNastran code to add grid to the model # print(model) # print(model.get_bdf_stats()) exec(mesh_pynas_code) # print(model) # print(model.get_bdf_stats()) # write Nastran mesh file model.write_bdf(filename, enddata=True) # TODO FIXME "BEGIN BULK" is missing
def write(fem_mesh, filename): """directly write a FemMesh to a Python mesh file fem_mesh: a FemMesh""" if not fem_mesh.isDerivedFrom("Fem::FemMesh"): FreeCAD.Console.PrintError("Not a FemMesh was given as parameter.\n") return femnodes_mesh = fem_mesh.Nodes femelement_table = meshtools.get_femelement_table(fem_mesh) if meshtools.is_solid_femmesh(fem_mesh): fem_mesh_type = "Solid" elif meshtools.is_face_femmesh(fem_mesh): fem_mesh_type = "Face" elif meshtools.is_edge_femmesh(fem_mesh): fem_mesh_type = "Edge" else: FreeCAD.Console.PrintError( "Export of this FEM mesh to Python not supported.\n") return f = pyopen(filename, "w") write_python_mesh_to_file(femnodes_mesh, femelement_table, fem_mesh_type, f) f.close()
def write_z88_input(self): timestart = time.process_time() FreeCAD.Console.PrintMessage("Write z88 input files to: {}\n".format(self.dir_name)) 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) self.element_count = len(self.femelement_table) self.set_z88_elparam() self.write_z88_mesh() self.write_z88_constraints() self.write_z88_face_loads() self.write_z88_materials() self.write_z88_elements_properties() self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() writing_time_string = ( "Writing time input file: {} seconds" .format(round((time.process_time() - timestart), 2)) ) FreeCAD.Console.PrintMessage(writing_time_string + " \n\n") return self.dir_name
def get_element_fluid1D_elements(self): # get element ids and write them into the objects FreeCAD.Console.PrintMessage('Fluid sections\n') if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.fluidsection_objects)
def setUpInput(doc, mesh, analysis): analysis = doc.getObject("Analysis") # create connextivity array elnodes for mapping local node number -> global node number elnodes = np.array([mesh.getElementNodes(el) for el in mesh.Volumes ]) # elnodes[elementIndex] = [node1,...,Node10] elo = dict(zip(mesh.Volumes, range(len( mesh.Volumes)))) # elo : {elementNumber : elementIndex} # create nodal coordinate array nocoord for node number -> (x,y,z) nocoord = np.asarray(mesh.Nodes.values() ) # nocoord[nodeIndex] = [x-coord, y-coord, z-coord] # create element material array: materialbyElement maps element number -> E, nu materials_lin = gsm(analysis, 'Fem::Material') fiwc = iw(analysis, doc.CalculiXccxTools, doc.FEMMeshGmsh, materials_lin, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None) fiwc.get_material_elements() materialbyElement = [] po_keys = [] # parentobject[el] = parent material object for element el po_values = [] counter = 0 for object in fiwc.material_objects: E = float( App.Units.Quantity( object['Object'].Material['YoungsModulus']).getValueAs('MPa')) Nu = float(object['Object'].Material['PoissonRatio']) for el in object['FEMElements']: po_keys.append(el) po_values.append(object['Object'].Name) counter += 1 materialbyElement.append([ el, E, Nu ]) # materialbyElement[elementIndex] = [elementNumber, E, Nu] parentobject = dict(zip(po_keys, po_values)) # determine elements connected to a node using FC API fet = mt.get_femelement_table( mesh ) # fet is dictionary: { elementid : [ nodeid, nodeid, ... , nodeid ] } net = mt.get_femnodes_ele_table( mesh.Nodes, fet ) # net is dictionary: {nodeID : [[eleID, NodePosition], [], ...], nodeID : [[], [], ...], ...} # set up interface element connectivity nodecount = len(nocoord) twins = {} # twins : {oldnode : [newnode, face number]} interface_elements = [] for obj in App.ActiveDocument.Objects: if obj.Name == "BooleanFragments": num_BF_els = len(App.ActiveDocument.BooleanFragments.Objects) num_Mat_obs = len(fiwc.material_objects) if num_BF_els != num_Mat_obs: print( "Each BooleanFragment element needs its own material object" ) raise SystemExit() shapecontacts = [] tk = [] tv = [] contactnum = 0 # number of contact faces between BooleanFragment elements for index, obj1 in enumerate(obj.Objects): for obj1face in obj1.Shape.Faces: el1faces = np.asarray(mesh.getFacesByFace(obj1face)) for obj2 in obj.Objects[index + 1:]: for obj2face in obj2.Shape.Faces: el2faces = np.asarray( mesh.getFacesByFace(obj2face)) contact = np.intersect1d( el1faces, el2faces ) # all volume element contact faces between obj1 and obj2 if contact != []: contactnum += 1 npflist = [] shapecontacts.append( contact ) # all volume element contact faces for contactface in contact: npflist.append( mesh.getElementNodes(contactface) ) # all nodes at the contact between obj1 and obj2 # flatten npflist and remove duplicate nodes cn = list( set([ node for npf in npflist for node in npf ])) cn.sort() for node in cn: if node not in tk: nodecount += 1 tk.append( int(node) ) # add an existing contact node to interface dict tv.append( [nodecount, contactnum] ) # add a new contact node (nodecount) to interface dict and the contact (contactnum) it is a member of nocoord = np.append( nocoord, [nocoord[node - 1]], axis=0 ) # add coordinates for new nodes twins = dict(zip(tk, tv)) # twins : {oldnode : [newnode, face number]} print("\nInterface twins: {}".format(twins)) for facecontacts in shapecontacts: for face in facecontacts: nodeset1 = list(mesh.getElementNodes(face)) nodeset2 = [] for node in mesh.getElementNodes(face): nodeset2.append(twins[node][0]) interface_elements.append( nodeset1 + nodeset2 ) # interface_elements[index] = [oldnode1,..,oldnode6, newnode1,..,newnode6] interface_elements = np.asarray( interface_elements ) # add interface elements for the face between obj1 and obj2 print("number of interface elements: {}".format(len(interface_elements))) for ie in interface_elements: print(ie) # reconnect volume elements to new interface nodes if interface_elements != []: membership = [""] * contactnum shiftelements = [] # reconnected elements for node in twins: if membership[twins[node][1] - 1] == "": membership[twins[node][1] - 1] = parentobject[net[node][0][ 0]] # elements that will stay with old nodes are in membership material object for element in net[node]: elnum = element[0] # element number if parentobject[elnum] != membership[ twins[node][1] - 1]: # reconnect element to new nodes nonum = int( math.log(element[1], 2) ) # local node number from binary node number net[node][1] shiftelements.append(elo[elnum]) elnodes[elo[elnum]][nonum] = twins[node][ 0] # connect element to new nodes noce = np.zeros((len(nocoord)), dtype=np.int16) for inno in range(len(nocoord)): i, j = np.where(elnodes == inno + 1) noce[inno] = len(i) # create boundary condition array dispfaces dispfaces = [] for obj in App.ActiveDocument.Objects: if obj.isDerivedFrom('Fem::ConstraintDisplacement'): bcnodes = [] bctype = [obj.xFree, obj.yFree, obj.zFree] bcvalue = [obj.xDisplacement, obj.yDisplacement, obj.zDisplacement] for part, boundaries in obj.References: for boundary in boundaries: ref = part.Shape.getElement(boundary) if type(ref) == Part.Vertex: bc = mesh.getNodesByVertex(ref) for bcn in bc: bcnodes.append(bcn) elif type(ref) == Part.Edge: bc = mesh.getNodesByEdge(ref) for bcn in bc: bcnodes.append(bcn) elif type(ref) == Part.Face: bc = mesh.getNodesByFace(ref) for bcn in bc: if bcn not in twins: bcnodes.append(bcn) else: print("No Boundaries Found") edge = list(set(bc) & set(twins)) interior = list(set(bc) - set(twins)) #print("\nset(bc) {}, \nset(twins) {}, \nedge of boundary: {}, \ninterior of boundary: {}".format(bc, twins, edge, interior)) for node in edge: for elem in net[node]: elnum = elo[elem[0]] if list(set(elnodes[elnum]) & set(interior)) != []: if elnum in shiftelements: bcnodes.append(twins[node][0]) else: bcnodes.append(node) bcnodes = list( dict.fromkeys(bcnodes)) #remove duplicates in bcnodes if bcnodes != []: dispfaces.append([bcnodes, bctype, bcvalue]) # create loaded faces and their global node numbers loadfaces_keys = [] loadfaces_values = [] for obj in App.ActiveDocument.Objects: if obj.isDerivedFrom('Fem::ConstraintPressure'): if obj.Reversed: sign = 1 else: sign = -1 for part, boundaries in obj.References: for boundary in boundaries: ref = part.Shape.getElement(boundary) if type(ref) == Part.Face: for faceID in mesh.getFacesByFace(ref): loadfaces_keys.append(faceID) loadfaces_values.append([ list(mesh.getElementNodes(faceID)), sign * obj.Pressure ]) else: print("No Faces with Pressure Loads") loadfaces = dict(zip(loadfaces_keys, loadfaces_values)) # re-order element nodes for el in elnodes: temp = el[1] el[1] = el[2] el[2] = temp temp = el[4] el[4] = el[6] el[6] = temp temp = el[8] el[8] = el[9] el[9] = temp return elnodes, nocoord, dispfaces, loadfaces, materialbyElement, interface_elements, noce
def get_element_rotation1D_elements(self): # get for each geometry edge direction the element ids and rotation norma if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_direction1D_set(self.femmesh, self.femelement_table, self.beamrotation_objects, self.theshape)
def get_element_geometry2D_elements(self): # get element ids and write them into the objects FreeCAD.Console.PrintMessage('Shell thicknesses\n') if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.shellthickness_objects)