Limiters
The limiters supertype is
This class of flux-limiters is applied only in the horizontal direction (on spectral advection operators).
Interfaces
ClimaCore.Limiters.QuasiMonotoneLimiter — Type
QuasiMonotoneLimiterThis limiter is inspired by the one presented in Guba et al [15]. In the reference paper, it is denoted by OP1, and is outlined in eqs. (37)-(40). Quasimonotone here is meant to be monotone with respect to the spectral element nodal values. This limiter involves solving a constrained optimization problem (a weighted least square problem up to a fixed tolerance) that is completely local to each element.
As in HOMME, the implementation idea here is the following: we need to find a grid field which is closest to the initial field (in terms of weighted sum), but satisfies the min/max constraints. So, first we find values that do not satisfy constraints and bring these values to a closest constraint. This way we introduce some change in the tracer mass, which we then redistribute so that the l2 error is smallest. This redistribution might violate constraints; thus, we do a few iterations (until abs(Δtracer_mass) <= rtol * tracer_mass).
ρq: tracer density Field, whereqdenotes tracer concentration per unit mass. This can be a scalar field, or a struct-valued field.ρ: fluid density Field (scalar).
Constructor
limiter = QuasiMonotoneLimiter(
ρq::Field;
rtol = eps(eltype(parent(ρq))),
convergence_stats = LimiterConvergenceStats()
)Creates a limiter instance for the field ρq with relative tolerance rtol, and convergence_stats, which collects statistics in apply_limiter! (e.g., number of times that convergence is met or not). Users can call
Limiters.print_convergence_stats(::QuasiMonotoneLimiter) to print the convergence stats.
Usage
Call compute_bounds! on the input fields:
compute_bounds!(limiter, ρq, ρ)Then call apply_limiter! on the output fields:
apply_limiter!(ρq, ρ, limiter)ClimaCore.Limiters.VerticalMassBorrowingLimiter — Type
VerticalMassBorrowingLimiter(q_min)A vertical-only mass borrowing limiter.
The mass borrower borrows tracer mass from an adjacent, lower layer. It conserves the total tracer mass and can avoid negative tracers.
q_min should be a tuple of minimum tracer values for each tracer.
At level k, it will first borrow the mass from the layer k+1 (lower level). If the mass is not sufficient in layer k+1, it will borrow mass from layer k+2. The borrower will proceed this process until the bottom layer. If the tracer mass in the bottom layer goes negative, it will repeat the process from the bottom to the top. In this way, the borrower works for any shape of mass profiles.
Example usage
ρ = fill(1.0, space)
q = fill((a = 0.1, b = 0.1), space)
limiter = VerticalMassBorrowingLimiter((0.0, 0.0))
Limiters.apply_limiter!(q, ρ, limiter)This code was adapted from E3SM
References:
- [16]
ClimaCore.Limiters.compute_bounds! — Function
compute_bounds!(limiter::QuasiMonotoneLimiter, ρq::Field, ρ::Field)Compute the desired bounds for the tracer concentration per unit mass q, based on the tracer density, ρq, and density, ρ, fields.
This is computed by
compute_element_bounds!- starts the ghost exchange (if distributed)
compute_neighbor_bounds_local!- completes the ghost exchange (if distributed)
compute_neighbor_bounds_ghost!(if distributed)
ClimaCore.Limiters.apply_limiter! — Function
apply_limiter!(ρq, ρ, limiter::QuasiMonotoneLimiter)Apply the limiter on the tracer density ρq, using the computed desired bounds on the concentration q and density ρ as an optimal weight. This iterates over each element, calling apply_limit_slab!. If the limiter fails to converge for any element, a warning is issued.
apply_limiter!(q::Fields.Field, ρ::Fields.Field, lim::VerticalMassBorrowingLimiter)Apply the vertical mass borrowing limiter lim to field q, given density ρ.
Internals
ClimaCore.Limiters.compute_element_bounds! — Function
compute_element_bounds!(limiter::QuasiMonotoneLimiter, ρq, ρ)Given two fields ρq and ρ, computes the min and max of q in each element, storing it in limiter.q_bounds.
Part of compute_bounds!.
ClimaCore.Limiters.compute_neighbor_bounds_local! — Function
compute_neighbor_bounds_local!(limiter::QuasiMonotoneLimiter, topology)Update the field limiter.q_bounds_nbr based on limiter.q_bounds in the local neighbors.
Part of compute_bounds!.
ClimaCore.Limiters.compute_neighbor_bounds_ghost! — Function
compute_neighbor_bounds_ghost!(limiter::QuasiMonotoneLimiter, topology)Update the field limiter.q_bounds_nbr based on limiter.q_bounds in the ghost neighbors. This should be called after the ghost exchange has completed.
Part of compute_bounds!.
ClimaCore.Limiters.apply_limit_slab! — Function
apply_limit_slab!(slab_ρq, slab_ρ, slab_WJ, slab_q_bounds, rtol)Apply the computed bounds of the tracer concentration (slab_q_bounds) in the limiter to slab_ρq, given the total mass slab_ρ, metric terms slab_WJ, and relative tolerance rtol. Return whether the tolerance condition could be satisfied.
ClimaCore.Limiters.column_massborrow! — Function
column_massborrow!(
q_data::AbstractArray,
ρ_data::AbstractArray,
ΔV_data::AbstractArray,
q_min::AbstractFloat,
)Apply vertical mass borrowing limiter to an array backing a single column of scalar data.