Limiters

The limiters supertype is

This class of flux-limiters is applied only in the horizontal direction (on spectral advection operators).

Interfaces

ClimaCore.Limiters.QuasiMonotoneLimiterType
QuasiMonotoneLimiter

This 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, where q denotes 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)
source
ClimaCore.Limiters.VerticalMassBorrowingLimiterType
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:

source
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.

source
apply_limiter!(q::Fields.Field, ρ::Fields.Field, lim::VerticalMassBorrowingLimiter)

Apply the vertical mass borrowing limiter lim to field q, given density ρ.

source

Internals

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.

source
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.

source