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
)[p["structure"]["type"]]
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"]
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)
mp["maxSize"] = meanSize
@ -324,12 +324,12 @@ class Anisotropy(object):
mp["chordalError"] = mp["maxSize"] / 2
faces = []
for group in groups:
for group in shapeGeometry.groups:
if group.GetName() in mp["facesToIgnore"]:
faces.append(group)
mesh = salomepl.mesh.Mesh(shape)
mesh = salomepl.mesh.Mesh(shapeGeometry.shape)
mesh.Tetrahedron(**mp)
if mp["viscousLayers"]:
@ -339,7 +339,7 @@ class Anisotropy(object):
smp = p["submesh"]
for submesh in smp:
for group in groups:
for group in shapeGeometry.groups:
if submesh["name"] == group.GetName():
subshape = group

View File

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

View File

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