Massive improvement

New: few control args
Mod: struct to dict conversion
New: configuration for flow
Fix: missed logs from openfoam package (checkMesh, etc)
This commit is contained in:
L-Nafaryus 2021-06-07 17:09:32 +05:00
parent 2532e20c53
commit 3d4e7abb66
9 changed files with 254 additions and 71 deletions

View File

@ -10,7 +10,26 @@ from utils import struct
import toml
import logging
CONFIG = os.path.join(ROOT, "conf/config.toml")
###
# Shell args
##
configPath = "conf/config.toml"
mode = "safe"
for n, arg in enumerate(sys.argv):
if arg == "-c" or arg == "--config":
configPath = sys.args[n + 1]
if arg == "-s" or arg == "--safe":
mode = "safe"
elif arg == "-a" or arg == "--all":
mode = "all"
###
# Load configuration and tools
##
CONFIG = os.path.join(ROOT, configPath)
config = struct(toml.load(CONFIG))
LOG = os.path.join(ROOT, "logs")
@ -31,26 +50,38 @@ logging.basicConfig(
)
logger = logging.getLogger(config.logger.name)
###
# Main
##
def main():
if checkEnv():
return
tasks = createTasks()
logger.info(f"args:\n\tconfig:\t{ configPath }\n\tmode:\t{ mode }")
for n, case in enumerate(tasks):
queue = createQueue()
for n, case in enumerate(queue):
logger.info("-" * 80)
logger.info(f"""main:
task:\t{ n + 1 } / { len(tasks) }
task:\t{ n + 1 } / { len(queue) }
cpu count:\t{ os.cpu_count() }
case:\t{ case }""")
###
# Compute mesh
##
computeMesh(case)
taskPath = os.path.join(case, "task.toml")
task = struct(toml.load(taskPath))
if not task.status.mesh or mode == "all":
computeMesh(case)
else:
logger.info("computeMesh: mesh already computed")
task = struct(toml.load(os.path.join(case, "task.toml")))
task = struct(toml.load(taskPath))
if not task.status.mesh:
logger.critical("mesh not computed: Skipping flow computation")
@ -59,30 +90,41 @@ def main():
###
# Compute flow
##
computeFlow(case)
if not task.status.flow or mode == "all":
computeFlow(case)
else:
logger.info("computeFlow: flow already computed")
def createTasks():
tasks = []
for structure in config.base.__dict__.keys():
###
# Special values
##
_theta = getattr(config, structure).parameters.theta
getattr(config, structure).parameters.theta = [ n * _theta[2] for n in range(int(_theta[0] / _theta[2]), int(_theta[1] / _theta[2]) + 1) ]
_thickness = getattr(config, structure).mesh.thickness
_count = len(getattr(config, structure).parameters.theta)
getattr(config, structure).mesh.thickness = [ _thickness[0] + n * (_thickness[1] - _thickness[0]) / (_count - 1) for n in range(0, _count) ]
def createQueue():
queue = []
###
# structure type / flow direction / coefficient theta
# Special values
##
parameters_theta = {}
mesh_thickness = {}
for structure in config.base.__dict__.keys():
theta = getattr(config, structure).parameters.theta
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
count = len(parameters_theta[structure])
mesh_thickness[structure] = [ thickness[0] + n * (thickness[1] - thickness[0]) / (count - 1) for n in range(0, count) ]
###
# structure type > flow direction > coefficient theta
##
for structure in config.base.__dict__.keys():
if getattr(config.base, structure):
for direction in getattr(config, structure).geometry.directions:
for n, theta in enumerate(getattr(config, structure).parameters.theta):
for n, theta in enumerate(parameters_theta[structure]):
# create dirs for case path
case = os.path.join(
f"{ BUILD }",
f"{ structure }",
@ -90,16 +132,27 @@ def createTasks():
f"theta-{ theta }"
)
taskPath = os.path.join(case, "task.toml")
if os.path.exists(taskPath) and mode == "safe":
queue.append(case)
continue
if not os.path.exists(case):
os.makedirs(case)
# prepare configuration for task
task = {
"logger": config.logger.__dict__,
"logger": dict(config.logger),
"structure": structure,
"status": {
"mesh": False,
"flow": False
},
"statistics": {
"meshTime": 0,
"flowTime": 0
},
"parameters": {
"theta": theta
},
@ -107,18 +160,21 @@ def createTasks():
"direction": direction,
"fillet": getattr(config, structure).geometry.fillet
},
"mesh": getattr(config, structure).mesh.__dict__
"mesh": dict(getattr(config, structure).mesh),
"flow": dict(config.flow)
}
#task["mesh"]["thickness"] = task["mesh"]["thickness"][int(n)]
# reassign special values
task["mesh"]["thickness"] = mesh_thickness[structure][n]
##
with open(os.path.join(case, "task.toml"), "w") as io:
toml.dump(task, io)
tasks.append(case)
##
queue.append(case)
return tasks
return queue
from salomepl.utils import runExecute, salomeVersion
@ -130,13 +186,24 @@ def computeMesh(case):
returncode = runExecute(port, scriptpath, ROOT, case)
etime = time.monotonic()
logger.info("computeMesh: elapsed time: {}".format(timedelta(seconds = etime - stime)))
task = struct(toml.load(os.path.join(case, "task.toml")))
elapsed = time.monotonic() - stime
logger.info("computeMesh: elapsed time: {}".format(timedelta(seconds = elapsed)))
if returncode == 0:
task.statistics.meshTime = elapsed
with open(os.path.join(case, "task.toml"), "w") as io:
toml.dump(dict(task), io)
import openfoam
def computeFlow(case):
###
# Case preparation
##
foamCase = [ "0", "constant", "system" ]
os.chdir(case)
@ -151,6 +218,9 @@ def computeFlow(case):
stime = time.monotonic()
###
# Mesh manipulations
##
if not os.path.exists("mesh.unv"):
logger.critical(f"computeFlow: missed 'mesh.unv'")
return
@ -164,48 +234,104 @@ def computeFlow(case):
openfoam.createPatch(dictfile = "system/createPatchDict.symetry")
openfoam.foamDictionary("constant/polyMesh/boundary", "entry0.defaultFaces.type", "wall")
openfoam.foamDictionary("constant/polyMesh/boundary", "entry0.defaultFaces.inGroups", "1 (wall)")
openfoam.foamDictionary(
"constant/polyMesh/boundary",
"entry0.defaultFaces.type",
"wall"
)
openfoam.foamDictionary(
"constant/polyMesh/boundary",
"entry0.defaultFaces.inGroups",
"1 (wall)"
)
openfoam.checkMesh()
out = openfoam.checkMesh()
if out:
logger.info(out)
scale = (1e-5, 1e-5, 1e-5)
openfoam.transformPoints(scale)
openfoam.transformPoints(task.flow.scale)
###
# Decomposition and initial approximation
##
openfoam.foamDictionary(
"constant/transportProperties",
"nu",
str(task.flow.constant.nu)
)
openfoam.decomposePar()
openfoam.renumberMesh()
pressureBF = task.flow.approx.pressure.boundaryField
velocityBF = task.flow.approx.velocity.boundaryField
direction = {
"[1, 0, 0]": 0,
"[0, 0, 1]": 1,
"[1, 1, 1]": 2
}[str(task.geometry.direction)]
openfoam.foamDictionary(
"0/p",
"boundaryField.inlet.value",
openfoam.uniform(pressureBF.inlet.value)
)
openfoam.foamDictionary(
"0/p",
"boundaryField.outlet.value",
openfoam.uniform(pressureBF.outlet.value)
)
openfoam.foamDictionary(
"0/U",
"boundaryField.inlet.value",
openfoam.uniform(velocityBF.inlet.value[direction])
)
openfoam.potentialFoam()
###
# Main computation
##
pressureBF = task.flow.main.pressure.boundaryField
velocityBF = task.flow.main.velocity.boundaryField
for n in range(os.cpu_count()):
openfoam.foamDictionary(f"processor{n}/0/U", "boundaryField.inlet.type", "pressureInletVelocity")
openfoam.foamDictionary(f"processor{n}/0/U", "boundaryField.inlet.value", "uniform (0 0 0)")
openfoam.foamDictionary(
f"processor{n}/0/U",
"boundaryField.inlet.type",
velocityBF.inlet.type
)
openfoam.foamDictionary(
f"processor{n}/0/U",
"boundaryField.inlet.value",
openfoam.uniform(velocityBF.inlet.value[direction])
)
returncode, out = openfoam.simpleFoam()
if out:
logger.info(out)
###
# Check results
##
elapsed = time.monotonic() - stime
logger.info("computeFlow: elapsed time: {}".format(timedelta(seconds = elapsed)))
if returncode == 0:
task.status.flow = True
task.statistics.flowTime = elapsed
with open(os.path.join(case, "task.toml"), "w") as io:
toml.dump({
"structure": task.structure,
"logger": task.logger.__dict__,
"status": task.status.__dict__,
"parameters": task.parameters.__dict__,
"geometry": task.geometry.__dict__,
"mesh": task.mesh.__dict__
}, io)
toml.dump(dict(task), io)
os.chdir(ROOT)
etime = time.monotonic()
logger.info("computeFlow: elapsed time: {}".format(timedelta(seconds = etime - stime)))
return returncode
def checkEnv():
missed = False

