Mod: flow computation

This commit is contained in:
L-Nafaryus 2021-08-12 20:00:30 +05:00
parent 6abbce9eb7
commit 9b023313b6
No known key found for this signature in database
GPG Key ID: C76D8DCD2727DBB7
7 changed files with 170 additions and 46 deletions

View File

@ -82,7 +82,7 @@ faceCentered = true
approx.pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } approx.pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
approx.pressure.boundaryField.outlet = { type = "fixedValue", value = 0 } approx.pressure.boundaryField.outlet = { type = "fixedValue", value = 0 }
# multiplication velocity value with direction vector # multiplication velocity value with flow direction vector
approx.velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 } approx.velocity.boundaryField.inlet = { type = "fixedValue", value = 6e-5 }
approx.velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } approx.velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" }

View File

@ -1,4 +1,42 @@
import click import click
import ast
class LiteralOption(click.Option):
def type_cast_value(self, ctx, value):
try:
return ast.literal_eval(value)
except:
raise click.BadParameter(f"{ value } (Type error)")
class KeyValueOption(click.Option):
def _convert(self, ctx, value):
if value.find("=") == -1:
raise click.BadParameter(f"{ value } (Missed '=')")
params = value.split("=")
if not len(params) == 2:
raise click.BadParameter(f"{ value } (Syntax error)")
key, val = params[0].strip(), params[1].strip()
if val[0].isalpha():
val = f"'{ val }'"
try:
return { key: ast.literal_eval(val) }
except:
raise click.BadParameter(f"{ value } (Type error)")
def type_cast_value(self, ctx, value):
if isinstance(value, list):
return [ self._convert(ctx, val) for val in value ]
else:
return self._convert(ctx, value)
#pass_anisotropy = click.make_pass_decorator(Anisotropy) #pass_anisotropy = click.make_pass_decorator(Anisotropy)
def version(): def version():
@ -20,10 +58,16 @@ def anisotropy():
@anisotropy.command() @anisotropy.command()
@click.option("-s", "--stage", "stage", type = click.Choice(["all", "mesh", "flow"]), default = "all") @click.option("-s", "--stage", "stage", type = click.Choice(["all", "mesh", "flow"]), default = "all")
@click.option("-p", "--param", "params", metavar = "key=value", multiple = True) @click.option("-p", "--param", "params", metavar = "key=value", multiple = True, cls = KeyValueOption)
def compute(stage, params): def compute(stage, params):
from anisotropy.core.main import Anisotropy from anisotropy.core.main import Anisotropy
args = dict()
for param in params:
args.update(param)
model = Anisotropy() model = Anisotropy()
model.db.setup() model.db.setup()
@ -33,14 +77,15 @@ def compute(stage, params):
for entry in paramsAll: for entry in paramsAll:
model.db.update(entry) model.db.update(entry)
(type, direction, theta) = ("simple", [1.0, 0.0, 0.0], 0.01) type, direction, theta = args["type"], args["direction"], args["theta"]
model.load(type, direction, theta) model.load(type, direction, theta)
# TODO: merge cli params with db params here # TODO: merge cli params with db params here
model.evalParams() model.evalParams()
model.update() model.update()
# TODO: do smth with output # TODO: single compute / queue
if stage == "all" or stage == "mesh": if stage == "all" or stage == "mesh":
((out, err, code), elapsed) = model.computeMesh(type, direction, theta) ((out, err, code), elapsed) = model.computeMesh(type, direction, theta)
@ -51,6 +96,10 @@ def compute(stage, params):
if stage == "all" or stage == "flow": if stage == "all" or stage == "flow":
((out, err, code), elapsed) = model.computeFlow(type, direction, theta) ((out, err, code), elapsed) = model.computeFlow(type, direction, theta)
model.load(type, direction, theta)
model.params["flowresult"]["calculationTime"] = elapsed
model.update()
@anisotropy.command() @anisotropy.command()
@click.argument("root") @click.argument("root")
@ -58,6 +107,7 @@ def compute(stage, params):
@click.argument("direction") @click.argument("direction")
@click.argument("theta") @click.argument("theta")
def computemesh(root, type, direction, theta): def computemesh(root, type, direction, theta):
# ISSUE: can't hide command from help, hidden = True doesn't work
# [Salome Environment] # [Salome Environment]
### ###

View File

