Mod: refactoring ultimate runner

This commit is contained in:
L-Nafaryus 2022-02-01 16:06:52 +05:00
parent 34313205d6
commit fb52e4c6c8
5 changed files with 138 additions and 149 deletions

View File

@ -33,7 +33,7 @@ env = {
def loadEnv():
prefix = "ANISOTROPY_"
prefix = "AP_"
for k, v in env.items():
environ[f"{ prefix }{ k }"] = v

View File

@ -1,37 +1,34 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import os
from os import PathLike
from pathlib import Path
from anisotropy.core.config import DefaultConfig
from os import environ
from datetime import datetime
import pathlib
import logging
from anisotropy.core.postProcess import PostProcess
from anisotropy.core.utils import Timer, ErrorHandler
from anisotropy.core.parallel import ParallelRunner
from anisotropy.database import Database, tables
from anisotropy import shaping
from anisotropy import meshing
from anisotropy import solving
from . import config
from . import postprocess
from . import utils
from . import ParallelRunner
logger = logging.getLogger(__name__)
from anisotropy.database import Database, tables as T
from anisotropy.shaping import Simple, BodyCentered, FaceCentered, Shape
from anisotropy.meshing import Mesh
from anisotropy.solving import OnePhaseFlow
class UltimateRunner(object):
def __init__(self, config = None, exec_id: int = None, typo: str = "master"):
# Configuration file
self.config = config or DefaultConfig()
def __init__(self, conf = None, exec_id: int = None, typo: str = "master"):
# Process recognition
self.typo = typo
# Configuration file
self.config = conf or config.DefaultConfig()
# Database preparation
self.database = Database(path = self.config["database"])
self.database = Database(self.config["database"])
self.exec_id = None
if exec_id:
@ -43,35 +40,38 @@ class UltimateRunner(object):
if not self.exec_id:
with self.database:
self.exec_id = T.Execution.create(date = datetime.now())
self.exec_id = tables.Execution.create(date = datetime.now())
# Parameters
self.queue = []
def createRow(self):
def prepare_database(self):
# create a row in each table for the current case
# shape
with self.database:
shape = self.database.getShape(execution = self.exec_id, **self.config.params)
if not shape:
shape = T.Shape(exec_id = self.exec_id, **self.config.params)
shape = tables.Shape(exec_id = self.exec_id, **self.config.params)
self.database.csave(shape)
# mesh
with self.database:
mesh = self.database.getMesh(execution = self.exec_id, **self.config.params)
if not mesh:
mesh = T.Mesh(shape_id = shape.shape_id)
mesh = tables.Mesh(shape_id = shape.shape_id)
self.database.csave(mesh)
# onephase flow
with self.database:
flow = self.database.getFlowOnephase(execution = self.exec_id, **self.config.params)
if not flow:
flow = T.FlowOnephase(mesh_id = mesh.mesh_id, **self.config.params)
flow = tables.FlowOnephase(mesh_id = mesh.mesh_id, **self.config.params)
self.database.csave(mesh)
def fill(self):
def prepare_queue(self):
self.config.expand()
logger.info(f"Preparing queue: { len(self.config.cases) }")
@ -101,7 +101,8 @@ class UltimateRunner(object):
@property
def casepath(self) -> PathLike:
params = self.config.params
path = Path(os.environ["ANISOTROPY_CWD"], os.environ["ANISOTROPY_BUILD_DIR"])
path = pathlib.Path(environ["AP_CWD"], environ["AP_BUILD_DIR"])
path /= "execution-{}".format(self.exec_id)
path /= "{}-[{},{},{}]-{}".format(
params["label"],
@ -111,7 +112,7 @@ class UltimateRunner(object):
return path.resolve()
def computeShape(self):
def compute_shape(self):
params = self.config.params
shapeParams = self.database.getShape(
params["label"],
@ -123,50 +124,53 @@ class UltimateRunner(object):
logger.info("Computing shape for {} with direction = {} and alpha = {}".format(
params["label"], params["direction"], params["alpha"]
))
shapeFile = self.casepath / "shape.step"
timer = Timer()
shapefile = self.casepath / "shape.step"
timer = utils.Timer()
if shapeFile.exists() and shapeParams.shapeStatus == "done" and not self.config["overwrite"]:
if (
shapefile.exists() and
shapeParams.shapeStatus == "done" and
not self.config["overwrite"]
):
logger.info("Shape exists. Skipping ...")
return
shapeSelected = {
"simple": Simple,
"bodyCentered": BodyCentered,
"faceCentered": FaceCentered
generate_shape = {
"simple": shaping.primitives.simple,
"bodyCentered": shaping.primitives.bodyCentered,
"faceCentered": shaping.primitives.faceCentered
}[shapeParams.label]
shape = shapeSelected(
direction = shapeParams.direction,
alpha = shapeParams.alpha,
r0 = shapeParams.r0,
filletsEnabled = shapeParams.filletsEnabled
)
with ErrorHandler() as (eh, handle):
handle(shape.build)()
try:
# generate shape
shape = generate_shape(
shapeParams.alpha,
shapeParams.direction,
r0 = shapeParams.r0,
filletsEnabled = shapeParams.filletsEnabled
)
if not eh.returncode:
# export
self.casepath.mkdir(exist_ok = True)
with ErrorHandler() as (eh, handle):
handle(shape.write)(shapeFile)
shape.write(shapefile)
if not eh.returncode:
except Exception as e:
logger.error(e)
shapeParams.shapeStatus = "failed"
else:
shapeParams.shapeStatus = "done"
shapeParams.volume = shape.shape.volume
shapeParams.volumeCell = shape.cell.volume
shapeParams.porosity = shapeParams.volume / shapeParams.volumeCell
else:
shapeParams.shapeStatus = "failed"
logger.error(eh.error)
# commit parameters
shapeParams.shapeExecutionTime = timer.elapsed()
self.database.csave(shapeParams)
def computeMesh(self):
err, returncode = "", 0
def compute_mesh(self):
params = self.config.params
meshParams = self.database.getMesh(
params["label"],
@ -178,59 +182,50 @@ class UltimateRunner(object):
logger.info("Computing mesh for {} with direction = {} and alpha = {}".format(
params["label"], params["direction"], params["alpha"]
))
meshFile = self.casepath / "mesh.mesh"
timer = Timer()
meshfile = self.casepath / "mesh.mesh"
timer = utils.Timer()
if meshFile.exists() and meshParams.meshStatus == "done" and not self.config["overwrite"]:
if (
meshfile.exists() and
meshParams.meshStatus == "done" and
not self.config["overwrite"]
):
logger.info("Mesh exists. Skipping ...")
return
# Shape
shape = None
shapeFile = self.casepath / "shape.step"
if not shapeFile.exists() and not shapeFile.is_file():
err = f"File not found: { shapeFile }"
returncode = 2
try:
# load shape
shapefile = self.casepath / "shape.step"
shape = shaping.Shape().read(shapefile)
if not returncode:
shape = Shape().read(shapeFile)
# generate mesh
parameters = meshing.MeshingParameters()
mesh = meshing.Mesh(shape)
mesh.generate(parameters)
# Mesh
if not returncode:
mesh = Mesh(shape.shape)
try:
mesh.generate()
except Exception as e:
err = e
returncode = 1
if not returncode:
# export
self.casepath.mkdir(exist_ok = True)
try:
mesh.write(meshFile)
mesh.write(self.casepath / "mesh.msh")
except Exception as e:
err = e
returncode = 1
mesh.write(meshfile)
mesh.write(self.casepath / "mesh.msh")
if not returncode:
except Exception as e:
logger.error(e)
meshParams.meshStatus = "failed"
else:
meshParams.meshStatus = "done"
meshParams.edges = len(self.mesh.edges)
meshParams.faces = len(self.mesh.faces)
meshParams.volumes = len(self.mesh.volumes)
else:
logger.error(err)
meshParams.meshStatus = "failed"
with self.database:
meshParams.meshExecutionTime = timer.elapsed()
meshParams.save()
# commit parameters
meshParams.meshExecutionTime = timer.elapsed()
self.database.csave(meshParams)
def computeFlow(self):
params = self.config.params
@ -245,55 +240,45 @@ class UltimateRunner(object):
logger.info("Computing flow for {} with direction = {} and alpha = {}".format(
params["label"], params["direction"], params["alpha"]
))
timer = Timer()
timer = utils.Timer()
# precalculate some parameters
flowParams.viscosityKinematic = flowParams.viscosity / flowParams.density
self.database.csave(flowParams)
with self.database:
flowParams.save()
#
flowParamsDict = self.database.getFlowOnephase(*query, to_dict = True)
with self.database:
flow = OnePhaseFlow(
direction = params["direction"],
**self.database.getFlowOnephase(*query, to_dict = True),
path = self.casepath
)
flow = solving.FlowOnephase(
direction = params["direction"],
**flowParamsDict,
path = self.casepath
)
# Shape
shapeFile = self.casepath / "shape.step"
if not shapeFile.exists() and not shapeFile.is_file():
err = f"File not found: { shapeFile }"
returncode = 2
if not returncode:
shape = Shape().read(shapeFile)
# Patches from occ to openfoam
patches = shape.patches(group = True, shiftIndex = True, prefix = "patch")
flow.createPatches(patches)
flow.write()
# Build a flow
try:
out, err, returncode = flow.build()
# load shape
shapefile = self.casepath / "shape.step"
shape = shaping.Shape().read(shapefile)
patches = shape.patches(group = True, shiftIndex = True, prefix = "patch")
# generate solution
flow.createPatches(patches)
flow.build()
except Exception as e:
# out, err, returncode = "", e, 1
logger.error(e, exc_info = True)
logger.error(e)
if returncode == 0:
flowParams.flowStatus = "done"
else:
# logger.error(err)
flowParams.flowStatus = "failed"
with self.database:
flowParams.flowExecutionTime = timer.elapsed()
flowParams.save()
else:
flowParams.flowStatus = "done"
def computePostProcess(self):
# commit parameters
flowParams.flowExecutionTime = timer.elapsed()
self.database.csave(flowParams)
def compute_postprocess(self):
params = self.config.params
flowParams = self.database.getFlowOnephase(
params["label"],
@ -306,33 +291,30 @@ class UltimateRunner(object):
params["label"], params["direction"], params["alpha"]
))
postProcess = PostProcess(self.casepath)
postProcess = postprocess.PostProcess(self.casepath)
if flowParams.flowStatus == "done":
flowParams.flowRate = postProcess.flowRate("outlet")
with self.database:
flowParams.save()
self.database.csave(flowParams)
self.dispose()
def pipeline(self, stage: str = None):
stage = stage or self.config["stage"]
if stage in ["shape", "all"]:
self.computeShape()
self.compute_shape()
if stage in ["mesh", "all"]:
self.computeMesh()
self.compute_mesh()
if stage in ["flow", "all"]:
self.computeFlow()
self.compute_flow()
if stage in ["postProcess", "all"]:
self.computePostProcess()
self.compute_postprocess()
@staticmethod
def subrunner(*args, **kwargs):
runner = UltimateRunner(config = kwargs["config"], exec_id = kwargs["exec_id"], typo = "worker")
runner.createRow()
runner = UltimateRunner(config = kwargs["config"], exec_id = kwargs["exec_id"])
runner.prepare_database()
runner.pipeline()

View File

@ -11,11 +11,11 @@ from . import tables
class Database(pw.SqliteDatabase):
def __init__(self, *args, **kwargs):
def __init__(self, filename: str = None, *args, **kwargs):
"""A Database object contains SQLite database with convient
properties and methods
"""
self.filepath = kwargs.get("path", None)
self.path = filename
self.pragmas_ = kwargs.get("pragmas", { "foreign_keys": 1, "journal_mode": "wal" })
self.field_types_ = kwargs.get("field_types", { "list": "text" })
self.autoconnect_ = kwargs.get("autoconnect", False)
@ -28,7 +28,7 @@ class Database(pw.SqliteDatabase):
autoconnect = self.autoconnect_
)
if self.filepath:
if self.path:
self.setup()
@property
@ -45,9 +45,9 @@ class Database(pw.SqliteDatabase):
:return:
Self.
"""
self.filepath = pathlib.Path(filename or self.filepath).resolve()
self.path = pathlib.Path(filename or self.path).resolve()
self.init(
self.filepath,
self.path,
pragmas = self.pragmas_
)
tables.database_proxy.initialize(self)

View File

@ -93,14 +93,21 @@ class Mesh:
return None if len(self.points) == 0 else self.points[0].size
@property
def geometry(self) -> ng_occ.OCCGeometry:
def geometry(self) -> ng_occ.OCCGeometry | None:
"""Netgen OCCGeometry object.
:return:
OCCGeometry object that can be used for meshing
or None if shape is not defined.
"""
return ng_occ.OCCGeometry(self.shape) if self.shape else None
if self.shape is not None:
if hasattr(self.shape, "geometry"):
return self.shape.geometry
else:
return ng_occ.OCCGeometry(self.shape)
return None
def generate(
self,

View File

@ -6,8 +6,10 @@ from anisotropy.openfoam import FoamCase, uniform
from numpy import array
import logging
logger = logging.getLogger(__name__)
class OnePhaseFlow(FoamCase):
def __init__(
self,
@ -132,7 +134,6 @@ class OnePhaseFlow(FoamCase):
p,
u
])
def createPatches(self, patches: dict):
# initial 43 unnamed patches ->
@ -172,7 +173,6 @@ class OnePhaseFlow(FoamCase):
self.append(createPatchDict)
def build(self) -> tuple[str, str, int]:
# TODO: configure working directory (FoamCase)
with self:
self.write()
@ -183,7 +183,7 @@ class OnePhaseFlow(FoamCase):
"scale": [1e-5, 1e-5, 1e-5]
})
R.renumberMesh()
#R.potentialFoam()
# R.potentialFoam()
self.read()