Mod: openfoam runner and presets

This commit is contained in:
L-Nafaryus 2021-12-15 22:21:04 +05:00
parent 49a7390473
commit c166be7801
No known key found for this signature in database
GPG Key ID: C76D8DCD2727DBB7
8 changed files with 292 additions and 87 deletions

View File

@ -18,7 +18,7 @@ from anisotropy.database import database, tables as T
from anisotropy.shaping import Simple, BodyCentered, FaceCentered 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 import OnePhaseFlow
from multiprocessing import current_process, parent_process from multiprocessing import current_process, parent_process
class UltimateRunner(object): class UltimateRunner(object):
@ -141,7 +141,8 @@ class UltimateRunner(object):
r0 = params.r0, r0 = params.r0,
filletsEnabled = params.filletsEnabled filletsEnabled = params.filletsEnabled
) )
out, err, returncode = self.shape.build() #out, err, returncode = self.shape.build()
self.shape.build()
os.makedirs(self.casepath(), exist_ok = True) os.makedirs(self.casepath(), exist_ok = True)
out, err, returncode = self.shape.export(path.join(self.casepath(), filename)) out, err, returncode = self.shape.export(path.join(self.casepath(), filename))
@ -178,7 +179,8 @@ class UltimateRunner(object):
# TODO: load from object or file # TODO: load from object or file
self.mesh = Mesh(self.shape.shape) self.mesh = Mesh(self.shape.shape)
out, err, returncode = self.mesh.build() #out, err, returncode = self.mesh.build()
self.mesh.build()
os.makedirs(self.casepath(), exist_ok = True) os.makedirs(self.casepath(), exist_ok = True)
out, err, returncode = self.mesh.export(path.join(self.casepath(), filename)) out, err, returncode = self.mesh.export(path.join(self.casepath(), filename))
@ -263,15 +265,20 @@ class UltimateRunner(object):
}) })
self.flow.append(createPatchDict) self.flow.append(createPatchDict)
out, err, returncode = self.flow.write() self.flow.write()
# Build a flow # Build a flow
out, err, returncode = self.flow.build() try:
out, err, returncode = self.flow.build()
except Exception as e:
out, err, returncode = "", e, 1
logger.error(e, exc_info = True)
if returncode == 0: if returncode == 0:
params.flowStatus = "done" params.flowStatus = "done"
else: else:
logger.error(err) #logger.error(err)
params.flowStatus = "failed" params.flowStatus = "failed"
with self.database: with self.database:
@ -284,20 +291,23 @@ class UltimateRunner(object):
stage = stage or self.config["stage"] stage = stage or self.config["stage"]
try: # TODO: fix flow
if stage in ["shape", "all"]: # TODO: change case path to execDATE/label-direction-theta/*
self.computeShape() # TODO: fix nprocs
#try:
if stage in ["shape", "all"]:
self.computeShape()
if stage in ["mesh", "all"]: if stage in ["mesh", "all"]:
self.computeMesh() self.computeMesh()
#elif stage in ["flow", "all"]: if stage in ["flow", "all"]:
# self.computeFlow() self.computeFlow()
#elif stage in ["postProcess", "all"]: #elif stage in ["postProcess", "all"]:
# self.postProcess() # self.postProcess()
except: #except Exception as e:
pass # logger.error(e)

View File

@ -3,35 +3,15 @@
# License: GNU GPL version 3, see the file "LICENSE" for details. # License: GNU GPL version 3, see the file "LICENSE" for details.
from .meshConversion import ideasUnvToFoam, netgenNeutralToFoam #from .meshConversion import ideasUnvToFoam, netgenNeutralToFoam
from .meshManipulation import createPatch, transformPoints, checkMesh, renumberMesh #from .meshManipulation import createPatch, transformPoints, checkMesh, renumberMesh
from .miscellaneous import foamDictionary #from .miscellaneous import foamDictionary
from .parallelProcessing import decomposePar #from .parallelProcessing import decomposePar
from .solvers import potentialFoam, simpleFoam #from .solvers import potentialFoam, simpleFoam
from .utils import version, foamClean, uniform from .utils import version, uniform #, foamClean
from .foamfile import FoamFile
from .foamcase import FoamCase
from .runner import FoamRunner
__all__ = [ from . import presets
# meshConversion from . import runnerPresets
"ideasUnvToFoam",
# meshManipulation
"createPatch",
"transformPoints",
"checkMesh",
"renumberMesh",
# miscellaneous
"foamDictionary",
# parallelProcessing
"decomposePar",
# solvers
"potentialFoam",
"simpleFoam",
# utils
"version",
"foamClean",
"uniform"
]

View File

@ -28,7 +28,7 @@ def checkMesh(case: str = None) -> str:
with open("checkMesh.log", "r") as io: with open("checkMesh.log", "r") as io:
warnings = [] warnings = []
for line in io: for line in io:
if re.search(r"***", line): if re.search(r"\*\*\*", line):
warnings.append(line.replace("***", "").strip()) warnings.append(line.replace("***", "").strip())
if warnings: if warnings:

