Mod: working mesh stage

This commit is contained in:
L-Nafaryus 2021-12-10 19:33:54 +05:00
parent 7454714d70
commit ace2cd0247
5 changed files with 104 additions and 134 deletions

View File

@ -61,22 +61,22 @@ class Config(object):
def expand(self): def expand(self):
self.cases = [] self.cases = []
# Expand structures for each direction and each theta # Expand structures for each direction and each alpha
for structure in self.content["structures"]: for structure in self.content["structures"]:
# ISSUE: precision error 0.06999999999999999 # ISSUE: precision error 0.06999999999999999
thetaA = round(arange( alphaA = round(arange(
structure["theta"][0], structure["alpha"][0],
structure["theta"][1] + structure["thetaStep"], structure["alpha"][1] + structure["alphaStep"],
structure["thetaStep"] structure["alphaStep"]
), 9) ), 9)
directionA = array(structure["directions"], dtype = float) directionA = array(structure["directions"], dtype = float)
for direction in directionA: for direction in directionA:
for theta in thetaA: for alpha in alphaA:
self.cases.append({ self.cases.append({
"label": structure["label"], "label": structure["label"],
"theta": theta, "alpha": alpha,
"thetaStep": structure["thetaStep"], "alphaStep": structure["alphaStep"],
"direction": direction, "direction": direction,
"r0": structure["r0"], "r0": structure["r0"],
"filletsEnabled": structure["filletsEnabled"] "filletsEnabled": structure["filletsEnabled"]
@ -101,13 +101,13 @@ class DefaultConfig(Config):
self.options = deepcopy(self.content["options"]) self.options = deepcopy(self.content["options"])
labels = ["simple", "bodyCentered", "faceCentered"] labels = ["simple", "bodyCentered", "faceCentered"]
thetas = [[0.01, 0.28], [0.01, 0.17], [0.01, 0.13]] alphas = [[0.01, 0.28], [0.01, 0.17], [0.01, 0.13]]
for label, theta in zip(labels, thetas): for label, alpha in zip(labels, alphas):
self.content["structures"].append({ self.content["structures"].append({
"label": label, "label": label,
"theta": theta, "alpha": alpha,
"thetaStep": 0.01, "alphaStep": 0.01,
"directions": [[1, 0, 0], [0, 0, 1], [1, 1, 1]], "directions": [[1, 0, 0], [0, 0, 1], [1, 1, 1]],
"r0": 1, "r0": 1,
"filletsEnabled": True "filletsEnabled": True

View File

@ -9,7 +9,7 @@ from os import path
from anisotropy.core.config import DefaultConfig from anisotropy.core.config import DefaultConfig
import logging import logging
from anisotropy.core.utils import parallel, ParallelRunner, setupLogger from anisotropy.core.utils import ParallelRunner, Timer
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -21,29 +21,34 @@ from anisotropy.shaping import Simple, BodyCentered, FaceCentered
from anisotropy.meshing import Mesh from anisotropy.meshing import Mesh
from anisotropy.openfoam.presets import CreatePatchDict from anisotropy.openfoam.presets import CreatePatchDict
from anisotropy.solving.onephase import OnePhaseFlow from anisotropy.solving.onephase import OnePhaseFlow
from multiprocessing import current_process, parent_process
class UltimateRunner(object): class UltimateRunner(object):
def __init__(self, config = None, exec_id = None, t_shape = None): def __init__(self, config = None, t_exec = None, t_shape = None):
# Configuration file
self.config = config or DefaultConfig() self.config = config or DefaultConfig()
self.type = "master" if not exec_id else "worker" # Process recognition
typo = True if not t_exec else False
#if current_process().name == "MainProcess" and parent_process() == None:
# current_process().name = "master"
if self.type == "master": # Database preparation
if typo: #current_process().name == "master":
self.prepareDatabase() self.prepareDatabase()
if self.type == "master": if typo: #current_process().name == "master":
with self.database: with self.database:
self.exec_id = T.Execution(date = datetime.now()) self.t_exec = T.Execution(date = datetime.now())
self.exec_id.save() self.t_exec.save()
self.t_shape = None self.t_shape = None
else: else:
self.exec_id = exec_id self.t_exec = t_exec
self.t_shape = t_shape self.t_shape = t_shape
# Parameters
self.shape = None self.shape = None
self.mesh = None self.mesh = None
self.flow = None self.flow = None
@ -52,10 +57,19 @@ class UltimateRunner(object):
def prepareDatabase(self): def prepareDatabase(self):
# NOTE: separate function in cause of unpicklability of connections # NOTE: separate function in cause of unpicklability of connections (use after process is started)
self.database = database self.database = database
self.database.setup(self.config["database"]) self.database.setup(self.config["database"])
def createRow(self):
# create a row in each table for the current case
with self.database:
self.t_mesh = T.Mesh(t_exec = self.t_exec, shape_id = self.t_shape)
self.t_mesh.save()
self.t_flow = T.FlowOnephase(t_exec = self.t_exec, mesh_id = self.t_mesh)
self.t_flow.save()
def fill(self): def fill(self):
self.config.expand() self.config.expand()
logger.info(f"Preparing queue: { len(self.config.cases) }") logger.info(f"Preparing queue: { len(self.config.cases) }")
@ -63,16 +77,17 @@ class UltimateRunner(object):
for case in self.config.cases: for case in self.config.cases:
with self.database: with self.database:
t_shape = T.Shape( t_shape = T.Shape(
exec_id = self.exec_id, exec_id = self.t_exec,
**case **case
) )
t_shape.save() t_shape.save()
self.queue.append(UltimateRunner( self.queue.append(UltimateRunner(
config = self.config, config = self.config,
exec_id = self.exec_id, t_exec = self.t_exec,
t_shape = t_shape t_shape = t_shape
)) ))
def start(self, queue: list = None, nprocs: int = None): def start(self, queue: list = None, nprocs: int = None):
nprocs = nprocs or self.config["nprocs"] nprocs = nprocs or self.config["nprocs"]
@ -90,62 +105,77 @@ class UltimateRunner(object):
def casepath(self): def casepath(self):
with self.database: with self.database:
params = T.Shape.get( params = T.Shape.get(
T.Shape.exec_id == self.exec_id, T.Shape.exec_id == self.t_exec,
T.Shape.shape_id == self.t_shape.shape_id T.Shape.shape_id == self.t_shape.shape_id
) )
direction = "direction-[{},{},{}]".format(*[ str(d) for d in params.direction ]) direction = "direction-[{},{},{}]".format(*[ str(d) for d in params.direction ])
theta = "theta-{}".format(params.theta) alpha = "alpha-{}".format(params.alpha)
dirpath = path.join(self.config["build"], params.label, direction, theta) dirpath = path.join(self.config["build"], params.label, direction, alpha)
return path.abspath(dirpath) return path.abspath(dirpath)
def computeShape(self): def computeShape(self):
if not self.type == "worker": #if current_process().name == "master":
return # return
with self.database: with self.database:
params = T.Shape.get( params = T.Shape.get(
T.Shape.exec_id == self.exec_id, T.Shape.exec_id == self.t_exec,
T.Shape.shape_id == self.t_shape.shape_id T.Shape.shape_id == self.t_shape.shape_id
) )
logger.info("Computing shape for {} with direction = {} and theta = {}".format(params.label, params.direction, params.theta)) logger.info("Computing shape for {} with direction = {} and alpha = {}".format(params.label, params.direction, params.alpha))
out, err, returncode = "", "", 0
filename = "shape.step" filename = "shape.step"
timer = Timer()
self.shape = {
shape = {
"simple": Simple, "simple": Simple,
"bodyCentered": BodyCentered, "bodyCentered": BodyCentered,
"faceCentered": FaceCentered "faceCentered": FaceCentered
}[params.label] }[params.label]
self.shape(params.direction) self.shape = shape(
direction = params.direction,
alpha = params.alpha,
r0 = params.r0,
filletsEnabled = params.filletsEnabled
)
self.shape.build() self.shape.build()
os.makedirs(self.casepath(), exist_ok = True) os.makedirs(self.casepath(), exist_ok = True)
self.shape.export(path.join(self.casepath(), filename)) out, err, returncode = self.shape.export(path.join(self.casepath(), filename))
if returncode == 0:
params.shapeStatus = "done"
params.shapeExecutionTime = timer.elapsed()
else:
logger.error(err)
params.shapeStatus = "failed"
params.shapeExecutionTime = timer.elapsed()
with self.database: with self.database:
params.shapeStatus = "Done"
params.save() params.save()
def computeMesh(self): def computeMesh(self):
if not self.type == "worker": #if not self.type == "worker":
return # return
with self.database: with self.database:
params = (T.Mesh.select(T.Shape, T.Mesh) t_params = T.Shape.get(
.join( T.Shape.exec_id == self.t_exec,
T.Mesh,
JOIN.INNER,
on = (T.Mesh.shape_id == T.Shape.shape_id)
).where(
T.Shape.exec_id == self.exec_id,
T.Shape.shape_id == self.t_shape.shape_id T.Shape.shape_id == self.t_shape.shape_id
)) )
params = T.Mesh.get(
T.Mesh.shape_id == self.t_shape.shape_id
)
logger.info("Computing mesh for {} with direction = {} and theta = {}".format(params.label, params.direction, params.theta)) logger.info("Computing mesh for {} with direction = {} and alpha = {}".format(t_params.label, t_params.direction, t_params.alpha))
filename = "mesh.mesh" filename = "mesh.mesh"
timer = Timer()
self.mesh = Mesh(self.shape.shape) self.mesh = Mesh(self.shape.shape)
self.mesh.build() self.mesh.build()
@ -153,6 +183,11 @@ class UltimateRunner(object):
os.makedirs(self.casepath(), exist_ok = True) os.makedirs(self.casepath(), exist_ok = True)
self.mesh.export(path.join(self.casepath(), filename)) self.mesh.export(path.join(self.casepath(), filename))
with self.database:
params.meshStatus = "done"
params.meshExecutionTime = timer.elapsed()
params.save()
def computeFlow(self): def computeFlow(self):
params = self.config.cases[0] params = self.config.cases[0]
flow = OnePhaseFlow(path = self.casepath()) flow = OnePhaseFlow(path = self.casepath())
@ -210,20 +245,21 @@ class UltimateRunner(object):
def pipeline(self, stage: str = None): def pipeline(self, stage: str = None):
self.prepareDatabase() self.prepareDatabase()
self.createRow()
stage = stage or self.config["stage"] stage = stage or self.config["stage"]
if stage in ["shape", "all"]: if stage in ["shape", "all"]:
self.computeShape() self.computeShape()
elif stage in ["mesh", "all"]: if stage in ["mesh", "all"]:
self.computeMesh() self.computeMesh()
elif stage in ["flow", "all"]: #elif stage in ["flow", "all"]:
self.computeFlow() # self.computeFlow()
elif stage in ["postProcess", "all"]: #elif stage in ["postProcess", "all"]:
self.postProcess() # self.postProcess()

View File

@ -220,75 +220,15 @@ def timer(func: FunctionType) -> (tuple, float):
class Timer(object): class Timer(object):
def __init__(self): def __init__(self):
self.start = time.monotonic() self.update()
def update(self):
self.start = time.monotonic()
def elapsed(self): def elapsed(self):
return time.monotonic() - self.start return time.monotonic() - self.start
def queue(cmd, qin, qout, *args):
while True:
# Get item from the queue
pos, var = qin.get()
# Exit point
if pos is None:
break
# Execute command
res = cmd(*var, *args)
# Put results to the queue
qout.put((pos, res))
return
def parallel(np, var, cmd):
varcount = len(var)
processes = []
nprocs = np if np <= cpu_count() else cpu_count()
qin = Queue(1)
qout = Queue()
# Create processes
for n in range(nprocs):
pargs = [cmd, qin, qout]
p = Process(target = queue, args = tuple(pargs))
processes.append(p)
# Start processes
for p in processes:
p.daemon = True
p.start()
# Fill queue
for n in range(varcount):
qin.put((n, var[n]))
for _ in range(nprocs):
qin.put((None, None))
# Get results
results = [[] for n in range(varcount)]
for n in range(varcount):
index, res = qout.get()
results[index] = res
# Wait until each processor has finished
for p in processes:
p.join()
return results
class ParallelRunner(object): class ParallelRunner(object):
def __init__(self, nprocs: int = 1, daemon: bool = True): def __init__(self, nprocs: int = 1, daemon: bool = True):
self.nprocs = nprocs self.nprocs = nprocs
@ -326,7 +266,7 @@ class ParallelRunner(object):
self.processes.append(Process( self.processes.append(Process(
target = self.queueRelease, target = self.queueRelease,
args = (self.queueInput, self.queueOutput), args = (self.queueInput, self.queueOutput),
name = f"PP-{ n + 1 }" name = f"worker-{ n + 1 }"
)) ))
for proc in self.processes: for proc in self.processes:
@ -349,10 +289,6 @@ class ParallelRunner(object):
self.__pos = -1 self.__pos = -1
def portIsFree(address, port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex((address, port)) == 0

View File

@ -31,12 +31,12 @@ class Shape(Model):
shape_id = AutoField() shape_id = AutoField()
exec_id = ForeignKeyField(Execution, backref = "executions") exec_id = ForeignKeyField(Execution, backref = "executions")
shapeStatus = TextField(null = True, default = "Idle") shapeStatus = TextField(null = True, default = "idle")
shapeCalculationTime = TimeField(null = True) shapeExecutionTime = TimeField(null = True)
label = TextField(null = True) label = TextField(null = True)
direction = JSONField(null = True) direction = JSONField(null = True)
theta = FloatField(null = True) alpha = FloatField(null = True)
r0 = FloatField(null = True) r0 = FloatField(null = True)
L = FloatField(null = True) L = FloatField(null = True)
@ -61,8 +61,8 @@ class Mesh(Model):
mesh_id = AutoField() mesh_id = AutoField()
shape_id = ForeignKeyField(Shape, backref = "shapes") shape_id = ForeignKeyField(Shape, backref = "shapes")
meshStatus = TextField(null = True, default = "Idle") meshStatus = TextField(null = True, default = "idle")
meshCalculationTime = TimeField(null = True) meshExecutionTime = TimeField(null = True)
elements = IntegerField(null = True) elements = IntegerField(null = True)
edges = IntegerField(null = True) edges = IntegerField(null = True)
@ -83,8 +83,8 @@ class FlowOnephase(Model):
flow_id = AutoField() flow_id = AutoField()
mesh_id = ForeignKeyField(Mesh, backref = "meshes") mesh_id = ForeignKeyField(Mesh, backref = "meshes")
flowStatus = TextField(null = True, default = "Idle") flowStatus = TextField(null = True, default = "idle")
flowCalculationTime = TimeField(null = True) flowExecutionTime = TimeField(null = True)
flowRate = FloatField(null = True) flowRate = FloatField(null = True)
permeability = FloatField(null = True) permeability = FloatField(null = True)

View File

@ -43,10 +43,8 @@ class TestCore(unittest.TestCase):
pathOld = os.path.abspath(".") pathOld = os.path.abspath(".")
config = self.core.DefaultConfig() config = self.core.DefaultConfig()
config.expand()
config.cases = [ config.cases[0] ]
runner = self.core.UltimateRunner(config = config, exec_id = True) runner = self.core.UltimateRunner(config = config)
runner.computeShape() runner.computeShape()
self.assertTrue(path.isfile(path.join(runner.casepath(), "shape.step"))) self.assertTrue(path.isfile(path.join(runner.casepath(), "shape.step")))