Mod: improved geometry construction by adding flexibility

New: StructureGeometry class
Fix: fixed invalid shapes (external edges on shapes, etc)
New: issues list
This commit is contained in:
L-Nafaryus 2021-10-06 22:15:05 +05:00
parent eda9a56a28
commit 1374ce0000
No known key found for this signature in database
GPG Key ID: C76D8DCD2727DBB7
8 changed files with 459 additions and 316 deletions

16
ISSUES.rst Normal file
View File

@ -0,0 +1,16 @@
List of known issues
====================
* ``Click`` // can't hide subcommand from help, ``hidden = True`` doesn't work.
* ``ideasUnvToFoam`` // can't import mesh with '-case' flag (temporary used ``os.chdir``).
* ``salome`` // removes commas from string list (example: "[1, 0, 0]") in the cli arguments.
* ``geompyBuilder`` // missing groups from father object in study tree.
* ``Anisotropy`` // writes ``Done`` status for failed operations (detected on mesh operations).
* ``Database`` // ``WHERE ..`` peewee operation error on update function with all control parameters (type, direction, theta) but fields are written to the database correctly.
* ``Database`` // awkward arguments and their order in the class init function.
* ``Mesh`` // outdated class.
* ``genmesh`` // awkward function, move precalculation parameters to Mesh class.
* ``Anisotropy`` // outdated functions for porosity and etc.
* ``Anisotropy`` // not sufficiently used variable ``env``.
* ``openfoam`` // outdated module, add functionality for FoamFile parsing, ``postProcess`` utility?.
* ``Database`` // add flexibility.

View File

@ -303,9 +303,9 @@ class Anisotropy(object):
faceCentered = FaceCentered faceCentered = FaceCentered
)[p["structure"]["type"]] )[p["structure"]["type"]]
shapeGeometry = structure(**p["structure"]) shapeGeometry = structure(**p["structure"])
shape, groups = shapeGeometry.build() shapeGeometry.build()
[length, surfaceArea, volume] = geompy.BasicProperties(shape, theTolerance = 1e-06) [length, surfaceArea, volume] = geompy.BasicProperties(shapeGeometry.shape, theTolerance = 1e-06)
### ###
@ -316,7 +316,7 @@ class Anisotropy(object):
mp = p["mesh"] mp = p["mesh"]
lengths = [ lengths = [
geompy.BasicProperties(edge)[0] for edge in geompy.SubShapeAll(shape, geompy.ShapeType["EDGE"]) geompy.BasicProperties(edge)[0] for edge in geompy.SubShapeAll(shapeGeometry.shape, geompy.ShapeType["EDGE"])
] ]
meanSize = sum(lengths) / len(lengths) meanSize = sum(lengths) / len(lengths)
mp["maxSize"] = meanSize mp["maxSize"] = meanSize
@ -324,12 +324,12 @@ class Anisotropy(object):
mp["chordalError"] = mp["maxSize"] / 2 mp["chordalError"] = mp["maxSize"] / 2
faces = [] faces = []
for group in groups: for group in shapeGeometry.groups:
if group.GetName() in mp["facesToIgnore"]: if group.GetName() in mp["facesToIgnore"]:
faces.append(group) faces.append(group)
mesh = salomepl.mesh.Mesh(shape) mesh = salomepl.mesh.Mesh(shapeGeometry.shape)
mesh.Tetrahedron(**mp) mesh.Tetrahedron(**mp)
if mp["viscousLayers"]: if mp["viscousLayers"]:
@ -339,7 +339,7 @@ class Anisotropy(object):
smp = p["submesh"] smp = p["submesh"]
for submesh in smp: for submesh in smp:
for group in groups: for group in shapeGeometry.groups:
if submesh["name"] == group.GetName(): if submesh["name"] == group.GetName():
subshape = group subshape = group

View File

