def get_region_data(self): """ Mesh regions """ cf_settings = self.cf_settings cf_settings['MeshRegions'] = {} cf_settings['BoundaryLayers'] = {} snappy_settings = self.snappy_settings snappy_settings['MeshRegions'] = {} 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: # Store parameters per region mr_rellen = mr_obj.RelativeLength if mr_rellen > 1.0: mr_rellen = 1.0 FreeCAD.Console.PrintError( "The meshregion: {} should not use a relative length greater " "than unity.\n".format(mr_obj.Name)) elif mr_rellen < 0.001: mr_rellen = 0.001 # Relative length should not be less than 0.1% of base length FreeCAD.Console.PrintError( "The meshregion: {} should not use a relative length smaller " "than 0.05.\n".format(mr_obj.Name)) tri_surface = "" snappy_mesh_region_list = [] patch_list = [] for (si, sub) in enumerate(mr_obj.References): elems = sub[1] elt = FreeCAD.ActiveDocument.getObject( sub[0]).Shape.getElement(elems) if elt.ShapeType == 'Face': facemesh = MeshPart.meshFromShape( elt, LinearDeflection=self.mesh_obj. STLLinearDeflection) tri_surface += "solid {}{}{}\n".format( mr_obj.Name, sub[0], elems) for face in facemesh.Facets: tri_surface += " facet normal 0 0 0\n" tri_surface += " outer loop\n" for i in range(3): p = [ i * self.scale for i in face.Points[i] ] tri_surface += " vertex {} {} {}\n".format( p[0], p[1], p[2]) tri_surface += " endloop\n" tri_surface += " endfacet\n" tri_surface += "solid {}{}{}\n".format( mr_obj.Name, sub[0], elems) if self.mesh_obj.MeshUtility == 'snappyHexMesh' and mr_obj.Baffle: # Save baffle references or faces individually baffle = "{}{}{}".format( mr_obj.Name, sub[0], elems) fid = open( os.path.join(self.triSurfaceDir, baffle + ".stl"), 'w') fid.write(tri_surface) fid.close() tri_surface = "" snappy_mesh_region_list.append(baffle) elif self.mesh_obj.MeshUtility == 'cfMesh' and mr_obj.NumberLayers > 1: # Similarity search for patch used in boundary layer meshing meshFaceList = self.mesh_obj.Part.Shape.Faces for (i, mf) in enumerate(meshFaceList): isSameGeo = CfdTools.isSameGeometry( elt, mf) if isSameGeo and ( mr_obj.NumberLayers > 1): # Only one matching face sfN = self.mesh_obj.ShapeFaceNames[i] self.ele_meshpatch_map[ mr_obj.Name].append(sfN) patch_list.append( self.mesh_obj.ShapeFaceNames[i]) # Limit expansion ratio to greater than 1.0 and less than 1.2 expratio = mr_obj.ExpansionRatio expratio = min(1.2, max(1.0, expratio)) cf_settings['BoundaryLayers'][ self.mesh_obj. ShapeFaceNames[i]] = { 'NumberLayers': mr_obj.NumberLayers, 'ExpansionRatio': expratio, 'FirstLayerHeight': self.scale * Units.Quantity( mr_obj.FirstLayerHeight). Value } else: FreeCAD.Console.PrintError( "Cartesian meshes only support surface refinement.\n" ) if self.mesh_obj.MeshUtility == 'cfMesh' or not mr_obj.Baffle: fid = open( os.path.join(self.triSurfaceDir, mr_obj.Name + '.stl'), 'w') fid.write(tri_surface) fid.close() if self.mesh_obj.MeshUtility == 'cfMesh': cf_settings['MeshRegions'][mr_obj.Label] = { 'RelativeLength': mr_rellen * self.clmax * self.scale, 'RefinementThickness': self.scale * Units.Quantity(mr_obj.RefinementThickness).Value, } elif self.mesh_obj.MeshUtility == 'snappyHexMesh': if not mr_obj.Baffle: snappy_mesh_region_list.append(mr_obj.Name) snappy_settings['MeshRegions'][mr_obj.Name] = { 'RegionName': tuple(snappy_mesh_region_list), 'RefinementLevel': mr_obj.RefinementLevel, 'EdgeRefinementLevel': mr_obj.RegionEdgeRefinement, 'Baffle': mr_obj.Baffle } else: FreeCAD.Console.PrintError( "The meshregion: " + mr_obj.Name + " is not used to create the mesh because the " "CharacteristicLength is 0.0 mm or the reference list is empty.\n" )
def setupPatchNames(self): print('Populating createPatchDict to update BC names') import CfdMeshTools # Init in case not meshed yet CfdMeshTools.CfdMeshTools(self.mesh_obj) settings = self.settings settings['createPatches'] = {} bc_group = self.bc_group mobj = self.mesh_obj # Make list of list of all boundary references for their corresponding boundary boundary_ref_lists = [] for bc_id, bc_obj in enumerate(bc_group): boundary_ref_lists.append(bc_obj.References) # Match them up with faces in the meshed part matched_faces = CfdTools.matchFacesToTargetShape( boundary_ref_lists, mobj.Part.Shape) bc_lists = [] for bc in bc_group: bc_lists.append([]) for i in range(len(matched_faces)): if matched_faces[i]: nb, bref = matched_faces[i][0] bc_lists[nb].append(mobj.ShapeFaceNames[i]) for k in range(len(matched_faces[i]) - 1): nb2, bref2 = matched_faces[i][k + 1] if nb2 != nb: cfdMessage( "Boundary '{}' reference {}:{} also assigned as " "boundary '{}' reference {}:{}\n".format( bc_group[nb].Label, bref[0], bref[1], bc_group[nb2].Label, bref2[0], bref2[1])) for bc_id, bc_obj in enumerate(bc_group): bcType = bc_obj.BoundaryType bcSubType = bc_obj.BoundarySubType patchType = CfdTools.getPatchType(bcType, bcSubType) settings['createPatches'][bc_obj.Label] = { 'PatchNamesList': tuple(bc_lists[bc_id] ), # Tuple used so that case writer outputs as an array 'PatchType': patchType } if self.mesh_obj.MeshUtility == 'snappyHexMesh': for regionObj in CfdTools.getMeshRefinementObjs(self.mesh_obj): if regionObj.Baffle: 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 overridden # by the actual boundary name and therefore won't exist anymore. for bc_id, bc_obj in enumerate(bc_group): bcType = bc_obj.BoundaryType if bcType == "baffle": tempBaffleList = [] tempBaffleListSlave = [] for regionObj in self.mesh_obj.Group: if hasattr(regionObj, "Proxy") and \ isinstance(regionObj.Proxy, CfdMeshRefinement._CfdMeshRefinement): # print regionObj.Name if regionObj.Baffle: for sub in regionObj.References: # print sub[0].Name elems = sub[1] elt = FreeCAD.ActiveDocument.getObject( sub[0]).Shape.getElement(elems) if elt.ShapeType == 'Face': bcFacesList = bc_obj.Shape.Faces for bf in bcFacesList: isSameGeo = CfdTools.isSameGeometry( bf, elt) if isSameGeo: tempBaffleList.append( regionObj.Name + sub[0] + elems) tempBaffleListSlave.append( regionObj.Name + sub[0] + elems + "_slave") settings['createPatchesSnappyBaffles'][bc_obj.Label] = { "PatchNamesList": tuple(tempBaffleList), "PatchNamesListSlave": tuple(tempBaffleListSlave) } # Add default faces flagName = False def_bc_list = [] for i in range(len(matched_faces)): if not matched_faces[i]: def_bc_list.append(mobj.ShapeFaceNames[i]) flagName = True if flagName: settings['createPatches']['defaultFaces'] = { 'PatchNamesList': tuple(def_bc_list), 'PatchType': "patch" }
def setupPatchNames(self): print('Populating createPatchDict to update BC names') import CfdCartTools # Init in case not meshed yet CfdCartTools.CfdCartTools(self.mesh_obj) 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): bc_refs = bc_obj.References for br in bc_refs: bf = FreeCAD.ActiveDocument.getObject( br[0]).Shape.getElement(br[1]) 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': tuple(bc_list ), # Tuple used so that case writer outputs as an array 'PatchType': patchType } # if bcType != "baffle": # 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.Baffle: 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: # Can this if statement not be lumped with previous? for regionObj in self.mesh_obj.MeshRegionList: # print regionObj.Name if regionObj.Baffle: for sub in regionObj.References: # print sub[0].Name for elems in sub[1]: elt = sub[0].Shape.getElement(elems) if elt.ShapeType == 'Face': bcFacesList = bc_obj.Shape.Faces for bf in bcFacesList: isSameGeo = CfdTools.isSameGeometry( 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": tuple(tempBaffleList), "PatchNamesListSlave": tuple(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': tuple(def_bc_list), 'PatchType': "patch" }