Test of the adjoint adj-tl_test/std#
Description#
Test suite for the adjoint and tangent-linear operators.
Running at least the adjoint test is mandatory before any variational
inversion, because a broken adjoint produces a wrong gradient and silently
diverges. This mode offers four complementary tests selected via the
testtype parameter.
Mathematical framework#
Let \(\mathbf{H} = \partial\mathcal{H}/\partial\mathbf{x}\) be the Jacobian of the (possibly non-linear) observation operator \(\mathcal{H}\) evaluated at the linearisation point \(\mathbf{x}_b\), and let \(\mathbf{H}^*\) be its adjoint (transpose for real-valued operators).
Adjoint test — testtype = 'adj'#
Verifies the fundamental identity
where the left-hand side is computed with the tangent-linear operator and the right-hand side with the adjoint. The ratio
must satisfy \(|r - 1| \lesssim \mathcal{O}(\varepsilon_\mathrm{mach})\). The mode reports \(|r-1|/\varepsilon_\mathrm{mach}\); values up to a few tens are acceptable.
When use_forward = True, \(\mathbf{H}\,\delta\mathbf{x}\) is
approximated by finite differences
\(\mathcal{H}(\mathbf{x}_b + \delta\mathbf{x}) - \mathcal{H}(\mathbf{x}_b)\),
which is only valid if \(\mathcal{H}\) is linear.
TL linearity test — testtype = 'tllinearity'#
Checks that the tangent-linear operator is genuinely linear:
The ratio of the two scalar sums should equal 1 to machine precision.
TL Taylor test — testtype = 'tltaylor'#
Verifies the first-order Taylor expansion:
The test iterates with decreasing \(\lambda\) (multiplied by
lambdalin at each step) and checks that the residual decreases as
\(\lambda^2\).
Symmetry test — testtype = 'adj_sym'#
For two independent random vectors \(\mathbf{u}\) and \(\mathbf{v}\), checks that \(\mathbf{H}^*\mathbf{H}\) and \(\mathbf{H}^*\mathbf{R}^{-1}\mathbf{H}\) are symmetric:
Test spaces#
When testspace = 'control', increments live in the control space
\(\delta\mathbf{x} \in \mathbb{R}^n\) directly.
When testspace = 'chi', increments are expressed in the reduced space
\(\boldsymbol{\chi} \in \mathbb{R}^n\) defined by
\(\delta\mathbf{x} = \mathbf{L}\boldsymbol{\chi}\) where
\(\mathbf{L} = \mathbf{B}^{1/2}\) is the square root of the background
error covariance matrix. This tests the full chain
\(\mathbf{L}^* \mathbf{H}^* \mathbf{H} \mathbf{L}\).
Practical guidance#
Run the adjoint test before the first inversion on any new configuration.
Use a shortened period if forward runs are expensive, but include calendar edge cases (month of February, year boundaries, etc.).
testspace = 'chi'is recommended before any inversion that uses spatial or temporal error correlations (\(\mathbf{B} \neq \mathbf{I}\)).
YAML arguments#
The following arguments are used to configure the plugin. pyCIF will return an exception at the initialization if mandatory arguments are not specified, or if any argument does not fit accepted values or type:
- increments : float, mandatory
Perturbation scale relative to the prior standard deviation: \(\delta\mathbf{x} = \mathrm{increments} \cdot \sigma_{\mathbf{x}}\).
- incrmode : “cst” or “rand”, optional, default “cst”
Type of increments to use in the test.
“cst”: Increments are the same for all dimensions of the control vector
“rand”: Increments are selected randomly with a Normal distribution centered to zero with standard deviation ${increments}
- testspace : “control” or “chi”, optional, default “control”
Space in which the test increment is defined.
“control”: Increment in control space \(\mathbf{x}\).
“chi”: Increment in the reduced \(\boldsymbol{\chi}\) space (\(\delta\mathbf{x} = \mathbf{B}^{1/2}\boldsymbol{\chi}\)); recommended when using spatial/temporal error correlations.
- testtype : “adj” or “tltaylor” or “tllinearity” or “adj_sym”, optional, default “adj”
Which test to run (see module docstring for equations).
“adj”: Full adjoint identity test: \(\langle H\delta x, H\delta x\rangle = \langle \delta x, H^*H\delta x\rangle\).
“tltaylor”: Taylor-expansion test: first-order residual decreases as \(O(\lambda^2)\).
“tllinearity”: Linearity test: \(H(\lambda\,\delta x) = \lambda\,H(\delta x)\).
“adj_sym”: Symmetry test: \(\langle H^*Hu,v\rangle = \langle H^*Hv,u\rangle\).
- reload_results : bool, optional, default False
Skip already-completed operator runs and reload their results from disk.
- random_seed : int, optional, default 0
NumPy random seed for drawing increments; used only with
incrmode = 'rand'.
- check_transforms : bool, optional, default False
Run the adjoint test independently for each transform in the pipeline. Results are logged to the main pyCIF log and to
$workdir/check_transforms.log, one line per transform.
- use_forward : bool, optional, default False
Approximate the TL by finite differences \(\mathcal{H}(x_b+\delta x)-\mathcal{H}(x_b)\). Valid only for linear operators.
- taylor_iter : int, optional, default 1
Number of \(\lambda\) halvings in the Taylor test (
testtype = 'tltaylor').
- lambdalin : float, optional, default 0.1
Multiplicative factor applied to the increment at each iteration of the Taylor and linearity tests.
Requirements#
The current plugin requires the present plugins to run properly:
Requirement name |
Requirement type |
Explicit definition |
Any valid |
Default name |
Default version |
|---|---|---|---|---|---|
obsvect |
False |
True |
standard |
std |
|
controlvect |
True |
True |
standard |
std |
|
obsoperator |
True |
True |
standard |
std |
|
simulator |
True |
True |
gausscost |
std |
YAML template#
Please find below a template for a YAML configuration:
1mode:
2 plugin:
3 name: adj-tl_test
4 version: std
5 type: mode
6
7 # Mandatory arguments
8 increments: XXXXX # float
9
10 # Optional arguments
11 incrmode: XXXXX # cst|rand
12 testspace: XXXXX # control|chi
13 testtype: XXXXX # adj|tltaylor|tllinearity|adj_sym
14 reload_results: XXXXX # bool
15 random_seed: XXXXX # int
16 check_transforms: XXXXX # bool
17 use_forward: XXXXX # bool
18 taylor_iter: XXXXX # int
19 lambdalin: XXXXX # float
See also