@ -2,26 +2,22 @@
# 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.structure import StructureGeometry
from math import pi, sqrt from math import pi, sqrt
from anisotropy.salomepl import geometry import logging
class BodyCentered(object): class BodyCentered(StructureGeometry):
def __init__(self, **kwargs): @property
def name(self):
self.direction = kwargs.get("direction", [1, 0, 0]) """Shape name.
self.theta = kwargs.get("theta", 0.01) """
self.L = kwargs.get("L", 1) return "bodyCentered"
self.r0 = kwargs.get("r0", self.L * sqrt(3) / 4)
self.radius = kwargs.get("radius", self.r0 / (1 - self.theta))
self.filletsEnabled = kwargs.get("filletsEnabled", False)
self.fillets = kwargs.get("fillets", 0)
self.volumeCell = None
@property
def L(self):
return self.r0 * 4 / sqrt(3)
def build(self): def build(self):
geompy = geometry.getGeom()
### ###
# Pore Cell # Pore Cell
## ##
@ -42,7 +38,7 @@ class BodyCentered(object):
zh = height zh = height
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
spos1 = (0, 0, 0) spos1 = (0, 0, 0)
spos2 = (0, 0, 0) spos2 = (0, 0, 0)
@ -50,40 +46,41 @@ class BodyCentered(object):
# Bounding box # Bounding box
## ##
if self.direction == [1, 0, 0]: if self.direction == [1, 0, 0]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
sk.addPointsAbsolute(0, yw, zh) sk.addPointsAbsolute(0, yw, zh)
sk.addPointsAbsolute(xl, 0, zh) sk.addPointsAbsolute(xl, 0, zh)
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, diag) poreCell = self.geo.MakePrismVecH(inletface, vecflow, diag)
elif self.direction == [0, 0, 1]: elif self.direction == [0, 0, 1]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
sk.addPointsAbsolute(2 * xl, yw, 0) sk.addPointsAbsolute(2 * xl, yw, 0)
sk.addPointsAbsolute(xl, 2 * yw, 0) sk.addPointsAbsolute(xl, 2 * yw, 0)
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, zh) poreCell = self.geo.MakePrismVecH(inletface, vecflow, zh)
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06)
inletface = geompy.MakeScaleTransform(inletface, oo, scale) self.shapeCell = poreCell
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -113,33 +110,33 @@ class BodyCentered(object):
point.append((self.L / 3 + xl, self.L / 3 + yw, 4 * self.L / 3 + zh)) point.append((self.L / 3 + xl, self.L / 3 + yw, 4 * self.L / 3 + zh))
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
spos1 = (0, 0, 0) spos1 = (0, 0, 0)
spos2 = (0, 0, 0) spos2 = (0, 0, 0)
### ###
# Bounding box # Bounding box
## ##
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
for p in point: for p in point:
sk.addPointsAbsolute(*p) sk.addPointsAbsolute(*p)
inletface = geompy.MakeFaceWires([sk.wire()], False) inletface = self.geo.MakeFaceWires([sk.wire()], False)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, self.L * sqrt(3)) poreCell = self.geo.MakePrismVecH(inletface, vecflow, self.L * sqrt(3))
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06) self.shapeCell = poreCell
inletface = geompy.MakeScaleTransform(inletface, oo, scale) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale) poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -153,78 +150,63 @@ class BodyCentered(object):
### ###
# Grains # Grains
## ##
ox = geompy.MakeVectorDXDYDZ(1, 0, 0) ox = self.geo.MakeVectorDXDYDZ(1, 0, 0)
oy = geompy.MakeVectorDXDYDZ(0, 1, 0) oy = self.geo.MakeVectorDXDYDZ(0, 1, 0)
oz = geompy.MakeVectorDXDYDZ(0, 0, 1) oz = self.geo.MakeVectorDXDYDZ(0, 0, 1)
xy = geompy.MakeVectorDXDYDZ(1, 1, 0) xy = self.geo.MakeVectorDXDYDZ(1, 1, 0)
xmy = geompy.MakeVectorDXDYDZ(1, -1, 0) xmy = self.geo.MakeVectorDXDYDZ(1, -1, 0)
grain = geompy.MakeSpherePntR(geompy.MakeVertex(*spos1), self.radius) grain = self.geo.MakeSpherePntR(self.geo.MakeVertex(*spos1), self.radius)
lattice1 = geompy.MakeMultiTranslation2D(grain, ox, self.L, xn, oy, self.L, yn) lattice1 = self.geo.MakeMultiTranslation2D(grain, ox, self.L, xn, oy, self.L, yn)
lattice1 = geompy.MakeMultiTranslation1D(lattice1, oz, self.L, zn) lattice1 = self.geo.MakeMultiTranslation1D(lattice1, oz, self.L, zn)
#grain = geompy.MakeSpherePntR(geompy.MakeVertex(*spos2), radius) #grain = self.geo.MakeSpherePntR(self.geo.MakeVertex(*spos2), radius)
#lattice2 = geompy.MakeMultiTranslation2D(grain, xy, length, xn + 1, xmy, length, yn + 1) #lattice2 = self.geo.MakeMultiTranslation2D(grain, xy, length, xn + 1, xmy, length, yn + 1)
#lattice2 = geompy.MakeMultiTranslation1D(lattice2, oz, L, zn) #lattice2 = self.geo.MakeMultiTranslation1D(lattice2, oz, L, zn)
lattice2 = geompy.MakeTranslation(lattice1, 0.5 * self.L, 0.5 * self.L, 0.5 * self.L) lattice2 = self.geo.MakeTranslation(lattice1, 0.5 * self.L, 0.5 * self.L, 0.5 * self.L)
grains = geompy.ExtractShapes(lattice1, geompy.ShapeType["SOLID"], True) grains = self.geo.ExtractShapes(lattice1, self.geo.ShapeType["SOLID"], True)
grains += geompy.ExtractShapes(lattice2, geompy.ShapeType["SOLID"], True) grains += self.geo.ExtractShapes(lattice2, self.geo.ShapeType["SOLID"], True)
grains = geompy.MakeFuseList(grains, False, False) grains = self.geo.MakeFuseList(grains, False, False)
grains = geompy.MakeScaleTransform(grains, oo, scale) grains = self.geo.MakeScaleTransform(grains, oo, scale)
grainsOrigin = None grainsOrigin = None
if self.filletsEnabled: if self.filletsEnabled:
grainsOrigin = geompy.MakeScaleTransform(grains, oo, 1 / scale) grainsOrigin = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
grains = geompy.MakeFilletAll(grains, self.fillets * scale) grains = self.geo.MakeFilletAll(grains, self.fillets * scale)
self.shapeLattice = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
###
# Shape
##
self.shape = self.geo.MakeCutList(poreCell, [grains])
self.shape = self.geo.MakeScaleTransform(self.shape, oo, 1 / scale, theName = self.name)
isValid, _ = self.isValid()
if not isValid:
self.heal()
### ###
# Groups # Groups
#
# inlet, outlet, simetry(N), strips(optional), wall
## ##
shape = geompy.MakeCutList(poreCell, [grains]) self.groups = []
shape = geompy.MakeScaleTransform(shape, oo, 1 / scale, theName = "bodyCentered") groupAll = self.createGroupAll(self.shape)
sall = geompy.CreateGroup(shape, geompy.ShapeType["FACE"]) self.groups.append(self.createGroup(self.shape, inletface, "inlet", [grains], 1 / scale))
geompy.UnionIDs(sall, self.groups.append(self.createGroup(self.shape, outletface, "outlet", [grains], 1 / scale))
geompy.SubShapeAllIDs(shape, geompy.ShapeType["FACE"]))
inlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "inlet") for n, face in enumerate(symetryface):
inletshape = geompy.MakeCutList(inletface, [grains]) self.groups.append(self.createGroup(self.shape, face, f"symetry{ n }", [grains], 1 / scale))
inletshape = geompy.MakeScaleTransform(inletshape, oo, 1 / scale)
geompy.UnionList(inlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, inletshape, True), geompy.ShapeType["FACE"]))
outlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "outlet")
outletshape = geompy.MakeCutList(outletface, [grains])
outletshape = geompy.MakeScaleTransform(outletshape, oo, 1 / scale)
geompy.UnionList(outlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, outletshape, True), geompy.ShapeType["FACE"]))
symetry = []
for (n, face) in enumerate(symetryface):
name = "symetry" + str(n)
symetry.append(geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = name))
symetryshape = geompy.MakeCutList(face, [grains])
symetryshape = geompy.MakeScaleTransform(symetryshape, oo, 1 / scale)
geompy.UnionList(symetry[n], geompy.SubShapeAll(
geompy.GetInPlace(shape, symetryshape, True), geompy.ShapeType["FACE"]))
groups = []
groups.append(inlet)
groups.append(outlet)
groups.extend(symetry)
if self.filletsEnabled: if self.filletsEnabled:
strips = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "strips") shapeShell = self.geo.ExtractShapes(self.shape, self.geo.ShapeType["SHELL"], True)[0]
shapeShell = geompy.ExtractShapes(shape, geompy.ShapeType["SHELL"], True) self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin]))
stripsShape = geompy.MakeCutList(shapeShell[0], groups + [grainsOrigin])
geompy.UnionList(strips, geompy.SubShapeAll(
geompy.GetInPlace(shape, stripsShape, True), geompy.ShapeType["FACE"]))
groups.append(strips)
wall = geompy.CutListOfGroups([sall], groups, theName = "wall") self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))
groups.append(wall)
return shape, groups

