def get_region_data(self): # mesh regions self.ele_length_map = {} # { 'ElementString' : element length } self.ele_node_map = {} # { 'ElementString' : [element nodes] } if not self.mesh_obj.MeshRegionList: # print (' No mesh regions.') pass else: print (' Mesh regions, we need to get the elements.') # by the use of MeshRegion object and a BooleanSplitCompound there could be problems with node numbers see # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 part = self.part_obj if self.mesh_obj.MeshRegionList: if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): # other part obj might not have a Proxy, thus an exception would be raised if (part.Proxy.Type == "FeatureBooleanFragments" or part.Proxy.Type == "FeatureSlice" or part.Proxy.Type == "FeatureXOR"): error_message = " The mesh to shape is a boolean split tools Compound and the mesh has mesh region list. GMSH could return unexpected meshes in such circumstances. It is strongly recommended to extract the shape to mesh from the Compound and use this one." FreeCAD.Console.PrintError(error_message + "\n") # TODO: no gui popup because FreeCAD will be in a endless print loop # as long as the pop up is on --> maybe find a better solution for # either of both --> thus the pop up is in task panel for mr_obj in self.mesh_obj.MeshRegionList: # print(mr_obj.Name) # print(mr_obj.CharacteristicLength) # print(Units.Quantity(mr_obj.CharacteristicLength).Value) if mr_obj.CharacteristicLength: if mr_obj.References: for sub in mr_obj.References: # print(sub[0]) # Part the elements belongs to # check if the shape of the mesh region is an element of the Part to mesh, if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): # print(" One element of the meshregion " + mr_obj.Name + " is not an element of the Part to mesh.") # print(" But we are going to try to find it in the Shape to mesh :-)") search_ele_in_shape_to_mesh = True for elems in sub[1]: # print(elems) # elems --> element if search_ele_in_shape_to_mesh: # we're going to try to find the element in the Shape to mesh and use the found element as elems ele_shape = FemMeshTools.get_element(sub[0], elems) # the method getElement(element) does not return Solid elements found_element = FemMeshTools.find_element_in_shape(self.part_obj.Shape, ele_shape) if found_element: elems = found_element else: FreeCAD.Console.PrintError("One element of the meshregion " + mr_obj.Name + " could not be found in the Part to mesh. It will be ignored.\n") # print(elems) # element if elems not in self.ele_length_map: self.ele_length_map[elems] = Units.Quantity(mr_obj.CharacteristicLength).Value else: FreeCAD.Console.PrintError("The element " + elems + " of the meshregion " + mr_obj.Name + " has been added to another mesh region.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the reference list is empty.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the CharacteristicLength is 0.0 mm.\n") for eleml in self.ele_length_map: ele_shape = FemMeshTools.get_element(self.part_obj, eleml) # the method getElement(element) does not return Solid elements ele_vertexes = FemMeshTools.get_vertexes_by_element(self.part_obj.Shape, ele_shape) self.ele_node_map[eleml] = ele_vertexes print(' {}'.format(self.ele_length_map)) print(' {}'.format(self.ele_node_map))
def get_region_data(self): # mesh regions self.ele_length_map = {} # { 'ElementString' : element length } self.ele_node_map = {} # { 'ElementString' : [element nodes] } if not self.mesh_obj.MeshRegionList: # print (' No mesh regions.') pass else: print (' Mesh regions, we need to get the elements.') # by the use of MeshRegion object and a BooleanSplitCompound there could be problems with node numbers see # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 part = self.part_obj if self.mesh_obj.MeshRegionList: if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): # other part obj might not have a Proxy, thus an exception would be raised if (part.Proxy.Type == "FeatureBooleanFragments" or part.Proxy.Type == "FeatureSlice" or part.Proxy.Type == "FeatureXOR"): error_message = " The mesh to shape is a boolean split tools Compound and the mesh has mesh region list. Gmsh could return unexpected meshes in such circumstances. It is strongly recommended to extract the shape to mesh from the Compound and use this one." FreeCAD.Console.PrintError(error_message + "\n") # TODO: no gui popup because FreeCAD will be in a endless print loop # as long as the pop up is on --> maybe find a better solution for # either of both --> thus the pop up is in task panel for mr_obj in self.mesh_obj.MeshRegionList: # print(mr_obj.Name) # print(mr_obj.CharacteristicLength) # print(Units.Quantity(mr_obj.CharacteristicLength).Value) if mr_obj.CharacteristicLength: if mr_obj.References: for sub in mr_obj.References: # print(sub[0]) # Part the elements belongs to # check if the shape of the mesh region is an element of the Part to mesh, if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): # print(" One element of the meshregion " + mr_obj.Name + " is not an element of the Part to mesh.") # print(" But we are going to try to find it in the Shape to mesh :-)") search_ele_in_shape_to_mesh = True for elems in sub[1]: # print(elems) # elems --> element if search_ele_in_shape_to_mesh: # we're going to try to find the element in the Shape to mesh and use the found element as elems ele_shape = FemMeshTools.get_element(sub[0], elems) # the method getElement(element) does not return Solid elements found_element = FemMeshTools.find_element_in_shape(self.part_obj.Shape, ele_shape) if found_element: elems = found_element else: FreeCAD.Console.PrintError("One element of the meshregion " + mr_obj.Name + " could not be found in the Part to mesh. It will be ignored.\n") # print(elems) # element if elems not in self.ele_length_map: self.ele_length_map[elems] = Units.Quantity(mr_obj.CharacteristicLength).Value else: FreeCAD.Console.PrintError("The element " + elems + " of the meshregion " + mr_obj.Name + " has been added to another mesh region.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the reference list is empty.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the CharacteristicLength is 0.0 mm.\n") for eleml in self.ele_length_map: ele_shape = FemMeshTools.get_element(self.part_obj, eleml) # the method getElement(element) does not return Solid elements ele_vertexes = FemMeshTools.get_vertexes_by_element(self.part_obj.Shape, ele_shape) self.ele_node_map[eleml] = ele_vertexes print(' {}'.format(self.ele_length_map)) print(' {}'.format(self.ele_node_map))
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'] 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 get_group_data(self): self.group_elements = {} # TODO solids, faces, edges and vertexes seam not work together in one group, some print or make them work together # mesh groups and groups of analysis member if not self.mesh_obj.MeshGroupList: print (' No mesh group objects.') else: print (' Mesh group objects, we need to get the elements.') for mg in self.mesh_obj.MeshGroupList: new_group_elements = FemMeshTools.get_mesh_group_elements(mg, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError(" A group with this name exists already.\n") if self.analysis: print(' Group meshing.') new_group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError(" A group with this name exists already.\n") else: print(' No anlysis members for group meshing.') print(' {}'.format(self.group_elements))
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'] 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 write_z88_elements_properties(self): element_properties_file_path = self.file_name + 'elp.txt' elements_data = [] if FemMeshTools.is_edge_femmesh(self.femmesh): if len(self.beamsection_objects) == 1: beam_obj = self.beamsection_objects[0]['Object'] width = beam_obj.Width.getValueAs('mm') height = beam_obj.Height.getValueAs('mm') area = str(width * height) elements_data.append('1 ' + str(self.element_count) + ' ' + area + ' 0 0 0 0 0 0 ') print("Be aware, only trusses are supported for edge meshes!") else: print("Multiple beamsections for Z88 not yet supported!") elif FemMeshTools.is_face_femmesh(self.femmesh): if len(self.shellthickness_objects) == 1: thick_obj = self.shellthickness_objects[0]['Object'] thickness = str(thick_obj.Thickness.getValueAs('mm')) elements_data.append('1 ' + str(self.element_count) + ' ' + thickness + ' 0 0 0 0 0 0 ') else: print("Multiple thicknesses for Z88 not yet supported!") elif FemMeshTools.is_solid_femmesh(self.femmesh): elements_data.append('1 ' + str(self.element_count) + ' 0 0 0 0 0 0 0') else: print("Error!") f = open(element_properties_file_path, 'w') f.write(str(len(elements_data)) + '\n') for e in elements_data: f.write(e) f.write('\n') f.close()
def get_group_data(self): self.group_elements = {} # TODO: solids, faces, edges and vertexes don't seem to work together in one group, # some print or make them work together # mesh groups and groups of analysis member if not self.mesh_obj.MeshGroupList: print(' No mesh group objects.') else: print(' Mesh group objects, we need to get the elements.') for mg in self.mesh_obj.MeshGroupList: new_group_elements = FemMeshTools.get_mesh_group_elements( mg, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError( " A group with this name exists already.\n") if self.analysis: print(' Group meshing.') new_group_elements = FemMeshTools.get_analysis_group_elements( self.analysis, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError( " A group with this name exists already.\n") else: print(' No anlysis members for group meshing.') print(' {}'.format(self.group_elements))
def get_group_data(self): if self.analysis: print(' Group meshing.') import FemMeshTools self.group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj) print(self.group_elements) else: print(' NO group meshing.') self.ele_length_map = self.mesh_obj.CharacteristicLengthMap self.ele_node_map = {} if self.ele_length_map: import FemMeshTools print(self.ele_length_map) self.ele_node_map = {} for e in self.ele_length_map: if not e.startswith('Solid'): # Face, Edge, Vertex ele_shape = self.part_obj.Shape.getElement(e) else: # Solid ele_shape_index = int(e.lstrip('Solid')) - 1 ele_shape = self.part_obj.Shape.Solids[ele_shape_index] ele_vertexes = FemMeshTools.get_vertexes_by_element(self.part_obj.Shape, ele_shape) self.ele_node_map[e] = ele_vertexes print(self.ele_node_map)
def get_ccx_elsets_multiple_mat_multiple_beam(self): if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table( self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.beamsection_objects) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for beamsec_data in self.beamsection_objects: beamsec_obj = beamsec_data['Object'] for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['beamsection_obj'] = beamsec_obj elemids = [] for elemid in beamsec_data['FEMElements']: if elemid in mat_data['FEMElements']: elemids.append(elemid) ccx_elset['ccx_elset'] = elemids ccx_elset['ccx_elset_name'] = get_ccx_elset_beam_name( mat_obj.Name, beamsec_obj.Name, mat_data['ShortName'], beamsec_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_multiple_shell(self): 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) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for shellth_data in self.shellthickness_objects: shellth_obj = shellth_data['Object'] for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['shellthickness_obj'] = shellth_obj elemids = [] for elemid in shellth_data['FEMElements']: if elemid in mat_data['FEMElements']: elemids.append(elemid) ccx_elset['ccx_elset'] = elemids ccx_elset['ccx_elset_name'] = get_ccx_elset_shell_name( mat_obj.Name, shellth_obj.Name, mat_data['ShortName'], shellth_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def write_z88_elements_properties(self): element_properties_file_path = self.file_name + "elp.txt" elements_data = [] if FemMeshTools.is_edge_femmesh(self.femmesh): if len(self.beamsection_objects) == 1: beam_obj = self.beamsection_objects[0]["Object"] width = beam_obj.RectWidth.getValueAs("mm") height = beam_obj.RectHeight.getValueAs("mm") area = str(width * height) elements_data.append("1 " + str(self.element_count) + " " + area + " 0 0 0 0 0 0 ") print("Be aware, only trusses are supported for edge meshes!") else: print("Multiple beamsections for Z88 not yet supported!") elif FemMeshTools.is_face_femmesh(self.femmesh): if len(self.shellthickness_objects) == 1: thick_obj = self.shellthickness_objects[0]["Object"] thickness = str(thick_obj.Thickness.getValueAs("mm")) elements_data.append("1 " + str(self.element_count) + " " + thickness + " 0 0 0 0 0 0 ") else: print("Multiple thicknesses for Z88 not yet supported!") elif FemMeshTools.is_solid_femmesh(self.femmesh): elements_data.append("1 " + str(self.element_count) + " 0 0 0 0 0 0 0") else: print("Error!") f = open(element_properties_file_path, "w") f.write(str(len(elements_data)) + "\n") for e in elements_data: f.write(e) f.write("\n") f.close()
def get_element_geometry2D_elements(self): # get element ids and write them into the 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.shellthickness_objects)
def get_element_fluid1D_elements(self): # get element ids and write them into the 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.fluidsection_objects)
def get_z88_element_type(femmesh, femelement_table=None): import 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 neiter 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 neiter 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, face or solid femmesh') return 0 return 0
def get_element_geometry1D_elements(self): # get element ids and write them into the objects print("Beam 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.beamsection_objects)
def get_group_data(self): if self.analysis: print(' Group meshing.') self.group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj) print(' {}'.format(self.group_elements)) else: print(' NO group meshing.') self.ele_length_map = {} # { 'ElementString' : element length } self.ele_node_map = {} # { 'ElementString' : [element nodes] } if not self.mesh_obj.MeshRegionList: print (' No Mesh regions.') else: print (' Mesh regions, we need to get the elements.') if self.part_obj.Shape.ShapeType == 'Compound': # see http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 and http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 err = "GMSH could return unexpected meshes for a boolean split tools Compound. It is strongly recommended to extract the shape to mesh from the Compound and use this one." FreeCAD.Console.PrintError(err + "\n") for mr_obj in self.mesh_obj.MeshRegionList: # print(mr_obj.Name) # print(mr_obj.CharacteristicLength) # print(Units.Quantity(mr_obj.CharacteristicLength).Value) if mr_obj.CharacteristicLength: if mr_obj.References: for sub in mr_obj.References: # print(sub[0]) # Part the elements belongs to # check if the shape of the mesh region is an element of the Part to mesh, if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): # print(" One element of the meshregion " + mr_obj.Name + " is not an element of the Part to mesh.") # print(" But we gone try to find it in the Shape to mesh :-)") search_ele_in_shape_to_mesh = True for eles in sub[1]: # print(eles) # element if search_ele_in_shape_to_mesh: # we gone try to find the element it in the Shape to mesh and use the found element as eles ele_shape = FemMeshTools.get_element(sub[0], eles) # the method getElement(element) does not return Solid elements found_element = FemMeshTools.find_element_in_shape(self.part_obj.Shape, ele_shape) if found_element: eles = found_element else: FreeCAD.Console.PrintError("One element of the meshregion " + mr_obj.Name + " could not be found in the Part to mesh. It will be ignored.\n") # print(eles) # element if eles not in self.ele_length_map: self.ele_length_map[eles] = Units.Quantity(mr_obj.CharacteristicLength).Value else: FreeCAD.Console.PrintError("The element " + eles + " of the meshregion " + mr_obj.Name + " has been added to another mesh region.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the reference list is empty.\n") else: FreeCAD.Console.PrintError("The meshregion: " + mr_obj.Name + " is not used to create the mesh because the CharacteristicLength is 0.0 mm.\n") for elel in self.ele_length_map: ele_shape = FemMeshTools.get_element(self.part_obj, elel) # the method getElement(element) does not return Solid elements ele_vertexes = FemMeshTools.get_vertexes_by_element(self.part_obj.Shape, ele_shape) self.ele_node_map[elel] = ele_vertexes print(' {}'.format(self.ele_length_map)) print(' {}'.format(self.ele_node_map))
def get_ccx_elsets_multiple_mat_solid(self): 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) for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['ccx_elset'] = mat_data['FEMElements'] ccx_elset['ccx_elset_name'] = get_ccx_elset_solid_name(mat_obj.Name, None, mat_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def write_constraints_transform(self, f): f.write('\n***********************************************************\n') f.write('** Transform Constaints\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'] if trans_obj.TransformType == "Rectangular": f.write('*TRANSFORM, NSET=Rect' + trans_obj.Name + ', TYPE=R\n') coords = FemMeshTools.get_rectangular_coords(trans_obj) f.write(coords + '\n') elif trans_obj.TransformType == "Cylindrical": f.write('*TRANSFORM, NSET=Cylin' + trans_obj.Name + ', TYPE=C\n') coords = FemMeshTools.get_cylindrical_coords(trans_obj) f.write(coords + '\n')
def get_ccx_elsets_single_mat_multiple_shell(self): if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) mat_obj = self.material_objects[0]['Object'] FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.shellthickness_objects) for shellth_data in self.shellthickness_objects: shellth_obj = shellth_data['Object'] ccx_elset = {} ccx_elset['shellthickness_obj'] = shellth_obj ccx_elset['ccx_elset'] = shellth_data['FEMElements'] ccx_elset['ccx_elset_name'] = get_ccx_elset_shell_name(mat_obj.Name, shellth_obj.Name, None, shellth_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_single_shell(self): if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) shellth_obj = self.shellthickness_objects[0]['Object'] FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['shellthickness_obj'] = shellth_obj ccx_elset['ccx_elset'] = mat_data['FEMElements'] ccx_elset['ccx_elset_name'] = get_ccx_elset_shell_name(mat_obj.Name, shellth_obj.Name, mat_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_single_beam(self): if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) beamsec_obj = self.beamsection_objects[0]['Object'] FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['beamsection_obj'] = beamsec_obj ccx_elset['ccx_elset'] = mat_data['FEMElements'] ccx_elset['ccx_elset_name'] = get_ccx_elset_beam_name(mat_obj.Name, beamsec_obj.Name, mat_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def get_constraints_fluidsection_nodes(self): # get nodes for femobj in self.fluidsection_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] print("Constraint fluid section: " + femobj['Object'].Name) femobj[ 'Nodes'] = FemMeshTools.get_femnodes_by_femobj_with_references( self.femmesh, femobj)
def get_constraints_displacement_nodes(self): # get nodes for femobj in self.displacement_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] femobj['Nodes'] = FemMeshTools.get_femnodes_by_references(self.femmesh, femobj['Object'].References) # add nodes to constraint_conflict_nodes, needed by constraint plane rotation for node in femobj['Nodes']: self.constraint_conflict_nodes.append(node)
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ... # 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( self.femmesh, femobj)
def get_ccx_elsets_multiple_mat_solid(self): 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) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['ccx_elset'] = mat_data['FEMElements'] ccx_elset['ccx_elset_name'] = get_ccx_elset_solid_name(mat_obj.Name, None, mat_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def import_inp(filename): "create imported objects in FreeCAD, currently only FemMesh" m = read_inp(filename) mesh = FemMeshTools.make_femmesh(m) mesh_name = os.path.splitext(os.path.basename(filename))[0] mesh_object = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', mesh_name) mesh_object.FemMesh = mesh
def import_z88_mesh(filename, analysis=None): '''insert a FreeCAD FEM Mesh object in the ActiveDocument ''' mesh_data = read_z88_mesh(filename) mesh_name = os.path.basename(os.path.splitext(filename)[0]) femmesh = FemMeshTools.make_femmesh(mesh_data) if femmesh: mesh_object = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', mesh_name) mesh_object.FemMesh = femmesh
def get_constraints_fixed_nodes(self): # get nodes for femobj in self.fixed_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] print("Constraint fixed: " + femobj['Object'].Name) femobj[ 'Nodes'] = FemMeshTools.get_femnodes_by_femobj_with_references( self.femmesh, femobj) # add nodes to constraint_conflict_nodes, needed by constraint plane rotation for node in femobj['Nodes']: self.constraint_conflict_nodes.append(node)
def get_ccx_elsets_multiple_mat_multiple_beam(self): if not self.femelement_table: self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.beamsection_objects) FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects) for beamsec_data in self.beamsection_objects: beamsec_obj = beamsec_data['Object'] for mat_data in self.material_objects: mat_obj = mat_data['Object'] ccx_elset = {} ccx_elset['beamsection_obj'] = beamsec_obj elemids = [] for elemid in beamsec_data['FEMElements']: if elemid in mat_data['FEMElements']: elemids.append(elemid) ccx_elset['ccx_elset'] = elemids ccx_elset['ccx_elset_name'] = get_ccx_elset_beam_name(mat_obj.Name, beamsec_obj.Name, mat_data['ShortName'], beamsec_data['ShortName']) ccx_elset['mat_obj_name'] = mat_obj.Name ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'] self.ccx_elsets.append(ccx_elset)
def get_group_data(self): # TODO: solids, faces, edges and vertexes don't seem to work together in one group, # some print or make them work together # mesh group objects if not self.mesh_obj.MeshGroupList: # print (' No mesh group objects.') pass else: print(' Mesh group objects, we need to get the elements.') for mg in self.mesh_obj.MeshGroupList: new_group_elements = FemMeshTools.get_mesh_group_elements( mg, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError( " A group with this name exists already.\n") # group meshing for analysis analysis_group_meshing = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Fem/General").GetBool( "AnalysisGroupMeshing", True) if self.analysis and analysis_group_meshing: print(' Group meshing for analysis.') self.group_nodes_export = True new_group_elements = FemMeshTools.get_analysis_group_elements( self.analysis, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: FreeCAD.Console.PrintError( " A group with this name exists already.\n") else: print(' No Group meshing for analysis.') if self.group_elements: print(' {}'.format(self.group_elements))
def has_equal_references_shape_types(self): import FemMeshTools if not self.references: self.references_shape_type = None for ref in self.references: r = FemMeshTools.get_element(ref[0], ref[1]) # the method getElement(element) does not return Solid elements # print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1]) if self.references_shape_type is None: self.references_shape_type = r.ShapeType if r.ShapeType != self.references_shape_type: FreeCAD.Console.PrintError('Different ShapeTypes in Reference List not allowed\n') return False return True
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'] 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)]
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'] frc_obj = femobj['Object'] # in GUI defined frc_obj all ref_shape have the same shape type # TODO in FemTools: check if all RefShapes really have the same type an write type to dictionary femobj['RefShapeType'] = '' if frc_obj.References: first_ref_obj = frc_obj.References[0] first_ref_shape = first_ref_obj[0].Shape.getElement(first_ref_obj[1][0]) femobj['RefShapeType'] = first_ref_shape.ShapeType else: # frc_obj.References could be empty ! # TODO in FemTools: check FreeCAD.Console.PrintError('At least one Force Object has empty References!\n') 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 has_equal_references_shape_types(self): import FemMeshTools ref_shty = '' for ref in self.references: r = FemMeshTools.get_element(ref[0], ref[1]) # the method getElement(element) does not return Solid elements # print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1]) if not ref_shty: ref_shty = r.ShapeType if r.ShapeType != ref_shty: message = 'Multiple shape types are not allowed in the reference list.\n' FreeCAD.Console.PrintError(message) QMessageBox.critical(None, "Multiple ShapeTypes not allowed", message) return False return True
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 = 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 has_equal_references_shape_types(self): import FemMeshTools if not self.references: self.references_shape_type = None for ref in self.references: r = FemMeshTools.get_element( ref[0], ref[1] ) # the method getElement(element) does not return Solid elements # print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1]) if self.references_shape_type is None: self.references_shape_type = r.ShapeType if r.ShapeType != self.references_shape_type: FreeCAD.Console.PrintError( 'Different ShapeTypes in Reference List not allowed\n') return False return True
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 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 = 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 get_refshape_type(fem_doc_object): # returns the reference shape type # for force object: # in GUI defined frc_obj all frc_obj have at leas one ref_shape and ref_shape have all the same shape type # for material object: # in GUI defined material_obj could have no RefShape and RefShapes could be different type # we gone need the RefShapes to be the same type inside one fem_doc_object # TODO here: check if all RefShapes inside the object really have the same type import FemMeshTools if hasattr(fem_doc_object, 'References') and fem_doc_object.References: first_ref_obj = fem_doc_object.References[0] first_ref_shape = FemMeshTools.get_element(first_ref_obj[0], first_ref_obj[1][0]) st = first_ref_shape.ShapeType print(fem_doc_object.Name + ' has ' + st + ' reference shapes.') return st else: print(fem_doc_object.Name + ' has empty References.') return ''
def get_refshape_type(fem_doc_object): # returns the reference shape type # for force object: # in GUI defined frc_obj all frc_obj have at leas one ref_shape and ref_shape have all the same shape type # for material object: # in GUI defined material_obj could have no RefShape and RefShapes could be different type # we're going to need the RefShapes to be the same type inside one fem_doc_object # TODO: check if all RefShapes inside the object really have the same type import FemMeshTools if hasattr(fem_doc_object, 'References') and fem_doc_object.References: first_ref_obj = fem_doc_object.References[0] first_ref_shape = FemMeshTools.get_element(first_ref_obj[0], first_ref_obj[1][0]) st = first_ref_shape.ShapeType print(fem_doc_object.Name + ' has ' + st + ' reference shapes.') return st else: print(fem_doc_object.Name + ' has empty References.') return ''
def write_node_sets_constraints_planerotation(self, f): # get nodes self.get_constraints_planerotation_nodes() # write nodes to file if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes f.write( '\n***********************************************************\n') f.write('** Node set for plane rotation constraint\n') f.write('** written by {} function\n'.format( sys._getframe().f_code.co_name)) # info about self.constraint_conflict_nodes: # is used to check if MPC and constraint fixed and constraint displacement share same nodes, # because MPC's and constriants fixed an 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('*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 = FemMeshTools.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_node_sets_constraints_planerotation(self, f): # get nodes self.get_constraints_planerotation_nodes() # write nodes to file if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes f.write('\n***********************************************************\n') f.write('** Node set for plane rotation constraint\n') f.write('** written by {} function\n'.format(sys._getframe().f_code.co_name)) # info about self.constraint_conflict_nodes: # is used to check if MPC and constraint fixed and constraint displacement share same nodes, # because MPC's and constriants fixed an 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('*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 = FemMeshTools.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 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 importFrd(filename, analysis=None): m = readResult(filename) mesh_object = None if(len(m['Nodes']) > 0): if analysis is None: analysis_name = os.path.splitext(os.path.basename(filename))[0] import FemAnalysis analysis_object = FemAnalysis.makeFemAnalysis('Analysis') analysis_object.Label = analysis_name else: analysis_object = analysis # see if statement few lines later, if not analysis -> no FemMesh object is created ! if 'Nodes' in m: positions = [] for k, v in m['Nodes'].iteritems(): positions.append(v) p_x_max, p_y_max, p_z_max = map(max, zip(*positions)) p_x_min, p_y_min, p_z_min = map(min, zip(*positions)) x_span = abs(p_x_max - p_x_min) y_span = abs(p_y_max - p_y_min) z_span = abs(p_z_max - p_z_min) span = max(x_span, y_span, z_span) if (not analysis): import FemMeshTools mesh = FemMeshTools.make_femmesh(m) if len(m['Nodes']) > 0: mesh_object = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', 'ResultMesh') mesh_object.FemMesh = mesh analysis_object.Member = analysis_object.Member + [mesh_object] for result_set in m['Results']: eigenmode_number = result_set['number'] if eigenmode_number > 0: results_name = 'Mode_' + str(eigenmode_number) + '_results' else: results_name = 'Results' results = FreeCAD.ActiveDocument.addObject('Fem::FemResultObject', results_name) for m in analysis_object.Member: if m.isDerivedFrom("Fem::FemMeshObject"): results.Mesh = m break disp = result_set['disp'] l = len(disp) displacement = [] for k, v in disp.iteritems(): displacement.append(v) x_max, y_max, z_max = map(max, zip(*displacement)) if eigenmode_number > 0: max_disp = max(x_max, y_max, z_max) # Allow for max displacement to be 0.1% of the span # FIXME - add to Preferences max_allowed_disp = 0.001 * span scale = max_allowed_disp / max_disp else: scale = 1.0 if len(disp) > 0: results.DisplacementVectors = map((lambda x: x * scale), disp.values()) results.NodeNumbers = disp.keys() if(mesh_object): results.Mesh = mesh_object stress = result_set['stress'] if len(stress) > 0: mstress = [] for i in stress.values(): mstress.append(calculate_von_mises(i)) if eigenmode_number > 0: results.StressValues = map((lambda x: x * scale), mstress) results.Eigenmode = eigenmode_number else: results.StressValues = mstress if (results.NodeNumbers != 0 and results.NodeNumbers != stress.keys()): print("Inconsistent FEM results: element number for Stress doesn't equal element number for Displacement {} != {}" .format(results.NodeNumbers, len(results.StressValues))) results.NodeNumbers = stress.keys() x_min, y_min, z_min = map(min, zip(*displacement)) sum_list = map(sum, zip(*displacement)) x_avg, y_avg, z_avg = [i / l for i in sum_list] s_max = max(results.StressValues) s_min = min(results.StressValues) s_avg = sum(results.StressValues) / l disp_abs = [] for d in displacement: disp_abs.append(sqrt(pow(d[0], 2) + pow(d[1], 2) + pow(d[2], 2))) results.DisplacementLengths = disp_abs a_max = max(disp_abs) a_min = min(disp_abs) a_avg = sum(disp_abs) / l results.Stats = [x_min, x_avg, x_max, y_min, y_avg, y_max, z_min, z_avg, z_max, a_min, a_avg, a_max, s_min, s_avg, s_max] analysis_object.Member = analysis_object.Member + [results] if(FreeCAD.GuiUp): import FemGui FemGui.setActiveAnalysis(analysis_object)
def get_constraints_displacement_nodes(self): # get nodes for femobj in self.displacement_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] femobj['Nodes'] = FemMeshTools.get_femnodes_by_references(self.femmesh, femobj['Object'].References)
def get_constraints_temperature_nodes(self): # get nodes for femobj in self.temperature_objects: # femobj --> dict, FreeCAD document object is femobj['Object'] femobj['Nodes'] = FemMeshTools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
def get_boundary_layer_data(self): # mesh boundary layer, # currently only one boundary layer setting object is allowed, but multiple boundary can be selected # Mesh.CharacteristicLengthMin, must be zero, or a value less than first inflation layer height self.bl_setting_list = [] # list of dict, each item map to MeshBoundaryLayer object self.bl_boundary_list = [] # to remove duplicated boundary edge or faces if not self.mesh_obj.MeshBoundaryLayerList: print (' No mesh boundary layer setting document object.') else: print (' Mesh boundary layers, we need to get the elements.') if self.part_obj.Shape.ShapeType == 'Compound': # see http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 and http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 err = "GMSH could return unexpected meshes for a boolean split tools Compound. It is strongly recommended to extract the shape to mesh from the Compound and use this one." FreeCAD.Console.PrintError(err + "\n") for mr_obj in self.mesh_obj.MeshBoundaryLayerList: if mr_obj.MinimumThickness and Units.Quantity(mr_obj.MinimumThickness).Value > 0: if mr_obj.References: belem_list = [] for sub in mr_obj.References: # print(sub[0]) # Part the elements belongs to # check if the shape of the mesh boundary_layer is an element of the Part to mesh, if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): # print(" One element of the mesh boundary layer " + mr_obj.Name + " is not an element of the Part to mesh.") # print(" But we going to find it in the Shape to mesh :-)") search_ele_in_shape_to_mesh = True for elems in sub[1]: # print(elems) # elems --> element if search_ele_in_shape_to_mesh: # we try to find the element it in the Shape to mesh and use the found element as elems ele_shape = FemMeshTools.get_element(sub[0], elems) # the method getElement(element) does not return Solid elements found_element = FemMeshTools.find_element_in_shape(self.part_obj.Shape, ele_shape) if found_element: # also elems = found_element else: FreeCAD.Console.PrintError("One element of the mesh boudary layer " + mr_obj.Name + " could not be found in the Part to mesh. It will be ignored.\n") # print(elems) # element if elems not in self.bl_boundary_list: # fetch settings in DocumentObject, fan setting is not implemented belem_list.append(elems) self.bl_boundary_list.append(elems) else: FreeCAD.Console.PrintError("The element " + elems + " of the mesh boundary layer " + mr_obj.Name + " has been added to another mesh boudary layer.\n") setting = {} setting['hwall_n'] = Units.Quantity(mr_obj.MinimumThickness).Value setting['ratio'] = mr_obj.GrowthRate setting['thickness'] = sum([setting['hwall_n'] * setting['ratio'] ** i for i in range(mr_obj.NumberOfLayers)]) setting['hwall_t'] = setting['thickness'] # setting['hwall_n'] * 5 # tangetial cell dimension # hfar: cell dimension outside boundary should be set later if some character length is set if self.clmax > setting['thickness'] * 0.8 and self.clmax < setting['thickness'] * 1.6: setting['hfar'] = self.clmax else: setting['hfar'] = setting['thickness'] # set a value for safety, it may works as background mesh cell size # from face name -> face id is done in geo file write up #fan angle setup is not implemented yet if self.dimension == '2': setting['EdgesList'] = belem_list elif self.dimension == '3': setting['FacesList'] = belem_list else: FreeCAD.Console.PrintError("boundary layer is only supported for 2D and 3D mesh") self.bl_setting_list.append(setting) else: FreeCAD.Console.PrintError("The mesh boundary layer: " + mr_obj.Name + " is not used to create the mesh because the reference list is empty.\n") else: FreeCAD.Console.PrintError("The mesh boundary layer: " + mr_obj.Name + " is not used to create the mesh because the min thickness is 0.0 mm.\n") print(' {}'.format(self.bl_setting_list))
def get_constraints_pressure_faces(self): # TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ... # 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(self.femmesh, femobj)