View File

@ -2,4 +2,72 @@
# 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.
import os
import subprocess
import sys
from typing import List
import logging
logger = logging.getLogger(__name__)
class FoamRunner(object):
def __init__(self, command: str, args: List[str] = None, mpi: bool = False, cwd: str = None, logpath: str = None, exit: bool = False):
self.command = command
self.args = args
self.mpi = mpi
self.cwd = cwd or os.getcwd()
self.logpath = logpath
self.exit = exit
self.output = ""
self.error = ""
self.returncode = 0
def fullcommand(self) -> List[str]:
command = []
if self.mpi:
nprocs = os.cpu_count()
command.extend(["mpirun", "-np", str(nprocs), "--oversubscribe"])
command.append(self.command)
if self.args:
command.extend([ str(arg) for arg in self.args ])
return command
def run(self) -> tuple[str, str, int]:
try:
proc = subprocess.Popen(
self.fullcommand(),
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
encoding = "utf-8",
cwd = self.cwd
)
logger.debug(f"Starting subprocess: { proc.args }")
self.output, self.error = proc.communicate()
self.returncode = proc.returncode
except FileNotFoundError as err:
self.error = err
self.returncode = 2
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:
raise Exception(f"Subprocess failed: { proc.args }")
return self.output, self.error, self.returncode

View File

