New: cwd approach

Mod: improved cli
Fix: missed boundary condition for main flow
This commit is contained in:
L-Nafaryus 2021-08-30 16:56:57 +05:00
parent 750bf30e11
commit 5119e04a09
3 changed files with 144 additions and 79 deletions

View File

@ -78,26 +78,27 @@ faceCentered = true
fuseEdges = true fuseEdges = true
checkChartBoundary = false checkChartBoundary = false
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
# multiplication velocity value with flow direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flow] [structures.flow]
scale = [ 1e-5, 1e-5, 1e-5 ] scale = [ 1e-5, 1e-5, 1e-5 ]
transportProperties.nu = 1e-6 transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 } pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
velocity.boundaryField.inlet = { type = "fixedValue", value = 0.0 } velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 }
# multiplication velocity value with flow direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[[structures]] [[structures]]
[structures.structure] [structures.structure]
@ -166,26 +167,27 @@ faceCentered = true
fuseEdges = true fuseEdges = true
checkChartBoundary = false checkChartBoundary = false
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
# multiplication velocity value with direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flow] [structures.flow]
scale = [ 1e-5, 1e-5, 1e-5 ] scale = [ 1e-5, 1e-5, 1e-5 ]
transportProperties.nu = 1e-6 transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 } pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
velocity.boundaryField.inlet = { type = "fixedValue", value = 0.0 } velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 }
# multiplication velocity value with direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[[structures]] [[structures]]
[structures.structure] [structures.structure]
@ -254,24 +256,26 @@ faceCentered = true
fuseEdges = true fuseEdges = true
checkChartBoundary = false checkChartBoundary = false
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
# multiplication velocity value with direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flow] [structures.flow]
scale = [ 1e-5, 1e-5, 1e-5 ] scale = [ 1e-5, 1e-5, 1e-5 ]
transportProperties.nu = 1e-6 transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 } pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 }
velocity.boundaryField.inlet = { type = "fixedValue", value = 0.0 } velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }
[structures.flowapprox]
transportProperties.nu = 1e-6
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
pressure.boundaryField.outlet = { type = "fixedValue", value = 0 }
# multiplication velocity value with direction vector
velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }

View File

