Mod: improved mesh class

Mod: mesh subclass for each sample
New: foamfile, reader and writer
This commit is contained in:
L-Nafaryus 2021-10-20 21:48:59 +05:00
parent 77647b3370
commit b45954d153
No known key found for this signature in database
GPG Key ID: C76D8DCD2727DBB7
14 changed files with 755 additions and 309 deletions

View File

@ -291,104 +291,39 @@ class Anisotropy(object):
setupLogger(logger, logging.INFO, self.env["LOG"]) setupLogger(logger, logging.INFO, self.env["LOG"])
p = self.params p = self.params
### sGeometry, sMesh = dict(
# Shape simple = (Simple, SimpleMesh),
## bodyCentered = (BodyCentered, BodyCenteredMesh),
logger.info("Constructing shape ...") faceCentered = (FaceCentered, FaceCenteredMesh)
geompy = salomepl.geometry.getGeom()
structure = dict(
simple = Simple,
bodyCentered = BodyCentered,
faceCentered = FaceCentered
)[p["structure"]["type"]] )[p["structure"]["type"]]
shapeGeometry = structure(**p["structure"])
shapeGeometry.build()
[length, surfaceArea, volume] = geompy.BasicProperties(shapeGeometry.shape, theTolerance = 1e-06) # Shape
logger.info("Constructing shape ...")
geometry = sGeometry(**p["structure"])
geometry.build()
###
# Mesh # Mesh
##
logger.info("Prepairing mesh ...") logger.info("Prepairing mesh ...")
mesh = sMesh(geometry)
mesh.build()
params = db.Mesh()
mesh = mesh.Mesh(shapeGeometry)
algo3d = mesh.algo3d(Netgen3D)
algo3d.apply(**params)
mesh = smesh.Mesh(shape)
algo3d = mesh.Tetrahedron(algo = smeshBuilder.NETGEN_3D)
algo2d = mesh.Triangle(algo = smeshBuilder.NETGEN_2D)
hypo2d = algo2d.MaxElementArea(0.197375)
algo1d = mesh.Segment()
hypo1d = algo1d.AutomaticLength(1)
algo2d = mesh.Triangle(algo = smeshBuilder.NETGEN_2D, geom = strips)
hypo2d = algo2d.LengthFromEdges()
algo1d = mesh.Segment(algo = smeshBuilder.COMPOSITE, geom = strips)
hypo1d = algo1d.AutomaticLength(0.633882)
hypo1d.SetFineness( 1 )
mp = p["mesh"]
lengths = [
geompy.BasicProperties(edge)[0] for edge in geompy.SubShapeAll(shapeGeometry.shape, geompy.ShapeType["EDGE"])
]
meanSize = sum(lengths) / len(lengths)
mp["maxSize"] = meanSize
mp["minSize"] = meanSize * 1e-1
mp["chordalError"] = mp["maxSize"] / 2
faces = []
for group in shapeGeometry.groups:
if group.GetName() in mp["facesToIgnore"]:
faces.append(group)
mesh = salomepl.mesh.Mesh(shapeGeometry.shape)
mesh.Tetrahedron(**mp)
if mp["viscousLayers"]:
mesh.ViscousLayers(**mp, faces = faces)
# Submesh
smp = p["submesh"]
for submesh in smp:
for group in shapeGeometry.groups:
if submesh["name"] == group.GetName():
subshape = group
submesh["maxSize"] = meanSize * 1e-1
submesh["minSize"] = meanSize * 1e-3
submesh["chordalError"] = submesh["minSize"] * 1e+1
mesh.Triangle(subshape, **submesh)
self.update()
logger.info("Computing mesh ...") logger.info("Computing mesh ...")
out, err, returncode = mesh.compute() out, err, returncode = mesh.compute()
###
# Results
##
#p["meshresult"] = dict()
if not returncode: if not returncode:
mesh.removePyramids() mesh.removePyramids()
mesh.assignGroups() mesh.createGroups()
casePath = self.getCasePath(path) casePath = self.getCasePath(path)
os.makedirs(casePath, exist_ok = True) os.makedirs(casePath, exist_ok = True)
logger.info("Exporting mesh ...") logger.info("Exporting mesh ...")
returncode, err = mesh.exportUNV(os.path.join(casePath, "mesh.unv")) out, err, returncode = mesh.export(os.path.join(casePath, "mesh.unv"))
if returncode: if returncode:
logger.error(err) logger.error(err)
# NOTE: edit from here
meshStats = mesh.stats() meshStats = mesh.stats()
p["meshresult"].update( p["meshresult"].update(
surfaceArea = surfaceArea, surfaceArea = surfaceArea,

View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.openfoam.foamfile import FoamFile
class ControlDict(FoamFile):
def __init__(self):
ff = FoamFile(
"system/controlDict",
_location = "system"
)
self.header = ff.header
self.content = {
"application": "simpleFoam",
"startFrom": "startTime",
"startTime": 0,
"stopAt": "endTime",
"endTime": 2000,
"deltaT": 1,
"writeControl": "timeStep",
"writeInterval": 100,
"purgeWrite": 0,
"writeFormat": "ascii",
"writePrecision": 6,
"writeCompression": "off",
"timeFormat": "general",
"timePrecision": 6,
"runTimeModifiable": True
}

View File

@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
# This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.openfoam.utils import version
from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile
from PyFoam.Basics.FoamFileGenerator import FoamFileGenerator
import os
class FoamFile(object):
def __init__(self,
filename,
_version = 2.0,
_format = "ascii",
_class = "dictionary",
_location = None,
_object = None
):
self.path = os.path.abspath(filename)
self.header = {
"version": _version,
"format": _format,
"class": _class,
"object": _object or os.path.split(filename)[1]
}
self.content = {}
if _location:
self.header["location"] = f'"{ _location }"'
def __getitem__(self, key):
return self.content[key]
def __setitem__(self, key, value):
self.content[key] = value
def __delitem__(self, key):
del self.content[key]
def __len__(self):
return len(self.content)
def __iter__(self):
for key in self.content:
yield key
def read(self):
ppf = ParsedParameterFile(self.path)
self.header = ppf.header
self.content = ppf.content
def _template(self, header, content):
limit = 78
desc = [
"/*--------------------------------*- C++ -*----------------------------------*\\",
"| ========= | |",
"| \\\\ / F ield | OpenFOAM: The Open Source CFD Toolbox |",
"| \\\\ / O peration |",
"| \\\\ / A nd | |",
"| \\\\/ M anipulation | |",
"\*---------------------------------------------------------------------------*/"
]
desc[3] += " Version: {}".format(version() or "missed")
desc[3] += " " * (limit - len(desc[3])) + "|"
afterheader = "// " + 37 * "* " + "//"
endfile = "// " + 73 * "*" + " //"
return "\n".join([*desc, header, afterheader, content, endfile])
def write(self):
header = FoamFileGenerator({}, header = self.header)
header = header.makeString()[ :-2]
header = header.replace("\n ", "\n" + 4 * " ")
content = FoamFileGenerator(self.content)
content = content.makeString()[ :-1]
content = content.replace("\n ", "\n" + 4 * " ").replace(" \t// " + 73 * "*" + " //", "")
content = content.replace(" /* empty */ ", "")
prepared = self._template(header, content)
os.makedirs(os.path.split(self.path)[0], exist_ok = True)
with open(self.path, "w") as io:
_ = io.write(prepared)

View File

@ -1,8 +1,8 @@
/*--------------------------------*- C++ -*----------------------------------*\ /*--------------------------------*- C++ -*----------------------------------*\
| ========= | | | ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 | | \\ / O peration | Version: missed |
| \\ / A nd | Website: www.openfoam.com | | \\ / A nd | |
| \\/ M anipulation | | | \\/ M anipulation | |
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
FoamFile FoamFile
@ -14,7 +14,6 @@ FoamFile
object fvSolution; object fvSolution;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
solvers solvers
{ {
p p
@ -24,7 +23,6 @@ solvers
relTol 0.1; relTol 0.1;
smoother GaussSeidel; smoother GaussSeidel;
} }
U U
{ {
solver smoothSolver; solver smoothSolver;
@ -32,9 +30,7 @@ solvers
nSweeps 2; nSweeps 2;
tolerance 1e-08; tolerance 1e-08;
relTol 0.1; relTol 0.1;
} } /*Phi
/*Phi
{ {
solver GAMG; solver GAMG;
smoother GaussSeidel; smoother GaussSeidel;
@ -45,16 +41,14 @@ solvers
{ {
solver GAMG; solver GAMG;
smoother DIC; smoother DIC;
cacheAgglomeration on; cacheAgglomeration yes;
agglomerator faceAreaPair; agglomerator faceAreaPair;
nCellsInCoarsestLevel 10; nCellsInCoarsestLevel 10;
mergeLevels 1; mergeLevels 1;
tolerance 1e-06; tolerance 1e-06;
relTol 0.01; relTol 0.01;
} }
} }
potentialFlow potentialFlow
{ {
nNonOrthogonalCorrectors 20; nNonOrthogonalCorrectors 20;
@ -63,23 +57,19 @@ potentialFlow
PhiRefValue 0; PhiRefValue 0;
Phi 0; Phi 0;
} }
cache cache
{ {
grad(U); grad(p) /* empty */ ;
} }
SIMPLE SIMPLE
{ {
nNonOrthogonalCorrectors 10; nNonOrthogonalCorrectors 10;
residualControl residualControl
{ {
p 1e-5; p 1e-05;
U 1e-5; U 1e-05;
} }
} }
relaxationFactors relaxationFactors
{ {
fields fields
@ -91,6 +81,4 @@ relaxationFactors
U 0.5; U 0.5;
} }
} }
// ************************************************************************* // // ************************************************************************* //

View File

@ -7,7 +7,7 @@ import shutil
from .application import application from .application import application
def version() -> str: def version() -> str:
return os.environ["WM_PROJECT_VERSION"] return os.environ.get("WM_PROJECT_VERSION")
def foamCleanCustom(case: str = None): def foamCleanCustom(case: str = None):

View File

@ -58,7 +58,7 @@ class StructureGeometry(object):
# Geometry module # Geometry module
if not GEOM_IMPORTED: if not GEOM_IMPORTED:
raise ImportError("Cannot find the salome modules.") raise ImportError("Cannot find the salome geometry modules.")
else: else:
self.geo = geomBuilder.New() self.geo = geomBuilder.New()

View File

@ -4,122 +4,75 @@
import logging import logging
logger = logging.getLogger("anisotropy") SMESH_IMPORTED = False
try: try:
import SMESH import SMESH
from salome.smesh import smeshBuilder from salome.smesh import smeshBuilder
except ImportError: SMESH_IMPORTED = True
logger.debug("Trying to get SALOME mesh modules outside SALOME environment. Modules won't be imported.")
if globals().get("smeshBuilder"):
smesh = smeshBuilder.New()
else:
smesh = None
import enum
class Fineness(enum.Enum):
VeryCoarse = 0
Coarse = 1
Moderate = 2
Fine = 3
VeryFine = 4
Custom = 5
def getSmesh():
return smesh
def updateParams(old, new: dict):
old.SetMaxSize(new.get("maxSize", old.GetMaxSize()))
old.SetMinSize(new.get("minSize", old.GetMinSize()))
old.SetFineness(new.get("fineness", old.GetFineness()))
old.SetGrowthRate(new.get("growthRate", old.GetGrowthRate()))
old.SetNbSegPerEdge(new.get("nbSegPerEdge", old.GetNbSegPerEdge()))
old.SetNbSegPerRadius(new.get("nbSegPerRadius", old.GetNbSegPerRadius()))
old.SetChordalErrorEnabled(new.get("chordalErrorEnabled", old.GetChordalErrorEnabled()))
old.SetChordalError(new.get("chordalError", old.GetChordalError()))
old.SetSecondOrder(new.get("secondOrder", old.GetSecondOrder()))
old.SetOptimize(new.get("optimize", old.GetOptimize()))
old.SetQuadAllowed(new.get("quadAllowed", old.GetQuadAllowed()))
old.SetUseSurfaceCurvature(new.get("useSurfaceCurvature", old.GetUseSurfaceCurvature()))
old.SetFuseEdges(new.get("fuseEdges", old.GetFuseEdges()))
old.SetCheckChartBoundary(new.get("checkChartBoundary", old.GetCheckChartBoundary()))
except:
pass
class Mesh(object): class Mesh(object):
def __init__(self, shape, name = ""): def __init__(self, geom):
self.name = name if name else shape.GetName()
self.mesh = smesh.Mesh(shape, self.name)
self.geom = shape
self.algo = None
self.params = None
self.viscousLayers = None
self.submeshes = [] # Mesh module
if not SMESH_IMPORTED:
raise ImportError("Cannot find the salome mesh modules.")
def Tetrahedron(self, **kwargs): else:
self.algo = self.mesh.Tetrahedron(algo = smeshBuilder.NETGEN_1D2D3D) self.smesh = smeshBuilder.New()
self.params = self.algo.Parameters() self.smeshBuilder = smeshBuilder
self.params = updateParams(self.params, kwargs) # General attributes
self.geom = geom
self.mesh = self.smesh.Mesh(self.geom.shape, self.geom.name)
def _extrusionMethod(self, key: str): def algo3d(self, algo, type = "tetrahedron"):
return dict( smeshAlgo = self.mesh.__dict__.get(type.capitalize())
SURF_OFFSET_SMOOTH = smeshBuilder.SURF_OFFSET_SMOOTH, self.meshAlgorithm3d = algo()
FACE_OFFSET = smeshBuilder.FACE_OFFSET, self.meshAlgorithm3d.initialize(smeshAlgo(algo = self.meshAlgorithm3d.key))
NODE_OFFSET = smeshBuilder.NODE_OFFSET, self.mesh.AddHypothesis(self.meshAlgorithm3d.hypo)
).get(key, smeshBuilder.SURF_OFFSET_SMOOTH)
def ViscousLayers(self, return self.meshAlgorithm3d
thickness = 1,
numberOfLayers = 1,
stretchFactor = 0,
faces = [],
isFacesToIgnore = True,
extrMethod = "SURF_OFFSET_SMOOTH",
**kwargs
):
self.viscousLayers = self.algo.ViscousLayers( def algo2d(self, algo, type = "triangle"):
thickness, smeshAlgo = self.mesh.__dict__.get(type.capitalize())
numberOfLayers, self.meshAlgorithm2d = algo()
stretchFactor, self.meshAlgorithm2d.initialize(smeshAlgo(algo = self.meshAlgorithm2d.key))
faces, self.mesh.AddHypothesis(self.meshAlgorithm2d.hypo)
isFacesToIgnore,
self._extrusionMethod(extrMethod)
)
def Triangle(self, subshape, **kwargs): return self.meshAlgorithm2d
submesh = Submesh(self.mesh, subshape)
submesh.algo = self.mesh.Triangle(algo = smeshBuilder.NETGEN_1D2D, geom = subshape)
submesh.mesh = submesh.algo.subm
submesh.params = submesh.algo.Parameters()
submesh.params = updateParams(submesh.params, kwargs) def algo1d(self, algo, type = "segment"):
smeshAlgo = self.mesh.__dict__.get(type.capitalize())
self.meshAlgorithm1d = algo()
self.meshAlgorithm1d.initialize(smeshAlgo(algo = self.meshAlgorithm1d.key))
self.mesh.AddHypothesis(self.meshAlgorithm1d.hypo)
self.submeshes.append(submesh) return self.meshAlgorithm1d
def assignGroups(self, withPrefix = True): def createGroups(self, prefix = None):
prefix = "smesh_" if withPrefix else "" prefix = prefix or ""
for group in self.mesh.geompyD.GetGroups(self.geom): for group in self.shape.groups:
if group.GetName(): name = group.GetName()
self.mesh.GroupOnGeom(group, f"{ prefix }{ group.GetName() }", SMESH.FACE)
if name:
name = prefix + name
self.mesh.GroupOnGeom(group, name, SMESH.FACE)
def compute(self): def compute(self):
"""Compute mesh.
"""
isDone = self.mesh.Compute() isDone = self.mesh.Compute()
returncode = int(not isDone) out = ""
err = self.mesh.GetComputeErrors() err = self.mesh.GetComputeErrors()
returncode = int(not isDone)
return "", err, returncode return out, err, returncode
def stats(self): def stats(self):
return { return {
@ -132,19 +85,6 @@ class Mesh(object):
"pyramids": self.mesh.NbPyramids() "pyramids": self.mesh.NbPyramids()
} }
def exportUNV(self, path):
returncode = 0
error = ""
try:
self.mesh.ExportUNV(path)
except Exception as e:
error = e.details.text
returncode = 1
return returncode, error
def removePyramids(self): def removePyramids(self):
if self.mesh.NbPyramids() > 0: if self.mesh.NbPyramids() > 0:
pyramidCriterion = smesh.GetCriterion( pyramidCriterion = smesh.GetCriterion(
@ -161,13 +101,204 @@ class Mesh(object):
self.mesh.RemoveGroup(pyramidGroup) self.mesh.RemoveGroup(pyramidGroup)
self.mesh.RenumberElements() self.mesh.RenumberElements()
def export(
filename: str
):
"""Export a mesh.
Supported formats: unv.
:param filename:
Name of the file to store the given mesh in.
:return:
Output, error messages and returncode
"""
out, err, returncode = "", "", 0
ext = os.path.splitext(filename)[1][1: ]
try:
if ext == "unv":
self.mesh.ExportUNV(self.mesh, filename)
else:
raise NotImplementedError(f"{ ext } is not supported")
except NotImplementedError as e:
err = e
returncode = 1
except Exception as e:
err = e.details.text
returncode = 1
return out, err, returncode
class Submesh(object): class MeshAlgorithm(object):
def __init__(self, father, subshape, name = ""): pass
self.name = name if name else subshape.GetName()
self.mesh = None
self.geom = subshape
self.algo = None
self.params = None
class AlgorithmHypothesis(object):
pass
class Netgen3D(MeshAlgorithm):
"""
MaxElementVolume
Parameters
ViscousLayers
"""
def __init__(self, **kwargs):
self.key = smeshBuilder.NETGEN_3D
def initialize(self, algo, hypo): #thesises: list):
self.algo = algo
#self.hypo = self.algo.Parameters()
#for hypo in hypothesises:
self.hypo = self.__dict__[hypo.__name__]()
class ViscousLayers(AlgorithmHypothesis):
def __init__(self,
algo,
thickness = 1,
numberOfLayers = 1,
stretchFactor = 0,
faces = [],
isFacesToIgnore = True,
extrMethod = "SURF_OFFSET_SMOOTH",
**kwargs
):
extrusionMethod = dict(
SURF_OFFSET_SMOOTH = smeshBuilder.SURF_OFFSET_SMOOTH,
FACE_OFFSET = smeshBuilder.FACE_OFFSET,
NODE_OFFSET = smeshBuilder.NODE_OFFSET,
).get(extrMethod, smeshBuilder.SURF_OFFSET_SMOOTH)
self.hypo = self.algo.ViscousLayers(
thickness,
numberOfLayers,
stretchFactor,
faces,
isFacesToIgnore,
extrusionMethod
)
class Parameters(AlgorithmHypothesis):
def __init__(self, algo):
self.hypo = self.algo.Parameters()
@property
def minSize(self):
return self.hypo.GetMinSize()
@minSize.setter
def minSize(self, value):
self.hypo.SetMinSize(value)
@property
def maxSize(self):
return self.hypo.GetMaxSize()
@maxSize.setter
def maxSize(self, value):
self.hypo.SetMaxSize(value)
@property
def fineness(self):
return self.hypo.GetFineness()
@fineness.setter
def fineness(self, value):
self.hypo.SetFineness(value)
@property
def growthRate(self):
return self.hypo.GetGrowthRate()
@growthRate.setter
def growthRate(self, value):
self.hypo.SetGrowthRate(value)
@property
def nbSegPerEdge(self):
return self.hypo.GetNbSegPerEdge()
@nbSegPerEdge.setter
def nbSegPerEdge(self, value):
self.hypo.SetNbSegPerEdge(value)
@property
def nbSegPerRadius(self):
return self.hypo.GetNbSegPerRadius()
@nbSegPerRadius.setter
def nbSegPerRadius(self, value):
self.hypo.SetNbSegPerRadius(value)
@property
def chordalErrorEnabled(self):
return self.hypo.GetChordalErrorEnabled()
@chordalErrorEnabled.setter
def chordalErrorEnabled(self, value):
self.hypo.SetChordalErrorEnabled(value)
@property
def chordalError(self):
return self.hypo.GetChordalError()
@chordalError.setter
def chordalError(self, value):
self.hypo.SetChordalError(value)
@property
def secondOrder(self):
return self.hypo.GetSecondOrder()
@secondOrder.setter
def secondOrder(self, value):
self.hypo.SetSecondOrder(value)
@property
def optimize(self):
return self.hypo.GetOptimize()
@optimize.setter
def optimize(self, value):
self.hypo.SetOptimize(value)
@property
def quadAllowed(self):
return self.hypo.GetQuadAllowed()
@quadAllowed.setter
def quadAllowed(self, value):
self.hypo.SetQuadAllowed(value)
@property
def useSurfaceCurvature(self):
return self.hypo.GetUseSurfaceCurvature()
@useSurfaceCurvature.setter
def useSurfaceCurvature(self, value):
self.hypo.SetUseSurfaceCurvature(value)
@property
def fuseEdges(self):
return self.hypo.GetFuseEdges()
@fuseEdges.setter
def fuseEdges(self, value):
self.hypo.SetFuseEdges(value)
@property
def checkChartBoundary(self):
return self.hypo.GetCheckChartBoundary()
@checkChartBoundary.setter
def GetCheckChartBoundary(self, value):
self.hypo.SetCheckChartBoundary(value)
class MEFISTO(MeshAlgorithm):
pass

View File

@ -2,6 +2,6 @@
# This file is part of anisotropy. # This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details. # License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.samples.simple import Simple #from anisotropy.samples.simple import Simple
from anisotropy.samples.bodyCentered import BodyCentered #from anisotropy.samples.bodyCentered import BodyCentered
from anisotropy.samples.faceCentered import FaceCentered #from anisotropy.samples.faceCentered import FaceCentered

View File

@ -226,3 +226,26 @@ class BodyCentered(StructureGeometry):
self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall")) self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))
class BodyCenteredMesh(Mesh):
def build(self):
algo2d = self.mesh.Triangle(algo = self.smeshBuilder.NETGEN_1D2D)
hypo2d = algo2d.Parameters()
hypo2d.SetMaxSize(0.1)
hypo2d.SetMinSize(0.001)
hypo2d.SetFineness(5)
hypo2d.SetGrowthRate(0.3)
hypo2d.SetNbSegPerEdge(2)
hypo2d.SetNbSegPerRadius(3)
hypo2d.SetChordalErrorEnabled(True)
hypo2d.SetChordalError(0.05)
hypo2d.SetOptimize(True)
hypo2d.SetUseSurfaceCurvature(True)
algo3d = self.mesh.Tetrahedron(algo = self.smeshBuilder.NETGEN_3D)
#hypo3d = algo3d.Parameters()
#faces = [ group for group in self.geom.groups if group.GetName() in ["inlet", "outlet"] ]
#hypo3dVL = algo3d.ViscousLayers(...)

View File

@ -3,6 +3,7 @@
# License: GNU GPL version 3, see the file "LICENSE" for details. # License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.salomepl.geometry import StructureGeometry from anisotropy.salomepl.geometry import StructureGeometry
from anisotropy.salomepl.mesh import Mesh
from numpy import pi, sqrt, fix from numpy import pi, sqrt, fix
import logging import logging
@ -228,3 +229,27 @@ class FaceCentered(StructureGeometry):
self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin])) self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin]))
self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall")) self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))
class FaceCenteredMesh(Mesh):
def build(self):
algo2d = self.mesh.Triangle(algo = self.smeshBuilder.NETGEN_1D2D)
hypo2d = algo2d.Parameters()
hypo2d.SetMaxSize(0.1)
hypo2d.SetMinSize(0.001)
hypo2d.SetFineness(5)
hypo2d.SetGrowthRate(0.3)
hypo2d.SetNbSegPerEdge(2)
hypo2d.SetNbSegPerRadius(3)
hypo2d.SetChordalErrorEnabled(True)
hypo2d.SetChordalError(0.05)
hypo2d.SetOptimize(True)
hypo2d.SetUseSurfaceCurvature(True)
algo3d = self.mesh.Tetrahedron(algo = self.smeshBuilder.NETGEN_3D)
#hypo3d = algo3d.Parameters()
#faces = [ group for group in self.geom.groups if group.GetName() in ["inlet", "outlet"] ]
#hypo3dVL = algo3d.ViscousLayers(...)