@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
# This file is part of anisotropy.
# License: GNU GPL version 3, see the file "LICENSE" for details.
from typing import List
from .runner import FoamRunner
###
# meshConversion
##
def netgenNeutralToFoam(meshfile: str, **kwargs) -> tuple[str, str, int]:
command = "netgenNeutralToFoam"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = [ meshfile ]
return FoamRunner(command, args = args, **kwargs).run()
def ideasUnvToFoam(meshfile: str, **kwargs) -> tuple[str, str, int]:
command = "ideasUnvToFoam"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = [ meshfile ]
return FoamRunner(command, args = args, **kwargs).run()
###
# meshManipulation
##
def createPatch(dictfile: str = None, overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
command = "createPatch"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = []
if dictfile:
args.extend(["-dict", dictfile])
if overwrite:
args.append("-overwrite")
return FoamRunner(command, args = args, **kwargs).run()
def transformPoints(transformations: dict, **kwargs) -> tuple[str, str, int]:
command = "transformPoints"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = []
arg = []
for k, v in transformations.items():
if type(v) == int or type(v) == float:
value = str(v)
elif type(v) == tuple or type(v) == list:
value = "({} {} {})".format(*v)
arg.append("{}={}".format(k, value))
args.append(", ".join(arg))
return FoamRunner(command, args = args, **kwargs).run()
def checkMesh(allGeometry: bool = True, allTopology: bool = True, **kwargs) -> tuple[str, str, int]:
command = "checkMesh"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = []
if allGeometry:
args.append("-allGeometry")
if allTopology:
args.append("-allTopology")
return FoamRunner(command, args = args, **kwargs).run()
def renumberMesh(overwrite: bool = True, **kwargs) -> tuple[str, str, int]:
command = "renumberMesh"
kwargs.update(logpath = kwargs.get("logpath", f"{ command }.log"))
kwargs.update(exit = True)
args = []
if overwrite:
args.append("-overwrite")
return FoamRunner(command, args = args, **kwargs).run()
###
# miscellaneous
##
# def foamDictionary()
###
# parallelProcessing
##
def decomposePar(**kwargs) -> tuple[str, str, int]:
command = "decomposePar"
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
kwargs.update(exit = True)
args = []
return FoamRunner(command, args = args, **kwargs).run()
###
# solvers
##
def potentialFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
command = "potentialFoam"
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
kwargs.update(exit = True)
args = []
if parallel:
args.append("-parallel")
kwargs.update(mpi = True)
return FoamRunner(command, args = args, **kwargs).run()
def simpleFoam(parallel: bool = False, **kwargs) -> tuple[str, str, int]:
command = "simpleFoam"
kwargs.update(logpath = kwargs.get("logpath", f"{command}.log"))
kwargs.update(exit = True)
args = []
if parallel:
args.append("-parallel")
kwargs.update(mpi = True)
return FoamRunner(command, args = args, **kwargs).run()

View File

@ -4,7 +4,7 @@
import os import os
import shutil import shutil
from .application import application #from .application import application
def version() -> str: def version() -> str:
return os.environ.get("WM_PROJECT_VERSION") return os.environ.get("WM_PROJECT_VERSION")
@ -19,15 +19,15 @@ def foamCleanCustom(case: str = None):
if os.path.exists(os.path.join(path, d)): if os.path.exists(os.path.join(path, d)):
shutil.rmtree(os.path.join(path, d)) shutil.rmtree(os.path.join(path, d))
def foamClean(case: str = None): #def foamClean(case: str = None):
rmDirs = ["0", "constant", "system"] # rmDirs = ["0", "constant", "system"]
path = case if case else "" # path = case if case else ""
#
for d in rmDirs: # for d in rmDirs:
if os.path.exists(os.path.join(path, d)): # if os.path.exists(os.path.join(path, d)):
shutil.rmtree(os.path.join(path, d)) # shutil.rmtree(os.path.join(path, d))
#
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:

View File

@ -2,4 +2,4 @@
# 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 .onephase import OnePhaseFlow

View File

@ -2,19 +2,18 @@
# 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.
import anisotropy.openfoam as openfoam import anisotropy.openfoam.presets as F
from anisotropy.openfoam.presets import ( import anisotropy.openfoam.runnerPresets as R
ControlDict, FvSchemes, FvSolution, from anisotropy.openfoam import FoamCase, uniform
TransportProperties, TurbulenceProperties, CreatePatchDict, import logging
P, U
) logger = logging.getLogger(__name__)
from anisotropy.openfoam.foamcase import FoamCase
class OnePhaseFlow(FoamCase): class OnePhaseFlow(FoamCase):
def __init__(self, path: str = None): def __init__(self, path: str = None):
FoamCase.__init__(self, path = path) FoamCase.__init__(self, path = path)
controlDict = ControlDict() controlDict = F.ControlDict()
controlDict.update( controlDict.update(
startFrom = "latestTime", startFrom = "latestTime",
endTime = 5000, endTime = 5000,
@ -22,9 +21,9 @@ class OnePhaseFlow(FoamCase):
runTimeModifiable = "true" runTimeModifiable = "true"
) )
fvSchemes = FvSchemes() fvSchemes = F.FvSchemes()
fvSolution = FvSolution() fvSolution = F.FvSolution()
fvSolution["solvers"]["U"].update( fvSolution["solvers"]["U"].update(
nSweeps = 2, nSweeps = 2,
tolerance = 1e-08 tolerance = 1e-08
@ -56,20 +55,20 @@ class OnePhaseFlow(FoamCase):
) )
fvSolution["relaxationFactors"]["equations"]["U"] = 0.5 fvSolution["relaxationFactors"]["equations"]["U"] = 0.5
transportProperties = TransportProperties() transportProperties = F.TransportProperties()
transportProperties.update( transportProperties.update(
nu = 1e-06 nu = 1e-06
) )
turbulenceProperties = TurbulenceProperties() turbulenceProperties = F.TurbulenceProperties()
turbulenceProperties.content = dict( turbulenceProperties.content = dict(
simulationType = "laminar" simulationType = "laminar"
) )
boundaries = [ "inlet", "outlet", "symetry", "wall"] boundaries = [ "inlet", "outlet", "symetry", "wall"]
p = P() p = F.P()
p["boundaryField"] = {} p["boundaryField"] = {}
u = U() u = F.U()
u["boundaryField"] = {} u["boundaryField"] = {}
# ISSUE: add proxy from geometry direction to outlet boundaryField. # ISSUE: add proxy from geometry direction to outlet boundaryField.
@ -77,17 +76,17 @@ class OnePhaseFlow(FoamCase):
if boundary == "inlet": if boundary == "inlet":
p["boundaryField"][boundary] = dict( p["boundaryField"][boundary] = dict(
type = "fixedValue", type = "fixedValue",
value = "uniform 1e-3" value = uniform(1e-3)
) )
u["boundaryField"][boundary] = dict( u["boundaryField"][boundary] = dict(
type = "fixedValue", type = "fixedValue",
value = "uniform (0 0 -6e-5)" # * direction value = uniform([0, 0, -6e-5]) # * direction
) )
elif boundary == "outlet": elif boundary == "outlet":
p["boundaryField"][boundary] = dict( p["boundaryField"][boundary] = dict(
type = "fixedValue", type = "fixedValue",
value = "uniform 0" value = uniform(0)
) )
u["boundaryField"][boundary] = dict( u["boundaryField"][boundary] = dict(
type = "zeroGradient", type = "zeroGradient",
@ -99,7 +98,7 @@ class OnePhaseFlow(FoamCase):
) )
u["boundaryField"][boundary] = dict( u["boundaryField"][boundary] = dict(
type = "fixedValue", type = "fixedValue",
value = "uniform (0 0 0)" value = uniform([0, 0, 0])
) )
self.extend([ self.extend([
@ -112,24 +111,28 @@ class OnePhaseFlow(FoamCase):
u u
]) ])
def build(self): def build(self) -> tuple[str, str, int]:
# TODO: configure working directory (FoamCase) # TODO: configure working directory (FoamCase)
with self: with self:
self.write() self.write()
openfoam.netgenNeutralToFoam("mesh.mesh") R.netgenNeutralToFoam("mesh.mesh")
openfoam.createPatch() R.createPatch()
openfoam.checkMesh() R.checkMesh()
openfoam.transformPoints((1e-5, 1e-5, 1e-5)) R.transformPoints({
openfoam.renumberMesh() "scale": [1e-5, 1e-5, 1e-5]
openfoam.potentialFoam() })
R.renumberMesh()
R.potentialFoam()
self.read() self.read()
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]) # * direction
) )
self.write() self.write()
openfoam.simpleFoam() R.simpleFoam()
return "", "", 0