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.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.outlet = { type = "zeroGradient", value = "None" }

View File

@ -1,4 +1,42 @@
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)
def version():
@ -20,10 +58,16 @@ def anisotropy():
@anisotropy.command()
@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):
from anisotropy.core.main import Anisotropy
args = dict()
for param in params:
args.update(param)
model = Anisotropy()
model.db.setup()
@ -33,14 +77,15 @@ def compute(stage, params):
for entry in paramsAll:
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)
# TODO: merge cli params with db params here
model.evalParams()
model.update()
# TODO: do smth with output
# TODO: single compute / queue
if stage == "all" or stage == "mesh":
((out, err, code), elapsed) = model.computeMesh(type, direction, theta)
@ -51,6 +96,10 @@ def compute(stage, params):
if stage == "all" or stage == "flow":
((out, err, code), elapsed) = model.computeFlow(type, direction, theta)
model.load(type, direction, theta)
model.params["flowresult"]["calculationTime"] = elapsed
model.update()
@anisotropy.command()
@click.argument("root")
@ -58,6 +107,7 @@ def compute(stage, params):
@click.argument("direction")
@click.argument("theta")
def computemesh(root, type, direction, theta):
# ISSUE: can't hide command from help, hidden = True doesn't work
# [Salome Environment]
###

View File

@ -8,7 +8,7 @@ from copy import deepcopy
from anisotropy import env
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"])
setupLogger(logger, logging.INFO, env["LOG"])
@ -32,7 +32,9 @@ class Database(object):
Structure,
Mesh,
SubMesh,
MeshResult
MeshResult,
Flow,
FlowResult
])
@ -77,6 +79,20 @@ class Database(object):
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):
if not params:
logger.error("Trying to update db from empty parameters")
@ -106,6 +122,7 @@ class Database(object):
self._updateMeshResult(params.get("meshresult", {}), query, meshID)
# TODO: update method flow flow / flowresult
def _updateStructure(self, src: dict, queryMain) -> int:
raw = deepcopy(src)

View File

@ -119,9 +119,23 @@ class Anisotropy(object):
filletsEnabled = entry["structure"]["filletsEnabled"]
),
"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)
return paramsAll
@ -378,11 +392,13 @@ class Anisotropy(object):
if out:
logger.info(out)
# TODO: replace all task variables
openfoam.transformPoints(flow["scale"])
###
# Decomposition and initial approximation
#
# NOTE: Temporarily without decomposition
##
openfoam.foamDictionary(
"constant/transportProperties",
@ -390,7 +406,7 @@ class Anisotropy(object):
str(flow["constant"]["nu"])
)
openfoam.decomposePar()
#openfoam.decomposePar()
openfoam.renumberMesh()
@ -412,11 +428,11 @@ class Anisotropy(object):
"boundaryField.outlet.value",
openfoam.uniform(pressureBF["outlet"]["value"])
)
# TODO: flow variable
openfoam.foamDictionary(
"0/U",
"boundaryField.inlet.value",
openfoam.uniform(velocityBF.inlet.value[direction])
openfoam.uniform(velocityBF["inlet"]["value"])
)
openfoam.potentialFoam()
@ -424,21 +440,32 @@ class Anisotropy(object):
###
# Main computation
##
pressureBF = task.flow.main.pressure.boundaryField
velocityBF = task.flow.main.velocity.boundaryField
pressureBF = flow["pressure"]["boundaryField"]
velocityBF = flow["velocity"]["boundaryField"]
for n in range(os.cpu_count()):
openfoam.foamDictionary(
f"processor{n}/0/U",
"0/U",
"boundaryField.inlet.type",
velocityBF.inlet.type
velocityBF["inlet"]["type"]
)
openfoam.foamDictionary(
f"processor{n}/0/U",
"0/U",
"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()
if out:
logger.info(out)
@ -446,25 +473,21 @@ class Anisotropy(object):
###
# 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
postProcessing = "postProcessing/flowRatePatch(name=outlet)/0/surfaceFieldValue.dat"
with open(postProcessing, "r") as io:
lastLine = io.readlines()[-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:
toml.dump(dict(task), io)
self.update()
os.chdir(ROOT)
os.chdir(self.env["ROOT"])
return returncode

View File

@ -132,8 +132,37 @@ class MeshResult(BaseModel):
calculationTime = TimeField(null = True)
class Flow(BaseModel):
# TODO: flow model
pass
# TODO: find better way
flow_id = AutoField()
structure_id = ForeignKeyField(Structure, backref = "flows")
class FlowResults(BaseModel):
pass
approx_pressure_boundaryField_inlet_type = TextField(null = True)
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
# Execute command
res = cmd(*var, *args)
res = cmd(var, *args)
# Put results to the queue
qout.put((pos, res))
@ -189,10 +189,6 @@ def parallel(np, var, cmd):
qin = Queue(1)
qout = Queue()
logging.info("cpu count: {}".format(np))
logging.info("var: {}".format(var))
logging.info("cmd: {}".format(cmd))
# Create processes
for n in range(nprocs):
pargs = [cmd, qin, qout]

View File

@ -2,12 +2,21 @@ from .application import application
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)
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)
else:
_, returncode = application("simpleFoam", case = case, stderr = True)
out = ""
with open("simpleFoam.log", "r") as io: