Mod: working mesh stage
This commit is contained in:
parent
7454714d70
commit
ace2cd0247
@ -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
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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")))
|
||||||
|
Loading…
Reference in New Issue
Block a user