View File

@ -2,26 +2,21 @@
# 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.structure import StructureGeometry
from math import pi, sqrt from math import pi, sqrt
from anisotropy.salomepl import geometry
class FaceCentered(object): class FaceCentered(StructureGeometry):
def __init__(self, **kwargs): @property
def name(self):
self.direction = kwargs.get("direction", [1, 0, 0]) """Shape name.
self.theta = kwargs.get("theta", 0.01) """
self.L = kwargs.get("L", 1) return "faceCentered"
self.r0 = kwargs.get("r0", self.L * sqrt(2) / 4)
self.radius = kwargs.get("radius", self.r0 / (1 - self.theta))
self.filletsEnabled = kwargs.get("filletsEnabled", False)
self.fillets = kwargs.get("fillets", 0)
self.volumeCell = None
@property
def L(self):
return self.r0 * 4 / sqrt(2)
def build(self): def build(self):
geompy = geometry.getGeom()
### ###
# Pore Cell # Pore Cell
## ##
@ -42,7 +37,7 @@ class FaceCentered(object):
zh = width zh = width
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
spos1 = (-width * (xn - 1), 0, -width * (zn - 2)) spos1 = (-width * (xn - 1), 0, -width * (zn - 2))
spos2 = (-width * xn, 0, -width * (zn - 1)) spos2 = (-width * xn, 0, -width * (zn - 1))
@ -50,40 +45,40 @@ class FaceCentered(object):
# Bounding box # Bounding box
## ##
if self.direction == [1, 0, 0]: if self.direction == [1, 0, 0]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(0, 0, -zh) sk.addPointsAbsolute(0, 0, -zh)
sk.addPointsAbsolute(-xl, yw, -zh) sk.addPointsAbsolute(-xl, yw, -zh)
sk.addPointsAbsolute(-xl, yw, zh) sk.addPointsAbsolute(-xl, yw, zh)
sk.addPointsAbsolute(0, 0, zh) sk.addPointsAbsolute(0, 0, zh)
sk.addPointsAbsolute(0, 0, -zh) sk.addPointsAbsolute(0, 0, -zh)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, length) poreCell = self.geo.MakePrismVecH(inletface, vecflow, length)
elif self.direction == [0, 0, 1]: elif self.direction == [0, 0, 1]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(0, 0, -zh) sk.addPointsAbsolute(0, 0, -zh)
sk.addPointsAbsolute(xl, yw, -zh) sk.addPointsAbsolute(xl, yw, -zh)
sk.addPointsAbsolute(0, 2 * yw, -zh) sk.addPointsAbsolute(0, 2 * yw, -zh)
sk.addPointsAbsolute(-xl, yw, -zh) sk.addPointsAbsolute(-xl, yw, -zh)
sk.addPointsAbsolute(0, 0, -zh) sk.addPointsAbsolute(0, 0, -zh)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, 2 * zh) poreCell = self.geo.MakePrismVecH(inletface, vecflow, 2 * zh)
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06) self.shapeCell = poreCell
inletface = geompy.MakeScaleTransform(inletface, oo, scale) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale) poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -113,33 +108,33 @@ class FaceCentered(object):
point.append((-2 * width / 3 + xl, -2 * width / 3 + yw, width / 3 + zh)) point.append((-2 * width / 3 + xl, -2 * width / 3 + yw, width / 3 + zh))
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
spos1 = (-width * (xn - 1), 0, -width * (zn - 2)) spos1 = (-width * (xn - 1), 0, -width * (zn - 2))
spos2 = (-width * xn, 0, -width * (zn - 1)) spos2 = (-width * xn, 0, -width * (zn - 1))
### ###
# Bounding box # Bounding box
## ##
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
for p in point: for p in point:
sk.addPointsAbsolute(*p) sk.addPointsAbsolute(*p)
inletface = geompy.MakeFaceWires([sk.wire()], False) inletface = self.geo.MakeFaceWires([sk.wire()], False)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, self.L * sqrt(3)) poreCell = self.geo.MakePrismVecH(inletface, vecflow, self.L * sqrt(3))
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06) self.shapeCell = poreCell
inletface = geompy.MakeScaleTransform(inletface, oo, scale) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale) poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -153,78 +148,60 @@ class FaceCentered(object):
### ###
# Grains # Grains
## ##
ox = geompy.MakeVectorDXDYDZ(1, 0, 0) ox = self.geo.MakeVectorDXDYDZ(1, 0, 0)
oy = geompy.MakeVectorDXDYDZ(0, 1, 0) oy = self.geo.MakeVectorDXDYDZ(0, 1, 0)
oz = geompy.MakeVectorDXDYDZ(0, 0, 1) oz = self.geo.MakeVectorDXDYDZ(0, 0, 1)
xy = geompy.MakeVectorDXDYDZ(1, 1, 0) xy = self.geo.MakeVectorDXDYDZ(1, 1, 0)
xmy = geompy.MakeVectorDXDYDZ(1, -1, 0) xmy = self.geo.MakeVectorDXDYDZ(1, -1, 0)
grain = geompy.MakeSpherePntR(geompy.MakeVertex(*spos1), self.radius) grain = self.geo.MakeSpherePntR(self.geo.MakeVertex(*spos1), self.radius)
lattice1 = geompy.MakeMultiTranslation2D(grain, xy, length, xn, xmy, length, yn) lattice1 = self.geo.MakeMultiTranslation2D(grain, xy, length, xn, xmy, length, yn)
lattice1 = geompy.MakeMultiTranslation1D(lattice1, oz, self.L, zn - 1) lattice1 = self.geo.MakeMultiTranslation1D(lattice1, oz, self.L, zn - 1)
grain = geompy.MakeSpherePntR(geompy.MakeVertex(*spos2), self.radius) grain = self.geo.MakeSpherePntR(self.geo.MakeVertex(*spos2), self.radius)
lattice2 = geompy.MakeMultiTranslation2D(grain, xy, length, xn + 1, xmy, length, yn + 1) lattice2 = self.geo.MakeMultiTranslation2D(grain, xy, length, xn + 1, xmy, length, yn + 1)
lattice2 = geompy.MakeMultiTranslation1D(lattice2, oz, self.L, zn) lattice2 = self.geo.MakeMultiTranslation1D(lattice2, oz, self.L, zn)
grains = geompy.ExtractShapes(lattice1, geompy.ShapeType["SOLID"], True) grains = self.geo.ExtractShapes(lattice1, self.geo.ShapeType["SOLID"], True)
grains += geompy.ExtractShapes(lattice2, geompy.ShapeType["SOLID"], True) grains += self.geo.ExtractShapes(lattice2, self.geo.ShapeType["SOLID"], True)
grains = geompy.MakeFuseList(grains, False, False) grains = self.geo.MakeFuseList(grains, False, False)
grains = geompy.MakeScaleTransform(grains, oo, scale) grains = self.geo.MakeScaleTransform(grains, oo, scale)
grainsOrigin = None grainsOrigin = None
if self.filletsEnabled: if self.filletsEnabled:
grainsOrigin = geompy.MakeScaleTransform(grains, oo, 1 / scale) grainsOrigin = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
grains = geompy.MakeFilletAll(grains, self.fillets * scale) grains = self.geo.MakeFilletAll(grains, self.fillets * scale)
self.shapeLattice = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
###
# Shape
##
self.shape = self.geo.MakeCutList(poreCell, [grains])
self.shape = self.geo.MakeScaleTransform(self.shape, oo, 1 / scale, theName = self.name)
isValid, _ = self.isValid()
if not isValid:
self.heal()
### ###
# Groups # Groups
#
# inlet, outlet, simetry(N), strips(optional), wall
## ##
shape = geompy.MakeCutList(poreCell, [grains]) self.groups = []
shape = geompy.MakeScaleTransform(shape, oo, 1 / scale, theName = "faceCentered") groupAll = self.createGroupAll(self.shape)
sall = geompy.CreateGroup(shape, geompy.ShapeType["FACE"]) self.groups.append(self.createGroup(self.shape, inletface, "inlet", [grains], 1 / scale))
geompy.UnionIDs(sall, self.groups.append(self.createGroup(self.shape, outletface, "outlet", [grains], 1 / scale))
geompy.SubShapeAllIDs(shape, geompy.ShapeType["FACE"]))
inlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "inlet") for n, face in enumerate(symetryface):
inletshape = geompy.MakeCutList(inletface, [grains]) self.groups.append(self.createGroup(self.shape, face, f"symetry{ n }", [grains], 1 / scale))
inletshape = geompy.MakeScaleTransform(inletshape, oo, 1 / scale)
geompy.UnionList(inlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, inletshape, True), geompy.ShapeType["FACE"]))
outlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "outlet")
outletshape = geompy.MakeCutList(outletface, [grains])
outletshape = geompy.MakeScaleTransform(outletshape, oo, 1 / scale)
geompy.UnionList(outlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, outletshape, True), geompy.ShapeType["FACE"]))
symetry = []
for (n, face) in enumerate(symetryface):
name = "symetry" + str(n)
symetry.append(geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = name))
symetryshape = geompy.MakeCutList(face, [grains])
symetryshape = geompy.MakeScaleTransform(symetryshape, oo, 1 / scale)
geompy.UnionList(symetry[n], geompy.SubShapeAll(
geompy.GetInPlace(shape, symetryshape, True), geompy.ShapeType["FACE"]))
groups = []
groups.append(inlet)
groups.append(outlet)
groups.extend(symetry)
if self.filletsEnabled: if self.filletsEnabled:
strips = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "strips") shapeShell = self.geo.ExtractShapes(self.shape, self.geo.ShapeType["SHELL"], True)[0]
shapeShell = geompy.ExtractShapes(shape, geompy.ShapeType["SHELL"], True) self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin]))
stripsShape = geompy.MakeCutList(shapeShell[0], groups + [grainsOrigin])
geompy.UnionList(strips, geompy.SubShapeAll(
geompy.GetInPlace(shape, stripsShape, True), geompy.ShapeType["FACE"]))
groups.append(strips)
wall = geompy.CutListOfGroups([sall], groups, theName = "wall")
groups.append(wall)
return shape, groups
self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))