@ -8,7 +8,7 @@ from copy import deepcopy
from anisotropy import env from anisotropy import env
from anisotropy.core.utils import setupLogger from anisotropy.core.utils import setupLogger
from anisotropy.core.models import db, JOIN, Structure, Mesh, SubMesh, MeshResult from anisotropy.core.models import db, JOIN, Structure, Mesh, SubMesh, MeshResult, Flow, FlowResult
logger = logging.getLogger(env["logger_name"]) logger = logging.getLogger(env["logger_name"])
setupLogger(logger, logging.INFO, env["LOG"]) setupLogger(logger, logging.INFO, env["LOG"])
@ -32,7 +32,9 @@ class Database(object):
Structure, Structure,
Mesh, Mesh,
SubMesh, SubMesh,
MeshResult MeshResult,
Flow,
FlowResult
]) ])
@ -77,6 +79,20 @@ class Database(object):
return params return params
def loadGeneral(self) -> list:
query = (
Structure
.select()
.order_by(Structure.type, Structure.direction, Structure.theta)
)
response = []
for entry in query.dicts():
response.append({ "structure": entry })
return response
def update(self, params: dict): def update(self, params: dict):
if not params: if not params:
logger.error("Trying to update db from empty parameters") logger.error("Trying to update db from empty parameters")
@ -106,6 +122,7 @@ class Database(object):
self._updateMeshResult(params.get("meshresult", {}), query, meshID) self._updateMeshResult(params.get("meshresult", {}), query, meshID)
# TODO: update method flow flow / flowresult
def _updateStructure(self, src: dict, queryMain) -> int: def _updateStructure(self, src: dict, queryMain) -> int:
raw = deepcopy(src) raw = deepcopy(src)

View File

@ -119,9 +119,23 @@ class Anisotropy(object):
filletsEnabled = entry["structure"]["filletsEnabled"] filletsEnabled = entry["structure"]["filletsEnabled"]
), ),
"mesh": mesh, "mesh": mesh,
"submesh": deepcopy(entry["submesh"]) "submesh": deepcopy(entry["submesh"]),
"flow": deepcopy(entry["flow"])
} }
# TODO: optimize it
# For type = fixedValue only
_velocity = entryNew["flow"]["approx"]["velocity"]["boundaryField"]["inlet"]["value"]
entryNew["flow"]["approx"]["velocity"]["boundaryField"]["inlet"]["value"] = [
val * _velocity for val in entryNew["structure"]["direction"]
]
_velocity = entryNew["flow"]["velocity"]["boundaryField"]["inlet"]["value"]
entryNew["flow"]["velocity"]["boundaryField"]["inlet"]["value"] = [
val * _velocity for val in entryNew["structure"]["direction"]
]
paramsAll.append(entryNew) paramsAll.append(entryNew)
return paramsAll return paramsAll
@ -378,11 +392,13 @@ class Anisotropy(object):
if out: if out:
logger.info(out) logger.info(out)
# TODO: replace all task variables
openfoam.transformPoints(flow["scale"]) openfoam.transformPoints(flow["scale"])
### ###
# Decomposition and initial approximation # Decomposition and initial approximation
#
# NOTE: Temporarily without decomposition
## ##
openfoam.foamDictionary( openfoam.foamDictionary(
"constant/transportProperties", "constant/transportProperties",
@ -390,7 +406,7 @@ class Anisotropy(object):
str(flow["constant"]["nu"]) str(flow["constant"]["nu"])
) )
openfoam.decomposePar() #openfoam.decomposePar()
openfoam.renumberMesh() openfoam.renumberMesh()
@ -412,11 +428,11 @@ class Anisotropy(object):
"boundaryField.outlet.value", "boundaryField.outlet.value",
openfoam.uniform(pressureBF["outlet"]["value"]) openfoam.uniform(pressureBF["outlet"]["value"])
) )
# TODO: flow variable
openfoam.foamDictionary( openfoam.foamDictionary(
"0/U", "0/U",
"boundaryField.inlet.value", "boundaryField.inlet.value",
openfoam.uniform(velocityBF.inlet.value[direction]) openfoam.uniform(velocityBF["inlet"]["value"])
) )
openfoam.potentialFoam() openfoam.potentialFoam()
@ -424,21 +440,32 @@ class Anisotropy(object):
### ###
# Main computation # Main computation
## ##
pressureBF = task.flow.main.pressure.boundaryField pressureBF = flow["pressure"]["boundaryField"]
velocityBF = task.flow.main.velocity.boundaryField velocityBF = flow["velocity"]["boundaryField"]
for n in range(os.cpu_count()):
openfoam.foamDictionary( openfoam.foamDictionary(
f"processor{n}/0/U", "0/U",
"boundaryField.inlet.type", "boundaryField.inlet.type",
velocityBF.inlet.type velocityBF["inlet"]["type"]
) )
openfoam.foamDictionary( openfoam.foamDictionary(
f"processor{n}/0/U", "0/U",
"boundaryField.inlet.value", "boundaryField.inlet.value",
openfoam.uniform(velocityBF.inlet.value[direction]) velocityBF["inlet"]["value"]
) )
#for n in range(os.cpu_count()):
# 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() returncode, out = openfoam.simpleFoam()
if out: if out:
logger.info(out) logger.info(out)
@ -446,25 +473,21 @@ class Anisotropy(object):
### ###
# Check results # Check results
## ##
elapsed = time.monotonic() - stime
logger.info("computeFlow: elapsed time: {}".format(timedelta(seconds = elapsed)))
if returncode == 0: if returncode == 0:
task.status.flow = True
task.statistics.flowTime = elapsed
postProcessing = "postProcessing/flowRatePatch(name=outlet)/0/surfaceFieldValue.dat" postProcessing = "postProcessing/flowRatePatch(name=outlet)/0/surfaceFieldValue.dat"
with open(postProcessing, "r") as io: with open(postProcessing, "r") as io:
lastLine = io.readlines()[-1] lastLine = io.readlines()[-1]
flowRate = float(lastLine.replace(" ", "").replace("\n", "").split("\t")[1]) flowRate = float(lastLine.replace(" ", "").replace("\n", "").split("\t")[1])
task.statistics.flowRate = flowRate self.params["flowresult"] = dict(
flowRate = flowRate
)
with open(os.path.join(case, "task.toml"), "w") as io: self.update()
toml.dump(dict(task), io)
os.chdir(ROOT) os.chdir(self.env["ROOT"])
return returncode return returncode

