Limiters
The limiters supertype is
ClimaCore.Limiters.AbstractLimiter — TypeThis class of flux-limiters is applied only in the horizontal direction (on spectral advection operators).
Interfaces
ClimaCore.Limiters.QuasiMonotoneLimiter — TypeQuasiMonotoneLimiterThis 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.compute_bounds! — Functioncompute_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! — Functionapply_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.
Internals
ClimaCore.Limiters.compute_element_bounds! — Functioncompute_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! — Functioncompute_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! — Functioncompute_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! — Functionapply_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.