Mod: improved openfoam interface
Mod: improved runners exception handlers Delete: some useless trash New: post process pipeline block
This commit is contained in:
parent
8e769ec1ce
commit
49368cc681
@ -124,7 +124,7 @@ def init(path, verbose):
|
|||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-s", "--stage", "stage",
|
"-s", "--stage", "stage",
|
||||||
type = click.Choice(["all", "shape", "mesh", "flow", "postProcessing"]),
|
type = click.Choice(["all", "shape", "mesh", "flow", "postProcess"]),
|
||||||
default = "all",
|
default = "all",
|
||||||
help = "Current computation stage"
|
help = "Current computation stage"
|
||||||
)
|
)
|
||||||
@ -146,7 +146,10 @@ def init(path, verbose):
|
|||||||
count = True,
|
count = True,
|
||||||
help = "Increase verbose level"
|
help = "Increase verbose level"
|
||||||
)
|
)
|
||||||
def compute(path, configFile, nprocs, stage, overwrite, params, verbose):
|
@click.option(
|
||||||
|
"--exec-id", "execution"
|
||||||
|
)
|
||||||
|
def compute(path, configFile, nprocs, stage, overwrite, params, verbose, execution):
|
||||||
from anisotropy.core.runner import UltimateRunner
|
from anisotropy.core.runner import UltimateRunner
|
||||||
from anisotropy.core.config import DefaultConfig
|
from anisotropy.core.config import DefaultConfig
|
||||||
from anisotropy.core.utils import setupLogger
|
from anisotropy.core.utils import setupLogger
|
||||||
@ -170,7 +173,7 @@ def compute(path, configFile, nprocs, stage, overwrite, params, verbose):
|
|||||||
overwrite = overwrite
|
overwrite = overwrite
|
||||||
)
|
)
|
||||||
|
|
||||||
runner = UltimateRunner(config = config)
|
runner = UltimateRunner(config = config, exec_id = execution)
|
||||||
runner.fill()
|
runner.fill()
|
||||||
runner.start()
|
runner.start()
|
||||||
|
|
||||||
|
@ -1,380 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
import os, sys
|
|
||||||
import time
|
|
||||||
from datetime import timedelta, datetime
|
|
||||||
import shutil
|
|
||||||
import logging
|
|
||||||
from copy import deepcopy
|
|
||||||
from math import sqrt
|
|
||||||
|
|
||||||
import toml
|
|
||||||
|
|
||||||
from anisotropy import (
|
|
||||||
__version__, env,
|
|
||||||
openfoam
|
|
||||||
)
|
|
||||||
from anisotropy.core.utils import setupLogger, Timer
|
|
||||||
from anisotropy.core.database import Database
|
|
||||||
from anisotropy import salomepl
|
|
||||||
import anisotropy.salomepl.utils
|
|
||||||
import anisotropy.salomepl.geometry
|
|
||||||
import anisotropy.salomepl.mesh
|
|
||||||
from anisotropy.samples import Simple, FaceCentered, BodyCentered
|
|
||||||
|
|
||||||
logger = logging.getLogger(env["logger_name"])
|
|
||||||
#setupLogger(logger, logging.INFO, env["LOG"])
|
|
||||||
|
|
||||||
#peeweeLogger = logging.getLogger("peewee")
|
|
||||||
#peeweeLogger.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
class Anisotropy(object):
|
|
||||||
"""Ultimate class that organizes whole working process"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Constructor method"""
|
|
||||||
|
|
||||||
self.env = env
|
|
||||||
self.db = None #Database(self.env["db_name"], self.env["db_path"])
|
|
||||||
self.params = []
|
|
||||||
|
|
||||||
|
|
||||||
def load(self, structure_type: str, structure_direction: list, structure_theta: float):
|
|
||||||
"""Shortcut for `Database.setup` and `Database.load`.
|
|
||||||
|
|
||||||
See :class:`anisotropy.core.database.Database` for more details.
|
|
||||||
"""
|
|
||||||
self.db.setup()
|
|
||||||
self.params = self.db.load(structure_type, structure_direction, structure_theta)
|
|
||||||
|
|
||||||
def update(self, params: dict = None):
|
|
||||||
"""Shortcut for `Database.setup` and `Database.update`.
|
|
||||||
|
|
||||||
See :class:`anisotropy.core.database.Database` for more details.
|
|
||||||
"""
|
|
||||||
self.db.setup()
|
|
||||||
self.db.update(self.params if not params else params)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def version():
|
|
||||||
"""Returns versions of all used main programs
|
|
||||||
|
|
||||||
:return:
|
|
||||||
Versions joined by next line symbol
|
|
||||||
"""
|
|
||||||
versions = {
|
|
||||||
"anisotropy": __version__,
|
|
||||||
"Python": sys.version.split(" ")[0],
|
|
||||||
"Salome": "[missed]",
|
|
||||||
"OpenFOAM": "[missed]"
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
versions["Salome"] = salomepl.utils.SalomeManager().version()
|
|
||||||
versions["OpenFOAM"] = openfoam.version()
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return "\n".join([ f"{ k }: { v }" for k, v in versions.items() ])
|
|
||||||
|
|
||||||
|
|
||||||
def loadFromScratch(self, configpath: str = None) -> list:
|
|
||||||
"""Loads parameters from configuration file and expands special values
|
|
||||||
|
|
||||||
:return:
|
|
||||||
List of dicts with parameters
|
|
||||||
"""
|
|
||||||
config = configpath or self.env["CONFIG"]
|
|
||||||
|
|
||||||
if not os.path.exists(config):
|
|
||||||
logger.error("Missed configuration file")
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.info(f"Configuration file: { config }")
|
|
||||||
|
|
||||||
buf = toml.load(config).get("structures")
|
|
||||||
paramsAll = []
|
|
||||||
|
|
||||||
|
|
||||||
for entry in buf:
|
|
||||||
# Shortcuts
|
|
||||||
_theta = entry["structure"]["theta"]
|
|
||||||
thetaMin = int(_theta[0] / _theta[2])
|
|
||||||
thetaMax = int(_theta[1] / _theta[2]) + 1
|
|
||||||
thetaList = list(
|
|
||||||
map(lambda n: n * _theta[2], range(thetaMin, thetaMax))
|
|
||||||
)
|
|
||||||
|
|
||||||
_thickness = entry["mesh"]["thickness"]
|
|
||||||
count = len(thetaList)
|
|
||||||
thicknessList = list(
|
|
||||||
map(lambda n: _thickness[0] + n * (_thickness[1] - _thickness[0]) / (count - 1), range(0, count))
|
|
||||||
)
|
|
||||||
|
|
||||||
for direction in entry["structure"]["directions"]:
|
|
||||||
for n, theta in enumerate(thetaList):
|
|
||||||
mesh = deepcopy(entry["mesh"])
|
|
||||||
mesh["thickness"] = thicknessList[n]
|
|
||||||
|
|
||||||
entryNew = {
|
|
||||||
"structure": dict(
|
|
||||||
type = entry["structure"]["type"],
|
|
||||||
theta = theta,
|
|
||||||
direction = [ float(num) for num in direction ],
|
|
||||||
filletsEnabled = entry["structure"]["filletsEnabled"]
|
|
||||||
),
|
|
||||||
"mesh": mesh,
|
|
||||||
"submesh": deepcopy(entry["submesh"]),
|
|
||||||
"meshresult": dict(),
|
|
||||||
"flow": deepcopy(entry["flow"]),
|
|
||||||
"flowapproximation": deepcopy(entry["flowapproximation"]),
|
|
||||||
"flowresult": dict(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
paramsAll.append(entryNew)
|
|
||||||
|
|
||||||
return paramsAll
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getCasePath(self, path: str = None) -> str:
|
|
||||||
"""Constructs case path from control parameters
|
|
||||||
|
|
||||||
:return: Absolute path to case
|
|
||||||
:rtype: str
|
|
||||||
"""
|
|
||||||
structure = self.params.get("structure")
|
|
||||||
|
|
||||||
if not structure:
|
|
||||||
logger.error("Trying to use empty parameters")
|
|
||||||
return
|
|
||||||
|
|
||||||
if path:
|
|
||||||
path = os.path.join(path, "build")
|
|
||||||
|
|
||||||
else:
|
|
||||||
path = self.env["BUILD"]
|
|
||||||
|
|
||||||
return os.path.join(
|
|
||||||
path,
|
|
||||||
structure["type"],
|
|
||||||
"direction-{}".format(str(structure['direction']).replace(" ", "")),
|
|
||||||
f"theta-{ structure['theta'] }"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def computeMesh(self, path):
|
|
||||||
"""Computes a mesh on shape via Salome
|
|
||||||
|
|
||||||
:return: Process output, error messages and returncode
|
|
||||||
:rtype: tuple(str, str, int)
|
|
||||||
"""
|
|
||||||
p = self.params["structure"]
|
|
||||||
scriptpath = os.path.join(self.env["ROOT"], "anisotropy/core/cli.py")
|
|
||||||
salomeargs = [
|
|
||||||
"computemesh",
|
|
||||||
p["type"],
|
|
||||||
p["direction"],
|
|
||||||
p["theta"],
|
|
||||||
path
|
|
||||||
]
|
|
||||||
manager = salomepl.utils.SalomeManager()
|
|
||||||
casepath = self.getCasePath(path)
|
|
||||||
|
|
||||||
self.params["meshresult"]["meshStatus"] = "Computing"
|
|
||||||
self.update()
|
|
||||||
timer = Timer()
|
|
||||||
|
|
||||||
out, err, returncode = manager.execute(
|
|
||||||
scriptpath,
|
|
||||||
*salomeargs,
|
|
||||||
timeout = self.env["salome_timeout"],
|
|
||||||
root = self.env["ROOT"],
|
|
||||||
logpath = casepath
|
|
||||||
)
|
|
||||||
self.load(p["type"], p["direction"], p["theta"])
|
|
||||||
|
|
||||||
if not returncode:
|
|
||||||
self.params["meshresult"].update(
|
|
||||||
meshStatus = "Done",
|
|
||||||
meshCalculationTime = timer.elapsed()
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.params["meshresult"].update(
|
|
||||||
meshStatus = "Failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
return out, err, returncode
|
|
||||||
|
|
||||||
|
|
||||||
def genmesh(self, path):
|
|
||||||
"""Computes a mesh on shape
|
|
||||||
|
|
||||||
Warning: Working only inside Salome Environment
|
|
||||||
"""
|
|
||||||
|
|
||||||
setupLogger(logger, logging.INFO, self.env["LOG"])
|
|
||||||
p = self.params
|
|
||||||
|
|
||||||
sGeometry, sMesh = dict(
|
|
||||||
simple = (Simple, SimpleMesh),
|
|
||||||
bodyCentered = (BodyCentered, BodyCenteredMesh),
|
|
||||||
faceCentered = (FaceCentered, FaceCenteredMesh)
|
|
||||||
)[p["structure"]["type"]]
|
|
||||||
|
|
||||||
# Shape
|
|
||||||
logger.info("Constructing shape ...")
|
|
||||||
geometry = sGeometry(**p["structure"])
|
|
||||||
geometry.build()
|
|
||||||
|
|
||||||
# Mesh
|
|
||||||
logger.info("Prepairing mesh ...")
|
|
||||||
mesh = sMesh(geometry)
|
|
||||||
mesh.build()
|
|
||||||
|
|
||||||
logger.info("Computing mesh ...")
|
|
||||||
out, err, returncode = mesh.compute()
|
|
||||||
|
|
||||||
|
|
||||||
if not returncode:
|
|
||||||
mesh.removePyramids()
|
|
||||||
mesh.createGroups()
|
|
||||||
|
|
||||||
casePath = self.getCasePath(path)
|
|
||||||
os.makedirs(casePath, exist_ok = True)
|
|
||||||
logger.info("Exporting mesh ...")
|
|
||||||
out, err, returncode = mesh.export(os.path.join(casePath, "mesh.unv"))
|
|
||||||
|
|
||||||
if returncode:
|
|
||||||
logger.error(err)
|
|
||||||
|
|
||||||
# NOTE: edit from here
|
|
||||||
meshStats = mesh.stats()
|
|
||||||
p["meshresult"].update(
|
|
||||||
surfaceArea = surfaceArea,
|
|
||||||
volume = volume,
|
|
||||||
volumeCell = shapeGeometry.volumeCell,
|
|
||||||
**meshStats
|
|
||||||
)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.error(err)
|
|
||||||
|
|
||||||
p["meshresult"].update(
|
|
||||||
surfaceArea = surfaceArea,
|
|
||||||
volume = volume,
|
|
||||||
volumeCell = shapeGeometry.volumeCell
|
|
||||||
)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
|
|
||||||
def computeFlow(self, path):
|
|
||||||
"""Computes a flow on mesh via OpenFOAM
|
|
||||||
|
|
||||||
:return:
|
|
||||||
Process output, error messages and returncode
|
|
||||||
"""
|
|
||||||
###
|
|
||||||
# Case preparation
|
|
||||||
##
|
|
||||||
foamCase = [ "0", "constant", "system" ]
|
|
||||||
#self.params["flowresult"] = dict()
|
|
||||||
self.params["flowresult"]["flowStatus"] = "Computing"
|
|
||||||
self.update()
|
|
||||||
timer = Timer()
|
|
||||||
|
|
||||||
flow = self.params["flow"]
|
|
||||||
flowapproximation = self.params["flowapproximation"]
|
|
||||||
|
|
||||||
# ISSUE: ideasUnvToFoam cannot import mesh with '-case' flag so 'os.chdir' for that
|
|
||||||
casePath = self.getCasePath(path)
|
|
||||||
|
|
||||||
if not os.path.exists(casePath):
|
|
||||||
err = f"Cannot find case path { casePath }"
|
|
||||||
self.params["flowresult"]["flowStatus"] = "Failed"
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
return "", err, 1
|
|
||||||
|
|
||||||
os.chdir(casePath)
|
|
||||||
openfoam.foamClean()
|
|
||||||
|
|
||||||
for d in foamCase:
|
|
||||||
shutil.copytree(
|
|
||||||
os.path.join(self.env["openfoam_template"], d),
|
|
||||||
os.path.join(casePath, d)
|
|
||||||
)
|
|
||||||
|
|
||||||
###
|
|
||||||
# Mesh manipulations
|
|
||||||
##
|
|
||||||
if not os.path.exists("mesh.unv"):
|
|
||||||
os.chdir(path or self.env["ROOT"])
|
|
||||||
|
|
||||||
err = f"Missed 'mesh.unv'"
|
|
||||||
self.params["flowresult"]["flowStatus"] = "Failed"
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
return "", err, 1
|
|
||||||
|
|
||||||
out, err, returncode = openfoam.ideasUnvToFoam("mesh.unv")
|
|
||||||
|
|
||||||
out, err, returncode = openfoam.checkMesh()
|
|
||||||
|
|
||||||
if out: logger.warning(out)
|
|
||||||
|
|
||||||
out, err, returncode = openfoam.simpleFoam()
|
|
||||||
|
|
||||||
if not returncode:
|
|
||||||
self.params["flowresult"]["flowCalculationTime"] = timer.elapsed()
|
|
||||||
self.params["flowresult"]["flowStatus"] = "Done"
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.params["flowresult"]["flowStatus"] = "Failed"
|
|
||||||
|
|
||||||
self.update()
|
|
||||||
os.chdir(path or self.env["ROOT"])
|
|
||||||
|
|
||||||
return out, str(err, "utf-8"), returncode
|
|
||||||
|
|
||||||
|
|
||||||
def flowRate(self):
|
|
||||||
casePath = self.getCasePath()
|
|
||||||
foamPostProcessing = "postProcessing/flowRatePatch(name=outlet)/0/surfaceFieldValue.dat"
|
|
||||||
path = os.path.join(casePath, foamPostProcessing)
|
|
||||||
|
|
||||||
if not os.path.exists(path):
|
|
||||||
logger.warning(f"Unable to compute flow rate. Missed { path }")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
with open(path, "r") as io:
|
|
||||||
lastLine = io.readlines()[-1]
|
|
||||||
flowRate = float(lastLine.replace(" ", "").replace("\n", "").split("\t")[1])
|
|
||||||
|
|
||||||
self.params["flowresult"]["flowRate"] = flowRate
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
return flowRate
|
|
||||||
|
|
||||||
|
|
||||||
def porosity(self):
|
|
||||||
mr = self.params["meshresult"]
|
|
||||||
fr = self.params["flowresult"]
|
|
||||||
|
|
||||||
fr["porosity"] = mr["volume"] / mr["volumeCell"]
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
return fr["porosity"]
|
|
@ -2,4 +2,24 @@
|
|||||||
# This file is part of anisotropy.
|
# This file is part of anisotropy.
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from anisotropy.openfoam.runnerPresets import postProcess
|
||||||
|
from anisotropy.openfoam import datReader
|
||||||
|
|
||||||
|
|
||||||
|
class PostProcess(object):
|
||||||
|
def __init__(self, dirpath):
|
||||||
|
self.path = path.abspath(dirpath)
|
||||||
|
|
||||||
|
def flowRate(self, patch: str):
|
||||||
|
func = "patchFlowRate(patch={})".format(patch)
|
||||||
|
filepath = path.join(self.path, "postProcessing", func, "0", "surfaceFieldValue.dat")
|
||||||
|
postProcess(func, cwd = self.path)
|
||||||
|
surfaceFieldValue = datReader(filepath)
|
||||||
|
|
||||||
|
return surfaceFieldValue["sum(phi)"][-1]
|
||||||
|
|
||||||
|
@ -9,44 +9,36 @@ from os import path
|
|||||||
from anisotropy.core.config import DefaultConfig
|
from anisotropy.core.config import DefaultConfig
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from anisotropy.core.postProcess import PostProcess
|
||||||
from anisotropy.core.utils import ParallelRunner, Timer
|
from anisotropy.core.utils import ParallelRunner, Timer
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
from anisotropy.database import Database, tables as T
|
from anisotropy.database import Database, tables as T
|
||||||
|
|
||||||
from anisotropy.shaping import Simple, BodyCentered, FaceCentered
|
from anisotropy.shaping import Simple, BodyCentered, FaceCentered, Shape
|
||||||
from anisotropy.meshing import Mesh
|
from anisotropy.meshing import Mesh
|
||||||
from anisotropy.openfoam.presets import CreatePatchDict
|
|
||||||
from anisotropy.solving import OnePhaseFlow
|
from anisotropy.solving import OnePhaseFlow
|
||||||
from multiprocessing import current_process, parent_process
|
|
||||||
|
|
||||||
class UltimateRunner(object):
|
class UltimateRunner(object):
|
||||||
def __init__(self, config = None, exec_id: int = None): #t_exec = None, t_shape = None):
|
def __init__(self, config = None, exec_id: int = None, typo: str = "master"):
|
||||||
# Configuration file
|
# Configuration file
|
||||||
self.config = config or DefaultConfig()
|
self.config = config or DefaultConfig()
|
||||||
|
|
||||||
# Process recognition
|
# Process recognition
|
||||||
typo = True if not exec_id else False
|
self.typo = typo
|
||||||
#if current_process().name == "MainProcess" and parent_process() == None:
|
|
||||||
# current_process().name = "master"
|
|
||||||
|
|
||||||
# Database preparation
|
# Database preparation
|
||||||
if typo: #current_process().name == "master":
|
self.database = Database(path = self.config["database"])
|
||||||
self.database = Database(path = self.config["database"])
|
|
||||||
|
|
||||||
if typo: #current_process().name == "master":
|
if exec_id:
|
||||||
|
if self.database.getExecution(exec_id):
|
||||||
|
self.exec_id = exec_id
|
||||||
|
|
||||||
|
if not self.exec_id:
|
||||||
with self.database:
|
with self.database:
|
||||||
self.t_exec = T.Execution(date = datetime.now())
|
self.exec_id = T.Execution.create(date=datetime.now())
|
||||||
self.t_exec.save()
|
|
||||||
|
|
||||||
#self.t_shape = None
|
|
||||||
|
|
||||||
else:
|
|
||||||
#self.t_exec = self.database.getExecution(exec_id)
|
|
||||||
self.exec_id = exec_id
|
|
||||||
#self.t_exec = t_exec
|
|
||||||
#self.t_shape = t_shape
|
|
||||||
|
|
||||||
# Parameters
|
# Parameters
|
||||||
self.shape = None
|
self.shape = None
|
||||||
@ -59,12 +51,20 @@ class UltimateRunner(object):
|
|||||||
def createRow(self):
|
def createRow(self):
|
||||||
# create a row in each table for the current case
|
# create a row in each table for the current case
|
||||||
with self.database:
|
with self.database:
|
||||||
t_shape = T.Shape(exec_id = self.exec_id, **self.config.params)
|
shape = self.database.getShape(execution = self.exec_id, **self.config.params)
|
||||||
t_shape.save()
|
|
||||||
t_mesh = T.Mesh(shape_id = t_shape.shape_id)
|
if not shape:
|
||||||
t_mesh.save()
|
shape = T.Shape.create(exec_id = self.exec_id, **self.config.params)
|
||||||
t_flow = T.FlowOnephase(mesh_id = t_mesh.mesh_id)
|
|
||||||
t_flow.save()
|
mesh = self.database.getMesh(execution = self.exec_id, **self.config.params)
|
||||||
|
|
||||||
|
if not mesh:
|
||||||
|
mesh = T.Mesh.create(shape_id = shape)
|
||||||
|
|
||||||
|
flow = self.database.getFlowOnephase(execution = self.exec_id, **self.config.params)
|
||||||
|
|
||||||
|
if not flow:
|
||||||
|
flow = T.FlowOnephase.create(mesh_id = mesh)
|
||||||
|
|
||||||
def fill(self):
|
def fill(self):
|
||||||
self.config.expand()
|
self.config.expand()
|
||||||
@ -75,19 +75,11 @@ class UltimateRunner(object):
|
|||||||
config.chooseParams(idn)
|
config.chooseParams(idn)
|
||||||
config.minimize()
|
config.minimize()
|
||||||
|
|
||||||
#with self.database:
|
kwargs = {
|
||||||
# t_shape = T.Shape(
|
"config": config,
|
||||||
# exec_id = self.t_exec,
|
"exec_id": self.exec_id
|
||||||
# **case
|
}
|
||||||
# )
|
self.queue.append(kwargs)
|
||||||
# t_shape.save()
|
|
||||||
|
|
||||||
self.queue.append(UltimateRunner(
|
|
||||||
config = config,
|
|
||||||
exec_id = self.t_exec.exec_id
|
|
||||||
#t_exec = self.t_exec,
|
|
||||||
#t_shape = t_shape
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
def start(self, queue: list = None, nprocs: int = None):
|
def start(self, queue: list = None, nprocs: int = None):
|
||||||
@ -97,44 +89,22 @@ class UltimateRunner(object):
|
|||||||
parallel = ParallelRunner(nprocs = nprocs)
|
parallel = ParallelRunner(nprocs = nprocs)
|
||||||
parallel.start()
|
parallel.start()
|
||||||
|
|
||||||
for runner in self.queue:
|
for kwargs in self.queue:
|
||||||
parallel.append(runner.pipeline, args = [self.config["stage"]])
|
parallel.append(self.subrunner, kwargs = kwargs)
|
||||||
|
|
||||||
parallel.wait()
|
parallel.wait()
|
||||||
# TODO: if runner done - remove from queue; results from parallel function
|
|
||||||
|
|
||||||
def casepath(self):
|
def casepath(self):
|
||||||
#with self.database:
|
|
||||||
# params = T.Shape.get(
|
|
||||||
# T.Shape.exec_id == self.t_exec,
|
|
||||||
# T.Shape.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
params = self.config.params
|
params = self.config.params
|
||||||
shapeParams = self.database.getShape(
|
|
||||||
params["label"],
|
|
||||||
params["direction"],
|
|
||||||
params["alpha"],
|
|
||||||
self.exec_id
|
|
||||||
)
|
|
||||||
|
|
||||||
execution = "execution-{}".format(self.exec_id)
|
execution = "execution-{}".format(self.exec_id)
|
||||||
case = "{}-[{},{},{}]-{}".format(params["label"], *[ str(d) for d in params["direction"] ], params["alpha"])
|
case = "{}-[{},{},{}]-{}".format(params["label"], *[ str(d) for d in params["direction"] ], params["alpha"])
|
||||||
#alpha = "alpha-{}".format(shapeParams.alpha)
|
|
||||||
#dirpath = path.join(self.config["build"], shapeParams.label, direction, alpha)
|
|
||||||
dirpath = path.join(self.config["build"], execution, case)
|
dirpath = path.join(self.config["build"], execution, case)
|
||||||
|
|
||||||
return path.abspath(dirpath)
|
return path.abspath(dirpath)
|
||||||
|
|
||||||
def computeShape(self):
|
def computeShape(self):
|
||||||
#if current_process().name == "master":
|
out, err, returncode = "", "", 0
|
||||||
# return
|
|
||||||
|
|
||||||
#with self.database:
|
|
||||||
# params = T.Shape.get(
|
|
||||||
# T.Shape.exec_id == self.t_exec,
|
|
||||||
# T.Shape.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
|
|
||||||
params = self.config.params
|
params = self.config.params
|
||||||
shapeParams = self.database.getShape(
|
shapeParams = self.database.getShape(
|
||||||
params["label"],
|
params["label"],
|
||||||
@ -161,14 +131,19 @@ class UltimateRunner(object):
|
|||||||
r0 = shapeParams.r0,
|
r0 = shapeParams.r0,
|
||||||
filletsEnabled = shapeParams.filletsEnabled
|
filletsEnabled = shapeParams.filletsEnabled
|
||||||
)
|
)
|
||||||
#out, err, returncode = self.shape.build()
|
|
||||||
# TODO: wrap build function for exceptions
|
|
||||||
self.shape.build()
|
|
||||||
|
|
||||||
os.makedirs(self.casepath(), exist_ok = True)
|
try:
|
||||||
out, err, returncode = self.shape.export(path.join(self.casepath(), filename))
|
self.shape.build()
|
||||||
|
|
||||||
if returncode == 0:
|
except Exception as e:
|
||||||
|
err = e
|
||||||
|
returncode = 1
|
||||||
|
|
||||||
|
if not returncode:
|
||||||
|
os.makedirs(self.casepath(), exist_ok = True)
|
||||||
|
out, err, returncode = self.shape.export(path.join(self.casepath(), filename))
|
||||||
|
|
||||||
|
if not returncode:
|
||||||
shapeParams.shapeStatus = "done"
|
shapeParams.shapeStatus = "done"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -180,18 +155,7 @@ class UltimateRunner(object):
|
|||||||
shapeParams.save()
|
shapeParams.save()
|
||||||
|
|
||||||
def computeMesh(self):
|
def computeMesh(self):
|
||||||
#if not self.type == "worker":
|
out, err, returncode = "", "", 0
|
||||||
# return
|
|
||||||
|
|
||||||
#with self.database:
|
|
||||||
# t_params = T.Shape.get(
|
|
||||||
# T.Shape.exec_id == self.t_exec,
|
|
||||||
# T.Shape.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
# params = T.Mesh.get(
|
|
||||||
# T.Mesh.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
|
|
||||||
params = self.config.params
|
params = self.config.params
|
||||||
meshParams = self.database.getMesh(
|
meshParams = self.database.getMesh(
|
||||||
params["label"],
|
params["label"],
|
||||||
@ -206,16 +170,33 @@ class UltimateRunner(object):
|
|||||||
filename = "mesh.mesh"
|
filename = "mesh.mesh"
|
||||||
timer = Timer()
|
timer = Timer()
|
||||||
|
|
||||||
# TODO: load from object or file
|
if not self.shape:
|
||||||
self.mesh = Mesh(self.shape.shape)
|
filename = "shape.step"
|
||||||
#out, err, returncode = self.mesh.build()
|
filepath = path.join(self.casepath(), filename)
|
||||||
# TODO: wrap build function for exceptions
|
|
||||||
self.mesh.build()
|
|
||||||
|
|
||||||
os.makedirs(self.casepath(), exist_ok = True)
|
if not path.exists(filepath) and not path.isfile(filepath):
|
||||||
out, err, returncode = self.mesh.export(path.join(self.casepath(), filename))
|
err = f"File not found: { filepath }"
|
||||||
|
returncode = 2
|
||||||
|
|
||||||
if returncode == 0:
|
if not returncode:
|
||||||
|
self.shape = Shape()
|
||||||
|
self.shape.load(filepath)
|
||||||
|
|
||||||
|
if not returncode:
|
||||||
|
self.mesh = Mesh(self.shape.shape)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mesh.build()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
err = e
|
||||||
|
returncode = 1
|
||||||
|
|
||||||
|
if not returncode:
|
||||||
|
os.makedirs(self.casepath(), exist_ok = True)
|
||||||
|
out, err, returncode = self.mesh.export(path.join(self.casepath(), filename))
|
||||||
|
|
||||||
|
if not returncode:
|
||||||
meshParams.meshStatus = "done"
|
meshParams.meshStatus = "done"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -227,21 +208,6 @@ class UltimateRunner(object):
|
|||||||
meshParams.save()
|
meshParams.save()
|
||||||
|
|
||||||
def computeFlow(self):
|
def computeFlow(self):
|
||||||
# if not self.type == "worker":
|
|
||||||
# return
|
|
||||||
|
|
||||||
#with self.database:
|
|
||||||
# t_params = T.Shape.get(
|
|
||||||
# T.Shape.exec_id == self.t_exec,
|
|
||||||
# T.Shape.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
# m_params = T.Mesh.get(
|
|
||||||
# T.Mesh.shape_id == self.t_shape.shape_id
|
|
||||||
# )
|
|
||||||
# params = T.FlowOnephase.get(
|
|
||||||
# T.FlowOnephase.mesh_id == self.t_mesh.mesh_id
|
|
||||||
# )
|
|
||||||
|
|
||||||
params = self.config.params
|
params = self.config.params
|
||||||
flowParams = self.database.getFlowOnephase(
|
flowParams = self.database.getFlowOnephase(
|
||||||
params["label"],
|
params["label"],
|
||||||
@ -255,55 +221,26 @@ class UltimateRunner(object):
|
|||||||
))
|
))
|
||||||
timer = Timer()
|
timer = Timer()
|
||||||
|
|
||||||
self.flow = OnePhaseFlow(path = self.casepath())
|
self.flow = OnePhaseFlow(params["direction"], path = self.casepath())
|
||||||
|
|
||||||
# initial 43 unnamed patches ->
|
if not self.shape:
|
||||||
# 6 named patches (inlet, outlet, wall, symetry0 - 3/5) ->
|
filename = "shape.step"
|
||||||
# 4 inGroups (inlet, outlet, wall, symetry)
|
filepath = path.join(self.casepath(), filename)
|
||||||
createPatchDict = CreatePatchDict()
|
|
||||||
createPatchDict["patches"] = []
|
|
||||||
patches = {}
|
|
||||||
|
|
||||||
for n, patch in enumerate(self.shape.shape.faces):
|
if not path.exists(filepath) and not path.isfile(filepath):
|
||||||
# shifted index
|
err = f"File not found: { filepath }"
|
||||||
n += 1
|
returncode = 2
|
||||||
name = patch.name
|
|
||||||
|
|
||||||
if patches.get(name):
|
if not returncode:
|
||||||
patches[name].append(f"patch{ n }")
|
self.shape = Shape()
|
||||||
|
self.shape.load(filepath)
|
||||||
|
|
||||||
else:
|
faces = [ (n, face.name) for n, face in enumerate(self.shape.shape.faces) ]
|
||||||
patches[name] = [ f"patch{ n }" ]
|
createPatchDict = OnePhaseFlow.facesToPatches(faces)
|
||||||
|
|
||||||
for name in patches.keys():
|
|
||||||
if name == "inlet":
|
|
||||||
patchGroup = "inlet"
|
|
||||||
patchType = "patch"
|
|
||||||
|
|
||||||
elif name == "outlet":
|
|
||||||
patchGroup = "outlet"
|
|
||||||
patchType = "patch"
|
|
||||||
|
|
||||||
elif name == "wall":
|
|
||||||
patchGroup = "wall"
|
|
||||||
patchType = "wall"
|
|
||||||
|
|
||||||
else:
|
|
||||||
patchGroup = "symetry"
|
|
||||||
patchType = "symetryPlane"
|
|
||||||
|
|
||||||
createPatchDict["patches"].append({
|
|
||||||
"name": name,
|
|
||||||
"patchInfo": {
|
|
||||||
"type": patchType,
|
|
||||||
"inGroups": [patchGroup]
|
|
||||||
},
|
|
||||||
"constructFrom": "patches",
|
|
||||||
"patches": patches[name]
|
|
||||||
})
|
|
||||||
|
|
||||||
self.flow.append(createPatchDict)
|
self.flow.append(createPatchDict)
|
||||||
self.flow.write()
|
self.flow.write()
|
||||||
|
|
||||||
# Build a flow
|
# Build a flow
|
||||||
try:
|
try:
|
||||||
out, err, returncode = self.flow.build()
|
out, err, returncode = self.flow.build()
|
||||||
@ -323,16 +260,30 @@ class UltimateRunner(object):
|
|||||||
flowParams.flowExecutionTime = timer.elapsed()
|
flowParams.flowExecutionTime = timer.elapsed()
|
||||||
flowParams.save()
|
flowParams.save()
|
||||||
|
|
||||||
def pipeline(self, stage: str = None):
|
def computePostProcess(self):
|
||||||
self.database = Database(path = self.config["database"])
|
params = self.config.params
|
||||||
self.createRow()
|
flowParams = self.database.getFlowOnephase(
|
||||||
|
params["label"],
|
||||||
|
params["direction"],
|
||||||
|
params["alpha"],
|
||||||
|
self.exec_id
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("Computing post process for {} with direction = {} and alpha = {}".format(
|
||||||
|
params["label"], params["direction"], params["alpha"]
|
||||||
|
))
|
||||||
|
|
||||||
|
postProcess = PostProcess(self.casepath())
|
||||||
|
|
||||||
|
if flowParams.flowStatus == "done":
|
||||||
|
flowParams.flowRate = postProcess.flowRate("outlet")
|
||||||
|
|
||||||
|
with self.database:
|
||||||
|
flowParams.save()
|
||||||
|
|
||||||
|
def pipeline(self, stage: str = None):
|
||||||
stage = stage or self.config["stage"]
|
stage = stage or self.config["stage"]
|
||||||
|
|
||||||
# TODO: fix flow
|
|
||||||
# TODO: change case path to execDATE/label-direction-theta/*
|
|
||||||
# TODO: fix nprocs
|
|
||||||
#try:
|
|
||||||
if stage in ["shape", "all"]:
|
if stage in ["shape", "all"]:
|
||||||
self.computeShape()
|
self.computeShape()
|
||||||
|
|
||||||
@ -342,10 +293,16 @@ class UltimateRunner(object):
|
|||||||
if stage in ["flow", "all"]:
|
if stage in ["flow", "all"]:
|
||||||
self.computeFlow()
|
self.computeFlow()
|
||||||
|
|
||||||
#elif stage in ["postProcess", "all"]:
|
if stage in ["postProcess", "all"]:
|
||||||
# self.postProcess()
|
self.computePostProcess()
|
||||||
#except Exception as e:
|
|
||||||
# logger.error(e)
|
#logger.info("Pipeline done")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def subrunner(*args, **kwargs):
|
||||||
|
runner = UltimateRunner(config = kwargs["config"], exec_id = kwargs["exec_id"], typo = "worker")
|
||||||
|
runner.createRow()
|
||||||
|
runner.pipeline()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,11 +74,10 @@ def setupLogger(level: int, filepath: str = None):
|
|||||||
os.makedirs(filepath, exist_ok = True)
|
os.makedirs(filepath, exist_ok = True)
|
||||||
|
|
||||||
filehandler = logging.FileHandler(
|
filehandler = logging.FileHandler(
|
||||||
os.path.join(filepath, "{}.log".format(logger.name))
|
os.path.join(filepath, "{}.log".format("anisotropy"))
|
||||||
)
|
)
|
||||||
filehandler.setLevel(level)
|
filehandler.setLevel(logging.INFO)
|
||||||
filehandler.setFormatter(CustomFormatter())
|
filehandler.setFormatter(CustomFormatter())
|
||||||
#logger.addHandler(filehandler)
|
|
||||||
|
|
||||||
logging.root.addHandler(filehandler)
|
logging.root.addHandler(filehandler)
|
||||||
|
|
||||||
@ -182,21 +181,6 @@ def expand(source, sep = "_"):
|
|||||||
cur[kk] = v
|
cur[kk] = v
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#if os.path.exists(env["CONFIG"]):
|
|
||||||
# config = toml.load(env["CONFIG"])
|
|
||||||
|
|
||||||
# for restricted in ["ROOT", "BUILD", "LOG", "CONFIG"]:
|
|
||||||
# if config.get(restricted):
|
|
||||||
# config.pop(restricted)
|
|
||||||
|
|
||||||
# TODO: not working if custom config empty and etc
|
|
||||||
# for m, structure in enumerate(config["structures"]):
|
|
||||||
# for n, estructure in enumerate(env["structures"]):
|
|
||||||
# if estructure["name"] == structure["name"]:
|
|
||||||
# deepupdate(env["structures"][n], config["structures"][m])
|
|
||||||
|
|
||||||
# config.pop("structures")
|
|
||||||
# deepupdate(env, config)
|
|
||||||
|
|
||||||
def timer(func: FunctionType) -> (tuple, float):
|
def timer(func: FunctionType) -> (tuple, float):
|
||||||
"""(Decorator) Returns output of inner function and execution time
|
"""(Decorator) Returns output of inner function and execution time
|
||||||
|
@ -44,9 +44,9 @@ class Database(SqliteDatabase):
|
|||||||
|
|
||||||
def getExecution(self, idn):
|
def getExecution(self, idn):
|
||||||
query = models.Execution.select().where(models.Execution.exec_id == idn)
|
query = models.Execution.select().where(models.Execution.exec_id == idn)
|
||||||
self.connect()
|
|
||||||
table = query.get() if query.exists() else None
|
with self:
|
||||||
self.close()
|
table = query.get() if query.exists() else None
|
||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class Database(SqliteDatabase):
|
|||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def getShape(self, label, direction, alpha, execution = None):
|
def getShape(self, label = None, direction = None, alpha = None, execution = None, **kwargs):
|
||||||
execution = execution or self.getLatest()
|
execution = execution or self.getLatest()
|
||||||
query = (
|
query = (
|
||||||
models.Shape
|
models.Shape
|
||||||
@ -77,7 +77,7 @@ class Database(SqliteDatabase):
|
|||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def getMesh(self, label, direction, alpha, execution = None):
|
def getMesh(self, label = None, direction = None, alpha = None, execution = None, **kwargs):
|
||||||
execution = execution or self.getLatest()
|
execution = execution or self.getLatest()
|
||||||
query = (
|
query = (
|
||||||
models.Mesh
|
models.Mesh
|
||||||
@ -97,7 +97,7 @@ class Database(SqliteDatabase):
|
|||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def getFlowOnephase(self, label, direction, alpha, execution = None):
|
def getFlowOnephase(self, label = None, direction = None, alpha = None, execution = None, **kwargs):
|
||||||
execution = execution or self.getLatest()
|
execution = execution or self.getLatest()
|
||||||
query = (
|
query = (
|
||||||
models.FlowOnephase
|
models.FlowOnephase
|
||||||
|
@ -60,7 +60,6 @@ class Mesh(object):
|
|||||||
ext = os.path.splitext(filename)[1][1: ]
|
ext = os.path.splitext(filename)[1][1: ]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# TODO: write correct boundary names
|
|
||||||
if ext == "vol":
|
if ext == "vol":
|
||||||
self.mesh.Save(filename)
|
self.mesh.Save(filename)
|
||||||
|
|
||||||
|
@ -2,13 +2,7 @@
|
|||||||
# This file is part of anisotropy.
|
# This file is part of anisotropy.
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
||||||
|
|
||||||
|
from .utils import version, uniform, datReader
|
||||||
#from .meshConversion import ideasUnvToFoam, netgenNeutralToFoam
|
|
||||||
#from .meshManipulation import createPatch, transformPoints, checkMesh, renumberMesh
|
|
||||||
#from .miscellaneous import foamDictionary
|
|
||||||
#from .parallelProcessing import decomposePar
|
|
||||||
#from .solvers import potentialFoam, simpleFoam
|
|
||||||
from .utils import version, uniform #, foamClean
|
|
||||||
from .foamfile import FoamFile
|
from .foamfile import FoamFile
|
||||||
from .foamcase import FoamCase
|
from .foamcase import FoamCase
|
||||||
from .runner import FoamRunner
|
from .runner import FoamRunner
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
from .application import application
|
|
||||||
|
|
||||||
def ideasUnvToFoam(mesh: str, case: str = None) -> (str, int):
|
|
||||||
return application("ideasUnvToFoam", mesh, case = case, stderr = True)
|
|
||||||
|
|
||||||
|
|
||||||
def netgenNeutralToFoam(mesh: str, case: str = None) -> (str, int):
|
|
||||||
return application("netgenNeutralToFoam", mesh, case = case, stderr = True)
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
from .application import application
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
def createPatch(dictfile: str = None, case: str = None):
|
|
||||||
args = ["-overwrite"]
|
|
||||||
|
|
||||||
if dictfile:
|
|
||||||
args.extend(["-dict", dictfile])
|
|
||||||
|
|
||||||
application("createPatch", *args, case = case, stderr = True)
|
|
||||||
|
|
||||||
|
|
||||||
def transformPoints(scale, case: str = None):
|
|
||||||
_scale = f"({ scale[0] } { scale[1] } { scale[2] })"
|
|
||||||
|
|
||||||
application("transformPoints", "-scale", _scale, case = case, stderr = True)
|
|
||||||
|
|
||||||
|
|
||||||
def checkMesh(case: str = None) -> str:
|
|
||||||
_, err, returncode = application("checkMesh", "-allGeometry", "-allTopology", case = case, stderr = True)
|
|
||||||
out = ""
|
|
||||||
|
|
||||||
with open("checkMesh.log", "r") as io:
|
|
||||||
warnings = []
|
|
||||||
for line in io:
|
|
||||||
if re.search(r"\*\*\*", line):
|
|
||||||
warnings.append(line.replace("***", "").strip())
|
|
||||||
|
|
||||||
if warnings:
|
|
||||||
out = "checkMesh:\n\t{}".format("\n\t".join(warnings))
|
|
||||||
|
|
||||||
return out, err, returncode
|
|
||||||
|
|
||||||
|
|
||||||
def renumberMesh(case: str = None):
|
|
||||||
application("renumberMesh", "-overwrite", useMPI = False, case = case, stderr = True)
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
from .application import application
|
|
||||||
|
|
||||||
def foamDictionary(filepath: str, entry: str, value: str = None, case: str = None):
|
|
||||||
args = [filepath, "-entry", entry]
|
|
||||||
|
|
||||||
if value:
|
|
||||||
args.extend(["-set", value])
|
|
||||||
|
|
||||||
application("foamDictionary", *args, case = case, stderr = False)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
from .application import application
|
|
||||||
|
|
||||||
def decomposePar(case: str = None):
|
|
||||||
application("decomposePar", case = case, stderr = True)
|
|
||||||
|
|
@ -48,25 +48,30 @@ class FoamRunner(object):
|
|||||||
|
|
||||||
logger.debug(f"Starting subprocess: { proc.args }")
|
logger.debug(f"Starting subprocess: { proc.args }")
|
||||||
|
|
||||||
|
if self.logpath:
|
||||||
|
with proc, open(self.logpath, "w") as io:
|
||||||
|
while True:
|
||||||
|
output = proc.stdout.read(1)
|
||||||
|
|
||||||
|
if output == "" and proc.poll() is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not output == "":
|
||||||
|
io.write(output)
|
||||||
|
|
||||||
self.output, self.error = proc.communicate()
|
self.output, self.error = proc.communicate()
|
||||||
self.returncode = proc.returncode
|
self.returncode = proc.returncode
|
||||||
|
|
||||||
|
if self.logpath and self.error:
|
||||||
|
with open(self.logpath, "a") as io:
|
||||||
|
io.write(self.error)
|
||||||
|
|
||||||
except FileNotFoundError as err:
|
except FileNotFoundError as err:
|
||||||
self.error = err.args[1]
|
self.error = err.args[1]
|
||||||
self.returncode = 2
|
self.returncode = 2
|
||||||
|
|
||||||
logger.error(self.error, exc_info = True)
|
logger.error(self.error, exc_info = True)
|
||||||
|
|
||||||
if self.logpath:
|
|
||||||
with open(self.logpath, "w") as io:
|
|
||||||
if self.output:
|
|
||||||
io.write(self.output)
|
|
||||||
|
|
||||||
if self.error:
|
|
||||||
io.write(self.error)
|
|
||||||
|
|
||||||
io.write(f"Exit code { self.returncode }")
|
|
||||||
|
|
||||||
if not self.returncode == 0 and self.exit:
|
if not self.returncode == 0 and self.exit:
|
||||||
raise Exception(f"Subprocess failed: { self.error }")
|
raise Exception(f"Subprocess failed: { self.error }")
|
||||||
|
|
||||||
|
@ -9,29 +9,39 @@ from .runner import FoamRunner
|
|||||||
# meshConversion
|
# meshConversion
|
||||||
##
|
##
|
||||||
|
|
||||||
def netgenNeutralToFoam(meshfile: str, **kwargs) -> tuple[str, str, int]:
|
def netgenNeutralToFoam(meshfile: str, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "netgenNeutralToFoam"
|
command = "netgenNeutralToFoam"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
args = [ meshfile ]
|
args = [ meshfile ]
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def ideasUnvToFoam(meshfile: str, **kwargs) -> tuple[str, str, int]:
|
def ideasUnvToFoam(meshfile: str, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "ideasUnvToFoam"
|
command = "ideasUnvToFoam"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
args = [ meshfile ]
|
args = [ meshfile ]
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# meshManipulation
|
# meshManipulation
|
||||||
##
|
##
|
||||||
|
|
||||||
def createPatch(dictfile: str = None, overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
|
def createPatch(dictfile: str = None, overwrite: bool = True, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "createPatch"
|
command = "createPatch"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -43,10 +53,15 @@ def createPatch(dictfile: str = None, overwrite: bool = True, **kwargs) -> tuple
|
|||||||
if overwrite:
|
if overwrite:
|
||||||
args.append("-overwrite")
|
args.append("-overwrite")
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def transformPoints(transformations: dict, **kwargs) -> tuple[str, str, int]:
|
def transformPoints(transformations: dict, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "transformPoints"
|
command = "transformPoints"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -64,10 +79,15 @@ def transformPoints(transformations: dict, **kwargs) -> tuple[str, str, int]:
|
|||||||
|
|
||||||
args.append(", ".join(arg))
|
args.append(", ".join(arg))
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def checkMesh(allGeometry: bool = True, allTopology: bool = True, **kwargs) -> tuple[str, str, int]:
|
def checkMesh(allGeometry: bool = True, allTopology: bool = True, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "checkMesh"
|
command = "checkMesh"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -79,10 +99,15 @@ def checkMesh(allGeometry: bool = True, allTopology: bool = True, **kwargs) -> t
|
|||||||
if allTopology:
|
if allTopology:
|
||||||
args.append("-allTopology")
|
args.append("-allTopology")
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def renumberMesh(overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
|
def renumberMesh(overwrite: bool = True, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "renumberMesh"
|
command = "renumberMesh"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -91,7 +116,12 @@ def renumberMesh(overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
|
|||||||
if overwrite:
|
if overwrite:
|
||||||
args.append("-overwrite")
|
args.append("-overwrite")
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
@ -105,20 +135,25 @@ def renumberMesh(overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
|
|||||||
# parallelProcessing
|
# parallelProcessing
|
||||||
##
|
##
|
||||||
|
|
||||||
def decomposePar(**kwargs) -> tuple[str, str, int]:
|
def decomposePar(run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "decomposePar"
|
command = "decomposePar"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
args = []
|
args = []
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# solvers
|
# solvers
|
||||||
##
|
##
|
||||||
|
|
||||||
def potentialFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
|
def potentialFoam(parallel: bool = False, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "potentialFoam"
|
command = "potentialFoam"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -128,10 +163,15 @@ def potentialFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
|
|||||||
args.append("-parallel")
|
args.append("-parallel")
|
||||||
kwargs.update(mpi = True)
|
kwargs.update(mpi = True)
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
|
||||||
def simpleFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
|
def simpleFoam(parallel: bool = False, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
command = "simpleFoam"
|
command = "simpleFoam"
|
||||||
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
|
||||||
kwargs.update(exit = True)
|
kwargs.update(exit = True)
|
||||||
@ -141,4 +181,32 @@ def simpleFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
|
|||||||
args.append("-parallel")
|
args.append("-parallel")
|
||||||
kwargs.update(mpi = True)
|
kwargs.update(mpi = True)
|
||||||
|
|
||||||
return FoamRunner(command, args = args, **kwargs).run()
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
|
||||||
|
###
|
||||||
|
# postProcessing
|
||||||
|
##
|
||||||
|
|
||||||
|
def postProcess(func: str = None, latestTime: bool = False, run: bool = True, **kwargs) -> FoamRunner:
|
||||||
|
command = "postProcess"
|
||||||
|
kwargs.update(logpath=kwargs.get("logpath", f"{command}.log"))
|
||||||
|
kwargs.update(exit = True)
|
||||||
|
args = []
|
||||||
|
|
||||||
|
if func:
|
||||||
|
args.extend(["-func", func])
|
||||||
|
|
||||||
|
if latestTime:
|
||||||
|
args.append("-latestTime")
|
||||||
|
|
||||||
|
runner = FoamRunner(command, args = args, **kwargs)
|
||||||
|
|
||||||
|
if run:
|
||||||
|
runner.run()
|
||||||
|
|
||||||
|
return runner
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This file is part of anisotropy.
|
|
||||||
# License: GNU GPL version 3, see the file "LICENSE" for details.
|
|
||||||
|
|
||||||
from .application import application
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
def potentialFoam(case: str = None, useMPI: bool = False):
|
|
||||||
if useMPI:
|
|
||||||
out, err, returncode = application("potentialFoam", "-parallel", useMPI = True, case = case, stderr = True)
|
|
||||||
|
|
||||||
else:
|
|
||||||
out, err, returncode = application("potentialFoam", case = case, stderr = True)
|
|
||||||
|
|
||||||
return out, err, returncode
|
|
||||||
|
|
||||||
|
|
||||||
def simpleFoam(case: str = None, useMPI: bool = False):
|
|
||||||
if useMPI:
|
|
||||||
out, err, returncode = application("simpleFoam", "-parallel", useMPI = True, case = case, stderr = True)
|
|
||||||
|
|
||||||
else:
|
|
||||||
out, err, returncode = application("simpleFoam", case = case, stderr = True)
|
|
||||||
|
|
||||||
out = ""
|
|
||||||
|
|
||||||
with open("simpleFoam.log", "r") as io:
|
|
||||||
for line in io:
|
|
||||||
if re.search("solution converged", line):
|
|
||||||
out = "simpleFoam:\n\t{}".format(line.strip())
|
|
||||||
|
|
||||||
return out, err, returncode
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class volVectorField;
|
|
||||||
location "0";
|
|
||||||
object U;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
dimensions [0 1 -1 0 0 0 0];
|
|
||||||
|
|
||||||
|
|
||||||
internalField uniform (0 0 0);
|
|
||||||
|
|
||||||
boundaryField
|
|
||||||
{
|
|
||||||
inlet
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform (0 0 -6e-5);
|
|
||||||
}
|
|
||||||
outlet
|
|
||||||
{
|
|
||||||
type zeroGradient;
|
|
||||||
}
|
|
||||||
symetryPlane
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform (0 0 0);
|
|
||||||
}
|
|
||||||
wall
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform (0 0 0);
|
|
||||||
}
|
|
||||||
strips
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform (0 0 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultFaces
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform (0 0 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,55 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class volScalarField;
|
|
||||||
location "0";
|
|
||||||
object p;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
dimensions [0 2 -2 0 0 0 0];
|
|
||||||
|
|
||||||
|
|
||||||
internalField uniform 0;
|
|
||||||
|
|
||||||
boundaryField
|
|
||||||
{
|
|
||||||
inlet
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform 0.001;
|
|
||||||
}
|
|
||||||
outlet
|
|
||||||
{
|
|
||||||
type fixedValue;
|
|
||||||
value uniform 0;
|
|
||||||
}
|
|
||||||
symetryPlane
|
|
||||||
{
|
|
||||||
type zeroGradient;
|
|
||||||
}
|
|
||||||
wall
|
|
||||||
{
|
|
||||||
type zeroGradient;
|
|
||||||
}
|
|
||||||
strips
|
|
||||||
{
|
|
||||||
type zeroGradient;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultFaces
|
|
||||||
{
|
|
||||||
type zeroGradient;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,22 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
location "constant";
|
|
||||||
object transportProperties;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
transportModel Newtonian;
|
|
||||||
|
|
||||||
nu 1e-06;
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,23 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
location "constant";
|
|
||||||
object turbulenceProperties;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
simulationType laminar;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,28 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
object collapseDict;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
collapseEdgesCoeffs
|
|
||||||
{
|
|
||||||
// Edges shorter than this absolute value will be merged
|
|
||||||
minimumEdgeLength 2e-7;
|
|
||||||
|
|
||||||
// The maximum angle between two edges that share a point attached to
|
|
||||||
// no other edges
|
|
||||||
maximumMergeAngle 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,80 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
location "system";
|
|
||||||
object controlDict;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
application simpleFoam;
|
|
||||||
|
|
||||||
startFrom latestTime; //startTime;
|
|
||||||
|
|
||||||
startTime 0;
|
|
||||||
|
|
||||||
stopAt endTime;
|
|
||||||
|
|
||||||
endTime 5000;
|
|
||||||
|
|
||||||
deltaT 1;
|
|
||||||
|
|
||||||
writeControl timeStep;
|
|
||||||
|
|
||||||
writeInterval 50;
|
|
||||||
|
|
||||||
purgeWrite 0;
|
|
||||||
|
|
||||||
writeFormat ascii;
|
|
||||||
|
|
||||||
writePrecision 6;
|
|
||||||
|
|
||||||
writeCompression off;
|
|
||||||
|
|
||||||
timeFormat general;
|
|
||||||
|
|
||||||
timePrecision 6;
|
|
||||||
|
|
||||||
runTimeModifiable true;
|
|
||||||
|
|
||||||
functions
|
|
||||||
{
|
|
||||||
flowRatePatch(name=inlet)
|
|
||||||
{
|
|
||||||
name inlet;
|
|
||||||
type surfaceFieldValue;
|
|
||||||
libs ( "libfieldFunctionObjects.so" );
|
|
||||||
writeControl timeStep;
|
|
||||||
writeInterval 1;
|
|
||||||
writeFields false;
|
|
||||||
log false;
|
|
||||||
regionType patch;
|
|
||||||
fields ( phi );
|
|
||||||
operation sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
flowRatePatch(name=outlet)
|
|
||||||
{
|
|
||||||
name outlet;
|
|
||||||
type surfaceFieldValue;
|
|
||||||
libs ( "libfieldFunctionObjects.so" );
|
|
||||||
writeControl timeStep;
|
|
||||||
writeInterval 1;
|
|
||||||
writeFields false;
|
|
||||||
log false;
|
|
||||||
regionType patch;
|
|
||||||
fields ( phi );
|
|
||||||
operation sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,168 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
object createPatchDict;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
pointSync false;
|
|
||||||
|
|
||||||
// Patches to create.
|
|
||||||
patches
|
|
||||||
(
|
|
||||||
{
|
|
||||||
name defaultFaces;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (defaultFaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name inlet;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type patch;
|
|
||||||
inGroups (inlet);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_inlet);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name outlet;
|
|
||||||
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type patch;
|
|
||||||
inGroups (outlet);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_outlet);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name wall;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type wall;
|
|
||||||
inGroups (wall);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_wall);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry0;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry0);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry1;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry1);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry2;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry2);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry3;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry3);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry4;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry4);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name symetry5;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type symetryPlane;
|
|
||||||
inGroups (symetryPlane);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_symetry5);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name strips;
|
|
||||||
|
|
||||||
patchInfo
|
|
||||||
{
|
|
||||||
type wall;
|
|
||||||
inGroups (wall);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructFrom patches;
|
|
||||||
patches (smesh_strips);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,26 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
object decomposeParDict;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
numberOfSubdomains 4;
|
|
||||||
|
|
||||||
method simple;
|
|
||||||
|
|
||||||
coeffs
|
|
||||||
{
|
|
||||||
n (2 2 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,53 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: v2012 |
|
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
location "system";
|
|
||||||
object fvSchemes;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
ddtSchemes
|
|
||||||
{
|
|
||||||
default steadyState;
|
|
||||||
}
|
|
||||||
|
|
||||||
gradSchemes
|
|
||||||
{
|
|
||||||
default Gauss linear;
|
|
||||||
// grad(Phi) Gauss linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
divSchemes
|
|
||||||
{
|
|
||||||
default none;
|
|
||||||
div(phi,U) bounded Gauss linearUpwind grad(U);
|
|
||||||
div((nuEff*dev2(T(grad(U))))) Gauss linear;
|
|
||||||
div(nonlinearStress) Gauss linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
laplacianSchemes
|
|
||||||
{
|
|
||||||
default Gauss linear corrected;
|
|
||||||
// laplacian(1, Phi) Gauss linear corrected;
|
|
||||||
}
|
|
||||||
|
|
||||||
interpolationSchemes
|
|
||||||
{
|
|
||||||
default linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
snGradSchemes
|
|
||||||
{
|
|
||||||
default corrected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
@ -1,84 +0,0 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
|
||||||
| ========= | |
|
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
|
||||||
| \\ / O peration | Version: missed |
|
|
||||||
| \\ / A nd | |
|
|
||||||
| \\/ M anipulation | |
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
FoamFile
|
|
||||||
{
|
|
||||||
version 2.0;
|
|
||||||
format ascii;
|
|
||||||
class dictionary;
|
|
||||||
location "system";
|
|
||||||
object fvSolution;
|
|
||||||
}
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
solvers
|
|
||||||
{
|
|
||||||
p
|
|
||||||
{
|
|
||||||
solver GAMG;
|
|
||||||
tolerance 1e-06;
|
|
||||||
relTol 0.1;
|
|
||||||
smoother GaussSeidel;
|
|
||||||
}
|
|
||||||
U
|
|
||||||
{
|
|
||||||
solver smoothSolver;
|
|
||||||
smoother GaussSeidel;
|
|
||||||
nSweeps 2;
|
|
||||||
tolerance 1e-08;
|
|
||||||
relTol 0.1;
|
|
||||||
} /*Phi
|
|
||||||
{
|
|
||||||
solver GAMG;
|
|
||||||
smoother GaussSeidel;
|
|
||||||
tolerance 1e-08;
|
|
||||||
relTol 0.01;
|
|
||||||
}*/
|
|
||||||
Phi
|
|
||||||
{
|
|
||||||
solver GAMG;
|
|
||||||
smoother DIC;
|
|
||||||
cacheAgglomeration yes;
|
|
||||||
agglomerator faceAreaPair;
|
|
||||||
nCellsInCoarsestLevel 10;
|
|
||||||
mergeLevels 1;
|
|
||||||
tolerance 1e-06;
|
|
||||||
relTol 0.01;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
potentialFlow
|
|
||||||
{
|
|
||||||
nNonOrthogonalCorrectors 20;
|
|
||||||
PhiRefCell 0;
|
|
||||||
PhiRefPoint 0;
|
|
||||||
PhiRefValue 0;
|
|
||||||
Phi 0;
|
|
||||||
}
|
|
||||||
cache
|
|
||||||
{
|
|
||||||
grad(p) /* empty */ ;
|
|
||||||
}
|
|
||||||
SIMPLE
|
|
||||||
{
|
|
||||||
nNonOrthogonalCorrectors 10;
|
|
||||||
residualControl
|
|
||||||
{
|
|
||||||
p 1e-05;
|
|
||||||
U 1e-05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
relaxationFactors
|
|
||||||
{
|
|
||||||
fields
|
|
||||||
{
|
|
||||||
p 0.3;
|
|
||||||
}
|
|
||||||
equations
|
|
||||||
{
|
|
||||||
U 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ************************************************************************* //
|
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
from numpy import ndarray
|
||||||
#from .application import application
|
#from .application import application
|
||||||
|
|
||||||
def version() -> str:
|
def version() -> str:
|
||||||
@ -30,7 +31,7 @@ def foamCleanCustom(case: str = None):
|
|||||||
# application("foamCleanTutorials", useMPI = False, case = case, stderr = True)
|
# application("foamCleanTutorials", useMPI = False, case = case, stderr = True)
|
||||||
|
|
||||||
def uniform(value) -> str:
|
def uniform(value) -> str:
|
||||||
if type(value) == list or type(value) == tuple:
|
if type(value) == list or type(value) == tuple or type(value) == ndarray:
|
||||||
return f"uniform ({ value[0] } { value[1] } { value[2] })"
|
return f"uniform ({ value[0] } { value[1] } { value[2] })"
|
||||||
|
|
||||||
elif type(value) == int or type(value) == float:
|
elif type(value) == int or type(value) == float:
|
||||||
@ -38,3 +39,51 @@ def uniform(value) -> str:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def datReader(filename: str):
|
||||||
|
header = []
|
||||||
|
content = []
|
||||||
|
|
||||||
|
with open(filename, "r") as io:
|
||||||
|
for line in io.readlines():
|
||||||
|
if line.startswith("#"):
|
||||||
|
header.append(line)
|
||||||
|
|
||||||
|
else:
|
||||||
|
content.append(line)
|
||||||
|
|
||||||
|
columns = []
|
||||||
|
|
||||||
|
if header[-1].find(":") < 0:
|
||||||
|
for column in header[-1].replace("#", "").split("\t"):
|
||||||
|
columns.append(column.strip())
|
||||||
|
|
||||||
|
header.pop(-1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
for column in range(len(content[0].split("\t"))):
|
||||||
|
columns.append(str(column))
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
|
||||||
|
for row in header:
|
||||||
|
key, value = row.replace("#", "").split(":")
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = float(value.strip())
|
||||||
|
|
||||||
|
except:
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
|
output[key.strip()] = value
|
||||||
|
|
||||||
|
for column in columns:
|
||||||
|
output[column] = []
|
||||||
|
|
||||||
|
for row in content:
|
||||||
|
values = row.split("\t")
|
||||||
|
|
||||||
|
for column, value in zip(columns, values):
|
||||||
|
output[column].append(float(value))
|
||||||
|
|
||||||
|
return output
|
@ -43,6 +43,14 @@ class Shape(object):
|
|||||||
|
|
||||||
return out, err, returncode
|
return out, err, returncode
|
||||||
|
|
||||||
|
def load(self, filename: str):
|
||||||
|
ext = os.path.splitext(filename)[1][1:]
|
||||||
|
|
||||||
|
if ext in ["step", "iges", "brep"]:
|
||||||
|
self.shape = OCCGeometry(filename).shape
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"{ext} is not supported")
|
||||||
|
|
||||||
def normal(self, face: FACE) -> numpy.array:
|
def normal(self, face: FACE) -> numpy.array:
|
||||||
"""
|
"""
|
||||||
|
@ -5,12 +5,13 @@
|
|||||||
import anisotropy.openfoam.presets as F
|
import anisotropy.openfoam.presets as F
|
||||||
import anisotropy.openfoam.runnerPresets as R
|
import anisotropy.openfoam.runnerPresets as R
|
||||||
from anisotropy.openfoam import FoamCase, uniform
|
from anisotropy.openfoam import FoamCase, uniform
|
||||||
|
from numpy import array
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class OnePhaseFlow(FoamCase):
|
class OnePhaseFlow(FoamCase):
|
||||||
def __init__(self, path: str = None):
|
def __init__(self, direction, path: str = None):
|
||||||
FoamCase.__init__(self, path = path)
|
FoamCase.__init__(self, path = path)
|
||||||
|
|
||||||
controlDict = F.ControlDict()
|
controlDict = F.ControlDict()
|
||||||
@ -80,7 +81,7 @@ class OnePhaseFlow(FoamCase):
|
|||||||
)
|
)
|
||||||
u["boundaryField"][boundary] = dict(
|
u["boundaryField"][boundary] = dict(
|
||||||
type = "fixedValue",
|
type = "fixedValue",
|
||||||
value = uniform([0, 0, -6e-5]) # * direction
|
value = uniform(array(direction) * -6e-5) # uniform([0, 0, -6e-5])
|
||||||
)
|
)
|
||||||
|
|
||||||
elif boundary == "outlet":
|
elif boundary == "outlet":
|
||||||
@ -111,6 +112,55 @@ class OnePhaseFlow(FoamCase):
|
|||||||
u
|
u
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def facesToPatches(faces: tuple[int, str]):
|
||||||
|
# initial 43 unnamed patches ->
|
||||||
|
# 6 named patches (inlet, outlet, wall, symetry0 - 3/5) ->
|
||||||
|
# 4 inGroups (inlet, outlet, wall, symetry)
|
||||||
|
|
||||||
|
createPatchDict = F.CreatePatchDict()
|
||||||
|
createPatchDict["patches"] = []
|
||||||
|
patches = {}
|
||||||
|
|
||||||
|
for n, name in faces:
|
||||||
|
# shifted index
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
if patches.get(name):
|
||||||
|
patches[name].append(f"patch{n}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
patches[name] = [f"patch{n}"]
|
||||||
|
|
||||||
|
for name in patches.keys():
|
||||||
|
if name == "inlet":
|
||||||
|
patchGroup = "inlet"
|
||||||
|
patchType = "patch"
|
||||||
|
|
||||||
|
elif name == "outlet":
|
||||||
|
patchGroup = "outlet"
|
||||||
|
patchType = "patch"
|
||||||
|
|
||||||
|
elif name == "wall":
|
||||||
|
patchGroup = "wall"
|
||||||
|
patchType = "wall"
|
||||||
|
|
||||||
|
else:
|
||||||
|
patchGroup = "symetry"
|
||||||
|
patchType = "symetryPlane"
|
||||||
|
|
||||||
|
createPatchDict["patches"].append({
|
||||||
|
"name": name,
|
||||||
|
"patchInfo": {
|
||||||
|
"type": patchType,
|
||||||
|
"inGroups": [patchGroup]
|
||||||
|
},
|
||||||
|
"constructFrom": "patches",
|
||||||
|
"patches": patches[name]
|
||||||
|
})
|
||||||
|
|
||||||
|
return createPatchDict
|
||||||
|
|
||||||
def build(self) -> tuple[str, str, int]:
|
def build(self) -> tuple[str, str, int]:
|
||||||
# TODO: configure working directory (FoamCase)
|
# TODO: configure working directory (FoamCase)
|
||||||
with self:
|
with self:
|
||||||
@ -129,7 +179,7 @@ class OnePhaseFlow(FoamCase):
|
|||||||
|
|
||||||
self.U["boundaryField"]["outlet"] = dict(
|
self.U["boundaryField"]["outlet"] = dict(
|
||||||
type = "pressureInletVelocity",
|
type = "pressureInletVelocity",
|
||||||
value = uniform([0, 0, 0]) # * direction
|
value = uniform([0, 0, 0])
|
||||||
)
|
)
|
||||||
self.write()
|
self.write()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user