View File

@ -132,8 +132,37 @@ class MeshResult(BaseModel):
calculationTime = TimeField(null = True) calculationTime = TimeField(null = True)
class Flow(BaseModel): class Flow(BaseModel):
# TODO: flow model # TODO: find better way
pass flow_id = AutoField()
structure_id = ForeignKeyField(Structure, backref = "flows")
class FlowResults(BaseModel): approx_pressure_boundaryField_inlet_type = TextField(null = True)
pass approx_pressure_boundaryField_inlet_value = FloatField(null = True)
approx_pressure_boundaryField_outlet_type = TextField(null = True)
approx_pressure_boundaryField_outlet_value = FloatField(null = True)
approx_velocity_boundaryField_inlet_type = TextField(null = True)
approx_velocity_boundaryField_inlet_value = ListField(null = True)
approx_velocity_boundaryField_outlet_type = TextField(null = True)
approx_velocity_boundaryField_outlet_value = ListField(null = True)
pressure_boundaryField_inlet_type = TextField(null = True)
pressure_boundaryField_inlet_value = FloatField(null = True)
pressure_boundaryField_outlet_type = TextField(null = True)
pressure_boundaryField_outlet_value = FloatField(null = True)
velocity_boundaryField_inlet_type = TextField(null = True)
velocity_boundaryField_inlet_value = ListField(null = True)
velocity_boundaryField_outlet_type = TextField(null = True)
velocity_boundaryField_outlet_value = ListField(null = True)
class FlowResult(BaseModel):
flowresult_id = AutoField()
flow_id = ForeignKeyField(Flow, backref = "flowresults")
flowRate = FloatField(null = True)
calculationTime = TimeField(null = True)

View File

@ -171,7 +171,7 @@ def queue(cmd, qin, qout, *args):
break break
# Execute command # Execute command
res = cmd(*var, *args) res = cmd(var, *args)
# Put results to the queue # Put results to the queue
qout.put((pos, res)) qout.put((pos, res))
@ -189,10 +189,6 @@ def parallel(np, var, cmd):
qin = Queue(1) qin = Queue(1)
qout = Queue() qout = Queue()
logging.info("cpu count: {}".format(np))
logging.info("var: {}".format(var))
logging.info("cmd: {}".format(cmd))
# Create processes # Create processes
for n in range(nprocs): for n in range(nprocs):
pargs = [cmd, qin, qout] pargs = [cmd, qin, qout]

View File

@ -2,12 +2,21 @@ from .application import application
import re import re
def potentialFoam(case: str = None): def potentialFoam(case: str = None, useMPI: bool = False):
if useMPI:
application("potentialFoam", "-parallel", useMPI = True, case = case, stderr = True) application("potentialFoam", "-parallel", useMPI = True, case = case, stderr = True)
else:
application("potentialFoam", case = case, stderr = True)
def simpleFoam(case: str = None):
def simpleFoam(case: str = None, useMPI: bool = False):
if useMPI:
_, returncode = application("simpleFoam", "-parallel", useMPI = True, case = case, stderr = True) _, returncode = application("simpleFoam", "-parallel", useMPI = True, case = case, stderr = True)
else:
_, returncode = application("simpleFoam", case = case, stderr = True)
out = "" out = ""
with open("simpleFoam.log", "r") as io: with open("simpleFoam.log", "r") as io: