# Code Description

Presently, the ordinary differential equations (ODEs) of the qgs model are at most bilinear
in their variables \(\eta_i\) (\(1\leq i\leq\) `ndim`

).
This system of ODEs can therefore be expressed as the sum of
a constant, a matrix multiplication, and a tensor contraction:

This expression can be further simplified by adding a dummy variable that is identically equal to one: \(\eta_0\equiv 1\). This extra variable allows one to merge \(c_i\), \(m_{i,j}\), and \(t_{i,j,k}\) into the tensor \(\mathcal{T}_{i,j,k}\), in which the linear terms are represented by \(\mathcal{T}_{i,j,0}\) and the constant term by \(\mathcal{T}_{i,0,0}\):

The tensor \(\mathcal{T}\) is computed and stored in the `QgsTensor`

.
Recasting the system of ordinary differential
equations for \(\eta_i\) in the form of a tensor contraction has certain
advantages. Indeed, the symmetry of the tensor contraction allows for a unique representation
of \(\mathcal{T}_{i,j,k}\), if it is taken to be upper triangular in the last two
indices (\(\mathcal{T}_{i,j,k} \equiv 0\) if \(j > k\)). Since
\(\mathcal{T}_{i,j,k}\) is known to be sparse, it is stored using the
coordinate list representation, i.e. a list of tuples
\((i,j,k,\mathcal{T}_{i,j,k})\) defined by the class `sparse.COO`

.
This representation renders the computation of the tendencies \(\text{d}\eta_i/\text{d}t\) computationally very efficient as
well as conveniently parallelizable.

The form of the ODEs allows also to easily compute the Jacobian matrix of the system. Indeed, denoting the right-hand side of the equations as \(\text{d}\eta_i/\text{d}t = f_i\), the expression reduces to

The differential form of the tangent linear model (TL) for a small perturbation \(\boldsymbol{\delta\eta}^\text{TL}\) of a trajectory \(\boldsymbol{\eta}^{\ast}\) is then simply [Kal03]

## Computational flow

The computational flow is as follows:

The parameters are specified by instantiating a

`QgParams`

.The inner products are computed and stored in

`AtmosphericInnerProducts`

and`OceanicInnerProducts`

objects.The tensor of the tendencies terms are computed in a

`QgsTensor`

object.The functions

`create_tendencies`

create Numba optimized functions that return the tendencies and the Jacobian matrix.These functions are passed to the numerical integrator in the module

`integrator`

.

## Additional technical information

qgs is optimized to run ensembles of initial conditions on multiple cores, using Numba jit-compilation and multiprocessing workers.

qgs has a tangent linear model optimized to run ensembles of initial conditions as well, with a broadcast integration of the tangent model thanks to Numpy.

## References

- Kal03
E. Kalnay.

*Atmospheric modeling, data assimilation, and predictability*. Cambridge university press, 2003.