Variables
Variable definition synopsis
There are eight types of user defined variables:
Each of these are stored in arb using the same general data structure (fortran funk_type in general_module.f90). Any of these variables can be defined by a user-written expression which is read by and interpreted by setup_equations.pl and maxima, as per
centring_variable <name> [units] "expression" ON <region> options # comments
where centring
is one of CELL
,
FACE
, NODE
or NONE
, and
variable
is one of the above eight variables, both typed in
uppercase.
Variables that have CELL
, FACE
or
NODE
centrings have one value associated with each element
of the associated CELL
, FACE
or
NODE
centred <region>
(respectively).
Variables that have NONE
centring are not associated with a
region, and have only one value. If centring
is omitted
then NONE
centring is assumed for CONSTANT
variables, while CELL
centring is assumed for all other
variables.
If a variable centring and type has already been defined within an
arb file, the variable may be redefined without re-specifying the
centring and type again using the VARIABLE
keyword. Also,
if a variable is redefined, you can use the variable name in the new
expression to refer to the variable expression as previously defined.
This combination of features is useful for incrementing or modifying a
previously defined variable. Note that if there is a self-reference to a
variable in its expression but the variable has not yet been defined,
then a zero value is substituted for this self-reference. Also note that
it is good practice to place braces around self-references as they are
substituted in place, and omitting these braces can lead to order of
mathematical operations (BODMAS) errors (definitely a common gotcha
bug!).
The following are some examples of variable definition statements:
CELL_UNKNOWN <u[l=1]> [m/s] "4.d0" ON <allcells> # this specifies an unknown vector variable (actually the 1st (i.e. x) direction component), defined over the region <allcells>, with an initial value of 4 m/s CELL_EQUATION <equation[l=1]> "<u[l=1]>-<cellx[l=1]>" ON <allcells> # this specifies an equation variable, defined over the region <allcells>. The equation has the solution <u[l=]> = <cellx[l=1]>, where <cellx[l=1]> is the location of the cell in the 1st (i.e. x) direction NONE_CONSTANT <c_total> [M] 45.d+3 convertunits # this is a none-centred (i.e., no spatial dependence) constant, which has a numerical value (no quotes), and will be converted from M (molar) to standard units (mol/m^3) after being read in CONSTANT <c_free> "<c_total>/2" # this is also a none-centred constant, but the value is defined in terms of another constant so is defined using an expression VARIABLE <c_free> "(<c_free>) + 1.d0" # redefinition of <c_free>, but using the previous definition as a starting point FACE_TRANSIENT <f_t> [1] "0.d0" "faceif(facedelta(<boundaries>),2.d0,0.d0)" ON <allfaces> # a dimensionless transient variable that is initially 0.d0 on <allfaces>, but during timestep updates becomes 2 only on the boundary faces (<boundaries>) of the domain
Along with the user defined variables, there are also system defined
variables which can be used in user-written expressions and are known as
SYSTEM
variables, however these
cannot be set within the arb file.
All variables have an associated compound variable type (scalar, vector or tensor). These compounds are mainly used for input/output in the *.msh files.
The rest of this chapter covers these variable definition statements in more detail.
Variable names
Each variable must have a unique name, delimited by the
<
and >
characters. Besides these
characters, the variable may contain spaces and any other
non-alphanumeric characters except for the hash character #
(which indicates that a comment follows), the apersand
&
(which indicates line continuation) and the character
doubles {{
and }}
(which indicate the start
and end of embedded perl code, respectively). Also, certain variable
names are reserved for system variables as detailed below in [system
variables].
Every variable is defined as a component of either a scalar, vector
or tensor. The parent scalar, vector or tensor is known as the
variable’s compound variable. If the name ends with a direction index
contained within square braces []
, as in
<a vector[l=1]>
or
<another vector[l=3]>
, then the variable is
considered to be a component of a three dimensional vector compound. The
vector compound is written without the directional index, as in
<a vector>
or <another vector>
.
Similarly, if the name ends with a double direction index, as in
<a tensor[l=2,1]>
, then the variable is considered to
be a component of a three by three tensor compound, and its compound is
again written without the directional index as in
<a tensor>
. If the variable has no direction index
contained within square braces then the variable is a scalar and its
compound has only one component (that is, the scalar) and its compound
is written identically to its component or variable. All defined
components that are members of the same compound must have the same
centring and be defined over the same region, but they may be of
different types.
By default arb problems are three dimensional, however the number of
dimensions that are active can be altered by redefining the general
string variable <<dimensions>>
which lists the
number of active dimensions — by default this variable has the value of
1,2,3
implying that all three dimensions are active.
Components of compounds that are not explicitly defined within the arb
file are given a zero value (when used in dot dot
and
double dot ddot
colon operators for example).
Example scalar, vector and tensor variable definitions include:
CONSTANT <S> 1.d0 # a scalar variable CONSTANT <V[l=1]> 2.d0 # the first component of the compound vector <V> is 2 CONSTANT <V[l=3]> 1.d0 # the third component of the compound vector <V> is 1 CONSTANT <V_mag^2> "<V[l=1]>^2+<V[l=2]>^2+<V[l=3]>^2" # this will evaluate as 2^2+0^2+1^2=5 as <V[l=2]> is not been defined so will evaluate as zero CONSTANT <VV_dot> "dot(<V[l=:]>,<V[l=:]>)" # the dot colon operator calculates the dot product of two vectors by expanding the : to include all dimensions in <<dimensions>>, so <VV_dot> evaluates to be exactly the same as <V_mag^2> CONSTANT <V_mag> "mag(<V[l=:]>)" # the colon operator mag is equivalent to sqrt(dot(<V[l=:]>,<V[l=:]>)), which is the magnitude of the vector <V> CONSTANT <T[l=1,1]> 1.d0 # component 1,1 of tensor T CONSTANT <T[l=2,2]> 2.d0 # component 2,2 of tensor T CONSTANT <T_mag> "mag(<T[l=:,:]>)" # evaluates to second invariant of T, noting that only components 1,1 and 2,2 are non-zero here CONSTANT <T:vv> "ddot(<T[l=:,:]>,<V[l=:]>*<V[l=:]>)" # calculates the double dot product of T:VV BLOCK REPLACEMENTS R "<<dimensions>>" W "1,2" # within this code block the problem dimensions are changed to ignore the 3rd dimension CONSTANT <VV_dot> "dot(<V[l=:]>,<V[l=:]>)" # now <VV_dot> = 2^2+0^2 = 4 as the dimensions of the problem have been redefined within this code block END_BLOCK
As well as specifying the cell compound rank (ie scalar, vector or
tensor), the []
contained at the end of a variable name can
also be used to specify what relative timestep (or relstep
)
a variable corresponds to. Relative timesteps are used (primarily) in
transient problems to signify which timestep a variable corresponds to.
Noting that in transient simulations typically time is continuously
advancing, then [r=0]
implies that the variable corresponds
to the latest timestep, [r=1]
implies that the variable
corresponds to the preceeding timestep, [r=2]
implies that
the variable corresponds to the timestep before the preceeding timestep,
etc. TRANSIENT
variables are updated in decreasing
relstep
index when a new timestep is started (…,
r=2
, r=1
, r=0
), so that typically
within a transient simulation [r=2]
variable values will be
updated (ie, overwritten) by [r=1]
values, and
[r=0]
values by [r=1]
values, etc, such that
the variable values progress forwards in time. If unspecified, any
variable defaults to the the current timestep, or equivalently
[r=0]
. Hence the names <a[r=0]>
and
<a>
are equivalent.
Example relative timestep specifications include:
CONSTANT <dt> [s] 1.d0 NONE_TRANSIENT <t[r=0]> "0.d0" "<t[r=1]>+<dt>" # this transient has an initial value of 0, and upon update is <t[r=1]>+<dt>, noting that during a timestep update variables are evaluated in increasing `r` order NONE_TRANSIENT <t[r=1]> "<t[r=0]>-<dt>" "<t[r=0]>" # initially this variable will be 0-1=-1s, and on timestep update will adopt the latest <t[r=0]> value NONE_OUTPUT <a[r=0]> "<t[r=0]>+2" NONE_OUTPUT <a> "<t>+2" # exactly the same as the above CONSTANT <V2[l=1,r=0]> 3.d0 # the order of the l direction indicies and r relstep indicies doesn't matter, although they are standardised to alphabetical order internally CONSTANT <V2[r=0,l=1]> 3.d0 # same as the above
Note that while the arb transient simulation notation has been
designed for solving transient problems, in reality the notation may be
used more generally. For example the transient simulations functionality
can be used to perform multiple steady-state simulations with input
parameters changing in a user defined way as a function of the
<timestep>
. As an example, in the following the
material diffusivity <D>
increases as a function of
the <timestep>
:
CELL_UNKNOWN <A> "1.d0" ON <domain> # an unknown is defined on all cells in the domain CELL_EQUATION <A transport> "celldiv(<D>*facegrad(<A>))" ON <domain> # a steady state diffusion equation is solved on each cell NONE_TRANSIENT <D> "" "<timestep>*1.d-10" # the diffusivity changes from 1.d-10 t 1.d-9 over the 10 'timesteps' GENERAL_OPTIONS timestepmax=10 # setting the maximum timesteps in the simulation # in reality this problem would also require boundary conditions to be set on <boundaries> for additional unknown variables
Variable definition modifiers
Along with the standard variable definition statements, variable statements can also be used to cancel, append or apply a default value for a variable using a definition modifier. The modifiers trail the variable definition keyword and are:
-
= cancel: means to cancel a variable if it has previously been defined. A legacy notation ofCANCEL
is equivalent+
= append: means to add the value of the expression on to any previously defined expressions. If the variable has previously not been defined then this modifier performs no action*
= default: means to only implement the (entire) definition statement if the variable has not previously been defined. This is useful for setting default values for variables, or equivalently, making sure that variable definition statements do not overwrite previous definition statements
Example uses of definition modifiers are:
CONSTANT <A> 1.d0 CONSTANT- <A> # cancels <A> = 1.d0 definition CONSTANT <A> "<a variable>" # now <A> = <a variable> CONSTANT+ <A> "<b variable>" # now <A> = <a variable> + <b variable> CONSTANT* <A> 3.d0 # statement is ignored as <A> has already been defined CONSTANT <A> "<A>*4" # careful, as <A> = <a variable> + <b variable>*4, which is most likely a bug CONSTANT <A> "(<A>)*4" # probably what was wanted, as now <A> = (<a variable> + <b variable>*4)*4 CONSTANT <A> CANCEL # legacy equivalent to CONSTANT- <A> that cancels <A> FACE_DERIVED <A> "<facex[l=1]>" ON <allfaces> # completely new definition for <A>
Variable units
Units are defined using the []
brackets that follow the
variable name. The units definition is optional, defaulting to ‘1’
(implying non-dimensional) if not defined. Units are generally just
strings that are passed through the code to the output files, however
the code has some capability of converting between different unit types
using the convertunits
string as detailed below. To use the
convertunits
script the units must be specified using
fairly simple mathematical forms. Example units specifications that are
compatible with convertunits
include:
CONSTANT <A> [m^3/s] 2.d0 CONSTANT <B> [m3 s-1] 4.d0 CONSTANT <C> [nM/s] 5.d0 convertunits # convertunits will convert the number to standard basis on read CONSTANT <D> [pJ K /kg] 3.d0 convertunits CONSTANT <E> [A/(m s)] 0.1d0 # ERROR! use of brackets in units is not allowed
Variable expression or numerical value
Following the units definition an expression can be specified, or as
an alternative for CONSTANT
variables only, a numerical
value can be specified instead. All user variables require either an
expression or numerical value.
Expressions must be quoted in either single ('
) or
double ("
) quotes, and will contain a combination of
mathematical operations (+-*/()
etc), maxima functions
(log
, sin
, etc), arb operators
(celldiv
, facesum
, etc) and arb variables and
regions (<a variable>
, <allcells>
,
etc). Variable expressions are interpreted using the setup_equations.pl
script (and in turn maxima
) and are hard coded into the
fortran exectuable, with the implication that every time an expression
is altered the setup script will need to be rerun and the code
recompiled.
Unlike variable expressions numerical values may only be specified
for CONSTANT
variables (any centring) and are distinguished
from variable expression by NOT being quoted. Numerical values
are read directly by the fortran exectuable (as opposed to the setup
script setup_equations.pl),
meaning that if a numerical constant value is changed then the fortran
code does not have to be recompiled - this is the advantage of using
numerical values. It is good practice to use the character ‘d’ to
specify the exponent in any numerical value, as these values are read by
fortran and within fortran this notation means that a full double
precision float value (roughly 16 significant figures) will be specified
as opposed to only a real float specification (roughly only 8
significant figures, although actually any ‘e’ exponents are converted
to ‘d’ exponents before being read anyway).
The following gives some examples of variable expressions and numerical values
CELL_DERIVED <A> "<cellx[l=1]>^2" ON <allcells> # double quotes specify an expression FACE_CONSTANT <C> '<facex[l=2]>+<facex[l=3]>' ON <allfaces> # single quotes also specify an expression CELL_OUTPUT <B> "(6!)*log(<cellvol>)" ON <boundarycells> # here we use the maxima factorial expression (only works with integers) and the natural log function CONSTANT <diameter> [mm] 4.d0 convertunits # a numerical value is specified for <diameter> CONSTANT <diameter_mm> [mm] "4.d0" # this is also a constant value, but as it is contained in an expression changing this value will result in code recompilation - bad practice CONSTANT <diameter_m> [m] "noneconvertunits(<diameter_mm>)" # this ends up having the same value as <diameter> CELL_CONSTANT <silly rho> [kg/m^3] 0.123e23 ON <allcells> # all <silly rho> variables are assigned a constant value
A special case of constant variables can be specified using the
REGION_LIST
and REGION_CONSTANT
keyword
combinations. The purpose of these keywords is to allow a constant to be
read in (directly by the fortran exectuable) that has different constant
values for different regions. This definition can be used in the file to
assign different numerical values to either a cell/face/node centred
constant in specific regions. Two statements are required for this type
of constant definition: The first defines the list of regions where the
next constant will be set (REGION_LIST
) and the second
defines the constant and sets/lists the corresponding numerical values
(REGION_CONSTANT
). The region names in the statement must
have the same centring as the following statement. Furthermore, the
regions over which the constant is defined must include all of the
regions listed within the previous statement.
REGION_LIST <region1> <region2> ... <regionN> # comments CELL_REGION_CONSTANT <name> [units] value1 value2 ... valueN ON <region> options # comments FACE_REGION_CONSTANT <name> [units] value1 value2 ... valueN ON <region> options # comments
In the following example the two regions
<subset A>
and <subset B>
are cell
regions that are subsets of <allcells>
. The following
commands define two property constant variables over these regions:
CELL_REGION <subset A> "withinbox(0,1,0,1,0,1)" ON <allcells> # defines a region that is a subset of <allcells> CELL_REGION <subset B> "compound(<domain>-<subset A>)" ON <domain> # this is any cell that is within <domain> (itself a subset of <allcells>) but not within <subset A> REGION_LIST <subset A> <subset B> # this is the list of regions that is applied to every following constant list command until another region list command is specified CELL_REGION_CONSTANT <rho> [kg/m^3] 500.d0 300.d0 ON <allcells> # defines <rho> to be 500 within <subset A>, 300 within <subset B> and 0 elsewhere within <allcells> CELL_REGION_CONSTANT <mu> [Pa s] 1.d0 0.5d0 ON <allcells>
REGION_LIST
/REGION_CONSTANT
keywords are
useful for specifying constant material properties that vary with
position.
Variable centring and region
All variables must have a centring. If not defined then
NONE
centring is assumed.
Additionally, all variables that are CELL
,
FACE
or NODE
centred must be defined on a
region that has the same centring as the variable. The associated region
is defined using the ON <region>
notation. Variables
may be defined on regions that are either static or dynamic (noting that
dynamic regions change as the simulation progresses), however if a
variable is defined on a dynamic region then it will actually be
assigned values on all elements within the parent static region that
houses the dynamic region. For example, in the following
CELL_DERIVED <dynamic variable> "<phi>" ON <dynamic region> # variable is defined on a dynamic region CELL_DERIVED_REGION <dynamic region> "variable(<a changing variable>)" ON <allcells>
the DERIVED
variable
<dynamic variable>
will adopt of the value of
<phi>
for every cell element within
<dynamic region>
. Noting that
<dynamic region>
is a dynamic region that is a subset
of the static (system) region <allcells>
,
<dynamic variable>
will actually be defined for all
cells within <allcells>
, but be zero if the cell is
contained within <allcells>
but not within the
current <dynamic region>
.
Note that referring to a variable value outside its (static parent) region of definition will produce a memory error when the fortran executable is running.
If not specified by default a CELL
centred variable will
be defined over <domain>
if it is an equation, or
<allcells>
otherwise. Similarly if not specified a
FACE
variable will be defined over
<boundaries>
if it is an equation, or
<allfaces>
otherwise. A NODE
variable
will be defined over <allnodes>
if it is not
specified. If in doubt, specify!
Variable types
The eight user variable types are now defined in more detail:
CONSTANT
Constant variables are evaluated once at the start of a simulation. They may be defined either by expression language (if quoted in single or double quotes) or just as a numerical constant (if not quoted) read directly by the fortran executable. The advantage of the latter method is that setup_equations.pl doesn’t have to be run again, so simulation setup is faster.
Defining statements:
CELL_CONSTANT <name> [units] "expression" ON <region> options # comments FACE_CONSTANT <name> [units] "expression" ON <region> options # comments NODE_CONSTANT <name> [units] "expression" options # comments NONE_CONSTANT <name> [units] "expression" options # comments CELL_CONSTANT <name> [units] numerical_constant ON <region> options # comments FACE_CONSTANT <name> [units] numerical_constant ON <region> options # comments NODE_CONSTANT <name> [units] numerical_constant options # comments NONE_CONSTANT <name> [units] numerical_constant options # comments
Examples:
CELL_CONSTANT <test constant> "<cellx[l=1]>^2" ON <boundarycells> FACE_CONSTANT <test constant 2> [m] "<facex[l=2]>" # default region of <allfaces> will be implied CONSTANT <mu> [Pa s] 1.0d-3 # fluid viscosity NONE_CONSTANT <rho> [kg/m^3] 997 # fluid density
As discussed above, constants may also be defined using the
REGION_LIST
and REGION_CONSTANT
keyword
combination, defined by
REGION_LIST <region1> <region2> ... <regionN> # comments CELL_REGION_CONSTANT <name> [units] value1 value2 ... valueN ON <region> options # comments FACE_REGION_CONSTANT <name> [units] value1 value2 ... valueN ON <region> options # comments
An example of this type of specification is
REGION_LIST <inlet> <outlet> # some face regions FACE_REGION_CONSTANT <electric field> [V/m] 10 20. ON <boundaries>
TRANSIENT
Transient variables are used only in transient simulations, and are evaluated at the start of each timestep. Transient variables are typically used to store previous timestep values, or to provide constant data to a simulation that depends explicitly on the time. Transient variables are defined using two expressions, with the first representing the initial value for the variable and the second used to update the variable at the start of each timestep:
CELL_TRANSIENT <name> [units] "initial expression" "update expression" ON <region> options # comments FACE_TRANSIENT <name> [units] "initial expression" "update expression" ON <region> options # comments NONE_TRANSIENT <name> [units] "initial expression" "update expression" options # comments NONE_TRANSIENT <name> [units] "" "update expression" options # this will use the update expression as the initial expression NONE_TRANSIENT <name> [units] "update expression" options # the initial expression here depends on rstep
Along with the rules detailed for other variables, transient
variables are associated with particular relative timesteps (or
relsteps). Relative timesteps indicate how many timesteps previous to
the current one the variable refers to. The value of a variable is
defined in a similar manner to the direction of a variable, using an
index in square brackets at the end of the variable name: For example
<t[r=0]>
would represent the time at the end of the
current timestep, <t[r=1]>
would be time at the end
of the previous timestep, <t[r=2]>
the time at the
end of (earlier) timestep before that one and so on. If an index is
omitted from a definition, then r=0
is assumed. Actually,
any type of variable can be associated with any particular relative
timestep, but it is rare to do this with anything other than a transient
variable.
Along with the usual (in this case second) expression definition, the
optional first expression is applied once (only) at the start of a
simulation, and represents the variable’s initial condition. If an
initial expression is not given at all (no quotation marks present for
this field), then the value of zero is assumed if the variable has
r=0
, or the update expression otherwise. If the initial
expression is not specified but quotation marks are present for this
field, then the update expression is substituted for the initial
expression - ie, a shorthand way of repeating the update expression.
The second expression for the transient variable is the update
expression that is applied once at the start of each timestep. These
expressions are applied in the order of decreasing relstep (relative
timestep), meaning that the earliest time value is calculated first,
followed by the next timestep value, until the current time
(r=0
) is reached. Circular references are not allowed in
the expression — in practice this is not limiting by carefully
considering the relstep update order of variables.
Examples:
NONE_TRANSIENT <t[r=0]> "0.d0" "<t[r=1]>+<dt>" # current end-of-timestep time (r=0) NONE_TRANSIENT <t[r=1]> "<t>-<dt>" "<t>" # time at last step (r=1) NONE_TRANSIENT <t[r=2]> "<t[r=1]>-<dt>" "<t[r=1]>" # time at step before last step (r=2, assuming a constant dt) NONE_TRANSIENT <z[r=1]> [m] "<z>-<w_0>*<dt>" "<z_real>" # position of ball at last step (r=1) NONE_TRANSIENT <w[r=1]> [m/s] "<w>" "<w_real>" # velocity of ball at last step (r=1)
DERIVED
Derived variables can depend on any other variables and are updated
as the UNKNOWN
variables are updated within the main Newton
iteration loop. These variables are the main workhorse variables used to
setup systems of equations to be solved.
The defining statements are:
CELL_DERIVED <name> [units] "expression" ON <region> options # comments FACE_DERIVED <name> [units] "expression" ON <region> options # comments NODE_DERIVED <name> [units] "expression" ON <region> options # comments NONE_DERIVED <name> [units] "expression" options # comments
Examples:
FACE_DERIVED <tau[l=1,1]> "<p> - <mu>*2.d0*facegrad[l=1](<u[l=1]>)" output CELL_DERIVED <graddivp[l=1]> "celldivgrad[l=1](<p>)" # divergence based pressure gradient
UNKNOWN
Unknown variables are those upon which the EQUATION
variables ultimately depend. The objective of the Newton iteration loop
is to choose appropriate UNKNOWN
values such that all
equations are satisfied (that is, equal zero). The expression for an
UNKNOWN
variable is the initial value used at the start of
the first Newton iteration loop in a simulation. Choosing initial values
that are as close as possible to the final solution gives the best
chance of a simulation converging. In transient simulations the initial
value for the variable usually has the physical meaning of the variables
value at the zeroth timestep. In subsequent timesteps the
UNKNOWN
variables maintain the values from the end of the
converged previous timestep when commencing each new Newton iteration
loop. Usually when restarting a simulation (by default)
input
is specified for these variables so that they start
the Newton loop with the values from the stored msh
file.
Defining statements:
CELL_UNKNOWN <name> [units] magnitude "expression" ON <region> options # comments FACE_UNKNOWN <name> [units] magnitude "expression" ON <region> options # comments NODE_UNKNOWN <name> [units] magnitude "expression" ON <region> options # comments NONE_UNKNOWN <name> [units] magnitude "expression" options # comments
Note that all UNKNOWN
variables require a single scalar
magnitude value that is used to normalise (or non-dimensionalise) their
values when computing the Newton residual. By default this magnitude is
calculated by examining the magnitude of the initial expression, however
in some situations (such as a concentration that is initially zero) this
process cannot determine this magnitude and instead it must be specified
explicitly via the magnitude
option (detailed in variable options list).
Examples:
CELL_UNKNOWN <u[l=1]> 1.d0 "<u_av>" # a velocity component CELL_UNKNOWN <p> [] 1.d0 "1.d0-<cellx[l=1]>" # pressure NONE_UNKNOWN <p_in> [Pa] 1.d0 "1.d0" # the pressure at the inlet
EQUATION
Equation variables represent the equations to be satisfied. The
equation expressions should be formulated so that when the equation is
satisfied, the expression equals zero. The number of
EQUATION
variables (in a per-element sense) must equal the
number of UNKNOWN
variables (again in a per-element sense).
Furthermore, for the system to be well posed the equations must be
functionally independent, meaning that no single equation can be made
from a combination of the other equations.
Defining statements:
CELL_EQUATION <name> [units] "expression" ON <region> options # comments FACE_EQUATION <name> [units] "expression" ON <region> options # comments NODE_EQUATION <name> [units] "expression" options # comments NONE_EQUATION <name> [units] "expression" options # comments
As for the UNKNOWN
variables, EQUATION
variables require a single scalar magnitude value which is used
normalise their value when calculating the Newton loop residual. By
default these are calculated from a combination of the initial
unconverged EQUATION
variable values, and from the product
of the derivatives of the EQUATION
variables with respect
to the UNKNOWN
variables, multiplied by each
UNKNOWN
magnitude. Generally this works as satisfactorily,
however the magnitude can be set independently using various
magnitude
options as listed in the variable options list.
Examples:
CELL_EQUATION <continuity> "celldiv(<u_f>)" ON <domain> # continuity FACE_EQUATION <outlet noslip> "dot(<u[l=:]>,<facetang1[l=:]>)" ON <outlet> # no component tangential to outlet NONE_EQUATION <p_in for flowrate> "<u_av_calc>-<u_av>" # set flowrate through inlet to give required average velocity
OUTPUT
Output variables are evaluated once convergence of the solution has
been reached. While designed for output purposes, they do not have to be
output (by specifying the option nooutput
) and can instead
also be regarded as variables that are only evaluated once the Newton
loop has converged. This can be handy in transient simulations if you
want a variable to be calculated at the end of a timestep that will be
carried over to the next timestep, but that is not involved in the
actual iteration procedure.
Defining statements:
CELL_OUTPUT <name> [units] "expression" ON <region> options # comments FACE_OUTPUT <name> [units] "expression" ON <region> options # comments NODE_OUTPUT <name> [units] "expression" options # comments NONE_OUTPUT <name> [units] "expression" options # comments
Examples:
NONE_OUTPUT <F_drag> [N] "facesum(<facearea>*dot(<facenorm[l=:]>,<tau[l=:,1]>),<cylinder>)" # force on object in axial direction
CONDITION
CONDITION
variables control the running of the
simulation. They can initiate the following actions: output, stop,
convergence, indicate an error, cause timestep or newtstep rewinding and
a bell. CONDITION
variables are evaluated (tested) at
various stages in the running of the code, depending on the particular
action being tested.
Defining statements:
CELL_CONDITION <name> [units] "expression" ON <region> options # comments FACE_CONDITION <name> [units] "expression" ON <region> options # comments NODE_CONDITION <name> [units] "expression" options # comments NONE_CONDITION <name> [units] "expression" options # comments
For a CONDITION
variable, if the evaluated expression is
positive (>0) then the condition is satisfied and the corresponding
action will take place. Note that an action will take place if any of
the condition variables that correspond to it are positive (in fact,
after one positive value is found the remainder are not even evaluated).
More than one action can be specified for each CONDITION
variable. If a CONDITION
variable is either
CELL
, FACE
or NODE
centred then
it is evaluated for every element in its associated region, and the
relevant actions are performed if the variable value is positive for any
the associated elements. Note also that as CONDITION
variables are evaluated in the order they are defined, they are only
evaluated if the relevant condition has not already become true. Hence,
a CONDITION
variable value may not become positive in a
simulation (ie, in the output) if another CONDITION
variable of the same type (eg, outputcondition
) is
evaluated as true before hand.
What action is performed when the CONDITION
variable
becomes positive is specified via options, with the alternatives being
outputcondition
, stopcondition
,
convergencecondition
, errorcondition
,
timesteprewindcondition
,
newtsteprewindcondition
(not fully implemented) and
bellcondition
. More details are listed below in variable options list.
Examples:
NONE_CONDITION <time based stop condition> "<t>-<tend>" stopcondition # when this becomes true (>0.) the simulation stops NONE_CONDITION <bouncing bell> "noneif(<z>,-1.d0,1.d0)" bellcondition # is positive when <z> is negative at the end of a timestep NONE_CONDITION <output test> "<t>-<tout>-<dtout>" outputcondition # this will be true (>0.) whenever we are <dtout> from last output
LOCAL
LOCAL
variables are like DERIVED
(or
OUTPUT
or really any other) variables, except that they are
not stored, but rather evaluated only when required. LOCAL
variables may be used instead of DERIVED
variables to save
memory. This strategy makes sense if the variable is only going to be
used only once or twice at each location. LOCAL
variables
may also be used to split up an otherwise long expression into smaller
(and possibly common) sub-statements, dependent on the local conditions.
For example, in the examples given below, LOCAL
variables
are used to calculate the second derivative of the normal velocity to a
wall, in the normal direction to a wall.
Defining statements:
CELL_LOCAL <name> [units] "expression" ON <region> options # comments FACE_LOCAL <name> [units] "expression" ON <region> options # comments NODE_LOCAL <name> [units] "expression" options # comments NONE_LOCAL <name> [units] "expression" options # comments
When referred to in other variable expressions, LOCAL
statements can either be inlined, or evaluated independently depending
on the option inline
. By default inline
is on
for all LOCAL
variables as this tends to result in the most
efficient code. However if a LOCAL
variable is referred to
many times in the expression of another variable then it is possible
that using noinline
may result in slightly more efficient
code. Note that the output
option can also be specified for
a LOCAL
, which is a good strategy to (slightly) lower
memory usage if the variable being output is not used for anything else.
The region over which a LOCAL
is defined is only really
relevant if the output
option is on.
Note also that a LOCAL
variable may depend on the locale
of the calling statement: For example for the evaluation of
<u_n>
in the following examples we refer to the
<facenorm>
of the face on which the local variable is
calculated. For this type of LOCAL
variable it would not
make sense to output this separately over <allcells>
,
as the <facenorm>
would be undefined and an error
would result.
Examples:
CELL_LOCAL <u_n> "dot(<u[l=:]>,cellave[lastface](<facenorm[l=:]>))" CELL_LOCAL <d u_n d x[l=1]> "cellgrad[l=1](<u_n>)" CELL_LOCAL <d u_n d x[l=2]> "cellgrad[l=2](<u_n>)" CELL_LOCAL <d u_n d x_n> "dot(<d u_n d x[l=:]>,cellave[lastface](<facenorm[l=:]>))" FACE_LOCAL <d^2 u_n d x_n^2> "facegrad(<d u_n d x_n>)" ON <boundaries> output
SYSTEM
In addition to the user variables there are a number of system
defined variables. See ref: system variables
in VariableRegion.pm.
Variable options
Variable options synopsis
Following the region specification a comma separated list of options may be given for each variable. Options are used to specify additional information about variables, including how variables are output or input, how they are updated during convergence iterations, or how they are changed during timestep rewinds.
Variable options are generally specified using lowercase keywords,
written without spaces or ’_’ characters separating words. Options
statements such as output
that can be either true or false
can be specified using two formats: In the first a true value is implied
by simply stating the option name, as in output
, while a
false value is specified by preceding the option with a no
,
as in nooutput
; In the second format the true or false
strings are written explicitly using fortran syntax, as in
output=.true.
or output=.false.
. Other types
of options accept a value, set using the option=value
syntax. Setting an option that normally accepts a value to an empty
string clears its definition, as in option=
. Values can be
quoted via either single of double quotes. If the value is a variable
name, (as in magnitude=<a variable>
) the variable
name need not be quoted. Additionally, while most options are specific
to the (component) variable being defined, some options such as
output
are actually specific to the compound variable that
the current variable being defined is a component of. Not all options
apply to all variable types.
Internally each option may be read by either the setup_equations.pl script (indicated by ‘p’ for perl in the following table) or by the fortran executable (indicated by ‘f’ for fortran in the table) — whether the option is read by the setup script or the fortran executable determines whether the simulation has to be recompiled when the option changes, with ‘p’ requiring recompilation and ‘f’ not.
Following the general philosophy of the arb syntax, options that are
read last take precedence over options that are read first. Hence,
options that are assigned to a variable lower down an input file take
precedence over those that are assigned higher up in the file, and on a
single variable definition line options that are written further to the
right take precedence over options that are to the left. A special
clearoptions
keyword can be used to remove any options that
have been assigned to a variable previously. For example, in the
following:
CELL_DERIVED <A> "<facex[l=1]>" output # <A> now has output defined VARIABLE <A> nooutput # but this is now superseded by nooutput VARIABLE <A> output,nooutput,clearoptions,nooutput,output # clearoptions removes all previous options, but then output is finally read
the variable <A>
eventually ends up with only the
two options nooutput
and output
, however
output
was read last so takes precedence.
The keywords DEFAULT_OPTIONS
and
OVERRIDE_OPTIONS
can also be specified to either set
default options or override the options, respectively, for certain
groups of variables or regions being read in. In their most basic
form:
DEFAULT_OPTIONS
: adds the following options to every subsequent variable, until cleared again using a blank statement. When listed in order, default options precede a variable’s individually specified options - hence, in the case of conflicting option statements, individual options take precedence over default options (ie, the individual options have a higher priority).OVERRIDE_OPTIONS
: does the same asDEFAULT OPTIONS
, except that these options are inserted after a variable’s individually specified options, and so in the case of conflicting option statements, take precedence over the individual options (ie, the override options have a higher priority).
If either of these keywords is given without any trailing options, as in the example definition of
DEFAULT OPTIONS
then the (in this case) DEFAULT_OPTIONS
are cleared and
are no longer applied to the following variables and regions.
Actually the DEFAULT_OPTIONS
and
OVERRIDE_OPTIONS
have many more specific varieties that
apply to classes of variables and/or regions. In the above two basic
forms, the options are applied to all following variables and regions
until cancelled again by an empty definition. In there more complex form
however they can be applied to individual groups of centrings,
variable/region types and variable/regions. The more general format of
these commands is defined via
DEFAULT_centring_type_entity_OPTIONS list,of,comma,separated,options OVERRIDE_centring_type_entity_OPTIONS list,of,comma,separated,options
where centring=CELL|FACE|NODE|NONE
,
type=UNKNOWN|DERIVED|EQUATION|OUTPUT|TRANSIENT|NEWTIENT|CONDITION|LOCAL
and entity=VARIABLE|REGION
. If any of
centring
, type
or entity
are left
out then the command is assumed to apply to all relevant following
definition statements (until cancelled again by the same command, but
now with no trailing options). As examples
DEFAULT_CELL_VARIABLE_OPTIONS output # sets the output option to be on by default for <a> and <c>, but not <d> and <e> OVERRIDE_DERIVED_OPTIONS nooutput # sets the output option to be off (override) for <d> only CELL_UNKNOWN <a> FACE_DERIVED <d> CELL_LOCAL <c> DEFAULT_CELL_VARIABLE_OPTIONS # cancels the default options again for the cell centred variables CELL_LOCAL <e> OVERRIDE_DERIVED_OPTIONS # clears the particular override option again
Variable options list
The various options are now listed. In the following the ‘|’ notation implies ‘or’:
derivative|noderivative
-
For
DERIVED|EQUATION|LOCAL
(p): Do or do not calculate Jacobian derivatives for this variable. If this derivative is not calculated then convergence will be slowed, however in rare instances where derivatives could be ill-defined, not able to be calculated or undergo step changes (not-continuous) then setting the derivative of a function to zero may allow a simulation to converge. Default isderivative
for allDERIVED|EQUATION|LOCAL
variables (and makes no sense for any other type of variable). positive|negative|nocheck
-
For
DERIVED|UNKNOWN|EQUATION|LOCAL
(p): Check at each iteration that variable is positive or negative, or do not check. derivative|noderivative
-
For
DERIVED|EQUATION|LOCAL
(p): Do or do not calculate Jacobian derivatives for this variable. If this derivative is not calculated then convergence will be slowed, however in rare instances where derivatives could be ill-defined and the residual is not heavily dependent on the variable then ignoring its derivative may allow a simulation to converge. positive|negative|nocheck
-
For
DERIVED|UNKNOWN|EQUATION|LOCAL
(p): Check at each iteration that variable is positive or negative, or do not check. Including one of thesepositive|negative
options causes the code to check the sign of the relevant variable. In theory this could be used for quantities like concentrations that are only physically meaningful when positive. By using an expression such as1-<concentration>
and including thepositive
option an upper limit for a variable can also be enforced. In practice using these types of limiting conditions to prevent equation singularities slows convergence to an unfeasibly slow rate. It is usually better to choose the form of the equations so that they are stable even for small unphysical excursions, and then check once convergence has been achieved that the results are physical. output|nooutput
-
For all user variables (f): Output compound to msh files. For example,
if
output
is specified for the vector<v[l=1]>
, then all components of this vector (including any empty components) will be written to the msh file. A vector such as<v>
(in compound notation) will appear as a vector ingmsh
. The default isoutput
for allUNKNOWN
andOUTPUT
variables, as well asCELL
centredDERIVED
variables and anyTRANSIENT
variables that do not correspond to the oldest storedrelstep
(that is,output
is on forrelstep
< max(relstepmax
,1), noting that therelstepmax
data is not required for a simulation restart). All other variables havenooutput
by default. compoundoutput|nocompoundoutput
-
For all user variables (f): These are synonyms for
output|nooutput
. componentoutput|nocomponentoutput
-
For all user variables (f): Output just this component to the msh files.
For example, if
output
is specified for the vector<v[l=1]>
then this specific component will be output to the msh file as<v[l=1]>
and will appear as a scalar. Theoutput
(or equivalentlycompoundoutput
) andcomponentoutput
variables may be set independently. The default isnocomponentoutput
for all variables. stepoutput|nostepoutputupdate|stepoutputnoupdate|nostepoutput
-
For all user variables (f): Output compound to the step file, which
typically is written to more regularly that the msh files and contains
data used to monitor simulation convergence or process conditions. The
nosetpoutputupdate
option does not write the variable to the step file, but does update its value when the step file is written. This is useful if you want anOUTPUT
variable updated during the step file output as another variable depends upon it, but you don’t want the variable output. Thestepoutputnoupdate
alternative does the opposite, in that the variable is not updated when the step file is written but its value is still written. This is useful for recording when (eg) the msh file was last written. Finally thenostepoutput
option neither updates or writes the value to the step file. The default isstepoutput
for allUNKNOWN
,DERIVED
,OUTPUT
andTRANSIENT
NONE
centred variables that correspond to the current timestep (relstep
=0). compoundstepoutput|nocompoundstepoutputupdate|compoundstepoutputnoupdate|nocompoundstepoutput
-
For all user variables (f): Synonyms of
stepoutput|nostepoutputupdate|stepoutputnoupdate|nostepoutput
as above componentstepoutput|nocomponentstepoutputupdate|componentstepoutputnoupdate|nocomponentstepoutput
-
For all user variables (f): As per
stepoutput|nostepoutputupdate|stepoutputnoupdate|nostepoutput
, but applied to the component variable rather than its compound. input|noinput
-
For all stored user variables (ie, not
LOCAL
) (f): Read in compound from msh files when starting the simulation, overwriting any initial data set from expressions. It probably doesn’t make much sense to read inCONDITION
andEQUATION
variables, but you can… Default isinput
for allUNKNOWN
andTRANSIENT
variables andnoinput
for everything else. componentinput|nocomponentinput
-
For all stored user variables (ie, not
LOCAL
) (f): as forinput|noinput
, but for the individual component rather than the compound. elementdata|elementnodedata|elementnodelimiteddata
-
For
CELL
centred user varables (f): These options control howCELL
centred data is written to msh files for compound variables. If theelementdata
option is chosen then only one compound variable value per cell is written to the msh file, corresponding to the average or centroid value of that variable for the cell. When gmsh displayselementdata
using a contour plot the colour within each cell will be uniform (and the field will appear ‘blocky’). If insteadelementnodedata
is chosen instead then a value will be written to the msh file for every node that surrounds every cell. The average of these values will still equal the average (or centroid) value for the cell, however now gmsh will display a contour plot of this variable using a gradient of colours within each cell. This is preferable for data visualisation (the plots don’t appear ‘blocky’ anymore) but there are more values written to the msh file with the result that the msh file is larger. The final option,elementnodelimiteddata
is the same aselementnodedata
, however the gradient chosen to calculate the node values within each cell is limited such that no node value within a particular cell lies outside the bounds of the average (or centroid) values of the surrounding cells. This option is a sensible choice if data visualisation is required for a variable that should be bounded between strict limits - for example, concentrations that should not range below zero.elementnodedata
andelementnodelimiteddata
have no effect onFACE
,NODE
andNONE
centred variables. Default iselementnodelimiteddata
for allCELL
centred scalar variables, andelementdata
for everything else. compoundelementdata|compoundelementnodedata|compoundelementnodelimiteddata
-
For all
CELL
centred user variables (f): synonyms forelementdata|elementnodedata|elementnodelimiteddata
. componentelementdata|componentelementnodedata|componentelementnodelimiteddata
-
For all
CELL
centred user variables (f): as perelementdata|elementnodedata|elementnodelimiteddata
, but applied just to components. Default iscomponentelementdata
for all variables.
#p outputcondition,stopcondition,convergencecondition,bellcondition - for CONDITION, type of condition, can have multiple conditions for the one variable #f magnitude=value - for EQUATION, UNKNOWN specifies the initial variable magnitude to be used (rather than being based on the initial variable values) - a negative number will cause the magnitude to be set based upon the initial values (which is the default) #f dynamicmagnitude/staticmagnitude - for EQUATION, UNKNOWN, adjust magnitude of variable dynamically as the simulation progresses, or keep it constant at the initial magnitude #f dynamicmagnitudemultiplier=value - for EQUATION, UNKNOWN, multiplier to use when adjusting magnitude of variable dynamically (=>1.d0, with 1.d0 equivalent to static magnitudes, and large values placing no restriction on the change in magnitude from one newton iteration to the next) # clearoptions - remove all previously (to the left and above the clearoptions word) user-specified options for this variable #f timesteprewind - this variable gets rewound if a timestep rewind is performed #f timesteprewindmultiplier=value - and further that it is multiplied by this amount on rewind, either a number or a reference to a none-centred variable (can be a local) #f newtsteprewind - this variable gets rewound if a newtstep rewind is performed #p inline|noinline - where possible substitute this equation in other equations rather than evaluating as a separate variable (inline default for locals, noinline default for others) #p convertunits(|=finalunits) - for (NUMERICAL_)CONSTANT, convert variable magnitude when read into fortran from originalunits specified in arb file to finalunits. If finalunits is left out then convert to standard SI units
magnitude - (required): An order of magnitude estimate (postive and greater than zero real or double precision value) must be specified for all unknown variables. This magnitude is used when checking on the convergence of the solution.
conditions - : For transient and steady-state simulations, indicates when the Newton loop has converged. Is evaluated at the start of each Newton loop.
- : For a transient simulation, indicates when the simulation
should finish. Is evaluated at the end of each
successful timestep.
- : For a transient simulation, indicates when the output files
should be written. Is evaluated at the end of each
successful timestep.
- : For a transient simulation, indicates when a noise should be
made (this one’s a bit silly). Is evaluated at the end of each
successful timestep.
Expression Language Overview
The expression language refers to the psuedo-mathematical language that is used to represent each variable’s expression. arb uses the symbolic algebra program ‘maxima’ to parse this language and convert these expressions into executable (fortran), so any mathematical operators supported by ‘maxima’ are able to be used in this language. In addition to maxima’s features, the expression language also supports a number of arb specific discretisation operators that allow spatially varying problems to be expressed in scalar arithmetic. The discretisation operators are particularly suited to solving transport problems using the Finite Volume Method and are detailed in this section.
Discretisation Operators
Syntax
Discretisation operators produce a single result from the arguments that are contained within their parentheses (). They also accept options, contained within square brackets [], and placed between the operator name and any parentheses. Operators are (by convention) typed lowercase (although should parse in uppercase) and contain no underscores, as per
operator[option1,option2,...](<argument1>,<argument2>,...)
Example facegrad
and celldiv
operators
contained within variable definitions:
FACE_OUTPUT <phigrad> "facegrad[adjacentcells](<phi>)" ON <allfaces> # operator is facegrad, argument is <phi> and a single option of adjacentcells is specified CELL_EQUATION <continuity> "celldiv(<u_f>)" ON <domain> # operator is celldiv acting on single argument of <u_f>
Operator Centring
The centring of an operator refers to the centring of the result it produces. This centring must match or be consistent with the centring of the context in which the operator is placed. The centring of most operators corresponds to the first syllable of the operator name, however there are some exceptions. For the exceptions the centring of the operator is none, and the first syllable of the operator name corresponds to the centring of the first argument passed to the operator.
To illustrate, following the centring rule is celldiv
which generates the cell centred divergence of a face centred quantity.
This operator is cell centred and hence must be used in a cell centred
context. Note that the content expression passed into this operator
(actually its first argument) is face centred however. Similarly,
facegrad
is the gradient of a cell centred quantity
evaluated at a face, so this operator is face centred and must be used
in a face centred context, but its argument (content) has cell
centring.
"celldiv(<u_f>)" # cell context centring, face argument centring "facegrad(<phi>)" # face context centring, cell argument centring
Exceptions to the centring rule include the loop-type operators,
max
, min
, and sum
. For example,
cellmax
loops through a region of cells finding the maximum
value of an expression within those cells. Hence, this operator produces
a result which has no centring (none centred) so can be used in any
centring context, but its first argument has cell centring.
facesum
loops through a region of faces summing the values
of its first argument, hence producing a none centred result that can be
used in any centring context.
"cellmax(<phi>,0.d0)" # none context centring, cell centring of the first argument <phi> "facesum(<phi_f>,0.d0,<allfaces>)" # none context centring, face centring of the first argument <phi_f>
The centring of specific operators is detailed in the reference section.
Operator Arguments
Implicit Operator Arguments
Each operator accepts a certain number of arguments, however if an
argument is not specified then a default value may be used. For example,
cellmax
uses three arguments:
- an expression that is to evaluated in each cell
(
<expression>
), here denoted by a single variable, but more usually an expression of variables; - an initial, default expression for the operator
(
<default>
), which again could be an expression of variables; and - the cell centred content region over which the maximum will be
calculated and within which
<expression>
must be defined (<region>
).
Using implicit argument notation, operators expect the arguments in a
specific order, so cellmax
expects these three arguments in
the manner
"cellmax(<expression>,<default>,<region>)"
If less than the required number of arguments are passed to an operator, then a default value for the omitted arguments will be assumed (or if no defaults are available or are sensible, an error will be flagged). For example, using
"cellmax(<expression>)"
sets <default>
to -<huge>
(the
largest negative double precision number that the processor can store)
and <region>
to <noloop>
if (for
example) the expression was being used in a cell centred context. If in
doubt about what the default value for an argument is, specify it!
Explicit Operator Arguments
The alternative to the implicit argument notation is to specify the arguments explicitly (similar to argument passing in f90). Using explicit notation the order of the arguments that are passed explicitly is irrelevant, however the order of any arguments that are not explicitly named (and hence specified implicitly) still is. For example, the following will all produce the same result
"cellmax(expression=<expression>,default=<default>,region=<region>)" "cellmax(<expression>,<default>,<region>)" "cellmax(region=<region>,default=<default>,expression=<expression>)" "cellmax(<expression>,region=<region>,<default>)" "cellmax(region=<region>,<expression>,<default>)"
Note in the last case that although <expression>
was the second argument in the operator, it was the first implicitly
named operator, so would be read correctly. Using a combination of the
implicit and explicit passing is often convenient. For example, for the
cellmax
operator, the following form that uses a default
value of -<huge>
but performs the maximum comparison
over a specified region is handy
"cellmax(<expression>,region=<region>)" # as default is omitted, the last (third) argument must be explicitly named
Operator options are similar to variable options. Some operators
require a dimension, and this dimension (direction) is specified via the
options. For example, celldivgrad
calculates a gradient in
a certain direction dimension using the divergence of a face centred
scalar. To find this gradient in the second dimension you use the option
[l=2]
:
"celldivgrad[l=2](<face centred expression>)"
Some options are quite generic (eg, noderivative
),
however most are specific to the operator. There is no restriction on
the order that options are specified.
Details of individual discretisation operators follows. However
ultimate details of each operator (including argument order, options
etc) can be found in the code file VariableRegion.pm
which shows how they are expanded into working code. Use search strings
such as ref: celldiv
within this perl file to find the
specific code.
Discretisation Operators Listing
celldiv
: Divergence
Summary:
Uses Gauss’ theorem to calculate the divergence of a face centred vector component around a cell.
Statement:
"celldiv[options](expression=<expression>)"
Centring:
Operator is (context) cell centred, and expression is face centred.
Details:
Using Gauss’ theorem to evaluate divergences around cells is probably
the defining characteristic of Finite Volume methods.
celldiv
performs this operation.
Specifically, to discretise the divergence of a face centred vector \(\vect[j]{u}\) over a cell \(i\) that sits within the domain, Gauss’ theorem gives
\[\begin{aligned} \frac{1}{\scali[i]{V}} \int_{\scali[i]{V}} \vect{\nabla} \cdot \vect{u} dV & \Rightarrow \frac{1}{\scali[i]{V}} \sum_{j \in \scali[\text{nobcellfaces},i]{\mathbb{J}}} \frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[i,j]{N} \cdot \vecti[j]{u} \, dS \\ & = \explain{\sum_{j \in \scali[\text{nobcellfaces},i]{\mathbb{J}}} \frac{\vecti[i,j]{N} \cdot \vecti[j]{n} }{\scali[i]{V}}}{\normalsize\code{celldiv}} \frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[j]{n} \cdot \vecti[j]{u} \, dS \nonumber \\ %= \frac{1}{\scal[cell]{V}} \int_{\scal[cell]{S}} \vect[cell]{n} \cdot \vect{u} dS = \frac{1}{\scal[cell]{V}} \sum_j (\vect[cell]{n} \cdot \vecti[j]{n}) (\vect{u} \cdot \vecti[j]{n}) \scali[j]{S} \nonumber \\ & \Rightarrow `celldiv(dot(<u[l=:]>,<facenorm[l=:]>))` \end{aligned}\]
where \(\scali[i]{V}\) and \(\scali[j]{S}\) are the volume and total surface area of the cell \(i\) and face \(j\), respectively, \(\vecti[i,j]{N}\) is a unit normal pointing outward from cell \(i\) but located at face \(j\), \(\vecti[j]{n}\) is a normal associated with face \(j\), and the sum is conducted over the set of all face elements that surround cell \(i\), denoted by \(\scali[\text{nobcellfaces},i]{\mathbb{J}}\). In the equivalent coding the face centred vector \(\vecti[j]{u}\) is represented by the three component variables , and , and the unit normal associated with the face \(j\), \(\vecti[j]{n}\), is given by the system component variables , and . Note that as the divergence of a vector results in a scalar, the above operation produces a scalar for each cell it is performed in.
The region used by arb in performing the above sum as represented by \(\scali[\text{nobcellfaces},i]{\mathbb{J}}\) is (‘no-boundary-cell-faces’). This relative region specifies all faces that surround a given cell, unless that cell is a boundary cell. As boundary cells are not fully surrounded by faces Gauss’ theorem can not be applied. Hence, if the operator is used at a boundary cell then the region is taken relative (moved) to the closest domain cell that is adjacent the boundary cell, so this is where becomes evaluated. Physically it is inadvisable to use an equation that involves a divergence at a boundary cell anyway.
Options:
[noderivative] : No derivatives with respect to the unknown variables for the Newton-Raphson Jacobian are calculated for this operator (and its contents).
Examples:
CELL_EQUATION <continuity> "celldiv(<u_f>)" ON <domain> # continuity equation CELL_EQUATION <momentum[l=1]> "celldiv(<J_f[l=1]>)" ON <domain> # momentum conservation in direction l=1 CELL_EQUATION <momentum[l=2]> "celldiv(<J_f[l=2]>)" ON <domain> # momentum conservation in direction l=2
cellgrad
,
facegrad
or nodegrad
: Gradient
Summary:
Calculates a scalar component of a gradient from surrounding cell values at the location of a cell, face or node.
Statement:
Centring:
is context cell centred and is context face centred. In both cases is cell centred.
Details:
To calculate the gradient of a cell centred scalar \(\scali[i]{\phi}\) in coodinate direction \(2\) in cell \(i\), \[\frac{1}{\scali[i]{V}} \int_{\scali[i]{V}} \vecti[2]{e} \cdot \vect{\nabla} \phi dV \Rightarrow \sum_{i' \in \scali[\text{cellcells},i]{\mathbb{I}}} \scali[i,i']{\cellcentred{k}^{(2)}} \scali[i']{\phi} \Rightarrow \code{cellgrad[l=2](phi)} \nonumber\] where \(\vecti[2]{e}\) is a unit vector in coordinate direction \(2\), \(\scali[i,i']{\cellcentred{k}^{(2)}}\) is a predetermined kernel for this operation, and \(\scali[\text{cellcells},i]{\mathbb{I}}\) is the set of all cells in the vicinity of cell \(i\) that are used by this kernel. Kernels to calculate the cell gradient in the other coordinate directions, that is \(\scali[i,i']{\cellcentred{k}^{(1)}}\) and \(\scali[i,i']{\cellcentred{k}^{(3)}}\) also exist.
A gradient of a cell centred quantity evaluated at a face can be calculated similarly, for example \[\frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[3]{e} \cdot \vect{\nabla} \phi dS \Rightarrow \sum_{i \in \scali[\text{facecells},j]{\mathbb{I}}} \scali[j,i]{\facecentred{k}^{(3)}} \scali[i]{\phi} \Rightarrow \code{facegrad[l=3](phi)} \nonumber\] Gradients taken in directions relative to the face orientation are also available using the operator. Index \(4\) gives the gradient relative to the face’s normal, that is \[\frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[j]{n} \cdot \vect{\nabla} \phi dS \Rightarrow \sum_{i \in \scali[\text{facecells},j]{\mathbb{I}}} \scali[j,i]{\facecentred{k}^{(4)}} \scali[i]{\phi} \Rightarrow \code{facegrad[l=4](phi)} \nonumber\] In computational terms the face normal is represented by (,, ). Indices \(5\) and \(6\) give gradients in the directions of the first and second tangents for each face, respectively, that is \[\frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[j]{t}^{(1)} \cdot \vect{\nabla} \phi dS \Rightarrow \sum_{i \in \scali[\text{facecells},j]{\mathbb{I}}} \scali[j,i]{\facecentred{k}^{(5)}} \scali[i]{\phi} \Rightarrow \code{facegrad[l=5](phi)} \nonumber\] and \[\frac{1}{\scali[j]{S}} \int_{\scali[j]{S}} \vecti[j]{t}^{(2)} \cdot \vect{\nabla} \phi dS \Rightarrow \sum_{i \in \scali[\text{facecells},j]{\mathbb{I}}} \scali[j,i]{\facecentred{k}^{(6)}} \scali[i]{\phi} \Rightarrow \code{facegrad[l=6](phi)} \nonumber\] Computationally \(\vecti[j]{t}^{(1)}\) is represented by (,, ) and \(\vecti[j]{t}^{(2)}\) by (,, ), respectively. If the face has one dimension then \(\vecti[j]{t}^{(1)}\) will be directed along the face, and \(\vecti[j]{t}^{(2)}\) will be normal to both \(\vecti[j]{t}^{(1)}\) and \(vecti[j]{n}\). If the face has no or two dimensions (a point or a plane) then there are no preferential directions for these tangents. If no index is specified on the operator then is assumed.
Options:
, , etc: This index specifies the direction that the gradient will be taken in. For this index represents the dimension the gradient is taken in and must be specified. For if the index is specified and is \(\le 3\), this specifies the dimension the gradient is taken in. For an index \(\ge 4\), the direction is taken relative to the face orientation. specifies a gradient taken in the direction of the face normal, a gradient taken in the direction of the first tangent to the face and in the direction of the second tangent to the face. If the index is not specified for then is assumed — that is, a gradient taken normal to the face.
for only: Gradient is based on adjacent cells only, but attempts to be in the direction of the face normal (it is only an approximation, but should be accurate for structured meshes). Note, only works for direction — that is, the direction of the face normal.
for only: Similar to option in that it is based on adjacent cells only, but now it is in the direction of , which is a unit vector pointing from the centre of the cell immediate below the face (in the face’s normal direction) to the centre of the cell immediately above the face. Hence, for unstructured meshes, this gradient is not precisely in the same direction as the true .
, , etc: This specifies that the contained expression is a component of a vector, and that over any glued reflection boundaries, must be reflected in this direction. These options only need to be specified if the operator is going to be acting over (or next to) a glued, reflection boundary that is reflected in a direction that is the same as the vector’s component direction.
: As previously.
Examples:
FACE_DERIVED <T flux> "-<D>*facegrad(<T>)" ON <all faces> # some type of heat flux occuring across each face
CELL_DERIVED <dpdx[l=1]> "cellgrad[l=1](<p>)" # gradient of pressure in first dimension
: Interpolation to cell centring
Summary: Interpolates or averages an expression from (mainly) face centring to cell centring.
Statement:
Centring:
is context cell centred and generally takes a face centred expression (see option however).
Details:
Without any options, predefined kernels are used to interpolate the face centred expression from the faces that surround a cell to the centroid of that cell.
Options:
: Evaluates at the last face that was referenced in the context of the operator’s position, but treats the result as having cell centring.
: As above, but moves through glued boundaries to the actual last face that was used (if it was glued).
: Evaluates at the cell that is adjacent to the last face that was referenced in the context of the operator’s position. In this (exception) case is cell centred. For this case only etc options may be used/necessary as the cell may be on the other side of a glued reflection boundary.
: As previously.
: Interpolation
Summary: Interpolates or averages an expression from cell to face centring.
Statement:
Centring:
has face context centring. is cell centred. is face centred. is cell centred.
Details:
TODO
Options:
:
:
:
: As previously.
or : Sum
Summary: Performs a sum over a region of either cell or face elements.
Statement:
Centring:
Operators may be cell, face or none centred. Contents of is cell centred, contents of is face centred.
Details:
This operator sums the contained expression over a region of cell or face elements. If no region is specified, then default regions are applied, defined by:
Operator centring Expression centring Default region ——————- ——————— —————-
Options:
- : As previously.