View File

@ -3,6 +3,7 @@
# License: GNU GPL version 3, see the file "LICENSE" for details. # License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.salomepl.geometry import StructureGeometry from anisotropy.salomepl.geometry import StructureGeometry
from anisotropy.salomepl.mesh import Mesh
from numpy import pi, sqrt, fix from numpy import pi, sqrt, fix
import logging import logging
@ -211,3 +212,36 @@ class Simple(StructureGeometry):
self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin])) self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin]))
self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall")) self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))
class SimpleMesh(Mesh):
def build(self):
algo2d = self.mesh.Triangle(algo = self.smeshBuilder.NETGEN_1D2D)
hypo2d = algo2d.Parameters()
hypo2d.SetMaxSize(0.1)
hypo2d.SetMinSize(0.001)
hypo2d.SetFineness(5)
hypo2d.SetGrowthRate(0.3)
hypo2d.SetNbSegPerEdge(2)
hypo2d.SetNbSegPerRadius(3)
hypo2d.SetChordalErrorEnabled(True)
hypo2d.SetChordalError(0.05)
hypo2d.SetOptimize(True)
hypo2d.SetUseSurfaceCurvature(True)
algo3d = self.mesh.Tetrahedron(algo = self.smeshBuilder.NETGEN_3D)
#hypo3d = algo3d.Parameters()
#faces = [ group for group in self.geom.groups if group.GetName() in ["inlet", "outlet"] ]
#hypo3dVL = algo3d.ViscousLayers(...)
from anisotropy.openfoam.foamcase import ControlDict
class SimpleFlow(object): # FoamCase
def __init__(self):
controlDict = ControlDict()
controlDict["startFrom"] = "latestTime"
controlDict["endTime"] = 5000
controlDict["writeInterval"] = 100

