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
|
fuseEdges = true
|
||||||
checkChartBoundary = false
|
checkChartBoundary = false
|
||||||
|
|
||||||
[structures.flowapprox]
|
[structures.flowapproximation]
|
||||||
transportProperties.nu = 1e-6
|
transportProperties.nu = 1e-6
|
||||||
|
|
||||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||||
@ -167,7 +167,7 @@ faceCentered = true
|
|||||||
fuseEdges = true
|
fuseEdges = true
|
||||||
checkChartBoundary = false
|
checkChartBoundary = false
|
||||||
|
|
||||||
[structures.flowapprox]
|
[structures.flowapproximation]
|
||||||
transportProperties.nu = 1e-6
|
transportProperties.nu = 1e-6
|
||||||
|
|
||||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||||
@ -256,7 +256,7 @@ faceCentered = true
|
|||||||
fuseEdges = true
|
fuseEdges = true
|
||||||
checkChartBoundary = false
|
checkChartBoundary = false
|
||||||
|
|
||||||
[structures.flowapprox]
|
[structures.flowapproximation]
|
||||||
transportProperties.nu = 1e-6
|
transportProperties.nu = 1e-6
|
||||||
|
|
||||||
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 }
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
import ast
|
import ast
|
||||||
import os, shutil
|
import os, sys, shutil
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
class LiteralOption(click.Option):
|
class LiteralOption(click.Option):
|
||||||
@ -192,7 +192,7 @@ def compute(stage, nprocs, force, update, params, path):
|
|||||||
logger.info(f"Stage: { stage }")
|
logger.info(f"Stage: { stage }")
|
||||||
|
|
||||||
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("meshStatus") == "Done" or force:
|
||||||
(out, err, returncode), elapsed = timer(case.computeMesh)(path)
|
(out, err, returncode), elapsed = timer(case.computeMesh)(path)
|
||||||
|
|
||||||
if out: logger.info(out)
|
if out: logger.info(out)
|
||||||
@ -201,7 +201,7 @@ def compute(stage, nprocs, force, update, params, path):
|
|||||||
case.load(type, direction, theta)
|
case.load(type, direction, theta)
|
||||||
|
|
||||||
if case.params.get("meshresult"):
|
if case.params.get("meshresult"):
|
||||||
case.params["meshresult"]["calculationTime"] = elapsed
|
case.params["meshresult"]["meshCalculationTime"] = elapsed
|
||||||
case.update()
|
case.update()
|
||||||
|
|
||||||
if returncode:
|
if returncode:
|
||||||
@ -212,7 +212,7 @@ def compute(stage, nprocs, force, update, params, path):
|
|||||||
logger.info("Mesh exists. Skipping ...")
|
logger.info("Mesh exists. Skipping ...")
|
||||||
|
|
||||||
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("flowStatus") == "Done" or force:
|
||||||
(out, err, returncode), elapsed = timer(case.computeFlow)(path)
|
(out, err, returncode), elapsed = timer(case.computeFlow)(path)
|
||||||
|
|
||||||
if out: logger.info(out)
|
if out: logger.info(out)
|
||||||
@ -221,7 +221,7 @@ def compute(stage, nprocs, force, update, params, path):
|
|||||||
case.load(type, direction, theta)
|
case.load(type, direction, theta)
|
||||||
|
|
||||||
if case.params.get("flowresult"):
|
if case.params.get("flowresult"):
|
||||||
case.params["flowresult"]["calculationTime"] = elapsed
|
case.params["flowresult"]["flowCalculationTime"] = elapsed
|
||||||
case.update()
|
case.update()
|
||||||
|
|
||||||
if returncode:
|
if returncode:
|
||||||
@ -281,7 +281,7 @@ def kill(path, pidfile):
|
|||||||
SalomeManager().killall()
|
SalomeManager().killall()
|
||||||
|
|
||||||
@anisotropy.command(
|
@anisotropy.command(
|
||||||
help = "! Not a user command"
|
help = "! Internal command"
|
||||||
)
|
)
|
||||||
@click.argument("root")
|
@click.argument("root")
|
||||||
@click.argument("type")
|
@click.argument("type")
|
||||||
@ -392,9 +392,118 @@ def postprocessing(path, plot):
|
|||||||
plt.show()
|
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
|
# CLI entry
|
||||||
##
|
##
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
anisotropy()
|
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)
|
ret = func(*args, **kwargs)
|
||||||
done = True
|
done = True
|
||||||
|
|
||||||
except OperationalError:
|
except OperationalError as e:
|
||||||
pass
|
logger.error(e)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -110,10 +110,10 @@ class Database(object):
|
|||||||
if flowQuery.exists():
|
if flowQuery.exists():
|
||||||
params["flow"] = flowQuery.dicts().get()
|
params["flow"] = flowQuery.dicts().get()
|
||||||
|
|
||||||
flowapproxQuery = flowQuery.get().flowapprox
|
flowapproximationQuery = flowQuery.get().flowapproximations
|
||||||
|
|
||||||
if flowapproxQuery.exists():
|
if flowapproximationQuery.exists():
|
||||||
params["flowapprox"] = flowapproxQuery.dicts().get()
|
params["flowapproximation"] = flowapproximationQuery.dicts().get()
|
||||||
|
|
||||||
flowresultsQuery = flowQuery.get().flowresults
|
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", []):
|
for submeshParams in params.get("submesh", []):
|
||||||
tryUntilDone(self._updateSubMesh)(submeshParams, query, meshID)
|
tryUntilDone(self._updateSubMesh)(submeshParams, query, meshID)
|
||||||
|
|
||||||
tryUntilDone(self._updateMeshResult)(params.get("meshresult", {}), 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)
|
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:
|
def _updateStructure(self, src: dict, queryMain) -> int:
|
||||||
raw = deepcopy(src)
|
raw = deepcopy(src)
|
||||||
|
|
||||||
|
@ -101,7 +101,6 @@ class Anisotropy(object):
|
|||||||
buf = toml.load(config).get("structures")
|
buf = toml.load(config).get("structures")
|
||||||
paramsAll = []
|
paramsAll = []
|
||||||
|
|
||||||
# TODO: custom config and merge
|
|
||||||
|
|
||||||
for entry in buf:
|
for entry in buf:
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
@ -133,12 +132,12 @@ class Anisotropy(object):
|
|||||||
"mesh": mesh,
|
"mesh": mesh,
|
||||||
"submesh": deepcopy(entry["submesh"]),
|
"submesh": deepcopy(entry["submesh"]),
|
||||||
"flow": deepcopy(entry["flow"]),
|
"flow": deepcopy(entry["flow"]),
|
||||||
"flowapprox": deepcopy(entry["flowapprox"])
|
"flowapproximation": deepcopy(entry["flowapproximation"])
|
||||||
}
|
}
|
||||||
|
|
||||||
# For `type = fixedValue` only
|
# For `type = fixedValue` only
|
||||||
_velocity = entryNew["flowapprox"]["velocity"]["boundaryField"]["inlet"]["value"]
|
_velocity = entryNew["flowapproximation"]["velocity"]["boundaryField"]["inlet"]["value"]
|
||||||
entryNew["flowapprox"]["velocity"]["boundaryField"]["inlet"]["value"] = [
|
entryNew["flowapproximation"]["velocity"]["boundaryField"]["inlet"]["value"] = [
|
||||||
val * _velocity for val in entryNew["structure"]["direction"]
|
val * _velocity for val in entryNew["structure"]["direction"]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -380,7 +379,7 @@ class Anisotropy(object):
|
|||||||
foamCase = [ "0", "constant", "system" ]
|
foamCase = [ "0", "constant", "system" ]
|
||||||
|
|
||||||
flow = self.params["flow"]
|
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
|
# ISSUE: ideasUnvToFoam cannot import mesh with '-case' flag so 'os.chdir' for that
|
||||||
casePath = self.getCasePath()
|
casePath = self.getCasePath()
|
||||||
@ -447,8 +446,8 @@ class Anisotropy(object):
|
|||||||
|
|
||||||
openfoam.renumberMesh()
|
openfoam.renumberMesh()
|
||||||
|
|
||||||
pressureBF = flowapprox["pressure"]["boundaryField"]
|
pressureBF = flowapproximation["pressure"]["boundaryField"]
|
||||||
velocityBF = flowapprox["velocity"]["boundaryField"]
|
velocityBF = flowapproximation["velocity"]["boundaryField"]
|
||||||
|
|
||||||
openfoam.foamDictionary(
|
openfoam.foamDictionary(
|
||||||
"0/p",
|
"0/p",
|
||||||
|
@ -138,8 +138,9 @@ class MeshResult(BaseModel):
|
|||||||
prisms = IntegerField(null = True)
|
prisms = IntegerField(null = True)
|
||||||
pyramids = IntegerField(null = True)
|
pyramids = IntegerField(null = True)
|
||||||
|
|
||||||
status = TextField(null = True, default = "Idle")
|
meshStatus = TextField(null = True, default = "Idle")
|
||||||
calculationTime = TimeField(null = True)
|
meshCalculationTime = TimeField(null = True)
|
||||||
|
|
||||||
|
|
||||||
class Flow(BaseModel):
|
class Flow(BaseModel):
|
||||||
flow_id = AutoField()
|
flow_id = AutoField()
|
||||||
@ -153,17 +154,20 @@ class Flow(BaseModel):
|
|||||||
|
|
||||||
class FlowApproximation(BaseModel):
|
class FlowApproximation(BaseModel):
|
||||||
flow_approximation_id = AutoField()
|
flow_approximation_id = AutoField()
|
||||||
flow_id = ForeignKeyField(Flow, backref = "flowapprox")
|
flow_id = ForeignKeyField(Flow, backref = "flowapproximations")
|
||||||
|
|
||||||
pressure = JSONField(null = True)
|
pressure = JSONField(null = True)
|
||||||
velocity = JSONField(null = True)
|
velocity = JSONField(null = True)
|
||||||
transportProperties = JSONField(null = True)
|
transportProperties = JSONField(null = True)
|
||||||
|
|
||||||
|
|
||||||
class FlowResult(BaseModel):
|
class FlowResult(BaseModel):
|
||||||
flowresult_id = AutoField()
|
flowresult_id = AutoField()
|
||||||
flow_id = ForeignKeyField(Flow, backref = "flowresults")
|
flow_id = ForeignKeyField(Flow, backref = "flowresults")
|
||||||
|
|
||||||
flowRate = FloatField(null = True)
|
flowRate = FloatField(null = True)
|
||||||
|
porosity = FloatField(null = True)
|
||||||
|
permeability = FloatField(null = True)
|
||||||
|
|
||||||
status = TextField(null = True, default = "Idle")
|
flowStatus = TextField(null = True, default = "Idle")
|
||||||
calculationTime = TimeField(null = True)
|
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
|
.. figure:: ../static/er-diagram.png
|
||||||
:align: center
|
: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