(omega-dev-aux-vars)=

# Auxiliary Variables

Auxiliary variables are variables that need to be computed at every model time
step in order to advance the model state. Similar auxiliary variables are
grouped together in auxiliary variable groups. An auxiliary variable group is
implemented as a C++ class.

## Basic class structure

Each auxiliary group class has the same basic structure. It is a light-weight
class, since it needs to be copied to the GPU to perform computations. Each
class contains:
 - a constructor
 - public arrays for the auxiliary variables
 - public member function(s) that compute the variables
 - member functions for adding metadata and registering with IO
 - static strings that contain the names used for metadata and IO

Additionally, there may be enum members that store user-configurable options.

As an example, the class `KineticAuxVars` that groups kinetic energy and
velocity divergence has the following structure:
```c++
class KineticAuxVars {
 public:
   Array2DReal KineticEnergyCell;
   Array2DReal VelocityDivCell;

   KineticAuxVars(const HorzMesh *mesh, int NVertLayers);
   void addMetaData() const;
   void defineIOFields() const;

   KOKKOS_FUNCTION void
   computeVarsOnCell(int ICell, int KChunk,
                     const Array2DReal &NormalVelEdge) const;

 private:
   Array1DI4 NEdgesOnCell;
   Array2DI4 EdgesOnCell;
   Array2DR8 EdgeSignOnCell;
   Array1DR8 DcEdge;
   Array1DR8 DvEdge;
   Array1DR8 AreaCell;

   // names used in defining MetaData and IOFields
   static const std::string KineticEnergyCellName;
   static const std::string VelocityDivCellName;
};
```

## Configuration enums

Some auxiliary variables have user-configurable options. In that case, for each
option an enum is defined in the auxiliary group header file. For example, the
flux thickness choice is represented using
```c++
enum FluxThickEdgeOption { Center, Upwind };
```

## Constructor

The constructor takes in a mesh, and does the following:
- allocates the auxiliary variable arrays
- grabs the neccessary data from the mesh
- retrieves configuration options
- calls the `addMetaData()` and `defineIOFields()` helper functions

## Compute member functions

The compute functions operate on a vertical chunk of mesh elements and take in
the element index, the chunk index, and input arrays, which may contain state
variables or other auxiliary variables. There is no output argument, they write
their results directly to the member arrays. There might be more than one
compute function, if variables located on different mesh elements are grouped
together. For example, the `VorticityAuxVars` class provides both
```c++
void computeVarsOnVertex(int IVertex, int KChunk, const Array2DReal &LayerThickCell, const Array2DReal &NormalVelEdge);
void computeVarsOnEdge(int IEdge, int KChunk);
```
because the vorticity variables are first computed on vertices and then
averaged to edges. Note that the edge compute function doesn't take any array
arguments, because it operates only on the class member arrays.

## Implemented groups
The following auxiliary variable groups are currently implemented:
| Group | Auxiliary Variable | Available options |
| ----- | ------------------- | ------- |
| KineticAuxVars | KineticEnergyCell ||
|| VelocityDiv ||
| LayerThicknessAuxVars | FluxLayerThickEdge | Center or Upwind|
|| MeanLayerThickEdge ||
| VorticityAuxVars |  RelVortVertex ||
||  NormRelVortVertex ||
||  NormPlanetVortVertex ||
||  NormRelVortEdge ||
||  NormPlanetVortEdge ||
| VelocityDel2AuxVars |  Del2Edge ||
||  Del2DivCell ||
||  Del2RelVortVertex ||
| TracerAuxVars | HTracersEdge | Center or Upwind|
|| Del2TracersCell ||
| WindForcingAuxVars |  ZonalStressCell ||
||  MeridStressCell ||
||  NormalStressEdge ||
| SurfTracerRestAuxVars | TracersMonthlySurfClimoCell ||

## See Also

Additional information on forcing (currently wind forcing and surface tracer
restoring) is detailed in [](omega-dev-forcing).