@ -4,7 +4,8 @@
import click import click
import ast import ast
import os import os, shutil
import logging
class LiteralOption(click.Option): class LiteralOption(click.Option):
def type_cast_value(self, ctx, value): def type_cast_value(self, ctx, value):
@ -63,6 +64,29 @@ def version():
def anisotropy(): def anisotropy():
pass pass
@anisotropy.command(
help = "Initialize project in cwd"
)
def init():
from anisotropy import env
from anisotropy.core.utils import setupLogger
from anisotropy.core.main import logger, Database
setupLogger(logger, logging.INFO)
cwd = os.getcwd()
wds = [ "build", "logs" ]
for wd in wds:
os.makedirs(os.path.join(cwd, wd), exist_ok = True)
shutil.copy(env["CONFIG"], os.path.join(cwd, "anisotropy.toml"), follow_symlinks = True)
db = Database(env["db_name"], cwd)
db.setup()
logger.info(f"Initialized anisotropy project in { cwd }")
@anisotropy.command( @anisotropy.command(
help = """Computes cases by chain (mesh -> flow) help = """Computes cases by chain (mesh -> flow)
@ -81,19 +105,15 @@ def anisotropy():
default = 1, default = 1,
help = "Count of parallel processes" help = "Count of parallel processes"
) )
@click.option(
"-D", "--database", "database",
help = "Database path"
)
@click.option( @click.option(
"-f", "--force", "force", "-f", "--force", "force",
type = click.BOOL, is_flag = True,
default = False, default = False,
help = "Overwrite existing entries" help = "Overwrite existing entries"
) )
@click.option( @click.option(
"-u", "--update", "update", "-u", "--update", "update",
type = click.BOOL, is_flag = True,
default = False, default = False,
help = "Update db parameters from config" help = "Update db parameters from config"
) )
@ -104,10 +124,24 @@ def anisotropy():
cls = KeyValueOption, cls = KeyValueOption,
help = "Overwrite existing parameter (except control variables)" help = "Overwrite existing parameter (except control variables)"
) )
def compute(stage, nprocs, database, force, update, params): @click.option(
"-P", "--path", "path",
default = os.getcwd(),
help = "Specify directory to use (instead of cwd)"
)
def compute(stage, nprocs, force, update, params, path):
from anisotropy import env
from anisotropy.core.main import Anisotropy, Database, logger from anisotropy.core.main import Anisotropy, Database, logger
from anisotropy.core.utils import timer, parallel from anisotropy.core.utils import setupLogger, timer, parallel
env.update(
LOG = os.path.join(path, "logs"),
BUILD = os.path.join(path, "build"),
CONFIG = os.path.join(path, "anisotropy.toml"),
db_path = path
)
setupLogger(logger, logging.INFO, env["LOG"])
args = dict() args = dict()
for param in params: for param in params:
@ -115,30 +149,31 @@ def compute(stage, nprocs, database, force, update, params):
### ###
model = Anisotropy() model = Anisotropy()
model.db = Database(env["db_name"], env["db_path"])
if database: logger.info("Configuring database ...")
if database[-3: ] == ".db":
splitted = database.split("/")
db_path = "/".join(splitted[ :-1])
db_name = splitted[-1: ][0][ :-3]
else:
raise Exception("Invalid database extension")
model.db = Database(db_name, db_path)
logger.info("Constructing database, tables ...")
model.db.setup() model.db.setup()
def fill_db(): if model.db.isempty() or update:
if model.db.isempty() or update: paramsAll = model.loadFromScratch(env["CONFIG"])
paramsAll = model.loadFromScratch()
for entry in paramsAll: if args.get("type"):
model.db.update(entry) paramsAll = [ entry for entry in paramsAll if args["type"] == entry["structure"]["type"] ]
if args.get("direction"):
paramsAll = [ entry for entry in paramsAll if args["direction"] == entry["structure"]["direction"] ]
if args.get("theta"):
paramsAll = [ entry for entry in paramsAll if args["theta"] == entry["structure"]["theta"] ]
for entry in paramsAll:
model.db.update(entry)
logger.info("{} entries was updated.".format(len(paramsAll)))
else:
logger.info("Database was not modified.")
_, fill_elapsed = timer(fill_db)()
logger.info(f"Elapsed time = { fill_elapsed }")
### ###
def computeCase(stage, type, direction, theta): def computeCase(stage, type, direction, theta):
@ -152,7 +187,7 @@ def compute(stage, nprocs, database, force, update, params):
if stage == "all" or stage == "mesh": if stage == "all" or stage == "mesh":
if not case.params.get("meshresult", {}).get("status") == "Done" or force: if not case.params.get("meshresult", {}).get("status") == "Done" or force:
(out, err, returncode), elapsed = timer(case.computeMesh)() (out, err, returncode), elapsed = timer(case.computeMesh)(path)
if out: logger.info(out) if out: logger.info(out)
if err: logger.error(err) if err: logger.error(err)
@ -172,7 +207,7 @@ def compute(stage, nprocs, database, force, update, params):
if stage == "all" or stage == "flow": if stage == "all" or stage == "flow":
if not case.params.get("flowresult", {}).get("status") == "Done" or force: if not case.params.get("flowresult", {}).get("status") == "Done" or force:
(out, err, returncode), elapsed = timer(case.computeFlow)() (out, err, returncode), elapsed = timer(case.computeFlow)(path)
if out: logger.info(out) if out: logger.info(out)
if err: logger.error(err) if err: logger.error(err)
@ -219,7 +254,8 @@ def compute(stage, nprocs, database, force, update, params):
@click.argument("type") @click.argument("type")
@click.argument("direction") @click.argument("direction")
@click.argument("theta") @click.argument("theta")
def computemesh(root, type, direction, theta): @click.argument("path")
def computemesh(root, type, direction, theta, path):
# ISSUE: can't hide command from help, 'hidden = True' doesn't work # ISSUE: can't hide command from help, 'hidden = True' doesn't work
# [Salome Environment] # [Salome Environment]
@ -239,17 +275,27 @@ def computemesh(root, type, direction, theta):
os.path.join(root, "env/lib/python3.9/site-packages") os.path.join(root, "env/lib/python3.9/site-packages")
]) ])
from anisotropy.core.main import Anisotropy from anisotropy import env
from anisotropy.core.main import Anisotropy, Database
import salome import salome
### ###
model = Anisotropy() model = Anisotropy()
model.db = Database(env["db_name"], path)
model.load(type, direction, theta) model.load(type, direction, theta)
salome.salome_init() salome.salome_init()
model.genmesh() model.genmesh(path)
salome.salome_close() salome.salome_close()
@anisotropy.command(
help = "Post processing"
)
def postprocessing():
pass
### ###
# CLI entry # CLI entry
## ##

View File

