OpenFOAM users conference, 13-14 June 2023
(Fluidsimfoam perspective…)
CNRS researcher, stratified turbulence and scientific programming with Python
Fluiddyn project: open-source Python for fluid dynamics
(lab experiments, image processing and simulations)
Fluidsim: user centric CFD framework, specialized in pseudo-spectral methods
Snek5000: Fluidsim framework for the CFD code Nek5000 (success…)
Note
In my lab (LEGI), 0 Nek5000 user but many OpenFOAM users…
So let’s try to build a Fluidsim framework for OpenFOAM (Master 2 internship, Pooria Danaeifar)!
Fluidsim + OpenFOAM -> Fluidsimfoam
(Re)discovery of OpenFOAM
Study the standard workflow (official tutorials)
Study a particular solver (SedFoam) developed at LEGI
Write a parser for OpenFOAM input files (Lark grammar)
User experience is not optimum…
A (very) new Python package
Good quality software:
tested (coverage > 95%), documented, modular, user centric
A new workflow for OpenFOAM
Avoid manual copy and edition of OpenFOAM input files
Split the workflow in 2 steps
Described sets of potential simulations
Create the directory/files for 1 particular simulation and launch it
Integrated object oriented API (sim
object)
The set (and the associated parameters) are described in a small Python package called a “Fluidsimfoam solver”
Warning
“Fluidsim solver” and “OpenFOAM solvers” are very different things!
1 script with arguments to launch different simulations
Automation of case generation, simulation launching and postprocessing (parametric studies, optimization, …)
Programmatic generation of complex and parametrized input files (for example blockMeshDict
) and initial conditions (computed in Python)
Programmatic control of simulations at runtime (example here)
Note
Also facilities for simpler tasks… Much more with future versions…
Install
Launch a simulation with an existing solver
Reload a sim
object for runtime control / post-processing / plots
Create a new Fluidsimfoam solver from a case
Requirements: Python >=3.9 (with pip
) and OpenFOAM
Requirements: Mercurial (or manual download source code…) and Poetry
Run a script with
Content of the script:
from fluidsimfoam_dam import Simul
params = Simul.create_default_params()
params.output.sub_directory = "tuto_fluidsimfoam/dam"
params.control_dict.end_time = 4.0
params.parallel.method = "simple"
params.parallel.nsubdoms = 2
params.parallel.nsubdoms_xyz = [2, 1, 1]
params.constant.transport.water.nu = 0.5e-6
params.block_mesh_dict.height_dam = 0.5
params.block_mesh_dict.width_dam = 0.2
params.block_mesh_dict.nx = 80
params.block_mesh_dict.ny = 80
# creation of the simulation directory
sim = Simul(params)
# run the simulation (i.e. all necessary OpenFOAM commands)
sim.make.exec("run")
# or for programmatic control of the simulation
# sim.make.exec_async("run")
sim
objectApplications: runtime control / post-processing / plots
In a terminal:
which gives:
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.14.0 -- An enhanced Interactive Python. Type '?' for help.
Loading simulation
path_run: /home/users/me/Sim_data/tests_fluidsimfoam/dambreak/dambreak_run_2023-06-08_14-56-26
INFO sim: <class 'fluidsimfoam_dambreak.Simul'>
sim.output.log: <class 'fluidsimfoam.output.log.Log'>
sim.output.fields: <class 'fluidsimfoam.output.fields.Fields'>
input_files:
- in 0: U alpha_water p_rgh
- in constant: g transportProperties turbulenceProperties
- in system: blockMeshDict controlDict decomposeParDict fvSchemes fvSolution sampling setFieldsDict
sim.output: <class 'fluidsimfoam_dambreak.output.OutputDambreak'>
sim.oper: <class 'fluidsimfoam.operators.Operators'>
sim.init_fields: <class 'fluidsimfoam.init_fields.InitFields'>
sim.make: <class 'fluidsimfoam.make.MakeInvoke'>
`sim`, `params`, `np`, `plt` and `pd` variables are available
In [1]:
sim
objectThen, in IPython shell:
sim.params
sim.stop_time_loop()
sim.output.log.plot_clock_times()
sim.output.log.time_last
# Change a parameter affecting just one file:
sim.params.control_dict.end_time = 2
sim.input_files.control_dict.generate_file()
# Get the cells coordinates
x, y, z = sim.oper.get_cells_coords()
# Read output fields:
field = sim.output.fields.read_field("U", time_approx="last")
vx, vy, vz = field.get_components()
fluidsimfoam-dam
solver was created?fluidsimfoam-initiate-solver dambreak \
-c $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak
Important
Please try it for one of your case!
Errors? Create an issue here: https://foss.heptapod.net/fluiddyn/fluidsimfoam/-/issues
fluidsimfoam-dam
solver was created?Modify one file in the solver (output.py)
_helper_control_dict = Output._helper_control_dict.new(
"""
application interFoam
endTime 1
...
"""
)
_helper_control_dict.include_function('"sampling"', kind="#sinclude")
_helper_transport_properties = ConstantFileHelper(
"transportProperties",
{
"phases": ["water", "air"],
"water": {
"transportModel": "Newtonian",
"nu": 1e-06,
"rho": 1000,
},
"air": {...},
},
)
@classmethod
def _complete_params_block_mesh_dict(cls, params):
params._set_child(
"block_mesh_dict",
{
"scale": 0.146,
"nx": 46,
"lx": 4.0,
...
"x_dam": 2.0,
"width_dam": 0.16438,
"height_dam": 0.32873,
},
)
def _make_code_block_mesh_dict(self, params):
...
BlockMeshDict
bmd = BlockMeshDict()
bmd.set_scale(params.block_mesh_dict.scale)
for x_y_z_name in (
(0, 0, 0, "left_bot"),
(x_dam, 0, 0, "leftdam_bot"),
(x1_dam, 0, 0, "rightdam_bot"),
(lx, 0, 0, "right_bot"),
...
):
bmd.add_vertex(*x_y_z_name)
bmd.replicate_vertices_further_z(lz)
b_bot_left = bmd.add_hexblock_from_2d(
["left_bot", "leftdam_bot", "leftdam_topdam", "left_topdam"],
[nx_left, ny_bot, nz],
"left_bot",
)
Or classy_blocks!
Alternative to setFields
, funkySetFields
and codeStream
@classmethod
def _complete_params_alpha_a(cls, params):
params._set_child(
"init_fields",
attribs={"type": "tanh", "width": 0.005, "bed_height": 0.08},
)
def _make_tree_alpha_a(self, params):
field = VolScalarField("alpha_a", dimension="")
field.set_boundary("top", "fixedValue", "uniform 0")
...
if params.init_fields.type == "tanh":
x, y, z = self.sim.oper.get_cells_coords()
width = params.init_fields.width
bed_height = params.init_fields.bed_height
field.set_values(0.305 * (1.0 + np.tanh((bed_height - y) / width)))
else:
raise ValueError(f"Unsupported {params.init_fields.type = }")
return field
Strong underpinnings
A new workflow based on Python/IPython
Good bases for different Python usages related to OpenFOAM
Work in progress
Can greatly improve productivity of OpenFOAM users with Python skills
Become a community project
We need to build a community of users (creating issues and feature requests), contributors and core developers.
If you are interested, please (i) star the project on foss.heptapod.net and (ii) open issues!