Conventions
Spatial dimensions and directions
We use the following numbering schemes on Cartesian or curved structured meshes.
- The
orientations are numbered as1 => x, 2 => y, 3 => z. For example, numerical fluxes such asflux_central(u_ll, u_rr, orientation, equations::AbstractEquations)use theorientationin this way. - The
directions are numbered as1 => -x, 2 => +x, 3 => -y, 4 => +y, 5 => -z, 6 => +z. For example, theboundary_conditionsare ordered in this way when aTupleof 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_directionis normalized to be anormal_vectorused, for example, inFluxRotated.
Cells vs. elements vs. nodes
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 individualcells. In general, neither themeshnor thecells 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
solvers do not directly store their information inside themesh, but use own data structures. Specifically, for eachcellon which a solver wants to operate, the solver creates anelementto store solver-specific data. - For discretization schemes such as the discontinuous Galerkin or the finite element method, inside each
elementmultiplenodesmay be defined, which hold nodal information. The nodes are again a solver-specific component, just like the elements. - We often identify
elements,nodes, etc. with their (local or global) integer index. Convenience iterators such aseachelement,eachnodeuse these indices.
Keywords in elixirs
Trixi.jl is distributed with several examples in the form of elixirs, small Julia scripts containing everything to set up and run a simulation. Working interactively from the Julia REPL with these scripts can be quite convenient while for exploratory research and development of Trixi.jl. For example, you can use the convenience function trixi_include to include an elixir with some modified arguments. To enable this, it is helpful to use a consistent naming scheme in elixirs, since trixi_include can only perform simple replacements. Some standard variables names are
polydegfor the polynomial degree of a solversurface_fluxfor the numerical flux at surfacesvolume_fluxfor the numerical flux used in flux differencing volume terms
Moreover, convergence_test requires that the spatial resolution is set via the keywords
initial_refinement_level(an integer, e.g. for theTreeMeshand theP4estMesh) orcells_per_dimension(a tuple of integers, one per spatial dimension, e.g. for theStructuredMeshand theDGMultiMesh).
Variable names
- Use descriptive names (using
snake_casefor variables/functions andCamelCasefor types) - Use a suffix
_as inname_for local variables that would otherwise hide existing symbols. - Use a prefix
_as in_nameto 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#).
Array types and wrapping
To allow adaptive mesh refinement efficiently when using time integrators from OrdinaryDiffEq, Trixi.jl 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.jl. 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.jl). 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_odethat 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_arrayshould be used as default option.wrap_array_nativeshould only be used when necessary, e.g., to avoid additional overhead when interfacing with external C libraries such as HDF5, MPI, or visualization.