def get_region_data(self): """ Mesh regions """ self.ele_length_map = {} # { 'mrNameString' : element length } self.ele_refinethick_map = { } # { 'mrNameString' : refinement thickness } self.ele_firstlayerheight_map = { } # { 'mrNameString' : first layer height } self.ele_numlayer_map = {} # { 'mrNameString' : number of layers } self.ele_expratio_map = {} # { 'mrNameString' : expansion ratio } self.snappyMeshRegions = {} from collections import defaultdict self.ele_meshpatch_map = defaultdict(list) if not self.mesh_obj.MeshRegionList: print(' No mesh regions.') else: print(' Mesh regions, we need to get the elements.') if "Boolean" in self.part_obj.Name: err = "Cartesian meshes should not be generated for boolean split compounds." FreeCAD.Console.PrintError(err + "\n") for mr_obj in self.mesh_obj.MeshRegionList: if mr_obj.RelativeLength: if mr_obj.References: # Store parameters per region mr_rellen = mr_obj.RelativeLength if mr_rellen > 1.0: mr_rellen = 1.0 FreeCAD.Console.PrintError( "The meshregion: " + mr_obj.Name + " should not use a relative length greater than unity.\n" ) elif mr_rellen < 0.01: mr_rellen = 0.01 # Relative length should not be less than 1/100 of base length FreeCAD.Console.PrintError( "The meshregion: " + mr_obj.Name + " should not use a relative length smaller than 0.01.\n" ) self.ele_length_map[ mr_obj.Name] = mr_rellen * self.clmax * self.scale self.ele_refinethick_map[mr_obj.Name] = self.scale*Units.Quantity\ (mr_obj.RefinementThickness).Value self.ele_numlayer_map[ mr_obj.Name] = mr_obj.NumberLayers self.ele_expratio_map[ mr_obj.Name] = mr_obj.ExpansionRatio self.ele_firstlayerheight_map[mr_obj.Name] = self.scale*Units.Quantity\ (mr_obj.FirstLayerHeight).Value # STL containing the faces in the reference list # For long and many reasons related to snappy and baffles we cannot # use multi-region .stl for creating baffles. Therefore exporting each # mesh region face as an independent .stl surface. To not confuse cfMesh behaviour # leaving cfMesh as is. if self.mesh_obj.MeshUtility == "cfMesh": f = open( os.path.join(self.triSurfaceDir, mr_obj.Name + '.stl'), 'w') #f.write("solid {}\n".format(mr_obj.Name)) mr_obj.Name snappyTemp = [] subC = -1 for sub in mr_obj.References: subC += 1 # print(sub[0]) # Part the elements belongs to elems_list = [] elemC = -1 for elems in sub[1]: elemC += 1 # print(elems) # elems --> element if not elems in elems_list: elt = sub[0].Shape.getElement(elems) if elt.ShapeType == 'Face': facemesh = MeshPart.meshFromShape( elt, LinearDeflection=self.mesh_obj. STLLinearDeflection) # Write separate stls allowing for individual baffle definition if self.mesh_obj.MeshUtility == "snappyHexMesh": f = open( os.path.join( self.triSurfaceDir, mr_obj.Name + sub[0].Name + elems + '.stl'), 'w') snappyTemp.append(mr_obj.Name + sub[0].Name + elems) f.write( "solid {}\n".format(mr_obj.Name + "Sub" + str(subC) + "Elem" + str(elemC))) for face in facemesh.Facets: f.write(" facet normal 0 0 0\n") f.write(" outer loop\n") for i in range(3): p = face.Points[i] f.write(" vertex {} {} {}". format( self.scale * p[0], self.scale * p[1], self.scale * p[2])) f.write("\n") f.write(" endloop\n") f.write(" endfacet\n") f.write("endsolid {}\n".format( mr_obj.Name + "Sub" + str(subC) + "Elem" + str(elemC))) # Similarity search for patch used in boundary layer meshing meshFaceList = self.mesh_obj.Part.Shape.Faces for (i, mf) in enumerate(meshFaceList): import FemMeshTools isSameGeo = FemMeshTools.is_same_geometry( elt, mf) if isSameGeo: # Only one matching face sfN = self.mesh_obj.ShapeFaceNames[ i] self.ele_meshpatch_map[ mr_obj.Name].append(sfN) if self.mesh_obj.MeshUtility == "snappyHexMesh": f.close() else: FreeCAD.Console.PrintError( "Cartesian meshes only support surface refinement.\n" ) else: FreeCAD.Console.PrintError( "The element {} has already been added.\n" ) #f.write("endsolid {}\n".format(mr_obj.Name)) if self.mesh_obj.MeshUtility == "cfMesh": f.close() if self.mesh_obj.MeshUtility == "snappyHexMesh": self.snappyMeshRegions[mr_obj.Name] = snappyTemp 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") print(' {}'.format(self.ele_length_map))
def setupPatchNames(self): print('Populating createPatchDict to update BC names') settings = self.settings settings['createPatches'] = {} bc_group = self.bc_group mobj = self.mesh_obj bc_allocated = [] for bc_id, bc_obj in enumerate(bc_group): bc_list = [] meshFaceList = mobj.Part.Shape.Faces for (i, mf) in enumerate(meshFaceList): bcFacesList = bc_obj.Shape.Faces for bf in bcFacesList: isSameGeo = CfdTools.isSameGeometry(bf, mf) if isSameGeo: bc_list.append(mobj.ShapeFaceNames[i]) if mobj.ShapeFaceNames[i] in bc_allocated: print('Error: {} has been assigned twice'.format( mobj.ShapeFaceNames[i])) else: bc_allocated.append(mobj.ShapeFaceNames[i]) bcDict = bc_obj.BoundarySettings bcType = bcDict["BoundaryType"] bcSubType = bcDict["BoundarySubtype"] patchType = CfdTools.getPatchType(bcType, bcSubType) settings['createPatches'][bc_obj.Label] = { 'PatchNamesList': bc_list, 'PatchType': patchType } # In almost all cases the number of faces associated with a bc is going to be less than the number of # external or mesh faces. # if not (len(bc_list) == len(meshFaceList)): # raise Exception('Mismatch between boundary faces and mesh faces') if self.mesh_obj.MeshRegionList: for regionObj in self.mesh_obj.MeshRegionList: #if regionObj.snappedRefine: if regionObj.internalBaffle: settings['createPatchesFromSnappyBaffles'] = True if settings['createPatchesFromSnappyBaffles']: settings['createPatchesSnappyBaffles'] = {} # TODO Still need to include an error checker in the event that # an internal baffle is created using snappy but is not linked up # with a baffle boundary condition (as in there is no baffle boundary condition which # corresponds. Currently openfoam will throw a contextually # confusing error (only that the boundary does not exist). The primary difficulty with such a checker is # that it is possible to define a boundary face as a baffle, which will be overriden # by the actual boundary name and therefore won't exist anymore. for bc_id, bc_obj in enumerate(bc_group): bcDict = bc_obj.BoundarySettings bcType = bcDict["BoundaryType"] if bcType == "baffle": tempBaffleList = [] tempBaffleListSlave = [] if self.mesh_obj.MeshRegionList: for regionObj in self.mesh_obj.MeshRegionList: print regionObj.Name if regionObj.internalBaffle: for sub in regionObj.References: print sub[0].Name for elems in sub[1]: elt = sub[0].Shape.getElement(elems) if elt.ShapeType == 'Face': #isSameGeo = FemMeshTools.is_same_geometry(bf, mf) bcFacesList = bc_obj.Shape.Faces for bf in bcFacesList: import FemMeshTools isSameGeo = FemMeshTools.is_same_geometry( bf, elt) if isSameGeo: tempBaffleList.append( regionObj.Name + sub[0].Name + elems) tempBaffleListSlave.append( regionObj.Name + sub[0].Name + elems + "_slave") settings['createPatchesSnappyBaffles'][bc_obj.Label] = { "PatchNamesList": tempBaffleList, "PatchNamesListSlave": tempBaffleListSlave } # Add default faces flagName = False def_bc_list = [] for name in mobj.ShapeFaceNames: if not name in bc_allocated: def_bc_list.append(name) flagName = True if flagName: settings['createPatches']['defaultFaces'] = { 'PatchNamesList': def_bc_list, 'PatchType': "patch" }