OOPS
Dirac.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #ifndef OOPS_RUNS_DIRAC_H_
12 #define OOPS_RUNS_DIRAC_H_
13 
14 #include <memory>
15 #include <sstream>
16 #include <string>
17 #include <vector>
18 
19 #include "eckit/config/Configuration.h"
20 #include "oops/base/Geometry.h"
21 #include "oops/base/Increment.h"
26 #include "oops/base/State.h"
27 #include "oops/base/Variables.h"
28 #include "oops/mpi/mpi.h"
29 #include "oops/runs/Application.h"
30 #include "oops/util/DateTime.h"
31 #include "oops/util/Duration.h"
32 #include "oops/util/Logger.h"
33 
34 namespace oops {
35 
36 template <typename MODEL> class Dirac : public Application {
42  typedef std::shared_ptr<IncrementEnsemble<MODEL>> EnsemblePtr_;
43 
44  public:
45 // -----------------------------------------------------------------------------
46  explicit Dirac(const eckit::mpi::Comm & comm = oops::mpi::world()) : Application(comm) {
47  instantiateCovarFactory<MODEL>();
48  }
49 // -----------------------------------------------------------------------------
50  virtual ~Dirac() {}
51 // -----------------------------------------------------------------------------
52  int execute(const eckit::Configuration & fullConfig) const {
53  const eckit::LocalConfiguration backgroundConfig(fullConfig, "initial condition");
54  std::vector<eckit::LocalConfiguration> confs;
55  backgroundConfig.get("states", confs);
56  size_t nslots = confs.size();
57 
58  const eckit::mpi::Comm * commSpace = &this->getComm();
59  const eckit::mpi::Comm * commTime = &oops::mpi::myself();
60  if (nslots > 1) {
61  size_t ntasks = this->getComm().size();
62  ASSERT(ntasks % nslots == 0);
63  size_t myrank = this->getComm().rank();
64  size_t ntaskpslot = ntasks / nslots;
65  size_t myslot = myrank / ntaskpslot;
66 
67  // Create a communicator for same sub-window, to be used for communications in space
68  std::string sgeom = "comm_geom_" + std::to_string(myslot);
69  char const *geomName = sgeom.c_str();
70  commSpace = &this->getComm().split(myslot, geomName);
71  ASSERT(commSpace->size() == ntaskpslot);
72 
73  // Create a communicator for same local area, to be used for communications in time
74  size_t myarea = commSpace->rank();
75  std::string stime = "comm_time_" + std::to_string(myarea);
76  char const *timeName = stime.c_str();
77  commTime = &this->getComm().split(myarea, timeName);
78  ASSERT(commTime->size() == nslots);
79  }
80 
81  // Setup resolution
82  const eckit::LocalConfiguration resolConfig(fullConfig, "geometry");
83  const Geometry_ resol(resolConfig, *commSpace, *commTime);
84 
85  // Setup background state
86  State_ xx(resol, backgroundConfig);
87 
88  // Setup variables
89  const Variables vars = xx.variables();
90 
91  // Setup time
92  util::DateTime time = xx.validTime();
93 
94  // Apply B to Dirac
95  const eckit::LocalConfiguration covarConfig(fullConfig, "background error");
96 
97  // Covariance
98  std::unique_ptr<ModelSpaceCovarianceBase<MODEL>> B(CovarianceFactory<MODEL>::create(
99  covarConfig, resol, vars, xx, xx));
100 
101  // Setup Dirac
102  Increment_ dxdirin(resol, vars, time);
103  Increment_ dxdirout(resol, vars, time);
104  const eckit::LocalConfiguration diracConfig(fullConfig, "dirac");
105  dxdirin.dirac(diracConfig);
106  Log::test() << "Input Dirac increment: " << dxdirin << std::endl;
107 
108  // Apply 3D B matrix to Dirac increment
109  B->multiply(dxdirin, dxdirout);
110 
111  // Write increment
112  const eckit::LocalConfiguration output_B(fullConfig, "output B");
113  dxdirout.write(output_B);
114  Log::test() << "B * Increment: " << dxdirout << std::endl;
115 
116  // Setup localization and ensemble configurations
117  std::vector<eckit::LocalConfiguration> locConfigs;
118  if (covarConfig.has("localization")) {
119  locConfigs.push_back(eckit::LocalConfiguration(covarConfig, "localization"));
120  } else {
121  if (covarConfig.has("components")) {
122  std::vector<eckit::LocalConfiguration> confs;
123  covarConfig.get("components", confs);
124  for (const auto & conf : confs) {
125  const eckit::LocalConfiguration componentConf(conf, "covariance");
126  if (componentConf.has("localization")) {
127  locConfigs.push_back(eckit::LocalConfiguration(componentConf, "localization"));
128  }
129  }
130  }
131  }
132 
133  for (size_t jcomp = 0; jcomp < locConfigs.size(); ++jcomp) {
134  // Apply localization to Dirac
135 
136  // Setup Dirac
137  Increment_ dxdir(resol, vars, time);
138  const eckit::LocalConfiguration diracConfig(fullConfig, "dirac");
139  dxdir.dirac(diracConfig);
140 
141  // Setup localization
142  Localization_ loc_(resol, locConfigs[jcomp]);
143 
144  // Apply localization
145  loc_.multiply(dxdir);
146 
147  // Write increment
148  const eckit::LocalConfiguration output_localization(fullConfig, "output localization");
149  dxdir.write(output_localization);
150  Log::test() << "Localized Increment: " << dxdir << std::endl;
151  }
152 
153  if (fullConfig.has("output variance")) {
154  // Variance configuration
155  const eckit::LocalConfiguration output_variance(fullConfig, "output variance");
156 
157  // Setup variance
158  Increment_ variance(resol, vars, time);
159 
160  // Get variance
161  B->getVariance(variance);
162 
163  // Write increment
164  variance.write(output_variance);
165  Log::test() << "Randomized variance: " << variance << std::endl;
166  }
167 
168  return 0;
169  }
170 // -----------------------------------------------------------------------------
171  private:
172  std::string appname() const {
173  return "oops::Dirac<" + MODEL::name() + ">";
174  }
175 // -----------------------------------------------------------------------------
176 };
177 
178 } // namespace oops
179 #endif // OOPS_RUNS_DIRAC_H_
const eckit::mpi::Comm & getComm() const
Definition: Application.h:36
IncrementEnsemble< MODEL > Ensemble_
Definition: Dirac.h:41
std::shared_ptr< IncrementEnsemble< MODEL > > EnsemblePtr_
Definition: Dirac.h:42
Increment< MODEL > Increment_
Definition: Dirac.h:38
Geometry< MODEL > Geometry_
Definition: Dirac.h:37
Dirac(const eckit::mpi::Comm &comm=oops::mpi::world())
Definition: Dirac.h:46
std::string appname() const
Definition: Dirac.h:172
virtual ~Dirac()
Definition: Dirac.h:50
int execute(const eckit::Configuration &fullConfig) const
Definition: Dirac.h:52
Localization< MODEL > Localization_
Definition: Dirac.h:40
State< MODEL > State_
Definition: Dirac.h:39
Geometry class used in oops; subclass of interface class interface::Geometry.
Ensemble of inrements.
Increment class used in oops.
Abstract model-space localization class used by high level algorithms and applications.
virtual void multiply(Increment_ &dx) const
State class used in oops; subclass of interface class interface::State.
void dirac(const eckit::Configuration &)
Set Increment according to the configuration (used in Dirac application)
void write(const eckit::Configuration &) const
Write this Increment out to file.
const util::DateTime validTime() const
Accessor to the time of this State.
const Variables & variables() const
Accessor to variables associated with this State.
const eckit::mpi::Comm & myself()
Default communicator with each MPI task by itself.
Definition: oops/mpi/mpi.cc:90
const eckit::mpi::Comm & world()
Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
Definition: oops/mpi/mpi.cc:84
The namespace for the main oops code.