The conesDict reference

system/conesDict is where the Data Assimilation problem itself is configured, on top of the plain OpenFOAM case. This page goes through every option and ties it back to the EnKF formulation introduced in Data Assimilation, using the same notation: the extended state \(\mathbf{x}_k = [\mathbf{u}_k;\, \theta_k]\), observations \(\mathbf{y}_k\), sampling matrix \(\mathcal{H}(\mathbf{x}_k)\), anomalies \(\mathbf{X}\), \(\mathbf{S}\), observation covariance \(\mathbf{R}_k\) and Kalman gain \(\mathbf{K}\).

Algorithm and estimation switches

Key

Meaning

algorithm

The DA method. Currently only "EnKF" is implemented (conesEnKF).

stateEstSwitch

Whether the flow state \(\mathbf{u}_k\) is part of the extended state \(\mathbf{x}_k\) (true) or left untouched by the analysis (false).

paramEstSwitch

Whether the model parameters \(\theta_k\) are part of \(\mathbf{x}_k\) (true) or held fixed (false).

With both switches true, CONES performs the joint state-parameter EnKF described in Data Assimilation (“Ensemble Kalman Filter with extended state”): \(\mathbf{x}_k\) stacks the flow state and the parameters, and a single Kalman gain corrects both at once. With stateEstSwitch false, \(\mathbf{x}_k\) reduces to \(\theta_k\) alone — a pure parameter (e.g. boundary condition) calibration against observations, which is the setting used by the cavity tutorial.

State and observations

Key

Meaning

stateVar

The flow variables making up \(\mathbf{u}_k\), as a string of one-letter codes, e.g. "uvwp" for velocity + pressure. Only read when stateEstSwitch true.

obsVar

The observed variables making up \(\mathbf{y}_k\), e.g. "uvw". Determines both the sampling operator \(\mathcal{H}(\mathbf{x}_k)\) (built by projecting the model state at the observation cells for these variables) and the observation degrees of freedom per observation point.

obsFile

Path (relative to the case) to the observation netCDF database (mean and standard deviation of each obsVar at each observation location and time) — see The observation database for its exact format and how to build one.

observationWindow

Number of model time steps the forecast runs between two analysis phases. Together with endTime and deltaT from system/controlDict, it sets the total number of DA cycles:

\[n_{\text{cycles}} = \left\lfloor \frac{\text{endTime}}{ \text{observationWindow} \times \text{deltaT}} \right\rfloor\]

Parameter estimation

Only read when paramEstSwitch true; together they define what \(\theta_k\) actually contains.

Key

Meaning

parameterType

Where the parameter lives in the model, e.g. "BC" for a boundary condition value.

parameterVar

Which field component is estimated, e.g. "u" for a velocity component.

parameterPatchName

The boundary patch the parameter is read from/written to, e.g. "movingWall".

numberParameters

Size of \(\theta_k\), i.e. how many scalar parameters are appended to the state.

Multiple Data Assimilation (MDA)

Key

Meaning

mdaIterations

Number of ES-MDA (Ensemble Smoother with Multiple Data Assimilation) sub-iterations performed at each analysis phase.

At every sub-iteration, set_R() inflates the observation covariance by the iteration count \(N_{\text{mda}}\) (mdaIterations):

\[\mathbf{R}_i = N_{\text{mda}} \, \mathrm{diag}(\sigma^2)\]

and setObs() perturbs the observations with matching noise scaled by \(\sqrt{N_{\text{mda}}}\), so that summing the \(1/N_{\text{mda}}\) inflation factors over all sub-iterations recovers the original \(\mathbf{R}\), per the classic even-split ES-MDA scheme (Emerick & Reynolds). The Kalman gain and update are then recomputed for each sub-iteration, using the previous sub-iteration’s updated \(\mathbf{x}\) as the new background (update_background()). mdaIterations 1 is the classic, single-pass EnKF.

Inflation