@ -25,7 +25,7 @@ import anisotropy.salomepl.mesh
from anisotropy.samples import Simple, FaceCentered, BodyCentered from anisotropy.samples import Simple, FaceCentered, BodyCentered
logger = logging.getLogger(env["logger_name"]) logger = logging.getLogger(env["logger_name"])
setupLogger(logger, logging.INFO, env["LOG"]) #setupLogger(logger, logging.INFO, env["LOG"])
#peeweeLogger = logging.getLogger("peewee") #peeweeLogger = logging.getLogger("peewee")
#peeweeLogger.setLevel(logging.INFO) #peeweeLogger.setLevel(logging.INFO)
@ -83,18 +83,22 @@ class Anisotropy(object):
return "\n".join([ f"{ k }: { v }" for k, v in versions.items() ]) return "\n".join([ f"{ k }: { v }" for k, v in versions.items() ])
def loadFromScratch(self) -> list: def loadFromScratch(self, configpath: str = None) -> list:
"""Loads parameters from configuration file and expands special values """Loads parameters from configuration file and expands special values
:return: List of dicts with parameters :return: List of dicts with parameters
:rtype: list :rtype: list
""" """
config = configpath or self.env["CONFIG"]
if not os.path.exists(self.env["CONFIG"]): if not os.path.exists(config):
logger.error("Missed default configuration file") logger.error("Missed configuration file")
return return
buf = toml.load(self.env["CONFIG"]).get("structures") else:
logger.info(f"Configuration file: { config }")
buf = toml.load(config).get("structures")
paramsAll = [] paramsAll = []
# TODO: custom config and merge # TODO: custom config and merge
@ -204,7 +208,7 @@ class Anisotropy(object):
fillets = fillets fillets = fillets
) )
def getCasePath(self) -> str: def getCasePath(self, path: str = None) -> str:
"""Constructs case path from control parameters """Constructs case path from control parameters
:return: Absolute path to case :return: Absolute path to case
@ -216,15 +220,21 @@ class Anisotropy(object):
logger.error("Trying to use empty parameters") logger.error("Trying to use empty parameters")
return return
if path:
path = os.path.join(path, "build")
else:
path = self.env["BUILD"]
return os.path.join( return os.path.join(
self.env["BUILD"], path,
structure["type"], structure["type"],
"direction-{}".format(str(structure['direction']).replace(" ", "")), "direction-{}".format(str(structure['direction']).replace(" ", "")),
f"theta-{ structure['theta'] }" f"theta-{ structure['theta'] }"
) )
def computeMesh(self): def computeMesh(self, path):
"""Computes a mesh on shape via Salome """Computes a mesh on shape via Salome
:return: Process output, error messages and returncode :return: Process output, error messages and returncode
@ -237,6 +247,7 @@ class Anisotropy(object):
p["type"], p["type"],
p["direction"], p["direction"],
p["theta"], p["theta"],
path
] ]
manager = salomepl.utils.SalomeManager() manager = salomepl.utils.SalomeManager()
@ -249,12 +260,13 @@ class Anisotropy(object):
) )
def genmesh(self): def genmesh(self, path):
"""Computes a mesh on shape """Computes a mesh on shape
Warning: Working only inside Salome Environment Warning: Working only inside Salome Environment
""" """
setupLogger(logger, logging.INFO, self.env["LOG"])
p = self.params p = self.params
### ###
@ -327,10 +339,13 @@ class Anisotropy(object):
mesh.removePyramids() mesh.removePyramids()
mesh.assignGroups() mesh.assignGroups()
casePath = self.getCasePath() casePath = self.getCasePath(path)
os.makedirs(casePath, exist_ok = True) os.makedirs(casePath, exist_ok = True)
logger.info("Exporting mesh ...") logger.info("Exporting mesh ...")
mesh.exportUNV(os.path.join(casePath, "mesh.unv")) returncode, err = mesh.exportUNV(os.path.join(casePath, "mesh.unv"))
if returncode:
logger.error(err)
meshStats = mesh.stats() meshStats = mesh.stats()
p["meshresult"].update( p["meshresult"].update(
@ -352,7 +367,7 @@ class Anisotropy(object):
self.update() self.update()
def computeFlow(self): def computeFlow(self, path):
"""Computes a flow on mesh via OpenFOAM """Computes a flow on mesh via OpenFOAM
:return: Process output, error messages and returncode :return: Process output, error messages and returncode
@ -387,13 +402,13 @@ class Anisotropy(object):
## ##
if not os.path.exists("mesh.unv"): if not os.path.exists("mesh.unv"):
logger.error(f"missed 'mesh.unv'") logger.error(f"missed 'mesh.unv'")
os.chdir(self.env["ROOT"]) os.chdir(path or self.env["ROOT"])
return "", "", 1 return "", "", 1
out, err, returncode = openfoam.ideasUnvToFoam("mesh.unv") out, err, returncode = openfoam.ideasUnvToFoam("mesh.unv")
if returncode: if returncode:
os.chdir(self.env["ROOT"]) os.chdir(path or self.env["ROOT"])
return out, err, returncode return out, err, returncode
openfoam.createPatch(dictfile = "system/createPatchDict") openfoam.createPatch(dictfile = "system/createPatchDict")