We use the following numbering schemes on Cartesian or curved structured meshes.
- The
orientation
s are numbered as1 => x, 2 => y, 3 => z
. For example, numerical fluxes such asflux_central(u_ll, u_rr, orientation, equations::AbstractEquations)
use theorientation
in this way. - The
direction
s are numbered as1 => -x, 2 => +x, 3 => -y, 4 => +y, 5 => -z, 6 => +z
. For example, theboundary_conditions
are ordered in this way when aTuple
of boundary conditions per direction is passed to the constructor of aSemidiscretizationHyperbolic
. - For structured and unstructured curved meshes the concept of direction is
generalized via the variable
normal_direction
. This variable points in the normal direction at a given, curved surface. For the computation of boundary fluxes thenormal_direction
is normalized to be anormal_vector
used, for example, inFluxRotated
.
To uniquely distinguish between different components of the discretization, we use the following naming conventions:
- The computational domain is discretized by a
mesh
, which is made up of individualcell
s. In general, neither themesh
nor thecell
s should be aware of any solver-specific knowledge, i.e., they should not store anything that goes beyond the geometrical information and the connectivity. - The numerical
solver
s do not directly store their information inside themesh
, but use own data structures. Specifically, for eachcell
on which a solver wants to operate, the solver creates anelement
to store solver-specific data. - For discretization schemes such as the discontinuous Galerkin or the finite
element method, inside each
element
multiplenodes
may be defined, which hold nodal information. The nodes are again a solver-specific component, just like the elements. - We often identify
element
s,node
s, etc. with their (local or global) integer index. Convenience iterators such aseachelement
,eachnode
use these indices.
- Use descriptive names (using
snake_case
for variables/functions andCamelCase
for types) - Use a suffix
_
as inname_
for local variables that would otherwise hide existing symbols. - Use a prefix
_
as in_name
to indicate internal methods/data that are "fragile" in the sense that there's no guarantee that they might get changed without notice. These are also not documented with a docstring (but maybe with comments using#
).
To allow adaptive mesh refinement efficiently when using time integrators from
OrdinaryDiffEq,
Trixi allows to represent numerical solutions in two different ways. Some discussion
can be found online and
in form of comments describing Trixi.wrap_array
and Trixi.wrap_array_native
in the source code of Trixi.
The flexibility introduced by this possible wrapping enables additional
performance optimizations.
However, it comes at the cost of some additional abstractions (and needs to be
used with caution, as described in the source code of Trixi). Thus, we use the
following conventions to distinguish between arrays visible to the time integrator
and wrapped arrays mainly used internally.
- Arrays visible to the time integrator have a suffix
_ode
, e.g.,du_ode
,u_ode
. - Wrapped arrays do not have a suffix, e.g.,
du, u
.
Methods either accept arrays visible to the time integrator or wrapped arrays based on the following rules.
- When some solution is passed together with a semidiscretization
semi
, the solution must be au_ode
that needs to be wrapped viawrap_array(u_ode, semi)
(orwrap_array_native(u_ode, semi)
) for further processing. - When some solution is passed together with the
mesh, equations, solver, cache, ...
, it is already wrapped viawrap_array
(orwrap_array_native
). - Exceptions of this rule are possible, e.g. for AMR, but must be documented in the code.
wrap_array
should be used as default option.wrap_array_native
should only be used when necessary, e.g., to avoid additional overhead when interfacing with external C libraries such as HDF5, MPI, or visualization.