Example #1
0
    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"
                    )
Example #2
0
    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"
            }
Example #3
0
    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"
            }