# Numerics

This module contains a wide range of numerical utilities including math and discretization routines, state variable array caches, and helper types for supporting automatic differentiation.

`CryoGrid.Numerics.ArrayCache`

— Type`ArrayCache{T,TA} <: StateVarCache`

Simple state variable cache that writes directly into the given array.

`CryoGrid.Numerics.AutoGrid`

— Type`AutoGrid <: DiscretizationStrategy`

`CryoGrid.Numerics.DiffCache`

— Type`DiffCache{T,TCache}`

Wrapper around `PreallocationTools.DiffCache`

that stores state variables in forward-diff compatible cache arrays.

`CryoGrid.Numerics.DiscretizationStrategy`

— TypeBase type for discretization "strategies" that generate a spatial discretization (typically a grid).

`CryoGrid.Numerics.Grid`

— Type`struct Grid{S,G,Q,A} <: AbstractDiscretization{Q,1}`

Represents the 1D spatial discretization on which time integration is performed. `S`

is a `GridOffset`

, either `Edges`

or `Cells`

(always edges upon initial construction). The grid representation can be converted (allocation free) between grid edges and cells via the `cells`

and `edges`

methods. `G`

represents the geometry/volume on which the vertical 1D discretization is applied. `A`

is the underlying array type, and `Q`

is the numerical type (e.g. `Float64`

or a `Unitful.Quantity`

).

`CryoGrid.Numerics.PresetGrid`

— TypeSimple discretization strategy that just supplies a pre-specified grid.

`CryoGrid.Numerics.Profile`

— Type`Profile{N,idxTypes,valTypes}`

Represents a "profile" of values indexed typically over depth, i.e:

x₁: value 1 x₂: value 2 ...

where xᵢ are the indices.

`CryoGrid.Numerics.StateVars`

— Type`StateVars{names,griddvars,TU,TV,DF,DG}`

Generic container for holding discretized state arrays from symbolic variables (`Var`

types). The `uproto`

field represetns a "prototype" of the prognostic state array which should fully define the state of the system at any given point.

`CryoGrid.Numerics.StateVars`

— Method`StateVars(vars::NamedTuple, D::Numerics.AbstractDiscretization, cachector::Function, arrayproto::Type{A}=Vector) where {A<:AbstractVector}`

Constructs a `StateVars`

container from `vars`

and the given discretization `D`

. The function `cachector`

must accept argments `f(name::Symbol, x::AbstractVector)`

where `name`

is the name of the state variable and `x`

is the array generated by the discretization.

`CryoGrid.Numerics.divergence!`

— Method`divergence!(dx::AbstractVector, j::AbstractVector, Δj::AbstractVector)`

Calculates the first-order divergence over a 1D flux vector field `j`

and grid cell lengths `Δj`

. Divergences are added to existing values in `dx`

.

`CryoGrid.Numerics.flux!`

— Method`flux!(j::AbstractVector, x::AbstractVector, Δx::AbstractVector, k::AbstractVector)`

Calculates the first-order, non-linear spatial flux over a discretized variable `x`

with conductivity `k`

. `x`

is assumed to have shape `(N,)`

, `Δx`

shape `(N-1,)`

, and `j`

and `k`

shape `(N+1,)`

such that `j[2:end-1]`

represents the fluxes over the inner grid cell faces. Fluxes are added to existing values in `j`

.

`CryoGrid.Numerics.harmonicmean!`

— Method`harmonicmean!(h::AbstractVector, x::AbstractVector, w::AbstractVector)`

Vectorized harmonic mean of elements in `x`

with weights `w`

. Output is stored in `h`

, which should have size `length(x)-1`

.

`CryoGrid.Numerics.harmonicmean`

— Method`harmonicmean(x₁, x₂, w₁, w₂)`

Simple weighted harmonic mean of two values, x₁ and x₂.

`CryoGrid.Numerics.makegrid`

— Method```
makegrid(strategy::DiscretizationStrategy, bounds::NTuple{2,<:DistQuantity})
makegrid(layer::Layer, strategy::DiscretizationStrategy, bounds::NTuple{2,<:DistQuantity})
```

Constructs a `Grid`

spanning `bounds`

using the given `strategy`

. `makegrid`

can also be specified for specific `Layer`

types when layers have specific discretization requirements.

`CryoGrid.Numerics.nonlineardiffusion!`

— Method`nonlineardiffusion!(dx::AbstractVector, j::AbstractVector, x::AbstractVector, Δx::AbstractVector, k::AbstractVector, Δk::AbstractVector)`

Fast alternative to `flux!`

and `divergence!`

which computes fluxes and divergences (via `_flux_kernel`

and `_div_kernel`

) in a single pass. Note, however, that loop vectorization with `@turbo`

is not possible because of necessary loop-carried dependencies. Fluxes and divergences are added to the existing values stored in `j`

and `dx`

.

`CryoGrid.Numerics.updategrid!`

— Method```
updategrid!(grid::Grid{Edges}, edges)
updategrid!(grid::Grid{Edges}, z0, thick::AbstractVector)
```

Updates all `grid`

values based on new grid `edges`

or an initial `z0`

+ cell `thick`

.

`CryoGrid.Numerics.∇`

— Method`∇(f::F, x::AbstractArray) where {F}`

Takes a function `y = f(x)`

and vector-valued argument `x`

and returns a tuple: `(y, ∇ₓy)`

. The gradient is calculated using forward-mode automatic differentiation.

`CryoGrid.Numerics.∇`

— Method`∇(f::F, x::Number) where {F}`

Takes a function `y = f(x)`

and argument `x`

and returns a tuple: `(y, ∂y∂x)`

. The derivative is calculated using forward-mode automatic differentiation.