pyHype: Computational Fluid Dynamics in Python
pyHype is a Python framework for developing parallelized Computational Fluid Dynamics software to solve the hyperbolic 2D Euler equations on distributed, multi-block structured grids. I started developing pyHype as a challenge to create a python CFD package that competes with packages written in lower level languages like C/C++ and FORTRAN in terms of performance. It can be used as a solver to generate numerical predictions of 2D inviscid flow fields, or as a platform for developing new CFD techniques and methods. Contributions are welcome! I will be periodeically updating it, but there is no predetermined schedule.
Here is an example of an explosion simulation:
- 2 x 4 grid blocks (150 x 150 cells per block)
- 600 x 1200 cartesian grid
- Roe approximate riemann solver
- Venkatakrishnan flux limiter
- Piecewise-Linear second order reconstruction
- Green-Gauss gradient method
- RK4 time stepping with CFL=0.8
- Reflection boundary conditions
- Run on 4 processors
The example in given in examples/explosion_multi.
The first file to look at is examples/explosion_multi/config.py. This defines the solver settings used for the simulation.
from pyhype.fluids import Air
from pyhype.solver_config import SolverConfig
from pyhype.states import ConservativeState
from examples.explosion.initial_condition import ExplosionInitialCondition
air = Air(a_inf=343.0, rho_inf=1.0)
config = SolverConfig(
fvm_type="MUSCL",
fvm_spatial_order=2,
fvm_num_quadrature_points=1,
fvm_gradient_type="GreenGauss",
fvm_flux_function_type="Roe",
fvm_slope_limiter_type="Venkatakrishnan",
time_integrator="RK4",
initial_condition=ExplosionInitialCondition(),
interface_interpolation="arithmetic_average",
reconstruction_type=ConservativeState,
write_solution=True,
write_solution_mode="every_n_timesteps",
write_solution_name="explosion_multi",
write_solution_base=r"PATH_TO_STORE_DATA",
write_every_n_timesteps=50,
plot_every=10,
CFL=0.8,
t_final=0.07,
realplot=False,
profile=True,
fluid=air,
nx=150,
ny=150,
nghost=1,
use_JIT=True,
)
The next file examples/explosion_multi/initial_condition.py defines the initial condition on the grid, which governs the state of the state variables at the beginning of the simulation. In this example, the grid will have a square shaped high pressure region in the lower part.
from __future__ import annotations
import os
from typing import TYPE_CHECKING
from pyhype.states.primitive import PrimitiveState
from pyhype.states.conservative import ConservativeState
from pyhype.initial_conditions.base import InitialCondition
if TYPE_CHECKING:
from pyhype.blocks.quad_block import QuadBlock
os.environ["NUMPY_EXPERIMENTAL_ARRAY_FUNCTION"] = "0"
import numpy as np
class ExplosionInitialCondition(InitialCondition):
def apply_to_block(self, block: QuadBlock):
# Free stream
rhoL = 4.6968
pL = 404400.0
uL = 0.0
vL = 0.0
left_state = PrimitiveState(
fluid=block.config.fluid,
array=np.array([rhoL, uL, vL, pL]).reshape((1, 1, 4)),
).to_type(ConservativeState)
# Post shock
rhoR = 1.1742
pR = 101100.0
uR = 0.0
vR = 0.0
right_state = PrimitiveState(
fluid=block.config.fluid,
array=np.array([rhoR, uR, vR, pR]).reshape((1, 1, 4)),
).to_type(ConservativeState)
# Fill state vector in each block
_x_cond = np.logical_and(block.mesh.x >= 3, block.mesh.x <= 7)
_y_cond = np.logical_and(block.mesh.y >= 3, block.mesh.y <= 7)
block.state.data = np.where(
np.logical_and(_x_cond, _y_cond), left_state.data, right_state.data
)
block.state.make_non_dimensional()
The next file examples/explosion_multi/mesh.py defines the computational mesh for the simulation:
from pyhype.mesh.rectangular import RectagularMeshGenerator
mesh = RectagularMeshGenerator.generate(
BCE=["Reflection"],
BCW=["Reflection"],
BCN=["Reflection"],
BCS=["Reflection"],
east=10.0,
west=0.0,
north=20.0,
south=0.0,
n_blocks_horizontal=2,
n_blocks_vertical=4,
)
The last file examples/explosion_multi/explosion.py brings it all together:
from pyhype.solvers import Euler2D
from examples.explosion_multi.config import config
from examples.explosion_multi.mesh import mesh
if __name__ == "__main__":
exp_sim = Euler2D(
config=config,
mesh_config=mesh,
)
exp_sim.solve()
To run this simulation, make sure you are in /src_path/pyHype-main
, and run the make command
make run_explosion_multi
This framework will be available as an installable package soon.
Here is an example of a Mach 10 DMR simulation performed on five blocks. The simulation was performed with the following:
- 500 x 500 cells per block
- HLLL flux function
- Venkatakrishnan flux limiter
- Piecewise-Linear second order reconstruction
- Green-Gauss gradient method
- Strong-Stability-Preserving (SSP)-RK2 time stepping with CFL=0.4
The example in given in the file examples/dmr/dmr.py.
Here is an example of high-speed jet simulation performed on 5 blocks. The simulation was performed with the following:
- Mach 2 flow
- 100 x 1000 cell blocks
- HLLL flux function
- Venkatakrishnan flux limiter
- Piecewise-Linear second order reconstruction
- Green-Gauss gradient method
- RK2 time stepping with CFL=0.4
The example in given in the file examples/jet/jet.py.