version 0.6.0
Navier-Stokes equations

Namespaces

module  mod_compute_pressure_gradient
 Compute pressure gradient on the face grid.
 
module  fields_navier
 Declaration of the field arrays associated to the Navier-Stokes equations.
 
module  mod_solve_pressure
 This module solves the correction step of the pressure correction method.
 
module  variables_navier
 Define variables (time step, schemes, solvers, etc.) associated to the Navier-Stokes equations.
 

Functions

subroutine mod_apply_bc_on_pressure_increment::apply_bc_on_pressure_increment ()
 Set boundary conditions on pressure increment as a function of the ones defined for velocity field.
 
subroutine mod_initialize_hydrostatic_pressure::initialize_hydrostatic_pressure ()
 Initialize hydrostatic pressure. More...
 
subroutine mod_project_velocity::project_velocity ()
 Project the velocity on incompressible velocities This is useful when one initialize the velocity field with a non divergence free field.
 
subroutine mod_set_brinkman_term_coefficient::set_brinkman_term_coefficient (permeability, viscosity, brinkman_coef)
 Set Brinkman term coefficient \( \mu/K \). More...
 
subroutine solve_navier ()
 Solve the Navier-Stokes equations. More...
 
subroutine mod_solve_pressure::solve_pressure (density_star_face, brinkman_coef, carman_kozeny_coef)
 This routine solves the correction step of the pressure correction method. More...
 

Detailed Description

This directory contains the routines necessary to prepare the code to solve the Navier-Stokes equations. For incompressible flows, the Navier-Stokes has the following form: \( \operatorname{div} \mathbf{u} = 0 \tag{Continuity equation} \\ \)

\begin{align} \rho \frac{\partial \mathbf{u}}{\partial t} =& \\ &- \nabla p \tag{Pressure gradient term} \\ &+ \operatorname{div} \Big( \mu \big( \nabla\mathbf{u} + \nabla\mathbf{u}^{\intercal} \big) \Big) \tag{Stress term} \\ &- \rho \operatorname{div} \big( \mathbf{u} \otimes \mathbf{u} \big) \tag{Inertial term} \\ &+ \nabla r \big( \operatorname{div} \mathbf{u} \big) \tag{Grad-div term - optional} \\ &- \frac{\mu}{K} \mathbf{u} \tag{Brinkman term - optional} \\ &+ \mathbf{f} \tag{Source term - optional} \\ &+ \mathbf{g} \tag{Gravity term - optional} \\ &- \mathbf{L} \mathbf{u} \tag{Linear term - optional} \\ &+ \mathbf{a} \tag{Capillarity term - optional} \end{align}

To solve the velocity/pressure coupling, the pressure-correction methods are used. If viscosity is constant in the domain, which corresponds to monophasic flows in Notus (since viscosity is constant for a given fluid so far), the rotational pressure-correction method of Timmermans [2] is used. For mulptiphase flows, the Goda method [1] is used. These method are based on two steps:

Prediction step

This step computes a non-solenoidal predicted velocity \( \mathbf{u}^{*,n+1} \):

\[ \rho \left( \frac {\alpha \mathbf{u}^{*,n+1} + \beta \mathbf{u}^n + \gamma \mathbf{u}^{n-1}} {\Delta t} + \operatorname{div} \Big( (\zeta \mathbf{u}^n + \eta \mathbf{u}^{n-1}) \otimes \tilde{\mathbf{u}^*} \big) \right) = - \nabla p^n + \nabla \cdot \left[ \mu \left( {\nabla \mathbf{u}^{*,n+1} + \nabla^\top \mathbf{u}^{*,n+1}} \right) \right] \]

\[ B.C.(\mathbf{u}^{*,n+1}) \]

where values of \( \alpha, \beta, \gamma \) helps to switch from the 1st order Euler time discretization scheme to the 2nd order backward differential one:

\( \alpha = 1, \beta = -1, \gamma = 0 \) for the Euler scheme

\( \alpha = \frac {3} {2}, \beta = -2, \gamma = \frac {1} {2} \) for 2nd order BDF

The non linear term of the momentum equation is linearized in time at first or second order depending of the previous time order discretization scheme:

\( \zeta = 1, \eta = 0 \) if the Euler scheme is used

\( \zeta = 2, \eta = -1 \) (second time order extrapolation) if the 2nd order BDF is used

This term can be discretized explicitly \( \tilde{\mathbf{u}^*} = \mathbf{u}^{*,n} \) or implicitly \( \tilde{\mathbf{u}^*} = \mathbf{u}^{*,n+1} \)

Correction step

This step computes the pressure increment \( \varphi^{n+1} = p^{n+1} - p^n \).

\[ \nabla \cdot \left( \frac {\Delta t} {\alpha \rho} \nabla \varphi^{n+1} \right) = \nabla \cdot \mathbf{u}^{*,n+1} \]

\[ B.C.(\varphi^{n+1}) \]

Pressure and solenoidal velocity are then updated according to:

\[ p^{n+1} = p^n + \varphi^{n+1} - \chi \mu \nabla \cdot \mathbf{u}^{*,n+1} \]

\[ \mathbf{u}^{n+1} = \mathbf{u}^{*,n+1} - \frac {\Delta t} {\rho \alpha} \nabla \varphi^{n+1} \]

with \( \chi = 0\) (Goda method) or \(\chi = 1\) (Timmermans method).

The corresponding boundary conditions between velocity and pressure increment is the following: where a Dirichlet boundary condition is set to velocity, a Neumann one is set to pressure increment; where a Neumann boundary condition is set to velocity, a Dirichlet one of zero is set to pressure increment.

Methods to reduce computational CPU time

Regardless of the spatial discretization schemes used for the implicit or explicit predictor step, the Poisson equation of the pressure-correction methods must be solved with a linear solver. The iterative methods of BiCGStab(2) (or GMRES) with the geometric multigrid preconditioners PFMG or SMG of the high performance preconditioners and solvers library Hypre [3] is proposed in Notus. This computationally intensive calculation may be further complicated by a non-constant coefficient matrix, as is obtained with the non-uniform density flows. To reduce the impact of this computationally intensive calculation, the approach proposed by Dodd and Ferrante [4] for the Chorin pressure-correction method is extended to the pressure increment Poisson equation [6]. As a result, the variable coefficient matrix is reformulated into a constant coefficient matrix following

\[ \frac {\nabla \varphi^{n+1}} {\rho^n} \approx \frac {\nabla \varphi^{n+1}} {\rho^0} + \left( \frac {1}{\rho^n} - \frac {1}{\rho^0} \right) \nabla \varphi^n \]

where \( \rho^0 = \min(\rho^n) \). The resulting Poisson pressure increment equation follows,

\[ \Delta \varphi^{n+1} = \nabla \cdot \left[ \left( 1 - \frac {\rho^0} {\rho^n} \right) \nabla \varphi^n \right] + \frac {\rho^0}{\Delta t} \nabla \cdot \mathbf{u}^{*,n+1} \]

This method may yield significant performance increases. However, if density ratio is high, the method yields to a decrease of the time step to ensure stability.

Another (experimental) method exists in Notus to reduce computational time of the correction step in case of immersed domains into the Cartesian mesh. Frantzis and Grigoriadis [5] proposed to avoid applying the Neumann boundary condition of pressure increment on the immersed interface. Even if it is not mathematically consistent, it is shown in [5] that, with minor adaptation, the solution remains very close to the unmodified system ones. A modification to this method is implemented [6], wherein the correction step is solved on the whole domain including the inside of the immersed subdomain.

Description of the directory

The 2D/3D fields associated to this equation are defined in fields.f90 file.

The scalar variables such as the time step, the schemes, the residuals, etc. are defined in variables.f90 file.

Enumarations that help to do some choices (schemes, terms, etc.) are declared in enum.f90.

The time splitting method is done in solve_navier.f90 file that is separated into 2 parts: the first one solves the momentum equation, the second one solves the pressure increment thanks to the solve_pressure.f90 routine.

A set of upper level routines helps to discretize the Navier-Stokes equations: compute_pressure_gradient.f90, compute_surface_tension_term.f90, set_brinkman_term_coefficient.f90,

The directory contains some utilities: initialize_hydrostatic_pressure.f90, project_velocity.f90

Bibliography

[1] K. Goda, A multistep technique with implicit difference schemes for calculating two- or three-dimensional cavity flows, Journal of Computational Physics 30 (1979) 76–95.

[2] L. J. P. Timmermans, P. D. Minev, F. N. Van De Voss, An approximate projection scheme for incompressible flow using spectral elements, International Journal for Numerical Methods in Fluids 22 (1996) 673–688.

[3] R.D. Falgout, J.E. Jones, U.M. Yang, The Design and Implementation of hypre, a Library of Parallel High Performance Preconditioners, in: A.M. Bruaset, A. Tveito (Eds.), Numer. Solut. Partial Differ. Equ. Parallel Comput., Springer, Berlin, Heidelberg, 2006: pp. 267–294.

[4] M.S. Dodd, A. Ferrante, A fast pressure-correction method for incompressible two-fluid flows, J. Comput. Phys. 273 (2014) 416–434.

[5] C. Frantzis, D.G.E. Grigoriadis, An efficient method for two-fluid incompressible flows appropriate for the immersed boundary method, J. Comput. Phys. 376 (2019) 28–53.

[6] A. M. D. Jost, S. Glockner, A. Erriguible, Direct numerical simulations of fluids mixing above mixture critical point, Submitted to Journal of Supercritical Fluids, 2020

Function Documentation

◆ initialize_hydrostatic_pressure()

subroutine mod_initialize_hydrostatic_pressure::initialize_hydrostatic_pressure

This routine initialzes hydrostatic pressure inside the domain by solving hydrostatic equilibrium equation.

◆ set_brinkman_term_coefficient()

subroutine mod_set_brinkman_term_coefficient::set_brinkman_term_coefficient ( double precision, dimension(nx,ny,nz), intent(in)  permeability,
double precision, dimension(nx,ny,nz), intent(in)  viscosity,
type(t_face_field), intent(inout)  brinkman_coef 
)

This term is defined on velocity nodes. Permeabilty and viscosity are interpolated from cell center to faces thanks to the harmonic interpolation.

◆ solve_navier()

subroutine solve_navier

First part of the routine builds rhs and matrix of the prediction step, term by term. Then, the linear system is solved thanks to Hypre or MUMPS libraries.

The second part solves the correction step. This is done in solve_pressure.f90 that is called at the end of solve_navier.

◆ solve_pressure()

subroutine mod_solve_pressure::solve_pressure ( type(t_face_field), intent(in)  density_star_face,
type(t_face_field), intent(in)  brinkman_coef,
type(t_face_field), intent(in)  carman_kozeny_coef 
)

This routine fills the linear system relative to the correction step on pressure increment:

  1. Build rhs and matrix
  2. Solve linear system
  3. Compute pressure from pressure increment
  4. Correct velocity using pressure increment gradient (velocity_correction.f90)