Skip to content

Commit 43cc6d9

Browse files
authored
Exit minimization when initial gradient is too small (#1361)
* Exit minimization when initial gradient is too small * Reactivated 0 obs test
1 parent 63b22e9 commit 43cc6d9

8 files changed

Lines changed: 193 additions & 57 deletions

File tree

l95/test/CMakeLists.txt

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ list( APPEND l95_test_input
2020
testinput/4dvar.drpcgqn.yaml
2121
testinput/4dvar.drplanczos.yaml
2222
testinput/4dvar.drplanclmp.yaml
23+
testinput/4dvar.drplzero.yaml
2324
testinput/4dvar.fgmres.yaml
2425
testinput/4dvar.gmresr.yaml
2526
testinput/4dvar.hybrid.yaml
@@ -129,6 +130,7 @@ list( APPEND l95_testoutput
129130
testoutput/4dvar.drpcgqn.test
130131
testoutput/4dvar.drplanclmp.test
131132
testoutput/4dvar.drplanczos.test
133+
testoutput/4dvar.drplzero.test
132134
testoutput/4dvar.fgmres.test
133135
testoutput/4dvar.gmresr.test
134136
testoutput/4dvar.hybrid.test
@@ -479,10 +481,10 @@ ecbuild_add_test( TARGET test_l95_3dvar
479481
ARGS testinput/3dvar.yaml
480482
TEST_DEPENDS test_l95_forecast test_l95_makeobs3d )
481483

482-
#ecbuild_add_test( TESTNAME 3dvar_noobs
483-
# COMMAND l95_4dvar.x
484-
# ARGS testinput/3dvar_noobs.yaml
485-
# TEST_DEPENDS test_l95_forecast )
484+
ecbuild_add_test( TARGET test_3dvar_noobs
485+
COMMAND l95_4dvar.x
486+
ARGS testinput/3dvar_noobs.yaml
487+
TEST_DEPENDS test_l95_forecast test_l95_makeobs3d )
486488

487489
ecbuild_add_test( TARGET test_l95_3dvar_qc
488490
COMMAND l95_4dvar.x
@@ -509,91 +511,96 @@ ecbuild_add_test( TARGET test_l95_3dfgat
509511
# 4d variational tests
510512
#####################################################################
511513

512-
ecbuild_add_test( TARGET test_l95_4dvar.drgmresr
514+
ecbuild_add_test( TARGET test_l95_4dvar_drgmresr
513515
COMMAND l95_4dvar.x
514516
ARGS testinput/4dvar.drgmresr.yaml
515517
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
516518

517-
ecbuild_add_test( TARGET test_l95_4dvar.dripcg
519+
ecbuild_add_test( TARGET test_l95_4dvar_dripcg
518520
COMMAND l95_4dvar.x
519521
ARGS testinput/4dvar.dripcg.yaml
520522
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
521523

522-
ecbuild_add_test( TARGET test_l95_4dvar.dripcgqn
524+
ecbuild_add_test( TARGET test_l95_4dvar_dripcgqn
523525
COMMAND l95_4dvar.x
524526
ARGS testinput/4dvar.dripcgqn.yaml
525527
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
526528

527-
ecbuild_add_test( TARGET test_l95_4dvar.drpcg
529+
ecbuild_add_test( TARGET test_l95_4dvar_drpcg
528530
COMMAND l95_4dvar.x
529531
ARGS testinput/4dvar.drpcg.yaml
530532
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
531533

532-
ecbuild_add_test( TARGET test_l95_4dvar.drpcgqn
534+
ecbuild_add_test( TARGET test_l95_4dvar_drpcgqn
533535
COMMAND l95_4dvar.x
534536
ARGS testinput/4dvar.drpcgqn.yaml
535537
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
536538

537-
ecbuild_add_test( TARGET test_l95_4dvar.drplanczos
539+
ecbuild_add_test( TARGET test_l95_4dvar_drplanczos
538540
COMMAND l95_4dvar.x
539541
ARGS testinput/4dvar.drplanczos.yaml
540542
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
541543

542-
ecbuild_add_test( TARGET test_l95_4dvar.drplanclmp
544+
ecbuild_add_test( TARGET test_l95_4dvar_drplanclmp
543545
COMMAND l95_4dvar.x
544546
ARGS testinput/4dvar.drplanclmp.yaml
545547
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
546548

547-
ecbuild_add_test( TARGET test_l95_4dvar.fgmres
549+
ecbuild_add_test( TARGET test_l95_4dvar_fgmres
548550
COMMAND l95_4dvar.x
549551
ARGS testinput/4dvar.fgmres.yaml
550552
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
551553

552-
ecbuild_add_test( TARGET test_l95_4dvar.gmresr
554+
ecbuild_add_test( TARGET test_l95_4dvar_gmresr
553555
COMMAND l95_4dvar.x
554556
ARGS testinput/4dvar.gmresr.yaml
555557
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
556558

557-
ecbuild_add_test( TARGET test_l95_4dvar.ipcg
559+
ecbuild_add_test( TARGET test_l95_4dvar_ipcg
558560
COMMAND l95_4dvar.x
559561
ARGS testinput/4dvar.ipcg.yaml
560562
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
561563

562-
ecbuild_add_test( TARGET test_l95_4dvar.lbgmresr
564+
ecbuild_add_test( TARGET test_l95_4dvar_lbgmresr
563565
COMMAND l95_4dvar.x
564566
ARGS testinput/4dvar.lbgmresr.yaml
565567
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
566568

567-
ecbuild_add_test( TARGET test_l95_4dvar.pcg
569+
ecbuild_add_test( TARGET test_l95_4dvar_pcg
568570
COMMAND l95_4dvar.x
569571
ARGS testinput/4dvar.pcg.yaml
570572
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
571573

572-
ecbuild_add_test( TARGET test_l95_4dvar.planczos
574+
ecbuild_add_test( TARGET test_l95_4dvar_planczos
573575
COMMAND l95_4dvar.x
574576
ARGS testinput/4dvar.planczos.yaml
575577
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
576578

577-
ecbuild_add_test( TARGET test_l95_4dvar.rpcg
579+
ecbuild_add_test( TARGET test_l95_4dvar_rpcg
578580
COMMAND l95_4dvar.x
579581
ARGS testinput/4dvar.rpcg.yaml
580582
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
581583

582-
ecbuild_add_test( TARGET test_l95_4dvar.rplanczos
584+
ecbuild_add_test( TARGET test_l95_4dvar_rplanczos
583585
COMMAND l95_4dvar.x
584586
ARGS testinput/4dvar.rplanczos.yaml
585587
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
586588

587-
ecbuild_add_test( TARGET test_l95_4dvar.minres
589+
ecbuild_add_test( TARGET test_l95_4dvar_minres
588590
COMMAND l95_4dvar.x
589591
ARGS testinput/4dvar.minres.yaml
590592
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
591593

592-
ecbuild_add_test( TARGET test_l95_4dvar.modbias
594+
ecbuild_add_test( TARGET test_l95_4dvar_modbias
593595
COMMAND l95_4dvar.x
594596
ARGS testinput/4dvar.modbias.yaml
595597
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
596598

599+
ecbuild_add_test( TARGET test_l95_4dvar_drplzero
600+
COMMAND l95_4dvar.x
601+
ARGS testinput/4dvar.drplzero.yaml
602+
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
603+
597604
#ecbuild_add_test( TARGET test_l95_4dforcing
598605
# COMMAND l95_4dvar.x
599606
# ARGS testinput/4dforcing.yaml
@@ -605,25 +612,22 @@ ecbuild_add_test( TARGET test_l95_4dsaddlepoint
605612
ARGS testinput/4dsaddlepoint.yaml
606613
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d )
607614

608-
ecbuild_add_test( TARGET test_l95_4dvar.obsbias
615+
ecbuild_add_test( TARGET test_l95_4dvar_obsbias
609616
COMMAND l95_4dvar.x
610617
ARGS testinput/4dvar.obsbias.yaml
611618
TEST_DEPENDS test_l95_forecast test_l95_makeobsbias )
612619

613-
#--------------------------------------------------------------------
614-
615-
ecbuild_add_test( TARGET test_l95_4dvar.allbiases
620+
ecbuild_add_test( TARGET test_l95_4dvar_allbiases
616621
COMMAND l95_4dvar.x
617622
ARGS testinput/4dvar.allbiases.yaml
618623
TEST_DEPENDS test_l95_forecast test_l95_makeobsbias )
619-
#--------------------------------------------------------------------
620624

621-
ecbuild_add_test( TARGET test_l95_4dvar.alpha
625+
ecbuild_add_test( TARGET test_l95_4dvar_alpha
622626
COMMAND l95_4dvar.x
623627
ARGS testinput/4dvar.alpha.yaml
624628
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d test_l95_genenspert )
625629

626-
ecbuild_add_test( TARGET test_l95_4dvar.hybrid
630+
ecbuild_add_test( TARGET test_l95_4dvar_hybrid
627631
COMMAND l95_4dvar.x
628632
ARGS testinput/4dvar.hybrid.yaml
629633
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d test_l95_genenspert )
@@ -634,7 +638,7 @@ ecbuild_add_test( TARGET test_l95_4densvar
634638
ARGS testinput/4densvar.yaml
635639
TEST_DEPENDS test_l95_forecast test_l95_makeobs4d12h test_l95_genenspert )
636640

637-
ecbuild_add_test( TARGET test_l95_4densvar.hybrid
641+
ecbuild_add_test( TARGET test_l95_4densvar_hybrid
638642
COMMAND l95_4dvar.x
639643
MPI 9
640644
ARGS testinput/4densvar.hybrid.yaml

l95/test/testinput/3dvar_noobs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ cost function:
2121
covariance model: diagonal
2222
variational:
2323
minimizer:
24-
algorithm: DRIPCG
24+
algorithm: RPCG
2525
iterations:
2626
- ninner: 10
2727
gradient norm reduction: 1e-10
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
cost function:
2+
cost type: 4D-Var
3+
window begin: 2010-01-01T03:00:00Z
4+
window length: P1D
5+
geometry:
6+
resol: 40
7+
model:
8+
name: L95
9+
f: 8.0
10+
tstep: PT1H30M
11+
analysis variables: [x]
12+
background:
13+
date: 2010-01-01T03:00:00Z
14+
filename: Data/test.fc.2010-01-01T00:00:00Z.PT3H
15+
background error:
16+
covariance model: L95Error
17+
date: 2010-01-01T03:00:00Z
18+
length_scale: 1.0
19+
standard_deviation: 0.6
20+
observations:
21+
- obs operator: {}
22+
obs space:
23+
obsdatain: Data/l95.truth4d.2010-01-02T00:00:00Z.obt
24+
obsdataout: Data/l95.4dvar.drplanczos.2010-01-02T00:00:00Z.obt
25+
monitoring only: true
26+
obs error:
27+
covariance model: diagonal
28+
variational:
29+
minimizer:
30+
algorithm: DRPLanczos
31+
online diagnostics:
32+
write basis: true
33+
krylov basis:
34+
datadir: Data
35+
date: 2010-01-01T12:00:00Z
36+
exp: 4dvar.drplanczos
37+
type: krylov
38+
iterations:
39+
- ninner: 10
40+
gradient norm reduction: 1.0e-10
41+
geometry:
42+
resol: 40
43+
linear model:
44+
name: L95TLM
45+
tstep: PT1H30M
46+
trajectory:
47+
f: 8.0
48+
tstep: PT1H30M
49+
variable change: Identity
50+
diagnostics:
51+
departures: ombg
52+
test: on
53+
- ninner: 10
54+
gradient norm reduction: 1.0e-10
55+
geometry:
56+
resol: 40
57+
linear model:
58+
name: L95TLM
59+
tstep: PT1H30M
60+
trajectory:
61+
f: 8.0
62+
tstep: PT1H30M
63+
variable change: Identity
64+
test: on
65+
final:
66+
diagnostics:
67+
departures: oman
68+
prints:
69+
frequency: PT1H30M
70+
output:
71+
datadir: Data
72+
exp: test
73+
first: PT3H
74+
frequency: PT06H
75+
type: an
76+
77+
test:
78+
reference filename: testoutput/4dvar.drplzero.test
Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
Test : CostJb : Nonlinear Jb = 0
2-
Test : CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
3-
Test : CostFunction: Nonlinear J = 0
4-
Test : DRIPCGMinimizer: reduction in residual norm = 1
5-
Test : CostFunction::addIncrement: Analysis:
6-
Test : Valid time: 2010-01-02T00:00:00Z
7-
Test : Min=6.65953, Max=9.39191, Average=7.97085
8-
Test : CostJb : Nonlinear Jb = 0
9-
Test : CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
10-
Test : CostFunction: Nonlinear J = 0
11-
Test : DRIPCGMinimizer: reduction in residual norm = 1
12-
Test : CostFunction::addIncrement: Analysis:
13-
Test : Valid time: 2010-01-02T00:00:00Z
14-
Test : Min=6.65953, Max=9.39191, Average=7.97085
15-
Test : CostJb : Nonlinear Jb = 0
16-
Test : CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
17-
Test : CostFunction: Nonlinear J = 0
1+
CostJb : Nonlinear Jb = 0
2+
CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
3+
CostFunction: Nonlinear J = 0
4+
CostFunction::addIncrement: Analysis:
5+
Valid time: 2010-01-02T00:00:00Z
6+
Min=6.65953, Max=9.39191, Average=7.97085
7+
8+
9+
10+
CostJb : Nonlinear Jb = 0
11+
CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
12+
CostFunction: Nonlinear J = 0
13+
CostFunction::addIncrement: Analysis:
14+
Valid time: 2010-01-02T00:00:00Z
15+
Min=6.65953, Max=9.39191, Average=7.97085
16+
17+
18+
19+
CostJb : Nonlinear Jb = 0
20+
CostJo : Nonlinear Jo(Lorenz 95) = 0 --- No Observations
21+
CostFunction: Nonlinear J = 0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
CostJb : Nonlinear Jb = 0
2+
CostJo : Nonlinear Jo(Lorenz 95) = 123.856, nobs = 160, Jo/n = 0.774102, err = 0.4 (Monitoring only)
3+
CostFunction: Nonlinear J = 0
4+
CostFunction::addIncrement: Analysis:
5+
Valid time: 2010-01-01T03:00:00Z
6+
Min=7.0282, Max=8.19498, Average=7.97551
7+
8+
9+
10+
CostJb : Nonlinear Jb = 0
11+
CostJo : Nonlinear Jo(Lorenz 95) = 123.856, nobs = 160, Jo/n = 0.774102, err = 0.4 (Monitoring only)
12+
CostFunction: Nonlinear J = 0
13+
CostFunction::addIncrement: Analysis:
14+
Valid time: 2010-01-01T03:00:00Z
15+
Min=7.0282, Max=8.19498, Average=7.97551
16+
17+
18+
19+
CostJb : Nonlinear Jb = 0
20+
CostJo : Nonlinear Jo(Lorenz 95) = 123.856, nobs = 160, Jo/n = 0.774102, err = 0.4 (Monitoring only)
21+
CostFunction: Nonlinear J = 0

src/oops/assimilation/DRMinimizer.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
#ifndef OOPS_ASSIMILATION_DRMINIMIZER_H_
1212
#define OOPS_ASSIMILATION_DRMINIMIZER_H_
1313

14+
#include <limits>
1415
#include <memory>
1516
#include <string>
1617
#include <vector>
1718

18-
1919
#include "eckit/config/Configuration.h"
2020
#include "oops/assimilation/BMatrix.h"
2121
#include "oops/assimilation/ControlIncrement.h"
@@ -93,6 +93,12 @@ DRMinimizer<MODEL, OBS>::doMinimize(const eckit::Configuration & config) {
9393
const Bmat_ B(J_);
9494
const HtRinvH_ HtRinvH(J_, runOnlineAdjTest);
9595

96+
// Define minimisation starting point
97+
// dx
98+
CtrlInc_ * dx = new CtrlInc_(J_.jb());
99+
// dxh = B^{-1} dx
100+
CtrlInc_ dxh(J_.jb());
101+
96102
// Compute RHS (sum B^{-1} dx_{i}) + H^T R^{-1} d
97103
// dx_i = x_i - x_{i-1}; dx_1 = x_1 - x_b
98104
CtrlInc_ rhs(J_.jb());
@@ -110,11 +116,14 @@ DRMinimizer<MODEL, OBS>::doMinimize(const eckit::Configuration & config) {
110116
rhs *= -1.0;
111117
Log::info() << classname() << " rhs" << rhs << std::endl;
112118

113-
// Define minimisation starting point
114-
// dx
115-
CtrlInc_ * dx = new CtrlInc_(J_.jb());
116-
// dxh = B^{-1} dx
117-
CtrlInc_ dxh(J_.jb());
119+
// Check for zero gradient (for example if no obs)
120+
const double gnorm = dot_product(rhs, rhs);
121+
const double epsilon = config.getDouble("epsilon", std::numeric_limits<double>::epsilon());
122+
Log::info() << "Initial RHS squared norm = " << gnorm << std::endl;
123+
if (gnorm < epsilon) {
124+
Log::info() << "RHS smaller than " << epsilon << ", returning." << std::endl;
125+
return dx;
126+
}
118127

119128
// Set J[0] = 0.5 (x_i - x_b)^T B^{-1} (x_i - x_b) + 0.5 d^T R^{-1} d
120129
const double costJ0Jb = costJ0Jb_;

0 commit comments

Comments
 (0)