Internal docstrings
These functions are mostly relevant for implementing simulators in the Jutul framework.
Entities and variables
Variables
Variable types:
Jutul.JutulVariables
— TypeAbstract type for all variables in Jutul.
A variable is associated with a JutulEntity
through the associated_entity
function. A variable is local to that entity, and cannot depend on other entities. Variables are used by models to define:
- primary variables: Sometimes referred to as degrees of freedom, primary unknowns or solution variables
- parameters: Static quantities that impact the solution
- secondary variables: Can be computed from a combination of other primary and secondary variables and parameters.
Jutul.ScalarVariable
— TypeAbstract type for scalar variables (one entry per entity, e.g. pressure or temperature in each cell of a model)
Jutul.VectorVariables
— TypeAbstract type for vector variables (more than one entry per entity, for example saturations or displacements)
Variables API:
Jutul.degrees_of_freedom_per_entity
— FunctionNumber of independent primary variables / degrees of freedom per computational entity.
Jutul.values_per_entity
— FunctionNumber of values held by a primary variable. Normally this is equal to the number of degrees of freedom, but some special primary variables are most conveniently defined by having N values and N-1 independent variables.
Jutul.maximum_value
— FunctionUpper (inclusive) limit for variable.
Jutul.minimum_value
— FunctionLower (inclusive) limit for variable.
Jutul.variable_scale
— FunctionDefine a "typical" numerical value for a variable to scale the linear system entries.
Jutul.absolute_increment_limit
— FunctionAbsolute allowable change for variable during a nonlinear update.
Jutul.relative_increment_limit
— FunctionRelative allowable change for variable during a nonlinear update. A variable with value |x| and relative limit 0.2 cannot change more than |x|*0.2.
Jutul.associated_entity
— FunctionReturn the domain entity the equation is associated with
The entity a variable is associated with, and can hold partial derivatives with respect to.
Updating variables
Jutul.@jutul_secondary
— MacroDesignate the function as updating a secondary variable.
A generic evaluator is then defined, together with a function for getting the dependencies of that function upon the state. This is most easily documented with an example. If we define the following function annotated with the macro when updating the array containing the values of MyVarType
realized for some model:
@jutul_secondary function some_fn!(target, var::MyVarType, model, a, b, c, ix)
for i in ix
target[i] = a[i] + b[i] / c[i]
end
end
The purpose of the macro is to translate this into two functions. The first defines for the dependencies of the function with respect to the fields of the state (primary variables, secondary variables and parameters):
function get_dependencies(var::MyVarType, model)
return (:a, :b, :c)
end
The second function defines a generic version that takes in state, and automatically expands the set of dependencies into getfield
calls.
function update_secondary_variable!(array_target, var::MyVarType, model, state, ix)
some_fn!(array_target, var, model, state.a, state.b, state.c, ix)
end
Note that the input names of arguments 4 to end-1 matter, as these will be fetched from state, exactly as written.
Jutul.get_dependencies
— FunctionGet dependencies of variable when viewed as a secondary variable. Normally autogenerated with @jutul_secondary
Entities
Jutul.JutulEntity
— TypeSuper-type for all entities where JutulVariables
can be defined.
Jutul.Cells
— TypeEntity for Cells (closed volumes with averaged properties for a finite-volume solver)
Jutul.Faces
— TypeEntity for Faces (intersection between pairs of Cells
)
Jutul.Nodes
— TypeEntity for Nodes (intersection between multiple Faces
)
Entities API
Jutul.number_of_partials_per_entity
— Functionnumber_of_partials_per_entity(model::SimulationModel, entity::JutulEntity)
Get the number of local partial derivatives per entity in a model
for a given JutulEntity
. This is the sum of degrees_of_freedom_per_entity
for all primary variables defined on entity
.
Jutul.number_of_entities
— FunctionGet the number of entities (e.g. the number of cells) that the equation is defined on.
Get number of entities a cache is defined on.
Number of entities for vector stored in state (just the number of elements)
Number of entities for matrix stored in state (convention is number of columns)
Number of entities (e.g. Cells, Faces) a variable is defined on. By default, each primary variable exists on all cells of a discretized domain
Equations
Jutul.JutulEquation
— TypeAbstract type for all residual equations
Equations API
Jutul.number_of_equations
— FunctionGet the total number of equations on the domain of model.
Jutul.number_of_equations_per_entity
— FunctionGet the number of equations per entity. For example, mass balance of two components will have two equations per grid cell (= entity)
Automatic differentiation
Jutul.value
— FunctionTake value of AD.
value(d::Dict)
Call value on all elements of some Dict.
Jutul.as_value
— FunctionCreate a mapped array that produces only the values when indexed.
Only useful for AD arrays, otherwise it does nothing.
Jutul.local_ad
— Functionlocal_ad(state::T, index::I, ad_tag::∂T) where {T, I<:Integer, ∂T}
Create localad for state for index I of AD tag of type adtag
Jutul.JutulAutoDiffCache
— TypeAn AutoDiffCache is a type that holds both a set of AD values and a map into some global Jacobian.
Jutul.CompactAutoDiffCache
— TypeCache that holds an AD vector/matrix together with their positions.
Jutul.allocate_array_ad
— Functionallocate_array_ad(n[, m]; <keyword arguments>)
Allocate vector or matrix as AD with optionally provided context and a specified non-zero on the diagonal.
Arguments
n::Integer
: number of entries in vector, or number of rows ifm
is given.m::Integer
: number of rows (optional)
Keyword arguments
npartials = 1
: Number of partials derivatives to allocate for each elementdiag_pos = nothing
: Indices of where to put entities on the diagonal (if any)
Other keyword arguments are passed onto get_ad_entity_scalar
.
Examples:
Allocate a vector with a single partial:
julia> allocate_array_ad(2)
2-element Vector{ForwardDiff.Dual{nothing, Float64, 1}}:
Dual{nothing}(0.0,0.0)
Dual{nothing}(0.0,0.0)
Allocate a vector with two partials, and set the first to one:
julia> allocate_array_ad(2, diag_pos = 1, npartials = 2)
2-element Vector{ForwardDiff.Dual{nothing, Float64, 2}}:
Dual{nothing}(0.0,1.0,0.0)
Dual{nothing}(0.0,1.0,0.0)
Set up a matrix with two partials, where the first column has partials [1, 0] and the second [0, 1]:
julia> allocate_array_ad(2, 2, diag_pos = [1, 2], npartials = 2)
2×2 Matrix{ForwardDiff.Dual{nothing, Float64, 2}}:
Dual{nothing}(0.0,1.0,0.0) Dual{nothing}(0.0,1.0,0.0)
Dual{nothing}(0.0,0.0,1.0) Dual{nothing}(0.0,0.0,1.0)
allocate_array_ad(v::AbstractVector, ...)
Convert vector to AD vector.
allocate_array_ad(v::AbstractMatrix, ...)
Convert matrix to AD matrix.
Jutul.get_ad_entity_scalar
— Functionget_ad_entity_scalar(v::Real, npartials, diag_pos = nothing; <keyword_arguments>)
Get scalar with partial derivatives as AD instance.
Arguments
v::Real
: Value of AD variable.npartials
: Number of partial derivatives each AD instance holds.diag_pos
= nothing: Position(s) of where to set 1 as the partial derivative instead of zero.
Keyword arguments
tag = nothing
: Tag for AD instance. Two AD values of the different tag cannot interoperate to avoid perturbation confusion (see ForwardDiff documentation).
Jutul.get_entries
— FunctionGet the entries of the main autodiff cache for an equation.
Note: This only gets the .equation field's entries.
Get entries of autodiff cache. Entries are AD vectors that hold values and derivatives.
Matrix
Jutul.JutulMatrixLayout
— TypeAbstract type for matrix layouts. A layout determines how primary variables and equations are ordered in a sparse matrix representation. Note that this is different from the matrix format itself as it concerns the ordering itself: For example, if all equations for a single cell come in sequence, or if a single equation is given for all entities before the next equation is written.
Different layouts does not change the solution of the system, but different linear solvers support different layouts.
Jutul.EntityMajorLayout
— TypeEquations are grouped by entity, listing all equations and derivatives for entity 1 before proceeding to entity 2 etc.
For a test system with primary variables P, S and equations E1, E2 and two cells this will give the following ordering on the diagonal: (∂E1/∂p)₁, (∂E2/∂S)₁, (∂E1/∂p)₂, (∂E2/∂S)₂
Jutul.EquationMajorLayout
— TypeEquations are stored sequentially in rows, derivatives of same type in columns:
For a test system with primary variables P, S and equations E1, E2 and two cells this will give the following ordering on the diagonal: (∂E1/∂p)₁, (∂E1/∂p)₂, (∂E2/∂S)₁, (∂E2/∂S)₂
Jutul.BlockMajorLayout
— TypeSame as EntityMajorLayout
, but the system is a sparse matrix where each entry is a small dense matrix.
For a test system with primary variables P, S and equations E1, E2 and two cells this will give a diagonal of length 2: [(∂E1/∂p)₁ (∂E1/∂S)₁ ; (∂E2/∂p)₁ (∂E2/∂S)₁] [(∂E1/∂p)₂ (∂E1/∂S)₂ ; (∂E2/∂p)₂ (∂E2/∂S)₂]
Various
Jutul.convergence_criterion
— Functionconvergence_criterion(model, storage, eq, eq_s, r; dt = 1)
Get the convergence criterion values for a given equation. Can be checked against the corresponding tolerances.
Arguments
model
: model that generated the current equation.storage
: global simulator storage.eq::JutulEquation
: equation implementation currently being checkedeq_s
: storage foreq
where values are contained.r
: the local residual part corresponding to this model, as a matrix with column index equaling entity index
Jutul.partition
— Functionpartition(N::AbstractMatrix, num_coarse, weights = ones(size(N, 2)); partitioner = MetisPartitioner(), groups = nothing, n = maximum(N), group_by_weights = false, buffer_group = true)
Partition based on neighborship (with optional groups kept contigious after partitioning)
Jutul.load_balanced_endpoint
— Functionload_balanced_endpoint(block_index, nvals, nblocks)
Endpoint for interval block_index
that subdivides nvals
into nblocks
in a load balanced manner. This is done by adding one element to the first set of blocks whenever possible.