View File

@ -11,11 +11,19 @@ class struct:
for (k, v) in args[0].items():
if type(v) == dict:
setattr(self, k, struct(v))
else:
setattr(self, k, v)
else:
for (k, v) in kwargs.items():
setattr(self, k, v)
self.__dict__.update(kwargs)
def __iter__(self):
for k in self.__dict__:
if type(getattr(self, k)) == struct:
yield k, dict(getattr(self, k))
else:
yield k, getattr(self, k)
def __str__(self):
members = []

View File

@ -15,6 +15,8 @@ anisotropy-help()
echo ""
echo "Options:"
echo " -c, --config <path-to-file> Use custom configuration file."
echo " -s, --safe Safe mode (skip successfuly computed mesh/flow)"
echo " -a, --all All mode (overwrites everything)"
}
case $1 in
@ -33,7 +35,7 @@ case $1 in
run)
source ${OPENFOAM}
source env/bin/activate
python ${DIR}/anisotropy/anisotropy.py
python ${DIR}/anisotropy/anisotropy.py ${@:2}
deactivate
;;

View File

@ -43,7 +43,7 @@ useSurfaceCurvature = true
fuseEdges = true
checkChartBoundary = false
thickness = [0.005, 0.005]
thickness = [0.01, 0.005]
numberOfLayers = 2
stretchFactor = 1.2
isFacesToIgnore = true
@ -78,7 +78,7 @@ useSurfaceCurvature = true
fuseEdges = true
checkChartBoundary = false
thickness = [0.005, 0.005]
thickness = [0.005, 0.001]
numberOfLayers = 2
stretchFactor = 1.2
isFacesToIgnore = true
@ -113,8 +113,50 @@ useSurfaceCurvature = true
fuseEdges = true
checkChartBoundary = false
thickness = [0.001, 0.001]
thickness = [0.001, 0.0005]
numberOfLayers = 2
stretchFactor = 1.2
isFacesToIgnore = true
###
# Flow
##
[flow]
scale = [1e-5, 1e-5, 1e-5]
[flow.constant]
nu = 1e-6
[flow.approx.pressure.boundaryField]
inlet.type = "fixedValue"
inlet.value = 1e-3
outlet.type = "fixedValue"
outlet.value = 0
[flow.approx.velocity.boundaryField]
inlet.type = "fixedValue"
inlet.value = [
[ 6e-5, 6e-5, 0.0 ],
[ 0.0, 0.0, 6e-5 ],
[ 6e-5, 6e-5, 6e-5 ]
]
outlet.type = "zeroGradient"
outlet.value = "None"
[flow.main.pressure.boundaryField]
inlet.type = "fixedValue"
inlet.value = 1e-3
outlet.type = "fixedValue"
outlet.value = 0
[flow.main.velocity.boundaryField]
inlet.type = "pressureInletVelocity"
inlet.value = [
[ 0, 0, 0 ],
[ 0, 0, 0 ],
[ 0, 0, 0 ]
]
outlet.type = "zeroGradient"
outlet.value = "None"