Ensemble methods systematically underestimate the error covariance (the ensemble collapses over cycles); inflation counteracts this by artificially widening the ensemble spread of the updated state and/or parameters after each analysis.

Key

Meaning

inflationType

"deterministic" or "stochastic" (see below).

stateInflation

Inflation coefficient \(\lambda\) applied to the updated state. 0 disables state inflation.

parametersInflation

Inflation coefficient \(\lambda\) applied to the updated parameters. 0 disables parameter inflation.

Given an updated ensemble matrix (state or parameters) with per-member columns \(\mathbf{a}_i\) and ensemble mean \(\bar{\mathbf{a}}\), calculateInflation() implements:

  • Deterministic: every member is inflated by the same factor around the ensemble mean,

    \[\mathbf{a}_i \leftarrow \bar{\mathbf{a}} + (1+\lambda)(\mathbf{a}_i - \bar{\mathbf{a}})\]
  • Stochastic: each member gets its own inflation factor, drawn from a normal distribution of mean 0 and standard deviation \(\lambda\), truncated to \([-2\lambda, 2\lambda]\),

    \[\mathbf{a}_i \leftarrow (1+\epsilon_i)\, \mathbf{a}_i, \qquad \epsilon_i \sim \mathcal{N}(0, \lambda^2) \big|_{[-2\lambda, 2\lambda]}\]

Localisation: physical regions and covariance tapering

With few ensemble members, sampling noise creates spurious long-range correlations between the state and observations that have nothing to do with the real physics. CONES suppresses them in two independent, composable ways: a hard, physical partition of the domain (via topoSet, not a conesDict key), and a smooth, distance-based taper of the Kalman gain inside each partition (stateCovarianceLocalisation below). Both can be used together, only one, or neither.

Physical localisation (domain decomposition into regions)

This is what the tutorial’s system/topoSetDict sets up, before CONES itself even starts: each cellSet action defines a region of the mesh (a “clip”). At start-up, get_clippings() reads these clips, mergeClips() merges any that share cells, and one conesRegion is built per merged clip — keeping only the observations whose cell falls inside it, and dropping regions left with none.

Each region then runs its own, independent EnKF analysis (conesEnKF), built from only that region’s state cells and observations. An observation in one clip has zero influence on the update anywhere outside it, however close it might physically be to that clip’s boundary — this is a hard cutoff, decided once by the mesh topology, not by any conesDict option. If your case has a single topoSetDict action covering the whole DA domain (or none, when LHYPER_LOCALISATION_SWITCH is off on the Meso-NH side), there is only ever one region, and physical localisation plays no role.

State covariance localisation

Key

Meaning

stateCovarianceLocalisation

Whether to taper the Kalman gain with distance (true/false).

localisationLength

Characteristic length \(\ell\) of the localisation, in the same units as the mesh coordinates.

Where physical localisation draws a hard line between regions, covariance localisation works within a single region’s analysis: it damps the Kalman gain continuously with distance, instead of cutting it off, so state cells close to an observation are still corrected more than distant ones without discarding either. setL() builds a Gaussian weight from the euclidean distance \(d\) between each state cell and each observation:

\[c = \sqrt{-2 \ln(0.01)}, \qquad L(d) = \exp\!\left(-\frac{d^2}{2 (\ell / c)^2}\right)\]

so that the correlation has decayed to 1% of its peak value at distance \(d = \ell\)localisationLength is the practical “radius of influence” of each observation. \(L\) is then column-normalized (each observation’s weights sum to 1) and applied to the update as an element-wise (Schur/Hadamard) product on the Kalman gain term, rather than a matrix product:

\[\mathbf{x}^a = \mathbf{x}^f + \mathbf{L} \odot \mathbf{K} \, (\mathbf{y} - \mathcal{H}(\mathbf{x}^f))\]

Parameters are not localised (their weight is 1 for every observation), since they are typically global quantities (e.g. a single boundary condition) rather than spatially distributed ones.