View File

@ -2,26 +2,21 @@
# 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.structure import StructureGeometry
from math import pi, sqrt from math import pi, sqrt
from anisotropy.salomepl import geometry
class Simple(object): class Simple(StructureGeometry):
def __init__(self, **kwargs): @property
def name(self):
self.direction = kwargs.get("direction", [1, 0, 0]) """Shape name.
self.theta = kwargs.get("theta", 0.01) """
self.r0 = kwargs.get("r0", 1) return "simple"
self.L = kwargs.get("L", 2 * self.r0)
self.radius = kwargs.get("radius", self.r0 / (1 - self.theta))
self.filletsEnabled = kwargs.get("filletsEnabled", False)
self.fillets = kwargs.get("fillets", 0)
self.volumeCell = None
@property
def L(self):
return 2 * self.r0
def build(self): def build(self):
geompy = geometry.getGeom()
### ###
# Pore Cell # Pore Cell
## ##
@ -40,46 +35,46 @@ class Simple(object):
zh = height zh = height
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
### ###
# Bounding box # Bounding box
## ##
if self.direction == [1, 0, 0]: if self.direction == [1, 0, 0]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
sk.addPointsAbsolute(0, yw, zh) sk.addPointsAbsolute(0, yw, zh)
sk.addPointsAbsolute(xl, 0, zh) sk.addPointsAbsolute(xl, 0, zh)
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, width) poreCell = self.geo.MakePrismVecH(inletface, vecflow, width)
elif self.direction == [0, 0, 1]: elif self.direction == [0, 0, 1]:
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
sk.addPointsAbsolute(xl, 0, 0) sk.addPointsAbsolute(xl, 0, 0)
sk.addPointsAbsolute(2 * xl, yw, 0) sk.addPointsAbsolute(2 * xl, yw, 0)
sk.addPointsAbsolute(xl, 2 * yw, 0) sk.addPointsAbsolute(xl, 2 * yw, 0)
sk.addPointsAbsolute(0, yw, 0) sk.addPointsAbsolute(0, yw, 0)
inletface = geompy.MakeFaceWires([sk.wire()], True) inletface = self.geo.MakeFaceWires([sk.wire()], True)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, height) poreCell = self.geo.MakePrismVecH(inletface, vecflow, height)
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06) self.shapeCell = poreCell
inletface = geompy.MakeScaleTransform(inletface, oo, scale) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale) poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -108,31 +103,31 @@ class Simple(object):
point.append((self.L + xl, self.L + yw, self.L + zh)) point.append((self.L + xl, self.L + yw, self.L + zh))
scale = 100 scale = 100
oo = geompy.MakeVertex(0, 0, 0) oo = self.geo.MakeVertex(0, 0, 0)
### ###
# Bounding box # Bounding box
## ##
sk = geompy.Sketcher3D() sk = self.geo.Sketcher3D()
for p in point: for p in point:
sk.addPointsAbsolute(*p) sk.addPointsAbsolute(*p)
inletface = geompy.MakeFaceWires([sk.wire()], False) inletface = self.geo.MakeFaceWires([sk.wire()], False)
vecflow = geompy.GetNormal(inletface) vecflow = self.geo.GetNormal(inletface)
poreCell = geompy.MakePrismVecH(inletface, vecflow, self.L * sqrt(3)) poreCell = self.geo.MakePrismVecH(inletface, vecflow, self.L * sqrt(3))
[_, _, self.volumeCell] = geompy.BasicProperties(poreCell, theTolerance = 1e-06) self.shapeCell = poreCell
inletface = geompy.MakeScaleTransform(inletface, oo, scale) inletface = self.geo.MakeScaleTransform(inletface, oo, scale)
poreCell = geompy.MakeScaleTransform(poreCell, oo, scale) poreCell = self.geo.MakeScaleTransform(poreCell, oo, scale)
faces = geompy.ExtractShapes(poreCell, geompy.ShapeType["FACE"], False) faces = self.geo.ExtractShapes(poreCell, self.geo.ShapeType["FACE"], False)
symetryface = [] symetryface = []
for face in faces: for face in faces:
norm = geompy.GetNormal(face) norm = self.geo.GetNormal(face)
angle = round(geompy.GetAngle(norm, vecflow), 0) angle = round(self.geo.GetAngle(norm, vecflow), 0)
if (angle == 0 or angle == 180) and not face == inletface: if (angle == 0 or angle == 180) and not face == inletface:
outletface = face outletface = face
@ -146,70 +141,53 @@ class Simple(object):
### ###
# Grains # Grains
## ##
ox = geompy.MakeVectorDXDYDZ(1, 0, 0) ox = self.geo.MakeVectorDXDYDZ(1, 0, 0)
oy = geompy.MakeVectorDXDYDZ(0, 1, 0) oy = self.geo.MakeVectorDXDYDZ(0, 1, 0)
oz = geompy.MakeVectorDXDYDZ(0, 0, 1) oz = self.geo.MakeVectorDXDYDZ(0, 0, 1)
grain = geompy.MakeSphereR(self.radius) grain = self.geo.MakeSphereR(self.radius)
lattice = geompy.MakeMultiTranslation2D(grain, ox, self.L, xn, oy, self.L, yn) lattice = self.geo.MakeMultiTranslation2D(grain, ox, self.L, xn, oy, self.L, yn)
lattice = geompy.MakeMultiTranslation1D(lattice, oz, self.L, zn) lattice = self.geo.MakeMultiTranslation1D(lattice, oz, self.L, zn)
grains = geompy.ExtractShapes(lattice, geompy.ShapeType["SOLID"], True) grains = self.geo.ExtractShapes(lattice, self.geo.ShapeType["SOLID"], True)
grains = geompy.MakeFuseList(grains, False, False) grains = self.geo.MakeFuseList(grains, False, False)
grains = geompy.MakeScaleTransform(grains, oo, scale) grains = self.geo.MakeScaleTransform(grains, oo, scale)
grainsOrigin = None grainsOrigin = None
if self.filletsEnabled: if self.filletsEnabled:
grainsOrigin = geompy.MakeScaleTransform(grains, oo, 1 / scale) grainsOrigin = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
grains = geompy.MakeFilletAll(grains, self.fillets * scale) grains = self.geo.MakeFilletAll(grains, self.fillets * scale)
self.shapeLattice = self.geo.MakeScaleTransform(grains, oo, 1 / scale)
###
# Shape
##
self.shape = self.geo.MakeCutList(poreCell, [grains])
self.shape = self.geo.MakeScaleTransform(self.shape, oo, 1 / scale, theName = self.name)
isValid, _ = self.isValid()
if not isValid:
self.heal()
### ###
# Groups # Groups
#
# inlet, outlet, simetry(N), strips(optional), wall
## ##
shape = geompy.MakeCutList(poreCell, [grains]) self.groups = []
shape = geompy.MakeScaleTransform(shape, oo, 1 / scale, theName = "simple") groupAll = self.createGroupAll(self.shape)
sall = geompy.CreateGroup(shape, geompy.ShapeType["FACE"]) self.groups.append(self.createGroup(self.shape, inletface, "inlet", [grains], 1 / scale))
geompy.UnionIDs(sall, self.groups.append(self.createGroup(self.shape, outletface, "outlet", [grains], 1 / scale))
geompy.SubShapeAllIDs(shape, geompy.ShapeType["FACE"]))
inlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "inlet") for n, face in enumerate(symetryface):
inletshape = geompy.MakeCutList(inletface, [grains]) self.groups.append(self.createGroup(self.shape, face, f"symetry{ n }", [grains], 1 / scale))
inletshape = geompy.MakeScaleTransform(inletshape, oo, 1 / scale)
geompy.UnionList(inlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, inletshape, True), geompy.ShapeType["FACE"]))
outlet = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "outlet")
outletshape = geompy.MakeCutList(outletface, [grains])
outletshape = geompy.MakeScaleTransform(outletshape, oo, 1 / scale)
geompy.UnionList(outlet, geompy.SubShapeAll(
geompy.GetInPlace(shape, outletshape, True), geompy.ShapeType["FACE"]))
symetry = []
for (n, face) in enumerate(symetryface):
name = "symetry" + str(n)
symetry.append(geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = name))
symetryshape = geompy.MakeCutList(face, [grains])
symetryshape = geompy.MakeScaleTransform(symetryshape, oo, 1 / scale)
geompy.UnionList(symetry[n], geompy.SubShapeAll(
geompy.GetInPlace(shape, symetryshape, True), geompy.ShapeType["FACE"]))
groups = []
groups.append(inlet)
groups.append(outlet)
groups.extend(symetry)
if self.filletsEnabled: if self.filletsEnabled:
strips = geompy.CreateGroup(shape, geompy.ShapeType["FACE"], theName = "strips") shapeShell = self.geo.ExtractShapes(self.shape, self.geo.ShapeType["SHELL"], True)[0]
shapeShell = geompy.ExtractShapes(shape, geompy.ShapeType["SHELL"], True) self.groups.append(self.createGroup(self.shape, shapeShell, "strips", self.groups + [grainsOrigin]))
stripsShape = geompy.MakeCutList(shapeShell[0], groups + [grainsOrigin])
geompy.UnionList(strips, geompy.SubShapeAll(
geompy.GetInPlace(shape, stripsShape, True), geompy.ShapeType["FACE"]))
groups.append(strips)
wall = geompy.CutListOfGroups([sall], groups, theName = "wall")
groups.append(wall)
return shape, groups
self.groups.append(self.geo.CutListOfGroups([groupAll], self.groups, theName = "wall"))

