OOPS
ConvertIncrement.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018-2021 UCAR
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  */
7 
8 #ifndef OOPS_RUNS_CONVERTINCREMENT_H_
9 #define OOPS_RUNS_CONVERTINCREMENT_H_
10 
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "eckit/config/LocalConfiguration.h"
16 #include "oops/base/Geometry.h"
17 #include "oops/base/Increment.h"
19 #include "oops/base/State.h"
21 #include "oops/mpi/mpi.h"
22 #include "oops/runs/Application.h"
23 #include "oops/util/DateTime.h"
24 #include "oops/util/Duration.h"
25 #include "oops/util/Logger.h"
26 
27 namespace oops {
28 
29 template <typename MODEL> class ConvertIncrement : public Application {
35 
36  public:
37 // -------------------------------------------------------------------------------------------------
38  explicit ConvertIncrement(const eckit::mpi::Comm & comm = oops::mpi::world()) : Application(comm)
39  {
40  instantiateVariableChangeFactory<MODEL>();
41  }
42 // -------------------------------------------------------------------------------------------------
43  virtual ~ConvertIncrement() {}
44 // -------------------------------------------------------------------------------------------------
45  int execute(const eckit::Configuration & fullConfig) const {
46 // Setup resolution for intput and output
47  const eckit::LocalConfiguration inputResolConfig(fullConfig, "input geometry");
48  const Geometry_ resol1(inputResolConfig, this->getComm());
49 
50  const eckit::LocalConfiguration outputResolConfig(fullConfig, "output geometry");
51  const Geometry_ resol2(outputResolConfig, this->getComm());
52 
53 // Variable transform(s)
54  std::vector<bool> inverse;
55  std::vector<bool> adjoint;
56 
57  std::vector<eckit::LocalConfiguration> chvarconfs;
58  fullConfig.get("linear variable changes", chvarconfs);
59  for (size_t cv = 0; cv < chvarconfs.size(); ++cv) {
60  inverse.push_back(chvarconfs[cv].getBool("do inverse", false));
61  adjoint.push_back(chvarconfs[cv].getBool("do adjoint", false));
62  }
63 
64 // List of input and output increments
65  std::vector<eckit::LocalConfiguration> incrementsConf;
66  fullConfig.get("increments", incrementsConf);
67  int nincrements = incrementsConf.size();
68 
69 // Loop over increments
70  for (int jm = 0; jm < nincrements; ++jm) {
71 // Print output
72  Log::info() << "Converting increment " << jm+1 << " of " << nincrements << std::endl;
73 
74 // Datetime for incrmement
75  const util::DateTime incdatetime(incrementsConf[jm].getString("date"));
76 
77 // Variables for input increment
78  const Variables incvars(incrementsConf[jm], "input variables");
79 
80 // Read input
81  const eckit::LocalConfiguration inputConfig(incrementsConf[jm], "input");
82  Increment_ dxi(resol1, incvars, incdatetime);
83  dxi.read(inputConfig);
84  Log::test() << "Input increment: " << dxi << std::endl;
85 
86 // Copy and change resolution
87  std::unique_ptr<Increment_> dx(new Increment_(resol2, dxi)); // Pointer that can be reset
88 
89 // Trajectory state for linear variable transform
90  std::unique_ptr<State_> xtraj; // Pointer that can be reset
91 
92 // Variable transform(s)
93  for (size_t cv = 0; cv < chvarconfs.size(); ++cv) {
94  // Read trajectory
95  if (cv == 0) {
96  const eckit::LocalConfiguration trajConfig(incrementsConf[jm], "trajectory");
97  xtraj.reset(new State_(resol1, trajConfig));
98  ASSERT(xtraj->validTime() == dx->validTime()); // Check time is consistent
99  Log::test() << "Trajectory state: " << *xtraj << std::endl;
100  }
101 
102  // Create variable change
103  std::unique_ptr<LinearVariableChange_> lvc;
104  lvc.reset(LinearVariableChangeFactory_::create(*xtraj, *xtraj, resol2, chvarconfs[cv]));
105 
106  // Print info
107  Log::info() << "Variable transform " << cv+1 << " of " << chvarconfs.size() << ": "
108  << *lvc << std::endl;
109 
110  Increment_ xchvarout = lvc->multiply(*dx);
111  dx.reset(new Increment_(xchvarout));
112 
113  Log::test() << "Increment after variable transform: " << *dx << std::endl;
114  }
115 
116 // Write state
117  const eckit::LocalConfiguration outputConfig(incrementsConf[jm], "output");
118  dx->write(outputConfig);
119 
120  Log::test() << "Output increment: " << *dx << std::endl;
121  }
122  return 0;
123  }
124 // -------------------------------------------------------------------------------------------------
125  private:
126  std::string appname() const {
127  return "oops::ConvertIncrement<" + MODEL::name() + ">";
128  }
129 // -------------------------------------------------------------------------------------------------
130 };
131 
132 } // namespace oops
133 #endif // OOPS_RUNS_CONVERTINCREMENT_H_
const eckit::mpi::Comm & getComm() const
Definition: Application.h:36
Geometry< MODEL > Geometry_
LinearVariableChangeFactory< MODEL > LinearVariableChangeFactory_
std::string appname() const
Increment< MODEL > Increment_
LinearVariableChangeBase< MODEL > LinearVariableChange_
ConvertIncrement(const eckit::mpi::Comm &comm=oops::mpi::world())
int execute(const eckit::Configuration &fullConfig) const
Geometry class used in oops; subclass of interface class interface::Geometry.
Increment class used in oops.
static LinearVariableChangeBase< MODEL > * create(const State_ &, const State_ &, const Geometry_ &, const LinearVariableChangeParametersBase &parameters)
Create and return a new linear variable change.
State class used in oops; subclass of interface class interface::State.
void read(const eckit::Configuration &)
Read this Increment from file.
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.