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/damBreakImportant
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):
...BlockMeshDictbmd = 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 fieldStrong 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!