View File

@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
# This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details.
from anisotropy.salomepl import geometry
class StructureGeometry(object):
def __init__(
self,
direction: list = None,
theta: float = None,
r0: float = None,
#L: float = None,
#radius: float = None,
filletsEnabled: bool = False,
fillets: float = None,
**kwargs
):
"""Constructor method.
:param direction:
Flow vector that characterizes geometry.
:param theta:
Spheres overlap parameter.
:param r0:
Initial spheres radius.
:param filletsEnabled:
Enable fillets beetween spheres.
:param fillets:
Fillets radius.
"""
# Geometry parameters
self.direction = direction
self.theta = theta
self.r0 = r0
self.filletsEnabled = filletsEnabled
self.fillets = fillets
# General attributes
self.geo = geometry.getGeom()
self.shape = None
self.groups = []
self.shapeCell = None
self.shapeLattice = None
@property
def name(self):
"""(Override) Shape name.
"""
pass
@property
def L(self):
"""(Override) Parameter depending on the ``r0``.
"""
pass
@property
def radius(self):
"""Spheres radius
"""
return self.r0 / (1 - self.theta)
@property
def volumeCell(self):
"""General volume of the cell.
"""
return self.geo.BasicProperties(self.shapeCell, theTolerance = 1e-06)[2]
@property
def volume(self):
"""Volume of the structure.
"""
return self.geo.BasicProperties(self.shape, theTolerance = 1e-06)[2]
@property
def porosity(self):
"""Porosity of the structure.
"""
return self.volume / self.volumeCell
def build(self):
"""(Override) Construct shape and physical groups.
"""
pass
def isValid(self) -> (bool, str):
"""Check a topology of the given shape.
:return:
True, if the shape "seems to be valid" else False and description.
"""
return self.geo.CheckShape(self.shape, theIsCheckGeom = True, theReturnStatus = 1)
def heal(self):
"""Try to heal the shape.
"""
self.shape = self.geo.RemoveExtraEdges(self.shape, doUnionFaces = False)
def createGroupAll(self, mainShape):
"""Create group from all the shape faces.
:param mainShape:
Input shape.
:return:
Created group.
"""
group = self.geo.CreateGroup(mainShape, self.geo.ShapeType["FACE"])
self.geo.UnionIDs(
group,
self.geo.SubShapeAllIDs(mainShape, self.geo.ShapeType["FACE"])
)
return group
def createGroup(self, mainShape, subShape, name: str, cutShapes: list = None, scaleTransform: float = None):
"""Create group from the sub shape.
:param mainShape:
Input shape.
:param subShape:
Input sub shape.
:param name:
Name of the new group.
:param cutShapes:
List of shapes for cut from the sub shape.
:param scaleTransform:
Value of the scale transform regarding to the zero point.
:return:
Created group.
"""
group = self.geo.CreateGroup(mainShape, self.geo.ShapeType["FACE"], theName = name)
if cutShapes:
subShape = self.geo.MakeCutList(subShape, cutShapes)
if scaleTransform:
subShape = self.geo.MakeScaleTransform(subShape, self.geo.MakeVertex(0, 0, 0), scaleTransform)
self.geo.UnionList(
group,
self.geo.SubShapeAll(
self.geo.GetInPlace(mainShape, subShape, True),
self.geo.ShapeType["FACE"]
)
)
return group

File diff suppressed because one or more lines are too long