Mod: mesh oop style
New: submeshes Fix: salome current version Mod: default values for mesh parameters - less values in main config Fix: smesh_* style for boundary groups Move: notes to real notes, reserve docs for docs
This commit is contained in:
parent
a7adc59b70
commit
7f75e9c790
@ -112,7 +112,7 @@ def createQueue():
|
|||||||
|
|
||||||
for structure in config.base.__dict__.keys():
|
for structure in config.base.__dict__.keys():
|
||||||
|
|
||||||
theta = getattr(config, structure).parameters.theta
|
theta = getattr(config, structure).geometry.theta
|
||||||
parameters_theta[structure] = [ n * theta[2] for n in range(int(theta[0] / theta[2]), int(theta[1] / theta[2]) + 1) ]
|
parameters_theta[structure] = [ n * theta[2] for n in range(int(theta[0] / theta[2]), int(theta[1] / theta[2]) + 1) ]
|
||||||
|
|
||||||
thickness = getattr(config, structure).mesh.thickness
|
thickness = getattr(config, structure).mesh.thickness
|
||||||
@ -156,10 +156,8 @@ def createQueue():
|
|||||||
"meshTime": 0,
|
"meshTime": 0,
|
||||||
"flowTime": 0
|
"flowTime": 0
|
||||||
},
|
},
|
||||||
"parameters": {
|
|
||||||
"theta": theta
|
|
||||||
},
|
|
||||||
"geometry": {
|
"geometry": {
|
||||||
|
"theta": theta,
|
||||||
"direction": direction,
|
"direction": direction,
|
||||||
"fillet": getattr(config, structure).geometry.fillet
|
"fillet": getattr(config, structure).geometry.fillet
|
||||||
},
|
},
|
||||||
|
@ -11,17 +11,15 @@ name = "anisotropy"
|
|||||||
format = "%(levelname)s: %(message)s"
|
format = "%(levelname)s: %(message)s"
|
||||||
|
|
||||||
[base]
|
[base]
|
||||||
simple = false
|
simple = true
|
||||||
bodyCentered = true
|
bodyCentered = true
|
||||||
faceCentered = false
|
faceCentered = true
|
||||||
|
|
||||||
###
|
###
|
||||||
# Simple
|
# Simple
|
||||||
##
|
##
|
||||||
[simple.parameters]
|
|
||||||
theta = [0.01, 0.28, 0.01]
|
|
||||||
|
|
||||||
[simple.geometry]
|
[simple.geometry]
|
||||||
|
theta = [0.01, 0.28, 0.01]
|
||||||
directions = [
|
directions = [
|
||||||
[1, 0, 0],
|
[1, 0, 0],
|
||||||
[0, 0, 1],
|
[0, 0, 1],
|
||||||
@ -30,37 +28,20 @@ directions = [
|
|||||||
fillet = true
|
fillet = true
|
||||||
|
|
||||||
[simple.mesh]
|
[simple.mesh]
|
||||||
fineness = 3
|
viscousLayers = true
|
||||||
minSize = 0.05
|
|
||||||
maxSize = 0.1
|
|
||||||
growthRate = 0.5
|
|
||||||
nbSegPerEdge = 0.5
|
|
||||||
nbSegPerRadius = 0.5
|
|
||||||
chordalErrorEnabled = false
|
|
||||||
chordalError = -1
|
|
||||||
secondOrder = false
|
|
||||||
optimize = true
|
|
||||||
quadAllowed = false
|
|
||||||
useSurfaceCurvature = true
|
|
||||||
fuseEdges = true
|
|
||||||
checkChartBoundary = false
|
|
||||||
|
|
||||||
localSizeOnShape.strips = 0.01
|
|
||||||
|
|
||||||
viscousLayers = false
|
|
||||||
thickness = [0.01, 0.005]
|
thickness = [0.01, 0.005]
|
||||||
numberOfLayers = 1
|
|
||||||
stretchFactor = 1.2
|
[simple.mesh.submesh.strips]
|
||||||
isFacesToIgnore = true
|
growthRate = 0.2
|
||||||
|
nbSegPerEdge = 2
|
||||||
|
nbSegPerRadius = 3
|
||||||
|
|
||||||
###
|
###
|
||||||
# Body-centered
|
# Body-centered
|
||||||
##
|
##
|
||||||
[bodyCentered.parameters]
|
|
||||||
# TODO: 0.18
|
# TODO: 0.18
|
||||||
theta = [0.01, 0.17, 0.01]
|
|
||||||
|
|
||||||
[bodyCentered.geometry]
|
[bodyCentered.geometry]
|
||||||
|
theta = [0.01, 0.17, 0.01]
|
||||||
directions = [
|
directions = [
|
||||||
[1, 0, 0],
|
[1, 0, 0],
|
||||||
[0, 0, 1],
|
[0, 0, 1],
|
||||||
@ -69,36 +50,19 @@ directions = [
|
|||||||
fillet = true
|
fillet = true
|
||||||
|
|
||||||
[bodyCentered.mesh]
|
[bodyCentered.mesh]
|
||||||
fineness = 3
|
|
||||||
minSize = 0.05
|
|
||||||
maxSize = 0.5
|
|
||||||
growthRate = 0.5
|
|
||||||
nbSegPerEdge = 0.5
|
|
||||||
nbSegPerRadius = 0.5
|
|
||||||
chordalErrorEnabled = false
|
|
||||||
chordalError = -1
|
|
||||||
secondOrder = false
|
|
||||||
optimize = true
|
|
||||||
quadAllowed = false
|
|
||||||
useSurfaceCurvature = true
|
|
||||||
fuseEdges = true
|
|
||||||
checkChartBoundary = false
|
|
||||||
|
|
||||||
localSizeOnShape.strips = 0.01
|
|
||||||
|
|
||||||
viscousLayers = false
|
viscousLayers = false
|
||||||
thickness = [0.005, 0.0005]
|
thickness = [0.005, 0.0005]
|
||||||
numberOfLayers = 1
|
|
||||||
stretchFactor = 1.2
|
[bodyCentered.mesh.submesh.strips]
|
||||||
isFacesToIgnore = true
|
growthRate = 0.2
|
||||||
|
nbSegPerEdge = 2
|
||||||
|
nbSegPerRadius = 3
|
||||||
|
|
||||||
###
|
###
|
||||||
# Face-centered
|
# Face-centered
|
||||||
##
|
##
|
||||||
[faceCentered.parameters]
|
|
||||||
theta = [0.01, 0.13, 0.01]
|
|
||||||
|
|
||||||
[faceCentered.geometry]
|
[faceCentered.geometry]
|
||||||
|
theta = [0.01, 0.13, 0.01]
|
||||||
directions = [
|
directions = [
|
||||||
[1, 0, 0],
|
[1, 0, 0],
|
||||||
[0, 0, 1],
|
[0, 0, 1],
|
||||||
@ -107,28 +71,13 @@ directions = [
|
|||||||
fillet = true
|
fillet = true
|
||||||
|
|
||||||
[faceCentered.mesh]
|
[faceCentered.mesh]
|
||||||
fineness = 3
|
|
||||||
minSize = 0.01
|
|
||||||
maxSize = 0.5
|
|
||||||
growthRate = 0.5
|
|
||||||
nbSegPerEdge = 0.5
|
|
||||||
nbSegPerRadius = 0.5
|
|
||||||
chordalErrorEnabled = false
|
|
||||||
chordalError = -1
|
|
||||||
secondOrder = false
|
|
||||||
optimize = true
|
|
||||||
quadAllowed = false
|
|
||||||
useSurfaceCurvature = true
|
|
||||||
fuseEdges = true
|
|
||||||
checkChartBoundary = false
|
|
||||||
|
|
||||||
localSizeOnShape.strips = 0.01
|
|
||||||
|
|
||||||
viscousLayers = false
|
viscousLayers = false
|
||||||
thickness = [0.001, 0.0005]
|
thickness = [0.001, 0.0005]
|
||||||
numberOfLayers = 1
|
|
||||||
stretchFactor = 1.2
|
[faceCentered.mesh.submesh.strips]
|
||||||
isFacesToIgnore = true
|
growthRate = 0.2
|
||||||
|
nbSegPerEdge = 2
|
||||||
|
nbSegPerRadius = 3
|
||||||
|
|
||||||
###
|
###
|
||||||
# Flow
|
# Flow
|
||||||
|
@ -41,7 +41,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (inlet_);
|
patches (smesh_inlet);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (outlet_);
|
patches (smesh_outlet);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (wall_);
|
patches (smesh_wall);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -81,7 +81,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry0_);
|
patches (smesh_symetry0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry1_);
|
patches (smesh_symetry1);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -107,7 +107,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry2_);
|
patches (smesh_symetry2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry3_);
|
patches (smesh_symetry3);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -133,7 +133,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry4_);
|
patches (smesh_symetry4);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -146,7 +146,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (symetry5_);
|
patches (smesh_symetry5);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -159,7 +159,7 @@ patches
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructFrom patches;
|
constructFrom patches;
|
||||||
patches (strips_);
|
patches (smesh_strips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,34 +22,64 @@ import toml
|
|||||||
import logging
|
import logging
|
||||||
from anisotropy.utils import struct
|
from anisotropy.utils import struct
|
||||||
|
|
||||||
CONFIG = os.path.join(CASE, "task.toml")
|
|
||||||
config = struct(toml.load(CONFIG))
|
|
||||||
|
|
||||||
LOG = os.path.join(ROOT, "logs")
|
|
||||||
|
|
||||||
logging.basicConfig(
|
|
||||||
level = logging.INFO,
|
|
||||||
format = config.logger.format,
|
|
||||||
handlers = [
|
|
||||||
logging.StreamHandler(),
|
|
||||||
logging.FileHandler(f"{ LOG }/{ config.logger.name }.log")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
logger = logging.getLogger(config.logger.name)
|
|
||||||
|
|
||||||
from salomepl.simple import simple
|
from salomepl.simple import simple
|
||||||
from salomepl.faceCentered import faceCentered
|
from salomepl.faceCentered import faceCentered
|
||||||
from salomepl.bodyCentered import bodyCentered
|
from salomepl.bodyCentered import bodyCentered
|
||||||
|
|
||||||
from salomepl.geometry import getGeom
|
from salomepl.geometry import getGeom
|
||||||
from salomepl.mesh import smeshBuilder, meshCreate, meshCompute, meshStats, meshExport
|
from salomepl.mesh import Mesh, Fineness, ExtrusionMethod
|
||||||
|
|
||||||
|
def defaultParameters(**configParameters):
|
||||||
|
maxSize = 0.5
|
||||||
|
minSize = 0.05
|
||||||
|
|
||||||
|
fineness = Fineness.Custom.value
|
||||||
|
growthRate = 0.7
|
||||||
|
nbSegPerEdge = 0.3
|
||||||
|
nbSegPerRadius = 1
|
||||||
|
|
||||||
|
chordalErrorEnabled = True
|
||||||
|
chordalError = 0.25
|
||||||
|
|
||||||
|
secondOrder = False
|
||||||
|
optimize = True
|
||||||
|
quadAllowed = False
|
||||||
|
useSurfaceCurvature = True
|
||||||
|
fuseEdges = True
|
||||||
|
checkChartBoundary = False
|
||||||
|
|
||||||
|
viscousLayers = False
|
||||||
|
thickness = 0.005
|
||||||
|
numberOfLayers = 1
|
||||||
|
stretchFactor = 1
|
||||||
|
isFacesToIgnore = True
|
||||||
|
facesToIgnore = ["inlet", "outlet"]
|
||||||
|
faces = []
|
||||||
|
extrusionMethod = ExtrusionMethod.SURF_OFFSET_SMOOTH
|
||||||
|
|
||||||
|
p = locals()
|
||||||
|
del p["configParameters"]
|
||||||
|
|
||||||
|
if configParameters:
|
||||||
|
for k, v in p.items():
|
||||||
|
if configParameters.get(k) is not None:
|
||||||
|
p[k] = configParameters[k]
|
||||||
|
|
||||||
|
# Overwrite special values
|
||||||
|
if k == "fineness":
|
||||||
|
p["fineness"] = Fineness.__dict__[p["fineness"]].value
|
||||||
|
|
||||||
|
if k == "extrusionMethod":
|
||||||
|
p["extrusionMethod"] = ExtrusionMethod.__dict__[p["extrusionMethod"]]
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
def genmesh():
|
def genmesh(config):
|
||||||
|
|
||||||
logger.info(f"""genmesh:
|
logger.info(f"""genmesh:
|
||||||
structure type:\t{ config.structure }
|
structure type:\t{ config.structure }
|
||||||
coefficient:\t{ config.parameters.theta }
|
coefficient:\t{ config.geometry.theta }
|
||||||
fillet:\t{ config.geometry.fillet }
|
fillet:\t{ config.geometry.fillet }
|
||||||
flow direction:\t{ config.geometry.direction }""")
|
flow direction:\t{ config.geometry.direction }""")
|
||||||
|
|
||||||
@ -60,7 +90,7 @@ def genmesh():
|
|||||||
##
|
##
|
||||||
geompy = getGeom()
|
geompy = getGeom()
|
||||||
structure = globals().get(config.structure)
|
structure = globals().get(config.structure)
|
||||||
shape, groups = structure(config.parameters.theta, config.geometry.fillet, config.geometry.direction)
|
shape, groups = structure(config.geometry.theta, config.geometry.fillet, config.geometry.direction)
|
||||||
[length, surfaceArea, volume] = geompy.BasicProperties(shape, theTolerance = 1e-06)
|
[length, surfaceArea, volume] = geompy.BasicProperties(shape, theTolerance = 1e-06)
|
||||||
|
|
||||||
logger.info(f"""shape:
|
logger.info(f"""shape:
|
||||||
@ -71,31 +101,87 @@ def genmesh():
|
|||||||
###
|
###
|
||||||
# Mesh
|
# Mesh
|
||||||
##
|
##
|
||||||
facesToIgnore = []
|
config = dict(config)
|
||||||
|
|
||||||
|
mconfig = defaultParameters(**config["mesh"])
|
||||||
|
|
||||||
|
lengths = [ geompy.BasicProperties(edge)[0] for edge in geompy.SubShapeAll(shape, geompy.ShapeType["EDGE"]) ]
|
||||||
|
meanSize = sum(lengths) / len(lengths)
|
||||||
|
mconfig["maxSize"] = meanSize
|
||||||
|
mconfig["minSize"] = meanSize * 1e-1
|
||||||
|
mconfig["chordalError"] = mconfig["maxSize"] / 2
|
||||||
|
|
||||||
|
faces = []
|
||||||
for group in groups:
|
for group in groups:
|
||||||
if group.GetName() in ["inlet", "outlet"]:
|
if group.GetName() in mconfig["facesToIgnore"]:
|
||||||
facesToIgnore.append(group)
|
faces.append(group)
|
||||||
|
|
||||||
meshParameters = config.mesh
|
mconfig["faces"] = faces
|
||||||
meshParameters.facesToIgnore = facesToIgnore
|
|
||||||
meshParameters.extrusionMethod = smeshBuilder.SURF_OFFSET_SMOOTH
|
mesh = Mesh(shape)
|
||||||
|
mesh.Tetrahedron(**mconfig)
|
||||||
|
|
||||||
|
if mconfig["viscousLayers"]:
|
||||||
|
mesh.ViscousLayers(**mconfig)
|
||||||
|
|
||||||
mesh = meshCreate(shape, meshParameters, groups)
|
config["mesh"].update(mconfig)
|
||||||
returncode = meshCompute(mesh, groups)
|
smconfigs = config["mesh"]["submesh"]
|
||||||
|
|
||||||
if returncode == 0:
|
for name in smconfigs.keys():
|
||||||
config.status.mesh = True
|
for group in groups:
|
||||||
|
if group.GetName() == name:
|
||||||
|
subshape = group
|
||||||
|
|
||||||
|
smconfig = defaultParameters(**smconfigs[name])
|
||||||
|
smconfig["maxSize"] = meanSize * 1e-1
|
||||||
|
smconfig["minSize"] = meanSize * 1e-3
|
||||||
|
smconfig["chordalError"] = smconfig["minSize"] * 1e+1
|
||||||
|
|
||||||
|
mesh.Triangle(subshape, **smconfig)
|
||||||
|
config["mesh"]["submesh"][name].update(smconfig)
|
||||||
|
|
||||||
with open(CONFIG, "w") as io:
|
|
||||||
toml.dump(dict(config), io)
|
|
||||||
|
|
||||||
meshStats(mesh)
|
returncode, errors = mesh.compute()
|
||||||
meshExport(mesh, os.path.join(CASE, "mesh.unv"))
|
|
||||||
|
if not returncode:
|
||||||
|
config["status"]["mesh"] = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.error(errors)
|
||||||
|
|
||||||
|
with open(CONFIG, "w") as io:
|
||||||
|
toml.dump(config, io)
|
||||||
|
|
||||||
|
mesh.removePyramids()
|
||||||
|
mesh.assignGroups()
|
||||||
|
|
||||||
|
mesh.exportUNV(os.path.join(CASE, "mesh.unv"))
|
||||||
|
|
||||||
|
stats = ""
|
||||||
|
for k, v in mesh.stats().items():
|
||||||
|
stats += f"{ k }:\t\t{ v }\n"
|
||||||
|
|
||||||
|
logger.info(f"mesh stats:\n{ stats[ :-1] }")
|
||||||
|
|
||||||
salome.salome_close()
|
salome.salome_close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
genmesh()
|
CONFIG = os.path.join(CASE, "task.toml")
|
||||||
|
config = struct(toml.load(CONFIG))
|
||||||
|
|
||||||
|
LOG = os.path.join(ROOT, "logs")
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level = logging.INFO,
|
||||||
|
format = config.logger.format,
|
||||||
|
handlers = [
|
||||||
|
logging.StreamHandler(),
|
||||||
|
logging.FileHandler(f"{ LOG }/{ config.logger.name }.log")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(config.logger.name)
|
||||||
|
|
||||||
|
genmesh(config)
|
||||||
|
|
||||||
|
|
||||||
|
284
salomepl/mesh.py
284
salomepl/mesh.py
@ -2,201 +2,151 @@ import SMESH
|
|||||||
from salome.smesh import smeshBuilder
|
from salome.smesh import smeshBuilder
|
||||||
smesh = smeshBuilder.New()
|
smesh = smeshBuilder.New()
|
||||||
|
|
||||||
import logging
|
import enum
|
||||||
logger = logging.getLogger("anisotropy")
|
|
||||||
|
class Fineness(enum.Enum):
|
||||||
|
VeryCoarse = 0
|
||||||
|
Coarse = 1
|
||||||
|
Moderate = 2
|
||||||
|
Fine = 3
|
||||||
|
VeryFine = 4
|
||||||
|
Custom = 5
|
||||||
|
|
||||||
|
class ExtrusionMethod(object):
|
||||||
|
SURF_OFFSET_SMOOTH = smeshBuilder.SURF_OFFSET_SMOOTH
|
||||||
|
FACE_OFFSET = smeshBuilder.FACE_OFFSET
|
||||||
|
NODE_OFFSET = smeshBuilder.NODE_OFFSET
|
||||||
|
|
||||||
def getSmesh():
|
def getSmesh():
|
||||||
return smesh
|
return smesh
|
||||||
|
|
||||||
|
def updateParams(old, new: dict):
|
||||||
|
old.SetMaxSize(new.get("maxSize") if new.get("maxSize") else old.GetMaxSize())
|
||||||
|
old.SetMinSize(new.get("minSize") if new.get("minSize") else old.GetMinSize())
|
||||||
|
|
||||||
def meshCreate(shape, parameters, groups): #fineness, parameters, viscousLayers = None):
|
old.SetFineness(new.get("fineness") if new.get("fineness") else old.GetFineness())
|
||||||
"""
|
old.SetGrowthRate(new.get("growthRate") if new.get("growthRate") else old.GetGrowthRate())
|
||||||
Creates a mesh from a geometry.
|
old.SetNbSegPerEdge(new.get("nbSegPerEdge") if new.get("nbSegPerEdge") else old.GetNbSegPerEdge())
|
||||||
|
old.SetNbSegPerRadius(new.get("nbSegPerRadius") if new.get("nbSegPerRadius") else old.GetNbSegPerRadius())
|
||||||
|
|
||||||
Parameters:
|
old.SetChordalErrorEnabled(new.get("chordalErrorEnabled") if new.get("chordalErrorEnabled") else old.GetChordalErrorEnabled())
|
||||||
fineness (int): Fineness of mesh.
|
old.SetChordalError(new.get("chordalError") if new.get("chordalError") else old.GetChordalError())
|
||||||
|
|
||||||
0 - Very coarse,
|
old.SetSecondOrder(new.get("secondOrder") if new.get("secondOrder") else old.GetSecondOrder())
|
||||||
1 - Coarse,
|
old.SetOptimize(new.get("optimize") if new.get("optimize") else old.GetOptimize())
|
||||||
2 - Moderate,
|
old.SetQuadAllowed(new.get("quadAllowed") if new.get("quadAllowed") else old.GetQuadAllowed())
|
||||||
3 - Fine,
|
old.SetUseSurfaceCurvature(new.get("useSurfaceCurvature") if new.get("useSurfaceCurvature") else old.GetUseSurfaceCurvature())
|
||||||
4 - Very fine.
|
old.SetFuseEdges(new.get("fuseEdges") if new.get("fuseEdges") else old.GetFuseEdges())
|
||||||
|
old.SetCheckChartBoundary(new.get("checkChartBoundary") if new.get("checkChartBoundary") else old.GetCheckChartBoundary())
|
||||||
|
|
||||||
Returns:
|
|
||||||
Configured instance of class <SMESH.SMESH_Mesh>, containig the parameters and boundary groups.
|
|
||||||
|
|
||||||
"""
|
class Mesh(object):
|
||||||
###
|
def __init__(self, shape, name = ""):
|
||||||
# Netgen
|
self.name = name if name else shape.GetName()
|
||||||
##
|
self.mesh = smesh.Mesh(shape, self.name)
|
||||||
Fineness = {
|
self.geom = shape
|
||||||
0: "Very coarse",
|
self.algo = None
|
||||||
1: "Coarse",
|
self.params = None
|
||||||
2: "Moderate",
|
self.viscousLayers = None
|
||||||
3: "Fine",
|
|
||||||
4: "Very fine",
|
|
||||||
5: "Custom"
|
|
||||||
}[parameters.fineness]
|
|
||||||
|
|
||||||
# Mesh
|
self.submeshes = []
|
||||||
mesh = smesh.Mesh(shape)
|
|
||||||
netgen = mesh.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D)
|
|
||||||
|
|
||||||
# Parameters
|
|
||||||
param = netgen.Parameters()
|
|
||||||
param.SetMinSize(parameters.minSize)
|
|
||||||
param.SetMaxSize(parameters.maxSize)
|
|
||||||
param.SetFineness(parameters.fineness)
|
|
||||||
|
|
||||||
if parameters.fineness == 5:
|
def Tetrahedron(self, **kwargs):
|
||||||
param.SetGrowthRate(parameters.growthRate)
|
self.algo = self.mesh.Tetrahedron(algo = smeshBuilder.NETGEN_1D2D3D)
|
||||||
param.SetNbSegPerEdge(parameters.nbSegPerEdge)
|
self.params = self.algo.Parameters()
|
||||||
param.SetNbSegPerRadius(parameters.nbSegPerRadius)
|
|
||||||
|
|
||||||
|
|
||||||
param.SetChordalErrorEnabled(parameters.chordalErrorEnabled)
|
|
||||||
param.SetChordalError(parameters.chordalError)
|
|
||||||
|
|
||||||
param.SetSecondOrder(parameters.secondOrder)
|
self.params = updateParams(self.params, kwargs)
|
||||||
param.SetOptimize(parameters.optimize)
|
|
||||||
param.SetQuadAllowed(parameters.quadAllowed)
|
|
||||||
|
|
||||||
param.SetUseSurfaceCurvature(parameters.useSurfaceCurvature)
|
|
||||||
param.SetFuseEdges(parameters.fuseEdges)
|
|
||||||
param.SetCheckChartBoundary(parameters.checkChartBoundary)
|
|
||||||
|
|
||||||
|
|
||||||
logger.info("""meshCreate:
|
|
||||||
fineness:\t{}
|
|
||||||
min size:\t{}
|
|
||||||
max size:\t{}
|
|
||||||
growth rate:\t{}
|
|
||||||
nb segs per edge:\t{}
|
|
||||||
nb segs per radius:\t{}
|
|
||||||
limit size by surface curvature:\t{}
|
|
||||||
quad-dominated:\t{}
|
|
||||||
second order:\t{}
|
|
||||||
optimize:\t{}""".format(
|
|
||||||
Fineness, param.GetMinSize(), param.GetMaxSize(),
|
|
||||||
param.GetGrowthRate(), param.GetNbSegPerEdge(), param.GetNbSegPerRadius(),
|
|
||||||
True if param.GetUseSurfaceCurvature() else False,
|
|
||||||
True if param.GetQuadAllowed() else False,
|
|
||||||
True if param.GetSecondOrder() else False,
|
|
||||||
True if param.GetOptimize() else False))
|
|
||||||
|
|
||||||
|
def ViscousLayers(self,
|
||||||
###
|
thickness = 1,
|
||||||
# Local sizes
|
numberOfLayers = 1,
|
||||||
##
|
stretchFactor = 0,
|
||||||
for group in groups:
|
faces = [],
|
||||||
localSize = parameters.localSizeOnShape.__dict__.get(group)
|
isFacesToIgnore = True,
|
||||||
|
extrMethod = ExtrusionMethod.SURF_OFFSET_SMOOTH,
|
||||||
if localSize:
|
**kwargs
|
||||||
param.SetLocalSizeOnShape(group, localSize)
|
):
|
||||||
|
|
||||||
###
|
self.viscousLayers = self.algo.ViscousLayers(
|
||||||
# Viscous layers
|
thickness,
|
||||||
##
|
numberOfLayers,
|
||||||
if parameters.viscousLayers:
|
stretchFactor,
|
||||||
vlayer = netgen.ViscousLayers(
|
faces,
|
||||||
parameters.thickness,
|
isFacesToIgnore,
|
||||||
parameters.numberOfLayers,
|
extrMethod
|
||||||
parameters.stretchFactor,
|
|
||||||
parameters.facesToIgnore,
|
|
||||||
parameters.isFacesToIgnore,
|
|
||||||
parameters.extrusionMethod
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info("""meshCreate:
|
def Triangle(self, subshape, **kwargs):
|
||||||
viscous layers:
|
submesh = Submesh(self.mesh, subshape)
|
||||||
thickness:\t{}
|
submesh.algo = self.mesh.Triangle(algo = smeshBuilder.NETGEN_1D2D, geom = subshape)
|
||||||
number:\t{}
|
submesh.mesh = submesh.algo.subm
|
||||||
stretch factor:\t{}""".format(
|
submesh.params = submesh.algo.Parameters()
|
||||||
parameters.thickness,
|
|
||||||
parameters.numberOfLayers,
|
|
||||||
parameters.stretchFactor))
|
|
||||||
|
|
||||||
else:
|
submesh.params = updateParams(submesh.params, kwargs)
|
||||||
logger.info("""meshCreate:
|
|
||||||
viscous layers: false""")
|
|
||||||
|
|
||||||
return mesh
|
self.submeshes.append(submesh)
|
||||||
|
|
||||||
|
|
||||||
def meshCompute(mobj, groups):
|
|
||||||
"""Compute the mesh."""
|
|
||||||
status = mobj.Compute()
|
|
||||||
|
|
||||||
if status:
|
def assignGroups(self, withPrefix = True):
|
||||||
logger.info("meshCompute: computed")
|
prefix = "smesh_" if withPrefix else ""
|
||||||
|
|
||||||
###
|
for group in self.mesh.geompyD.GetGroups(self.geom):
|
||||||
# Post computing
|
if group.GetName():
|
||||||
##
|
self.mesh.GroupOnGeom(group, f"{ prefix }{ group.GetName() }", SMESH.FACE)
|
||||||
if mobj.NbPyramids() > 0:
|
|
||||||
logger.info(f"meshCompute: detected {mobj.NbPyramids()} pyramids: splitting volumes into tetrahedrons")
|
def compute(self):
|
||||||
|
isDone = self.mesh.Compute()
|
||||||
|
returncode = int(not isDone)
|
||||||
|
errors = self.mesh.GetComputeErrors()
|
||||||
|
|
||||||
|
return returncode, errors
|
||||||
|
|
||||||
|
def stats(self):
|
||||||
|
return {
|
||||||
|
"elements": self.mesh.NbElements(),
|
||||||
|
"edges": self.mesh.NbEdges(),
|
||||||
|
"faces": self.mesh.NbFaces(),
|
||||||
|
"volumes": self.mesh.NbVolumes(),
|
||||||
|
"tetrahedrons": self.mesh.NbTetras(),
|
||||||
|
"prisms": self.mesh.NbPrisms(),
|
||||||
|
"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):
|
||||||
|
if self.mesh.NbPyramids() > 0:
|
||||||
pyramidCriterion = smesh.GetCriterion(
|
pyramidCriterion = smesh.GetCriterion(
|
||||||
SMESH.VOLUME,
|
SMESH.VOLUME,
|
||||||
SMESH.FT_ElemGeomType,
|
SMESH.FT_ElemGeomType,
|
||||||
SMESH.FT_Undefined,
|
SMESH.FT_Undefined,
|
||||||
SMESH.Geom_PYRAMID
|
SMESH.Geom_PYRAMID
|
||||||
)
|
)
|
||||||
pyramidGroup = mobj.MakeGroupByCriterion("pyramids", pyramidCriterion)
|
pyramidGroup = self.mesh.MakeGroupByCriterion("pyramids", pyramidCriterion)
|
||||||
pyramidVolumes = mobj.GetIDSource(pyramidGroup.GetIDs(), SMESH.VOLUME)
|
pyramidVolumes = self.mesh.GetIDSource(pyramidGroup.GetIDs(), SMESH.VOLUME)
|
||||||
|
|
||||||
mobj.SplitVolumesIntoTetra(pyramidVolumes, smesh.Hex_5Tet)
|
self.mesh.SplitVolumesIntoTetra(pyramidVolumes, smesh.Hex_5Tet)
|
||||||
|
|
||||||
mobj.RemoveGroup(pyramidGroup)
|
self.mesh.RemoveGroup(pyramidGroup)
|
||||||
mobj.RenumberElements()
|
self.mesh.RenumberElements()
|
||||||
|
|
||||||
###
|
|
||||||
# Groups
|
|
||||||
##
|
|
||||||
for group in groups:
|
|
||||||
mobj.GroupOnGeom(group, f"{ group.GetName() }_", SMESH.FACE)
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.warning("meshCompute: not computed")
|
|
||||||
|
|
||||||
return not status
|
|
||||||
|
|
||||||
|
|
||||||
def meshStats(mobj):
|
|
||||||
"""
|
|
||||||
Print mesh information.
|
|
||||||
"""
|
|
||||||
stats = {
|
|
||||||
"Elements": mobj.NbElements(),
|
|
||||||
"Edges": mobj.NbEdges(),
|
|
||||||
"Faces": mobj.NbFaces(),
|
|
||||||
"Volumes": mobj.NbVolumes(),
|
|
||||||
"Tetrahedrons": mobj.NbTetras(),
|
|
||||||
"Prisms": mobj.NbPrisms(),
|
|
||||||
"Pyramids": mobj.NbPyramids()
|
|
||||||
}
|
|
||||||
info = "meshStats:\n"
|
|
||||||
|
|
||||||
for key in stats:
|
class Submesh(object):
|
||||||
info += f"\t{key}:\t{stats[key]}\n"
|
def __init__(self, father, subshape, name = ""):
|
||||||
|
self.name = name if name else subshape.GetName()
|
||||||
logger.info(info)
|
self.mesh = None
|
||||||
|
self.geom = subshape
|
||||||
|
self.algo = None
|
||||||
def meshExport(mobj, path):
|
self.params = None
|
||||||
"""
|
|
||||||
Export the mesh in a file in UNV format.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
path (string): full path to the expected directory.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
mobj.ExportUNV(path)
|
|
||||||
|
|
||||||
logger.info("""meshExport:
|
|
||||||
format:\t{}""".format("unv"))
|
|
||||||
|
|
||||||
except:
|
|
||||||
logger.error("""meshExport: Cannot export.""")
|
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ def startServer(port):
|
|||||||
return p
|
return p
|
||||||
|
|
||||||
def salomeVersion() -> str:
|
def salomeVersion() -> str:
|
||||||
return "Salome 9.6.0"
|
return "Salome 9.7.0 MPI"
|
||||||
|
|
||||||
def runExecute(port: int, scriptpath: str, *args) -> int:
|
def runExecute(port: int, scriptpath: str, *args) -> int:
|
||||||
|
|
||||||
cmd = ["salome", "start", "--shutdown-servers=1", "--port", str(port), "-t",
|
cmd = ["salome-9.7.0-mpi", "start", "--shutdown-servers=1", "--port", str(port), "-t",
|
||||||
scriptpath, "args:{}".format(", ".join([str(arg) for arg in args]))]
|
scriptpath, "args:{}".format(", ".join([str(arg) for arg in args]))]
|
||||||
|
|
||||||
logger.info("salome: {}".format(cmd[1 : 6]))
|
logger.info("salome: {}".format(cmd[1 : 6]))
|
||||||
|
Loading…
Reference in New Issue
Block a user