View File

@ -4,7 +4,7 @@ from .meshManipulation import createPatch, transformPoints, checkMesh, renumberM
from .miscellaneous import foamDictionary
from .parallelProcessing import decomposePar
from .solvers import potentialFoam, simpleFoam
from .utils import foamVersion, foamClean
from .utils import foamVersion, foamClean, uniform
__all__ = [
# meshConversion
@ -28,5 +28,6 @@ __all__ = [
# utils
"foamVersion",
"foamClean"
"foamClean",
"uniform"
]

View File

@ -11,13 +11,13 @@ def createPatch(dictfile: str = None, case: str = None):
application("createPatch", *args, case = case, stderr = True)
def transformPoints(scale: tuple, case: str = None):
scale_ = "{}".format(scale).replace(",", "")
def transformPoints(scale, case: str = None):
_scale = f"({ scale[0] } { scale[1] } { scale[2] })"
application("transformPoints", "-scale", scale_, case = case, stderr = True)
application("transformPoints", "-scale", _scale, case = case, stderr = True)
def checkMesh(case: str = None):
def checkMesh(case: str = None) -> str:
application("checkMesh", "-allGeometry", "-allTopology", case = case, stderr = True)
out = ""

View File

@ -14,3 +14,13 @@ def foamClean(case: str = None):
if os.path.exists(os.path.join(path, d)):
shutil.rmtree(os.path.join(path, d))
def uniform(value) -> str:
if type(value) == list or type(value) == tuple:
return f"uniform ({ value[0] } { value[1] } { value[2] })"
elif type(value) == int or type(value) == float:
return f"uniform { value }"
else:
return ""

View File

@ -87,14 +87,7 @@ def genmesh():
config.status.mesh = True
with open(CONFIG, "w") as io:
toml.dump({
"structure": config.structure,
"logger": config.logger.__dict__,
"status": config.status.__dict__,
"parameters": config.parameters.__dict__,
"geometry": config.geometry.__dict__,
"mesh": config.mesh.__dict__
}, io)
toml.dump(dict(config), io)
meshStats(mesh)
meshExport(mesh, os.path.join(CASE, "mesh.unv"))

View File

@ -28,7 +28,8 @@ def runExecute(port: int, scriptpath: str, *args) -> int:
scriptpath, "args:{}".format(", ".join([str(arg) for arg in args]))]
logger.info("salome: {}".format(cmd[1 : 6]))
logpath = os.path.join("/".join(args[0].split("/")[:-1]), "salome.log")
case = args[1]
logpath = os.path.join(case, "salome.log")
#p = subprocess.Popen(["salome", "start", "--shutdown-servers=1", "--port", str(port), "-t", scriptpath, "args:{}".format(", ".join([str(arg) for arg in args]))],
# stderr = subprocess.STDOUT)