View File

@ -1,35 +1,36 @@
# -*- coding: utf-8 -*-
# This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details.
class MeshAlgorithm(object): import logging
pass
class Netgen3D(MeshAlgorithm): SMESH_IMPORTED = False
def __init__(self, **kwargs):
self.key = smeshBuilder.NETGEN_3D
def initialize(self, algo): try:
self.algo = algo import SMESH
self.hypo = self.algo.Parameters() from salome.smesh import smeshBuilder
SMESH_IMPORTED = True
@property except:
def minSize(self):
return self.hypo.GetMinSize()
@minSize.setter
def minSize(self, value):
self.hypo.SetMinSize(value)
class MEFISTO(MeshAlgorithm):
pass pass
class Mesh(object): class Mesh(object):
def __init__(self, geom): def __init__(self, geom):
# Mesh module
if not SMESH_IMPORTED:
raise ImportError("Cannot find the salome mesh modules.")
else:
self.smesh = smeshBuilder.New() self.smesh = smeshBuilder.New()
self.smeshBuilder = smeshBuilder
# General attributes
self.geom = geom self.geom = geom
self.mesh = self.smesh.Mesh(self.geom.shape, self.geom.name) self.mesh = self.smesh.Mesh(self.geom.shape, self.geom.name)
def algo3d(self, algo: MeshAlgorithm, type = "tetrahedron"): def algo3d(self, algo, type = "tetrahedron"):
smeshAlgo = self.mesh.__dict__.get(type.capitalize()) smeshAlgo = self.mesh.__dict__.get(type.capitalize())
self.meshAlgorithm3d = algo() self.meshAlgorithm3d = algo()
self.meshAlgorithm3d.initialize(smeshAlgo(algo = self.meshAlgorithm3d.key)) self.meshAlgorithm3d.initialize(smeshAlgo(algo = self.meshAlgorithm3d.key))
@ -37,7 +38,7 @@ class Mesh(object):
return self.meshAlgorithm3d return self.meshAlgorithm3d
def algo2d(self, algo: MeshAlgorithm, type = "triangle"): def algo2d(self, algo, type = "triangle"):
smeshAlgo = self.mesh.__dict__.get(type.capitalize()) smeshAlgo = self.mesh.__dict__.get(type.capitalize())
self.meshAlgorithm2d = algo() self.meshAlgorithm2d = algo()
self.meshAlgorithm2d.initialize(smeshAlgo(algo = self.meshAlgorithm2d.key)) self.meshAlgorithm2d.initialize(smeshAlgo(algo = self.meshAlgorithm2d.key))
@ -45,7 +46,7 @@ class Mesh(object):
return self.meshAlgorithm2d return self.meshAlgorithm2d
def algo1d(self, algo: MeshAlgorithm, type = "segment"): def algo1d(self, algo, type = "segment"):
smeshAlgo = self.mesh.__dict__.get(type.capitalize()) smeshAlgo = self.mesh.__dict__.get(type.capitalize())
self.meshAlgorithm1d = algo() self.meshAlgorithm1d = algo()
self.meshAlgorithm1d.initialize(smeshAlgo(algo = self.meshAlgorithm1d.key)) self.meshAlgorithm1d.initialize(smeshAlgo(algo = self.meshAlgorithm1d.key))
@ -84,6 +85,22 @@ class Mesh(object):
"pyramids": self.mesh.NbPyramids() "pyramids": self.mesh.NbPyramids()
} }
def removePyramids(self):
if self.mesh.NbPyramids() > 0:
pyramidCriterion = smesh.GetCriterion(
SMESH.VOLUME,
SMESH.FT_ElemGeomType,
SMESH.FT_Undefined,
SMESH.Geom_PYRAMID
)
pyramidGroup = self.mesh.MakeGroupByCriterion("pyramids", pyramidCriterion)
pyramidVolumes = self.mesh.GetIDSource(pyramidGroup.GetIDs(), SMESH.VOLUME)
self.mesh.SplitVolumesIntoTetra(pyramidVolumes, smesh.Hex_5Tet)
self.mesh.RemoveGroup(pyramidGroup)
self.mesh.RenumberElements()
def export( def export(
filename: str filename: str
): ):
@ -117,3 +134,171 @@ class Mesh(object):
return out, err, returncode return out, err, returncode
class MeshAlgorithm(object):
pass
class AlgorithmHypothesis(object):
pass
class Netgen3D(MeshAlgorithm):
"""
MaxElementVolume
Parameters
ViscousLayers
"""
def __init__(self, **kwargs):
self.key = smeshBuilder.NETGEN_3D
def initialize(self, algo, hypo): #thesises: list):
self.algo = algo
#self.hypo = self.algo.Parameters()
#for hypo in hypothesises:
self.hypo = self.__dict__[hypo.__name__]()
class ViscousLayers(AlgorithmHypothesis):
def __init__(self,
algo,
thickness = 1,
numberOfLayers = 1,
stretchFactor = 0,
faces = [],
isFacesToIgnore = True,
extrMethod = "SURF_OFFSET_SMOOTH",
**kwargs
):
extrusionMethod = dict(
SURF_OFFSET_SMOOTH = smeshBuilder.SURF_OFFSET_SMOOTH,
FACE_OFFSET = smeshBuilder.FACE_OFFSET,
NODE_OFFSET = smeshBuilder.NODE_OFFSET,
).get(extrMethod, smeshBuilder.SURF_OFFSET_SMOOTH)
self.hypo = self.algo.ViscousLayers(
thickness,
numberOfLayers,
stretchFactor,
faces,
isFacesToIgnore,
extrusionMethod
)
class Parameters(AlgorithmHypothesis):
def __init__(self, algo):
self.hypo = self.algo.Parameters()
@property
def minSize(self):
return self.hypo.GetMinSize()
@minSize.setter
def minSize(self, value):
self.hypo.SetMinSize(value)
@property
def maxSize(self):
return self.hypo.GetMaxSize()
@maxSize.setter
def maxSize(self, value):
self.hypo.SetMaxSize(value)
@property
def fineness(self):
return self.hypo.GetFineness()
@fineness.setter
def fineness(self, value):
self.hypo.SetFineness(value)
@property
def growthRate(self):
return self.hypo.GetGrowthRate()
@growthRate.setter
def growthRate(self, value):
self.hypo.SetGrowthRate(value)
@property
def nbSegPerEdge(self):
return self.hypo.GetNbSegPerEdge()
@nbSegPerEdge.setter
def nbSegPerEdge(self, value):
self.hypo.SetNbSegPerEdge(value)
@property
def nbSegPerRadius(self):
return self.hypo.GetNbSegPerRadius()
@nbSegPerRadius.setter
def nbSegPerRadius(self, value):
self.hypo.SetNbSegPerRadius(value)
@property
def chordalErrorEnabled(self):
return self.hypo.GetChordalErrorEnabled()
@chordalErrorEnabled.setter
def chordalErrorEnabled(self, value):
self.hypo.SetChordalErrorEnabled(value)
@property
def chordalError(self):
return self.hypo.GetChordalError()
@chordalError.setter
def chordalError(self, value):
self.hypo.SetChordalError(value)
@property
def secondOrder(self):
return self.hypo.GetSecondOrder()
@secondOrder.setter
def secondOrder(self, value):
self.hypo.SetSecondOrder(value)
@property
def optimize(self):
return self.hypo.GetOptimize()
@optimize.setter
def optimize(self, value):
self.hypo.SetOptimize(value)
@property
def quadAllowed(self):
return self.hypo.GetQuadAllowed()
@quadAllowed.setter
def quadAllowed(self, value):
self.hypo.SetQuadAllowed(value)
@property
def useSurfaceCurvature(self):
return self.hypo.GetUseSurfaceCurvature()
@useSurfaceCurvature.setter
def useSurfaceCurvature(self, value):
self.hypo.SetUseSurfaceCurvature(value)
@property
def fuseEdges(self):
return self.hypo.GetFuseEdges()
@fuseEdges.setter
def fuseEdges(self, value):
self.hypo.SetFuseEdges(value)
@property
def checkChartBoundary(self):
return self.hypo.GetCheckChartBoundary()
@checkChartBoundary.setter
def GetCheckChartBoundary(self, value):
self.hypo.SetCheckChartBoundary(value)
class MEFISTO(MeshAlgorithm):
pass

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys; path = "/home/nafaryus/projects/anisotropy"; sys.path.extend([path, path + "/env/lib/python3.10/site-packages"]) import sys; path = "/home/nafaryus/projects/anisotropy"; sys.path.extend([path, path + "/env/lib/python3.10/site-packages"])
from anisotropy.samples import Simple, FaceCentered, BodyCentered from anisotropy.samples.faceCentered import FaceCentered, FaceCenteredMesh
s = Simple([1, 0, 0], 0.28, filletsEnabled = True) fc = FaceCentered([1, 0, 0], 0.12, filletsEnabled = True)
fc.build()
fcm = FaceCenteredMesh(fc)
fcm.build()

View File

@ -7,3 +7,4 @@ pandas
Click Click
matplotlib matplotlib
pyqt5 pyqt5
PyFoam