From 0859b6bdf5c09b7e2b0deb09d1363fa63c9e9c22 Mon Sep 17 00:00:00 2001 From: L-Nafaryus Date: Sat, 23 Oct 2021 17:36:17 +0500 Subject: [PATCH] Mod: database models --- anisotropy/config/default.toml | 249 ++------------------------------ anisotropy/core/config.py | 5 + anisotropy/core/main.py | 155 +------------------- anisotropy/core/runner.py | 46 ++++++ anisotropy/database/__init__.py | 0 anisotropy/database/database.py | 36 +++++ anisotropy/database/models.py | 104 +++++++++++++ anisotropy/database/utils.py | 34 +++++ anisotropy/samples/simple.py | 14 +- playground/analytics.ipynb | 2 +- playground/geometry.ipynb | 2 +- 11 files changed, 248 insertions(+), 399 deletions(-) create mode 100644 anisotropy/core/config.py create mode 100644 anisotropy/core/runner.py create mode 100644 anisotropy/database/__init__.py create mode 100644 anisotropy/database/database.py create mode 100644 anisotropy/database/models.py create mode 100644 anisotropy/database/utils.py diff --git a/anisotropy/config/default.toml b/anisotropy/config/default.toml index f72c3b4..f123e3f 100644 --- a/anisotropy/config/default.toml +++ b/anisotropy/config/default.toml @@ -12,270 +12,39 @@ bodyCentered = true faceCentered = true [[structures]] - [structures.structure] type = "simple" - # auto # from theta: list # theta: float - theta = [0.01, 0.28, 0.01] # [min, max, step] - # auto # from directions:list # direction: list + theta = [0.01, 0.28] + thetaStep = 0.01 directions = [ [1, 0, 0], [0, 0, 1], [1, 1, 1] ] - - # r0 = - # L = - # radius = - + r0 = 1 filletsEnabled = true - # auto # fillets: float - - [structures.mesh] - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.5 - nbSegPerEdge = 2 - nbSegPerRadius = 1 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - viscousLayers = true - thickness = [0.01, 0.005] # [min, max] # step is controlled by theta count - numberOfLayers = 1 - stretchFactor = 1 - isFacesToIgnore = true - facesToIgnore = ["inlet", "outlet"] - # auto # faces: list - extrusionMethod = "SURF_OFFSET_SMOOTH" - - [[structures.submesh]] - name = "strips" - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.2 - nbSegPerEdge = 2 - nbSegPerRadius = 3 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - [structures.flowapproximation] - 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] - scale = [ 1e-5, 1e-5, 1e-5 ] - - transportProperties.nu = 1e-6 - - pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } - pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 } - - velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 } - velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } - [[structures]] - [structures.structure] type = "bodyCentered" - # auto # from theta: list # theta: float - theta = [0.01, 0.17, 0.01] # [min, max, step] - # auto # from directions:list # direction: list + theta = [0.01, 0.17] + thetaStep = 0.01 directions = [ [1, 0, 0], [0, 0, 1], [1, 1, 1] ] - - # r0 = - # L = - # radius = - + r0 = 1 filletsEnabled = true - # auto # fillets: float - - [structures.mesh] - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.5 - nbSegPerEdge = 2 - nbSegPerRadius = 1 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - viscousLayers = true - thickness = [0.005, 0.0005] # [min, max] # step is controlled by theta count - numberOfLayers = 1 - stretchFactor = 1 - isFacesToIgnore = true - facesToIgnore = ["inlet", "outlet"] - # auto # faces: list - extrusionMethod = "SURF_OFFSET_SMOOTH" - - [[structures.submesh]] - name = "strips" - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.2 - nbSegPerEdge = 2 - nbSegPerRadius = 3 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - [structures.flowapproximation] - 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] - scale = [ 1e-5, 1e-5, 1e-5 ] - - transportProperties.nu = 1e-6 - - pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } - pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 } - - velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 } - velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } - [[structures]] - [structures.structure] type = "faceCentered" - # auto # from theta: list # theta: float - theta = [0.01, 0.12, 0.01] # [min, max, step] - # auto # from directions:list # direction: list + theta = [0.01, 0.12] + thetaStep = 0.01 directions = [ [1, 0, 0], [0, 0, 1], [1, 1, 1] ] - - # r0 = - # L = - # radius = - + r0 = 1 filletsEnabled = true - # auto # fillets: float - - [structures.mesh] - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.5 - nbSegPerEdge = 2 - nbSegPerRadius = 1 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - viscousLayers = true - thickness = [0.001, 0.0005] # [min, max] # step is controlled by theta count - numberOfLayers = 1 - stretchFactor = 1 - isFacesToIgnore = true - facesToIgnore = ["inlet", "outlet"] - # auto # faces: list - extrusionMethod = "SURF_OFFSET_SMOOTH" - - [[structures.submesh]] - name = "strips" - maxSize = 0.5 - minSize = 0.05 - - fineness = 5 - growthRate = 0.2 - nbSegPerEdge = 2 - nbSegPerRadius = 3 - - chordalErrorEnabled = true - chordalError = 0.25 - - secondOrder = false - optimize = true - quadAllowed = false - useSurfaceCurvature = true - fuseEdges = true - checkChartBoundary = false - - [structures.flowapproximation] - 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] - scale = [ 1e-5, 1e-5, 1e-5 ] - - transportProperties.nu = 1e-6 - - pressure.boundaryField.inlet = { type = "fixedValue", value = 1e-3 } - pressure.boundaryField.outlet = { type = "fixedValue", value = 0.0 } - - velocity.boundaryField.inlet = { type = "pressureInletVelocity", value = 0.0 } - velocity.boundaryField.outlet = { type = "zeroGradient", value = "None" } - diff --git a/anisotropy/core/config.py b/anisotropy/core/config.py new file mode 100644 index 0000000..e888062 --- /dev/null +++ b/anisotropy/core/config.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# This file is part of anisotropy. +# License: GNU GPL version 3, see the file "LICENSE" for details. + + diff --git a/anisotropy/core/main.py b/anisotropy/core/main.py index b8b61de..de8430b 100644 --- a/anisotropy/core/main.py +++ b/anisotropy/core/main.py @@ -137,77 +137,13 @@ class Anisotropy(object): "flowresult": dict(), } - # For `type = fixedValue` only - _velocity = entryNew["flowapproximation"]["velocity"]["boundaryField"]["inlet"]["value"] - entryNew["flowapproximation"]["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 - - def evalParams(self): - """Evals specific geometry(structure) parameters""" - - structure = self.params.get("structure") - - if not structure: - logger.error("Trying to eval empty parameters") - return - - if structure["type"] == "simple": - thetaMin = 0.01 - thetaMax = 0.28 - - r0 = 1 - L = 2 * r0 - radius = r0 / (1 - structure["theta"]) - - C1, C2 = 0.8, 0.5 - Cf = C1 + (C2 - C1) / (thetaMax - thetaMin) * (structure["theta"] - thetaMin) - delta = 0.2 - fillets = delta - Cf * (radius - r0) - - elif structure["type"] == "faceCentered": - thetaMin = 0.01 - thetaMax = 0.13 - - L = 1.0 - r0 = L * sqrt(2) / 4 - radius = r0 / (1 - structure["theta"]) - - C1, C2 = 0.3, 0.2 - Cf = C1 + (C2 - C1) / (thetaMax - thetaMin) * (structure["theta"] - thetaMin) - delta = 0.012 - fillets = delta - Cf * (radius - r0) - - elif structure["type"] == "bodyCentered": - thetaMin = 0.01 - thetaMax = 0.18 - - L = 1.0 - r0 = L * sqrt(3) / 4 - radius = r0 / (1 - structure["theta"]) - - C1, C2 = 0.3, 0.2 - Cf = C1 + (C2 - C1) / (thetaMax - thetaMin) * (structure["theta"] - thetaMin) - delta = 0.02 - fillets = delta - Cf * (radius - r0) - - self.params["structure"].update( - L = L, - r0 = r0, - radius = radius, - fillets = fillets - ) + def getCasePath(self, path: str = None) -> str: """Constructs case path from control parameters @@ -395,99 +331,10 @@ class Anisotropy(object): out, err, returncode = openfoam.ideasUnvToFoam("mesh.unv") - if returncode: - os.chdir(path or self.env["ROOT"]) - - self.params["flowresult"]["flowStatus"] = "Failed" - self.update() - - return out, err, returncode - - openfoam.createPatch(dictfile = "system/createPatchDict") - - openfoam.foamDictionary( - "constant/polyMesh/boundary", - "entry0.defaultFaces.type", - "wall" - ) - openfoam.foamDictionary( - "constant/polyMesh/boundary", - "entry0.defaultFaces.inGroups", - "1 (wall)" - ) - out, err, returncode = openfoam.checkMesh() if out: logger.warning(out) - - openfoam.transformPoints(flow["scale"]) - - ### - # Decomposition and initial approximation - # - # NOTE: Temporary without decomposition - ## - openfoam.foamDictionary( - "constant/transportProperties", - "nu", - str(flow["transportProperties"]["nu"]) - ) - # openfoam.decomposePar() - - openfoam.renumberMesh() - - pressureBF = flowapproximation["pressure"]["boundaryField"] - velocityBF = flowapproximation["velocity"]["boundaryField"] - - openfoam.foamDictionary( - "0/p", - "boundaryField.inlet.value", - openfoam.uniform(pressureBF["inlet"]["value"]) - ) - openfoam.foamDictionary( - "0/p", - "boundaryField.outlet.value", - openfoam.uniform(pressureBF["outlet"]["value"]) - ) - - openfoam.foamDictionary( - "0/U", - "boundaryField.inlet.value", - openfoam.uniform(velocityBF["inlet"]["value"]) - ) - - openfoam.potentialFoam() - - ### - # Main computation - ## - pressureBF = flow["pressure"]["boundaryField"] - velocityBF = flow["velocity"]["boundaryField"] - - openfoam.foamDictionary( - "0/U", - "boundaryField.inlet.type", - velocityBF["inlet"]["type"] - ) - openfoam.foamDictionary( - "0/U", - "boundaryField.inlet.value", - openfoam.uniform(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]) - # ) - out, err, returncode = openfoam.simpleFoam() if not returncode: diff --git a/anisotropy/core/runner.py b/anisotropy/core/runner.py new file mode 100644 index 0000000..5a2c60c --- /dev/null +++ b/anisotropy/core/runner.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# This file is part of anisotropy. +# License: GNU GPL version 3, see the file "LICENSE" for details. + +from datetime import datetime + +import anisotropy.samples as samples + +class UltimateRunner(object): + def __init__(self): + + self.database = Database(..) + self.datebase.setup() + + self._exec = Execution(date = datetime.now()) + self._exec.save() + + def computeMesh(self): + pass + + def _computeMesh(self): + """Function for Salome""" + + sample = samples.__dict__[..] + + # Build a shape + shape = sample.geometry(..) + shape.build() + shape.export(..) + + # Build a mesh + mesh = sample.mesh(shape) + mesh.build() + mesh.export(..) + + # Fill database + + + def computeFlow(self): + + sample = samples.__dict__[..] + + # Build a flow + flow = sample.onephaseflow(..) + flow.build() + diff --git a/anisotropy/database/__init__.py b/anisotropy/database/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/anisotropy/database/database.py b/anisotropy/database/database.py new file mode 100644 index 0000000..d61270d --- /dev/null +++ b/anisotropy/database/database.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# This file is part of anisotropy. +# License: GNU GPL version 3, see the file "LICENSE" for details. + +import os +from .models import ( + sqliteDB, + Execution, + Physics, + Shape, + Mesh, + Flow +) + + +class Database(object): + def __init__(self, filename: str): + self.filename = filename + self.database = sqliteDB + + def setup(self): + path = os.path.abspath(self.filename) + os.makedirs(path, exist_ok = True) + + self.database.init(path) + + if not os.path.exists(path): + self.database.create_tables([ + Execution, + Physics, + Shape, + Mesh, + Flow + ]) + + diff --git a/anisotropy/database/models.py b/anisotropy/database/models.py new file mode 100644 index 0000000..8b2662f --- /dev/null +++ b/anisotropy/database/models.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# This file is part of anisotropy. +# License: GNU GPL version 3, see the file "LICENSE" for details. + +from peewee import ( + SqliteDatabase, JOIN, + Model, Field, + AutoField, ForeignKeyField, + TextField, FloatField, + IntegerField, BooleanField, + TimeField, DateTimeField +) +from anisotropy.database.utils import ListField, JSONField + +sqliteDB = SqliteDatabase( + None, + pragmas = { "foreign_keys": 1 }, + field_types = { "list": "text" } +) + +class Execution(Model): + exec_id = AutoField() + + date = DateTimeField() + executionTime = TimeField(null = True) + + class Meta: + database = sqliteDB + db_table = "executions" + + +class Physics(Model): + physics_id = AutoField() + exec_id = ForeignKeyField(Execution, backref = "physics") + + volumeCell = FloatField(null = True) + volume = FloatField(null = True) + volumeRounded = FloatField(null = True) + porosity = FloatField(null = True) + porosityRounded = FloatField(null = True) + flowRate = FloatField(null = True) + permeability = FloatField(null = True) + + class Meta: + database = sqliteDB + db_table = "physics" + depends_on = Execution + + +class Shape(Model): + structure_id = AutoField() + exec_id = ForeignKeyField(Execution, backref = "physics") + + type = TextField() + direction = ListField() + theta = FloatField() + + r0 = FloatField(null = True) + L = FloatField(null = True) + radius = FloatField(null = True) + + filletsEnabled = BooleanField(null = True) + fillets = FloatField(null = True) + + class Meta: + database = sqliteDB + db_table = "shapes" + depends_on = Execution + + +class Mesh(Model): + mesh_id = AutoField() + exec_id = ForeignKeyField(Execution, backref = "meshes") + + elements = IntegerField(null = True) + edges = IntegerField(null = True) + faces = IntegerField(null = True) + volumes = IntegerField(null = True) + tetrahedrons = IntegerField(null = True) + prisms = IntegerField(null = True) + pyramids = IntegerField(null = True) + + meshStatus = TextField(null = True, default = "Idle") + meshCalculationTime = TimeField(null = True) + + class Meta: + database = sqliteDB + db_table = "meshes" + depends_on = Execution + + +class Flow(Model): + flow_id = AutoField() + exec_id = ForeignKeyField(Execution, backref = "flows") + + flowStatus = TextField(null = True, default = "Idle") + flowCalculationTime = TimeField(null = True) + + class Meta: + database = sqliteDB + db_table = "flows" + depends_on = Execution + + diff --git a/anisotropy/database/utils.py b/anisotropy/database/utils.py new file mode 100644 index 0000000..f3b34e4 --- /dev/null +++ b/anisotropy/database/utils.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# This file is part of anisotropy. +# License: GNU GPL version 3, see the file "LICENSE" for details. + +from peewee import TextField +import json + + +class ListField(TextField): + field_type = "list" + + def db_value(self, value): + return str(value) + + def python_value(self, value): + pval = [] + + for entry in value[1 : -1].split(","): + try: + pval.append(float(entry)) + + except: + pval.append(entry.strip().replace("'", "")) + + return pval + + +class JSONField(TextField): + def db_value(self, value): + return json.dumps(value) + + def python_value(self, value): + if value is not None: + return json.loads(value) diff --git a/anisotropy/samples/simple.py b/anisotropy/samples/simple.py index b9d1c2e..43feef3 100644 --- a/anisotropy/samples/simple.py +++ b/anisotropy/samples/simple.py @@ -224,7 +224,9 @@ class _Geometry(StructureGeometry): class _Mesh(Mesh): - def build(self): + def __init__(self, shape): + Mesh.__init__(self, shape) + algo2d = self.mesh.Triangle(algo = self.smeshBuilder.NETGEN_1D2D) hypo2d = algo2d.Parameters() hypo2d.SetMaxSize(0.1) @@ -244,9 +246,15 @@ class _Mesh(Mesh): #faces = [ group for group in self.geom.groups if group.GetName() in ["inlet", "outlet"] ] #hypo3dVL = algo3d.ViscousLayers(...) + def build(self): + out, err, returncode = self.mesh.compute() + + if not returncode: + self.mesh.removePyramids() + self.mesh.createGroups() -class _Flow(object): +class _OnePhaseFlow(object): def __init__(self): controlDict = ControlDict() controlDict.update( @@ -394,4 +402,4 @@ class _Flow(object): class Simple(object): geometry = _Geometry mesh = _Mesh - flow = _Flow + onephaseflow = _OnePhaseFlow diff --git a/playground/analytics.ipynb b/playground/analytics.ipynb index b1bd02d..e78ecab 100644 --- a/playground/analytics.ipynb +++ b/playground/analytics.ipynb @@ -1005,7 +1005,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/playground/geometry.ipynb b/playground/geometry.ipynb index c8cba52..65e07f8 100644 --- a/playground/geometry.ipynb +++ b/playground/geometry.ipynb @@ -38,7 +38,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" },