New: cli command 'query'
Remove: unknown trash Mod: database micro migration
This commit is contained in:
parent
422806777e
commit
193e1991f4
@ -78,7 +78,7 @@ faceCentered = true
|
||||
fuseEdges = true
|
||||
checkChartBoundary = false
|
||||
|
||||
[structures.flowapprox]
|
||||
[structures.flowapproximation]
|
||||
transportProperties.nu = 1e-6
|
||||
|
||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||
@ -167,7 +167,7 @@ faceCentered = true
|
||||
fuseEdges = true
|
||||
checkChartBoundary = false
|
||||
|
||||
[structures.flowapprox]
|
||||
[structures.flowapproximation]
|
||||
transportProperties.nu = 1e-6
|
||||
|
||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||
@ -256,7 +256,7 @@ faceCentered = true
|
||||
fuseEdges = true
|
||||
checkChartBoundary = false
|
||||
|
||||
[structures.flowapprox]
|
||||
[structures.flowapproximation]
|
||||
transportProperties.nu = 1e-6
|
||||
|
||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import click
|
||||
import ast
|
||||
import os, shutil
|
||||
import os, sys, shutil
|
||||
import logging
|
||||
|
||||
class LiteralOption(click.Option):
|
||||
@ -192,7 +192,7 @@ def compute(stage, nprocs, force, update, params, path):
|
||||
logger.info(f"Stage: { stage }")
|
||||
|
||||
if stage == "all" or stage == "mesh":
|
||||
if not case.params.get("meshresult", {}).get("status") == "Done" or force:
|
||||
if not case.params.get("meshresult", {}).get("meshStatus") == "Done" or force:
|
||||
(out, err, returncode), elapsed = timer(case.computeMesh)(path)
|
||||
|
||||
if out: logger.info(out)
|
||||
@ -201,7 +201,7 @@ def compute(stage, nprocs, force, update, params, path):
|
||||
case.load(type, direction, theta)
|
||||
|
||||
if case.params.get("meshresult"):
|
||||
case.params["meshresult"]["calculationTime"] = elapsed
|
||||
case.params["meshresult"]["meshCalculationTime"] = elapsed
|
||||
case.update()
|
||||
|
||||
if returncode:
|
||||
@ -212,7 +212,7 @@ def compute(stage, nprocs, force, update, params, path):
|
||||
logger.info("Mesh exists. Skipping ...")
|
||||
|
||||
if stage == "all" or stage == "flow":
|
||||
if not case.params.get("flowresult", {}).get("status") == "Done" or force:
|
||||
if not case.params.get("flowresult", {}).get("flowStatus") == "Done" or force:
|
||||
(out, err, returncode), elapsed = timer(case.computeFlow)(path)
|
||||
|
||||
if out: logger.info(out)
|
||||
@ -221,7 +221,7 @@ def compute(stage, nprocs, force, update, params, path):
|
||||
case.load(type, direction, theta)
|
||||
|
||||
if case.params.get("flowresult"):
|
||||
case.params["flowresult"]["calculationTime"] = elapsed
|
||||
case.params["flowresult"]["flowCalculationTime"] = elapsed
|
||||
case.update()
|
||||
|
||||
if returncode:
|
||||
@ -281,7 +281,7 @@ def kill(path, pidfile):
|
||||
SalomeManager().killall()
|
||||
|
||||
@anisotropy.command(
|
||||
help = "! Not a user command"
|
||||
help = "! Internal command"
|
||||
)
|
||||
@click.argument("root")
|
||||
@click.argument("type")
|
||||
@ -392,9 +392,118 @@ def postprocessing(path, plot):
|
||||
plt.show()
|
||||
|
||||
|
||||
@anisotropy.command()
|
||||
@click.option(
|
||||
"-p", "--param", "params",
|
||||
metavar = "key=value",
|
||||
multiple = True,
|
||||
cls = KeyValueOption,
|
||||
help = "Select by control parameter (type, direction, theta)"
|
||||
)
|
||||
@click.option(
|
||||
"-P", "--path", "path",
|
||||
default = os.getcwd(),
|
||||
help = "Specify directory to use (instead of cwd)"
|
||||
)
|
||||
@click.option(
|
||||
"--list", "printlist",
|
||||
is_flag = True,
|
||||
help = "Print a list of avaliable fields."
|
||||
)
|
||||
@click.option(
|
||||
"--export",
|
||||
metavar = "PATH",
|
||||
help = "Export query result to CSV."
|
||||
)
|
||||
@click.argument(
|
||||
"fields",
|
||||
required = False
|
||||
)
|
||||
def query(params, path, printlist, export, fields):
|
||||
from anisotropy import env
|
||||
from anisotropy.core.database import Database, Structure
|
||||
from pandas import DataFrame
|
||||
|
||||
env.update(
|
||||
LOG = os.path.join(path, "logs"),
|
||||
BUILD = os.path.join(path, "build"),
|
||||
CONFIG = os.path.join(path, "anisotropy.toml"),
|
||||
db_path = path
|
||||
)
|
||||
|
||||
args = dict()
|
||||
|
||||
for param in params:
|
||||
args.update(param)
|
||||
|
||||
fields = [ field.strip() for field in fields.split(",") ] if fields else []
|
||||
|
||||
###
|
||||
db = Database(env["db_name"], env["db_path"])
|
||||
db.setup()
|
||||
|
||||
searchargs = []
|
||||
|
||||
if args.get("type"):
|
||||
searchargs.append(Structure.type == args["type"])
|
||||
|
||||
if args.get("direction"):
|
||||
searchargs.append(Structure.direction == str(args["direction"]))
|
||||
|
||||
if args.get("theta"):
|
||||
searchargs.append(Structure.theta == args["theta"])
|
||||
|
||||
result = db.search(searchargs)
|
||||
result.sort(key = lambda src: f"{ src['type'] }{ src['direction'] }{ src['theta'] }")
|
||||
|
||||
df = DataFrame(result)
|
||||
df_keys = [ key for key in df.keys() ]
|
||||
|
||||
if printlist:
|
||||
click.echo("Avaliable fields for query:")
|
||||
click.echo("\t{}".format("\n\t".join(df_keys)))
|
||||
|
||||
return
|
||||
|
||||
if not result:
|
||||
click.echo("Empty result.")
|
||||
|
||||
return
|
||||
|
||||
|
||||
if fields:
|
||||
for field in fields:
|
||||
if field not in df_keys:
|
||||
click.echo(f"Unknown field '{ field }'. Try to use '--list' flag to see all avaliable fields.")
|
||||
|
||||
return
|
||||
|
||||
df = df[fields]
|
||||
|
||||
if export:
|
||||
df.to_csv(export, sep = ";")
|
||||
|
||||
else:
|
||||
click.echo(df.to_string())
|
||||
|
||||
|
||||
###
|
||||
# CLI entry
|
||||
##
|
||||
if __name__ == "__main__":
|
||||
anisotropy()
|
||||
try:
|
||||
anisotropy()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
click.echo("Interrupted!")
|
||||
|
||||
finally:
|
||||
from anisotropy.salomepl.utils import SalomeManager
|
||||
click.echo("Exiting ...")
|
||||
|
||||
if os.path.exists("anisotropy.pid"):
|
||||
os.remove("anisotropy.pid")
|
||||
|
||||
SalomeManager().killall()
|
||||
|
||||
sys.exit(0)
|
||||
|
@ -29,8 +29,8 @@ def tryUntilDone(func):
|
||||
ret = func(*args, **kwargs)
|
||||
done = True
|
||||
|
||||
except OperationalError:
|
||||
pass
|
||||
except OperationalError as e:
|
||||
logger.error(e)
|
||||
|
||||
return ret
|
||||
|
||||
@ -110,10 +110,10 @@ class Database(object):
|
||||
if flowQuery.exists():
|
||||
params["flow"] = flowQuery.dicts().get()
|
||||
|
||||
flowapproxQuery = flowQuery.get().flowapprox
|
||||
flowapproximationQuery = flowQuery.get().flowapproximations
|
||||
|
||||
if flowapproxQuery.exists():
|
||||
params["flowapprox"] = flowapproxQuery.dicts().get()
|
||||
if flowapproximationQuery.exists():
|
||||
params["flowapproximation"] = flowapproximationQuery.dicts().get()
|
||||
|
||||
flowresultsQuery = flowQuery.get().flowresults
|
||||
|
||||
@ -173,22 +173,73 @@ class Database(object):
|
||||
)
|
||||
)
|
||||
|
||||
structureID = tryUntilDone(self._updateStructure)(params["structure"], query)
|
||||
structureID = tryUntilDone(self._updateStructure)(params.get("structure", {}), query)
|
||||
|
||||
meshID = tryUntilDone(self._updateMesh)(params["mesh"], query, structureID)
|
||||
meshID = tryUntilDone(self._updateMesh)(params.get("mesh", {}), query, structureID)
|
||||
|
||||
for submeshParams in params.get("submesh", []):
|
||||
tryUntilDone(self._updateSubMesh)(submeshParams, query, meshID)
|
||||
|
||||
tryUntilDone(self._updateMeshResult)(params.get("meshresult", {}), query, meshID)
|
||||
|
||||
flowID = tryUntilDone(self._updateFlow)(params["flow"], query, structureID)
|
||||
flowID = tryUntilDone(self._updateFlow)(params.get("flow", {}), query, structureID)
|
||||
|
||||
tryUntilDone(self._updateFlowApproximation)(params.get("flowapprox", {}), query, flowID)
|
||||
tryUntilDone(self._updateFlowApproximation)(params.get("flowapproximation", {}), query, flowID)
|
||||
|
||||
tryUntilDone(self._updateFlowResult)(params.get("flowresult", {}), query, flowID)
|
||||
|
||||
|
||||
def search(self, args: list):
|
||||
result = {}
|
||||
query = (
|
||||
Structure
|
||||
.select(Structure, Mesh, SubMesh, MeshResult, Flow, FlowApproximation, FlowResult)
|
||||
.join(
|
||||
Mesh,
|
||||
JOIN.INNER,
|
||||
on = (Mesh.structure_id == Structure.structure_id)
|
||||
)
|
||||
.join(
|
||||
SubMesh,
|
||||
JOIN.INNER,
|
||||
on = (SubMesh.mesh_id == Mesh.mesh_id)
|
||||
)
|
||||
.join(
|
||||
MeshResult,
|
||||
JOIN.INNER,
|
||||
on = (MeshResult.mesh_id == Mesh.mesh_id)
|
||||
)
|
||||
.join(
|
||||
Flow,
|
||||
JOIN.INNER,
|
||||
on = (Flow.structure_id == Structure.structure_id)
|
||||
)
|
||||
.join(
|
||||
FlowApproximation,
|
||||
JOIN.INNER,
|
||||
on = (FlowApproximation.flow_id == Flow.flow_id)
|
||||
)
|
||||
.join(
|
||||
FlowResult,
|
||||
JOIN.INNER,
|
||||
on = (FlowResult.flow_id == Flow.flow_id)
|
||||
)
|
||||
)
|
||||
|
||||
for arg in args:
|
||||
query = query.where(arg)
|
||||
|
||||
|
||||
with self.__db.atomic():
|
||||
if not self.isempty():
|
||||
result = [ entry for entry in query.dicts() ]
|
||||
|
||||
else:
|
||||
logger.error("Missed Structure table")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _updateStructure(self, src: dict, queryMain) -> int:
|
||||
raw = deepcopy(src)
|
||||
|
||||
|
@ -101,8 +101,7 @@ class Anisotropy(object):
|
||||
buf = toml.load(config).get("structures")
|
||||
paramsAll = []
|
||||
|
||||
# TODO: custom config and merge
|
||||
|
||||
|
||||
for entry in buf:
|
||||
# Shortcuts
|
||||
_theta = entry["structure"]["theta"]
|
||||
@ -133,12 +132,12 @@ class Anisotropy(object):
|
||||
"mesh": mesh,
|
||||
"submesh": deepcopy(entry["submesh"]),
|
||||
"flow": deepcopy(entry["flow"]),
|
||||
"flowapprox": deepcopy(entry["flowapprox"])
|
||||
"flowapproximation": deepcopy(entry["flowapproximation"])
|
||||
}
|
||||
|
||||
# For `type = fixedValue` only
|
||||
_velocity = entryNew["flowapprox"]["velocity"]["boundaryField"]["inlet"]["value"]
|
||||
entryNew["flowapprox"]["velocity"]["boundaryField"]["inlet"]["value"] = [
|
||||
_velocity = entryNew["flowapproximation"]["velocity"]["boundaryField"]["inlet"]["value"]
|
||||
entryNew["flowapproximation"]["velocity"]["boundaryField"]["inlet"]["value"] = [
|
||||
val * _velocity for val in entryNew["structure"]["direction"]
|
||||
]
|
||||
|
||||
@ -380,7 +379,7 @@ class Anisotropy(object):
|
||||
foamCase = [ "0", "constant", "system" ]
|
||||
|
||||
flow = self.params["flow"]
|
||||
flowapprox = self.params["flowapprox"]
|
||||
flowapproximation = self.params["flowapproximation"]
|
||||
|
||||
# ISSUE: ideasUnvToFoam cannot import mesh with '-case' flag so 'os.chdir' for that
|
||||
casePath = self.getCasePath()
|
||||
@ -447,8 +446,8 @@ class Anisotropy(object):
|
||||
|
||||
openfoam.renumberMesh()
|
||||
|
||||
pressureBF = flowapprox["pressure"]["boundaryField"]
|
||||
velocityBF = flowapprox["velocity"]["boundaryField"]
|
||||
pressureBF = flowapproximation["pressure"]["boundaryField"]
|
||||
velocityBF = flowapproximation["velocity"]["boundaryField"]
|
||||
|
||||
openfoam.foamDictionary(
|
||||
"0/p",
|
||||
|
@ -138,8 +138,9 @@ class MeshResult(BaseModel):
|
||||
prisms = IntegerField(null = True)
|
||||
pyramids = IntegerField(null = True)
|
||||
|
||||
status = TextField(null = True, default = "Idle")
|
||||
calculationTime = TimeField(null = True)
|
||||
meshStatus = TextField(null = True, default = "Idle")
|
||||
meshCalculationTime = TimeField(null = True)
|
||||
|
||||
|
||||
class Flow(BaseModel):
|
||||
flow_id = AutoField()
|
||||
@ -153,17 +154,20 @@ class Flow(BaseModel):
|
||||
|
||||
class FlowApproximation(BaseModel):
|
||||
flow_approximation_id = AutoField()
|
||||
flow_id = ForeignKeyField(Flow, backref = "flowapprox")
|
||||
flow_id = ForeignKeyField(Flow, backref = "flowapproximations")
|
||||
|
||||
pressure = JSONField(null = True)
|
||||
velocity = JSONField(null = True)
|
||||
transportProperties = JSONField(null = True)
|
||||
|
||||
|
||||
class FlowResult(BaseModel):
|
||||
flowresult_id = AutoField()
|
||||
flow_id = ForeignKeyField(Flow, backref = "flowresults")
|
||||
|
||||
flowRate = FloatField(null = True)
|
||||
porosity = FloatField(null = True)
|
||||
permeability = FloatField(null = True)
|
||||
|
||||
status = TextField(null = True, default = "Idle")
|
||||
calculationTime = TimeField(null = True)
|
||||
flowStatus = TextField(null = True, default = "Idle")
|
||||
flowCalculationTime = TimeField(null = True)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 284 KiB |
@ -5,3 +5,21 @@ Current anisotropy database hierarchy:
|
||||
|
||||
.. figure:: ../static/er-diagram.png
|
||||
:align: center
|
||||
|
||||
peewee migration
|
||||
----------------
|
||||
|
||||
Example of Sqlite database migration and etc:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from playhouse.migrate import SqliteMigrator, migrate
|
||||
from peewee import SqliteDatabase, FloatField
|
||||
|
||||
db = SqliteDatabase("anisotropy.db")
|
||||
migrator = SqliteDatabase(db)
|
||||
|
||||
migrate(
|
||||
migrator.rename_column("MeshResult", "status", "meshStatus"),
|
||||
migrator.add_column("FlowResult", "porosity", FloatField(null = True))
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user