PoissonSolver
PinCFlow.PoissonSolver
— ModulePoissonSolver
Module for solving the Poisson equation and performing a corrector step.
Provides the functions needed to solve the Poisson equation of the semi-implicit time scheme, using a preconditioned BicGStab algorithm, and correcting the Exner-pressure, momentum and density fluctuations accordingly.
See also
PinCFlow.PoissonSolver.Horizontal
— TypeHorizontal
Singleton for dispatch to application of the horizontal part of the linear operator.
PinCFlow.PoissonSolver.Total
— TypeTotal
Singleton for dispatch to application of the full linear operator.
PinCFlow.PoissonSolver.apply_bicgstab!
— Functionapply_bicgstab!(state::State, tolref::AbstractFloat)::Tuple{Bool, <:Integer}
Solve the Poisson equation using a preconditioned BicGStab algorithm and return a tuple containing an error flag and the number of iterations.
Arguments
state
: Model state.tolref
: Reference tolerance for convergence criterion.
See also
PinCFlow.PoissonSolver.apply_corrector!
— Functionapply_corrector!(
state::State,
dt::AbstractFloat,
rayleigh_factor::AbstractFloat,
)::Tuple{Bool, <:Integer}
Perform the corrector step and return a tuple containing an error flag and the number of BicGStab iterations.
The left-hand side and the linear operator of the discrete Poisson equation are calculated. The equation is then solved for Exner-pressure differences, using a preconditioned BicGStab algorithm. Finally, the Exner-pressure, wind and density fluctuations are corrected accordingly.
Arguments
state
: Model state.dt
: Time step.rayleigh_factor
: Factor by which the Rayleigh-damping coefficient is multiplied.
See also
PinCFlow.PoissonSolver.apply_operator!
— Functionapply_operator!(
sin::AbstractArray{<:AbstractFloat, 3},
ls::AbstractArray{<:AbstractFloat, 3},
hortot::Total,
state::State,
)
Apply the total linear operator to the solution array sin
.
Before the operator is applied, the boundary/halo values of sin
are set, using set_zonal_boundaries_of_field!
, set_meridional_boundaries_of_field!
and set_vertical_halos_of_field!
. Note that in the vertical, only halo values need to be set (if the domain is parallelized in that direction), due to the solid-wall boundaries.
apply_operator!(
sin::AbstractArray{<:AbstractFloat, 3},
ls::AbstractArray{<:AbstractFloat, 3},
hortot::Horizontal,
state::State,
)
Apply the "horizontal part" of the linear operator (excluding the lower, center and upper diagonal) to the solution array sin
.
Before the operator is applied, the boundary/halo values of sin
are set, in the same way as in the method applying the total operator.
Arguments
sin
: Solution array.ls
: Result of applying the operator to the solution array.hortot
: Linear-operator mode.state
: Model state.
See also
PinCFlow.PoissonSolver.apply_preconditioner!
— Functionapply_preconditioner!(
sin::AbstractArray{<:AbstractFloat, 3},
sout::AbstractArray{<:AbstractFloat, 3},
state::State,
)
Apply a preconditioner to the Poisson problem.
This preconditioner integrates the auxiliary equation
\[\frac{\mathrm{d} s}{\mathrm{d} \eta} = \mathcal{L}_\mathrm{h} \left(s\right) + \mathcal{L}_\mathrm{v} \left(s\right) - b,\]
where $s$ is the iterative solution, $\eta$ is a pseudo-time variable, $\mathcal{L}_\mathrm{v}$ contains the lower, center and upper diagonals of the linear operator, $\mathcal{L}_\mathrm{h}$ contains all remaining elements, and $b$ is the left-hand side. The integration is performed in a semi-implicit manner, following
\[\left(1 - \Delta \eta \mathcal{L}_\mathrm{v}\right) \left(s^{\left(m + 1\right)}\right) = \left(1 + \Delta \eta \mathcal{L}_\mathrm{h}\right) \left(s^{\left(m\right)}\right) - \Delta \eta b,\]
where $\Delta \eta = \Delta \tau / 2 \left[\left(\Delta \widehat{x}\right)^{- 2} + \left(\Delta \widehat{y}\right)^{- 2}\right]^{- 1}$, with $\Delta \tau$ being a namelist parameter (state.namelist.poisson.dtau
). Therein, the implicit problem is solved with the Thomas algorithm for tridiagonal matrices. The number of iterations is given by state.namelist.poisson.preconditioner_iterations
. Since the Thomas algorithm consists of an upward elimination sweep and a downward pass, this method performs sequential one-way MPI communication if the domain is parallelized in the vertical.
Arguments
sin
: Residual array.sout
: Solution of the preconditioner.state
: Model state.
See also
PinCFlow.PoissonSolver.compute_lhs!
— Functioncompute_lhs!(state::State)::AbstractFloat
Compute the scaled left-hand side of the Poisson equation and return a reference tolerance for the convergence criterion by dispatching to a model-specific method.
compute_lhs!(
state::State,
model::Union{Boussinesq, PseudoIncompressible},
)::AbstractFloat
Compute the scaled left-hand side of the Poisson equation in pseudo-incompressible/Boussinesq mode and return a reference tolerance for the convergence criterion.
The scaled left-hand side is given by
\[\begin{align*} b & = \frac{\sqrt{\overline{\rho}}}{P} \frac{1}{J c_p} \left\{\frac{1}{\Delta \widehat{x}} \left[\left(J P\right)_{i + 1 / 2} u_{i + 1 / 2} - \left(J P\right)_{i - 1 / 2} u_{i - 1 / 2}\right]\right.\\ & \qquad \qquad \quad + \frac{1}{\Delta \widehat{y}} \left[\left(J P\right)_{j + 1 / 2} v_{j + 1 / 2} - \left(J P\right)_{j - 1 / 2} v_{j - 1 / 2}\right]\\ & \qquad \qquad \quad + \left.\frac{1}{\Delta \widehat{z}} \left[\left(J P\right)_{k + 1 / 2} \widehat{w}_{k + 1 / 2} - \left(J P\right)_{k - 1 / 2} \widehat{w}_{k - 1 / 2}\right]\right\} \end{align*}\]
and the reference tolerance is given by
\[\tau_\mathrm{ref} = \frac{\sum_{i, j, k} b_{i, j, k}^2}{\sum_{i, j, k} \left(b_{u, i, j, k}^2 + b_{v, i, j, k}^2 + b_{\widehat{w}, i, j, k}^2\right)},\]
where $b_u$, $b_v$ and $b_{\widehat{w}}$ are the zonal, meridional and vertical parts of $b$, respectively. Note that in Boussinesq mode, $P = P_0$ will cancel out, so that the appropriate divergence constraint remains.
compute_lhs!(state::State, model::Compressible)::AbstractFloat
Compute the scaled left-hand side of the Poisson equation in compressible mode and return a reference tolerance for the convergence criterion.
The scaled left-hand side is given by
\[\begin{align*} b & = \frac{\sqrt{\overline{\rho}}}{P} \frac{1}{J c_p} \left(\frac{U_{i + 1 / 2} - U_{i - 1 / 2}}{\Delta \widehat{x}} + \frac{V_{j + 1 / 2} - V_{j - 1 / 2}}{\Delta \widehat{y}} + \frac{\widehat{W}_{k + 1 / 2} - \widehat{W}_{k - 1 / 2}}{\Delta \widehat{z}}\right) - \frac{\sqrt{\overline{\rho}}}{P} F^P, \end{align*}\]
where $F^P$ is the diabatic heating, as computed by compute_volume_force
, and the reference tolerance is computed in the same way as in the method for pseudo-incompressible/Boussinesq mode, with $b_{F, i, j, k}^2$ added to the sum in the denominator, representing the heating term.
Arguments
state
: Model state.model
: Dynamic equations.
See also
PinCFlow.PoissonSolver.compute_operator!
— Functioncompute_operator!(
state::State,
dt::AbstractFloat,
rayleigh_factor::AbstractFloat,
)
Compute the tensor elements of the linear operator on the right-hand side of the Poisson equation.
The operator is obtained by rewriting the scaled Poisson equation
\[\frac{\sqrt{\overline{\rho}}}{P} \mathrm{LHS} = \frac{\sqrt{\overline{\rho}}}{P} \mathrm{RHS} \left(\frac{\sqrt{\overline{\rho}}}{P} s\right)\]
as
\[\frac{\sqrt{\overline{\rho}}}{P} \mathrm{LHS} = \sum_{\lambda, \mu, \nu} A_{i + \lambda, j + \mu, k + \nu} s_{i + \lambda, j + \mu, k + \nu},\]
where the Exner-pressure differences are given by $\Delta \pi = \left(\sqrt{\overline{\rho}} / P\right) \left(s / \Delta t\right)$.
Arguments
state
: Model state.dt
: Time step.rayleigh_factor
: Factor by which the Rayleigh-damping coefficient is multiplied.
See also
PinCFlow.PoissonSolver.correct!
— Functioncorrect!(state::State, dt::AbstractFloat, rayleigh_factor::AbstractFloat)
Correct the Exner-pressure, wind and density fluctuations such that the divergence constraint is satisfied, using the Exner-pressure differences obtained from the solution to the Poisson problem.
This method calls specific methods for the correction of each individual variable.
correct!(
state::State,
dt::AbstractFloat,
variable::U,
rayleigh_factor::AbstractFloat,
)
Correct the zonal wind to account for the pressure differences obtained from the solution to the Poisson problem.
The correction is given by
\[u_{i + 1 / 2} \rightarrow u_{i + 1 / 2} - \mathcal{C}_{i + 1 / 2}^{\rho u}\]
in Boussinesq/pseudo-incompressible mode and
\[U_{i + 1 / 2} \rightarrow U_{i + 1 / 2} - \left(J P\right)_{i + 1 / 2} \mathcal{C}_{i + 1 / 2}^{\rho u}\]
in compressible mode, with
\[\mathcal{C}_{i + 1 / 2}^{\rho u} = \left(1 + \beta_{\mathrm{R}, i + 1 / 2} \Delta t\right)^{- 1} \Delta t c_p \frac{P_{i + 1 / 2}}{\rho_{i + 1 / 2}} \mathcal{D}_{i + 1 / 2}^{\rho u}.\]
Therein, $\Delta t$ is the fractional time step given as input to this method and $c_p \left(P_{i + 1 / 2} / \rho_{i + 1 / 2}\right) \mathcal{D}_{i + 1 / 2}^{\rho u}$ is computed with compute_pressure_gradient
.
correct!(
state::State,
dt::AbstractFloat,
variable::V,
rayleigh_factor::AbstractFloat,
)
Correct the meridional wind to account for the pressure differences obtained from the solution to the Poisson problem.
The correction is given by
\[v_{j + 1 / 2} \rightarrow v_{j + 1 / 2} - \mathcal{C}_{j + 1 / 2}^{\rho v}\]
in Boussinesq/pseudo-incompressible mode and
\[V_{j + 1 / 2} \rightarrow V_{j + 1 / 2} - \left(J P\right)_{j + 1 / 2} \mathcal{C}_{j + 1 / 2}^{\rho v}\]
in compressible mode, with
\[\mathcal{C}_{j + 1 / 2}^{\rho v} = \left(1 + \beta_{\mathrm{R}, j + 1 / 2} \Delta t\right)^{- 1} \Delta t c_p \frac{P_{j + 1 / 2}}{\rho_{j + 1 / 2}} \mathcal{D}_{j + 1 / 2}^{\rho v},\]
where $c_p \left(P_{j + 1 / 2} / \rho_{j + 1 / 2}\right) \mathcal{D}_{j + 1 / 2}^{\rho v}$ is computed with compute_pressure_gradient
.
correct!(
state::State,
dt::AbstractFloat,
variable::W,
rayleigh_factor::AbstractFloat,
)
Correct the transformed vertical wind to account for the pressure differences obtained from the solution to the Poisson problem.
The correction is given by
\[\begin{align*} \widehat{w}_{k + 1 / 2} & \rightarrow \widehat{w}_{k + 1 / 2} - \left[1 + \beta_{\mathrm{R}, k + 1 / 2} \Delta t + \frac{\overline{\rho}_{k + 1 / 2}}{\rho_{k + 1 / 2}} \left(N \Delta t\right)^2\right]^{- 1}\\ & \quad \times \left\{\Delta t c_p \frac{P_{k + 1 / 2}}{\rho_{k + 1 / 2}} \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}} + \frac{\overline{\rho}_{k + 1 / 2}}{\rho_{k + 1 / 2}} \left(N \Delta t\right)^2 \left[\left(G^{1 3} \mathcal{C}^{\rho u}\right)_{k + 1 / 2} + \left(G^{23} \mathcal{C}^{\rho v}\right)_{k + 1 / 2}\right]\right\}, \end{align*}\]
in Boussinesq/pseudo-incompressible mode and
\[\begin{align*} \widehat{W}_{k + 1 / 2} & \rightarrow \widehat{W}_{k + 1 / 2} - \left[1 + \beta_{\mathrm{R}, k + 1 / 2} \Delta t + \frac{\left(P / \overline{\theta}\right)_{k + 1 / 2}}{\rho_{k + 1 / 2}} \left(N \Delta t\right)^2\right]^{- 1}\\ & \quad \times \left\{\Delta t c_p \left(J P\right)_{k + 1 / 2} \frac{P_{k + 1 / 2}}{\rho_{k + 1 / 2}} \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}} \vphantom{\frac{\left(P / \overline{\theta}\right)_{k + 1 / 2}}{\rho_{k + 1 / 2}}}\right.\\ & \qquad \quad + \left.\left(J P\right)_{k + 1 / 2} \frac{\left(P / \overline{\theta}\right)_{k + 1 / 2}}{\rho_{k + 1 / 2}} \left(N \Delta t\right)^2 \left[\left(G^{1 3} \mathcal{C}^{\rho u}\right)_{k + 1 / 2} + \left(G^{23} \mathcal{C}^{\rho v}\right)_{k + 1 / 2}\right]\right\}, \end{align*}\]
in compressible mode, where $c_p \left(P_{k + 1 / 2} / \rho_{k + 1 / 2}\right) \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}}$ is computed with compute_pressure_gradient
.
correct!(
state::State,
dt::AbstractFloat,
variable::RhoP,
rayleigh_factor::AbstractFloat,
)
Correct the density fluctuations to account for the pressure differences obtained from the solution to the Poisson problem.
The correction is given by
\[\begin{align*} \rho' & \rightarrow \rho' + \frac{\rho}{g} \left[1 + \beta_\mathrm{R} \Delta t + \frac{\overline{\rho}}{\rho} \left(N \Delta t\right)^2\right]^{- 1}\\ & \quad \times \left[- \frac{\overline{\rho}}{\rho} \left(N \Delta t\right)^2 J \left(c_p \frac{P_{k + 1 / 2}}{\rho_{k + 1 / 2}} \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}}\right)\right.\\ & \qquad \quad + \left.\frac{\overline{\rho}}{\rho} N^2 \Delta t J \left(1 + \beta_\mathrm{R} \Delta t\right) \left(G^{1 3} \mathcal{C}^{\rho u} + G^{2 3} \mathcal{C}^{\rho v}\right)\right], \end{align*}\]
in Boussinesq/pseudo-incompressible mode and
\[\begin{align*} \rho' & \rightarrow \rho' + \frac{\rho}{g} \left[1 + \beta_\mathrm{R} \Delta t + \frac{P / \overline{\theta}}{\rho} \left(N \Delta t\right)^2\right]^{- 1}\\ & \quad \times \left[- \frac{P / \overline{\theta}}{\rho} \left(N \Delta t\right)^2 J \left(c_p \frac{P_{k + 1 / 2}}{\rho_{k + 1 / 2}} \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}}\right)\right.\\ & \qquad \quad + \left.\frac{P / \overline{\theta}}{\rho} N^2 \Delta t J \left(1 + \beta_\mathrm{R} \Delta t\right) \left(G^{1 3} \mathcal{C}^{\rho u} + G^{2 3} \mathcal{C}^{\rho v}\right)\right], \end{align*}\]
in compressible mode, where $c_p \left(P_{k + 1 / 2} / \rho_{k + 1 / 2}\right) \mathcal{D}_{k + 1 / 2}^{\rho \widehat{w}}$ and $c_p \left(P_{k - 1 / 2} / \rho_{k - 1 / 2}\right) \mathcal{D}_{k - 1 / 2}^{\rho \widehat{w}}$ are computed with compute_pressure_gradient
, and used to interpolate to $\left(i, j, k\right)$.
correct!(state::State, variable::PiP)
Update the Exner-pressure fluctuations with the differences obtained from the solution to the Poisson problem.
Arguments
state
: Model state.dt
: Time step.variable
: Variable to correct.rayleigh_factor
: Factor by which the Rayleigh-damping coefficient is multiplied.
See also
PinCFlow.PoissonSolver.solve_poisson!
— Functionsolve_poisson!(
state::State,
dt::AbstractFloat,
rayleigh_factor::AbstractFloat,
tolref::AbstractFloat,
)::Tuple{Bool, <:Integer}
Solve the Poisson equation and return a tuple containing an error flag and the number of iterations.
Given a left-hand side and reference tolerance, this method computes the elements of the linear operator and solves the Poisson equation, using a preconditioned BicGStab algorithm. Both the Exner-pressure differences and the entire equation are scaled with $\sqrt{\overline{\rho}} / P$ in advance (the left-hand side has already been scaled at this point), so that the equation
\[\frac{\sqrt{\overline{\rho}}}{P} \mathrm{LHS} = \frac{\sqrt{\overline{\rho}}}{P} \mathrm{RHS} \left(\frac{\sqrt{\overline{\rho}}}{P} s\right)\]
is solved for $s$. The Exner-pressure differences are then given by $\Delta \pi = \left(\sqrt{\overline{\rho}} / P\right) \left(s / \Delta t\right)$.
Arguments
state
: Model state.dt
: Time step.rayleigh_factor
: Factor by which the Rayleigh-damping coefficient is multiplied.tolref
: Reference tolerance for convergence criterion.
See also