IODA
ObsSpaceParameters.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 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 OBSSPACEPARAMETERS_H_
9 #define OBSSPACEPARAMETERS_H_
10 
11 #include <string>
12 #include <vector>
13 
15 #include "ioda/Misc/Dimensions.h"
16 #include "ioda/io/ObsIoFactory.h"
17 #include "ioda/io/ObsIoParametersBase.h"
18 
19 #include "eckit/exception/Exceptions.h"
20 #include "eckit/mpi/Comm.h"
21 
22 #include "oops/base/ParameterTraitsVariables.h"
23 #include "oops/util/DateTime.h"
24 #include "oops/util/Logger.h"
25 #include "oops/util/parameters/OptionalParameter.h"
26 #include "oops/util/parameters/Parameter.h"
27 #include "oops/util/parameters/Parameters.h"
28 #include "oops/util/parameters/RequiredParameter.h"
29 #include "oops/util/parameters/RequiredPolymorphicParameter.h"
30 
31 
32 namespace eckit {
33  class Configuration;
34 }
35 
36 namespace ioda {
37 
38 
40  OOPS_CONCRETE_PARAMETERS(ObsFileInParameters, ObsIoParametersBase)
41 
42  public:
43  /// input obs file name
44  oops::RequiredParameter<std::string> fileName{"obsfile", this};
45 
46  /// reading from multiple files (1 per MPI task)
47  /// This option is not typically used. It is used to tell the system
48  /// to read observations from the ioda output files (one per MPI task)
49  /// from a prior run instead of reading and distributing from the original
50  /// file. This is currently being used in LETKF applictions.
51  oops::Parameter<bool> readFromSeparateFiles{"read obs from separate file", false, this};
52 };
53 
55  OOPS_CONCRETE_PARAMETERS(ObsFileOutParameters, ObsIoParametersBase)
56 
57  public:
58  /// output obs file name
59  oops::RequiredParameter<std::string> fileName{"obsfile", this};
60 };
61 
62 class ObsExtendParameters : public oops::Parameters {
63  OOPS_CONCRETE_PARAMETERS(ObsExtendParameters, oops::Parameters)
64 
65  public:
66  /// number of model levels in target of the averaging function
67  oops::RequiredParameter<int> numModelLevels{"average profiles onto model levels", this};
68 
69  /// number of model levels in target of the averaging function
70  oops::Parameter<std::vector<std::string>> nonMissingExtendedVars
71  {"variables filled with non-missing values",
72  { "latitude", "longitude", "datetime", "air_pressure", "air_pressure_levels" },
73  this};
74 };
75 
77  OOPS_ABSTRACT_PARAMETERS(ObsGenerateParametersBase, ObsIoParametersBase)
78 
79  public:
80  /// obs error estimates
81  oops::Parameter<std::vector<float>> obsErrors{"obs errors", { }, this};
82 };
83 
84 class EmbeddedObsGenerateRandomParameters : public oops::Parameters {
85  OOPS_CONCRETE_PARAMETERS(EmbeddedObsGenerateRandomParameters, Parameters)
86 
87  public:
88  /// number of observations
89  oops::RequiredParameter<int> numObs{"nobs", this};
90 
91  /// latitude range start
92  oops::RequiredParameter<float> latStart{"lat1", this};
93 
94  /// latitude range end
95  oops::RequiredParameter<float> latEnd{"lat2", this};
96 
97  /// longitude range start
98  oops::RequiredParameter<float> lonStart{"lon1", this};
99 
100  /// longitude range end
101  oops::RequiredParameter<float> lonEnd{"lon2", this};
102 
103  /// random seed
104  oops::OptionalParameter<int> ranSeed{"random seed", this};
105 };
106 
107 /// Options controlling the ObsIoGenerateRandom class
109  OOPS_CONCRETE_PARAMETERS(ObsGenerateRandomParameters, ObsGenerateParametersBase)
110 
111  public:
112  /// options shared by this class and the legacy implementation (LegacyObsGenerateParameters)
114 };
115 
116 class EmbeddedObsGenerateListParameters : public oops::Parameters {
117  OOPS_CONCRETE_PARAMETERS(EmbeddedObsGenerateListParameters, Parameters)
118 
119  public:
120  /// latitude values
121  oops::RequiredParameter<std::vector<float>> lats{"lats", this};
122 
123  /// longitude values
124  oops::RequiredParameter<std::vector<float>> lons{"lons", this};
125 
126  /// datetime values
127  oops::RequiredParameter<std::vector<std::string>> datetimes{"datetimes", this};
128 };
129 
130 /// Options controlling the ObsIoGenerateList class
132  OOPS_CONCRETE_PARAMETERS(ObsGenerateListParameters, ObsGenerateParametersBase)
133 
134  public:
135  /// options shared by this class and the legacy implementation (LegacyObsGenerateParameters)
137 };
138 
139 /// \brief Options in the 'generate' YAML section.
140 ///
141 /// \note If you add or remove any Parameter member variables from this class, be sure to update
142 /// ObsTopLevelParameters::deserialize() to match.
143 class LegacyObsGenerateParameters : public oops::Parameters {
144  OOPS_CONCRETE_PARAMETERS(LegacyObsGenerateParameters, Parameters)
145 
146  public:
147  /// specification for generating using the random method
148  oops::OptionalParameter<EmbeddedObsGenerateRandomParameters> random{"random", this};
149 
150  /// specification for generating using the list method
151  oops::OptionalParameter<EmbeddedObsGenerateListParameters> list{"list", this};
152 
153  /// options controlling obs record grouping
154  oops::Parameter<ObsGroupingParameters> obsGrouping{"obsgrouping", { }, this};
155 
156  /// obs error estimates
157  oops::Parameter<std::vector<float>> obsErrors{"obs errors", { }, this};
158 
159  /// maximum frame size
160  oops::Parameter<int> maxFrameSize{"max frame size", DEFAULT_FRAME_SIZE, this};
161 };
162 
163 class ObsIoParametersWrapper : public oops::Parameters {
164  OOPS_CONCRETE_PARAMETERS(ObsIoParametersWrapper, Parameters)
165  public:
166  oops::RequiredPolymorphicParameter<ObsIoParametersBase, ObsIoFactory>
167  obsIoInParameters{"type", this};
168 };
169 
170 class ObsTopLevelParameters : public oops::Parameters {
171  OOPS_CONCRETE_PARAMETERS(ObsTopLevelParameters, Parameters)
172 
173  public:
174  /// Reimplemented to store contents of the `obsdatain` or `generate` section (if present)
175  /// in the source member variable. This makes it possible for the options related to the source
176  /// of input data to be accessed in a uniform way (regardless of in which section they were
177  /// specified) by calling obsIoInParameters().
178  void deserialize(util::CompositePath &path, const eckit::Configuration &config) override;
179 
180  /// name of obs space
181  oops::RequiredParameter<std::string> obsSpaceName{"name", this};
182 
183  /// perturbation seed
184  oops::Parameter<int> obsPertSeed{"obs perturbations seed", 0, this};
185 
186  /// name of MPI distribution
187  oops::Parameter<std::string> distName{"distribution", "RoundRobin", this};
188 
189  /// simulated variables
190  oops::RequiredParameter<oops::Variables> simVars{"simulated variables", this};
191 
192  /// Halo distribution center
193  oops::OptionalParameter<std::vector<float>> haloCenter{"center", this};
194 
195  /// Halo distribution radius
196  oops::OptionalParameter<float> haloRadius{"radius", this};
197 
198  /// output specification by writing to a file
199  oops::OptionalParameter<ObsFileOutParameters> obsOutFile{"obsdataout", this};
200 
201  /// extend the ObsSpace with extra fixed-size records
202  oops::OptionalParameter<ObsExtendParameters> obsExtend{"extension", this};
203 
204  /// parameters indicating where to load data from
206  if (source.value() != boost::none)
207  return source.value()->obsIoInParameters.value();
208  throw eckit::BadValue("obsIoInParameters() must not be called before deserialize()", Here());
209  }
210 
211  private:
212  /// \brief Fill this section to read observations from a file.
213  oops::OptionalParameter<ObsFileInParameters> obsInFile{"obsdatain", this};
214 
215  /// \brief Fill this section to generate observations on the fly.
216  oops::OptionalParameter<LegacyObsGenerateParameters> obsGenerate{"generate", this};
217 
218  /// \brief Fill this section instead of `obsdatain` and `generate` to load observations from
219  /// any other source.
220  oops::OptionalParameter<ObsIoParametersWrapper> source{"source", this};
221 };
222 
224  public:
225  /// sub groups of parameters
227 
228  /// Constructor
229  ObsSpaceParameters(const util::DateTime & winStart, const util::DateTime & winEnd,
230  const eckit::mpi::Comm & comm, const eckit::mpi::Comm & timeComm) :
231  win_start_(winStart), win_end_(winEnd), comm_(comm),
233  new_dims_(), max_var_size_(0) {
234  // Record the MPI rank number. The rank number is being saved during the
235  // construction of the Parameters for the ObsSpace saveToFile routine.
236  // (saveToFile will uniquify the output file name by tagging on the MPI rank
237  // number) For some reason, querying the saved MPI communicator (comm_) during
238  // the deconstruction process (when saveToFile is being run) will not reliably
239  // return the correct rank number. It was attempted to put in an MPI barrier call
240  // in case the issue was one rank finishing up before the other got to the query, but
241  // the barrier command itself caused a crash. It appears that the saved MPI
242  // communicator is getting corrupted during the deconstruction, but this has not
243  // been fully debugged, and should therefore be looked at later.
244  mpi_rank_ = comm.rank();
245  if (timeComm.size() > 1) {
246  mpi_time_rank_ = timeComm.rank();
247  } else {
248  mpi_time_rank_ = -1;
249  }
250  }
251 
252  /// \brief deserialize the parameter sub groups
253  /// \param config "obs space" level configuration
254  void deserialize(const eckit::Configuration & config) {
255  oops::Log::trace() << "ObsSpaceParameters config: " << config << std::endl;
256  top_level_.validateAndDeserialize(config);
257  }
258 
259  /// \brief return the start of the DA timing window
260  const util::DateTime & windowStart() const {return win_start_;}
261 
262  /// \brief return the end of the DA timing window
263  const util::DateTime & windowEnd() const {return win_end_;}
264 
265  /// \brief return the associated MPI group communicator
266  const eckit::mpi::Comm & comm() const {return comm_;}
267 
268  /// \brief return the associated perturbations seed
269  int obsPertSeed() const {return top_level_.obsPertSeed;}
270 
271  /// \brief return the associated MPI time communicator
272  const eckit::mpi::Comm & timeComm() const {return time_comm_;}
273 
274  /// \brief set a new dimension scale
275  void setDimScale(const std::string & dimName, const Dimensions_t curSize,
276  const Dimensions_t maxSize, const Dimensions_t chunkSize) {
277  new_dims_.push_back(
278  NewDimensionScale<int>(dimName, curSize, maxSize, chunkSize));
279  }
280 
281  /// \brief get a new dimension scale
283 
284  /// \brief set the maximum variable size
285  void setMaxVarSize(const Dimensions_t maxVarSize) { max_var_size_ = maxVarSize; }
286 
287  /// \brief get the maximum variable size
288  Dimensions_t getMaxVarSize() const { return max_var_size_; }
289 
290  /// \brief get the MPI rank number
291  std::size_t getMpiRank() const { return mpi_rank_; }
292 
293  /// \brief get the MPI rank number
294  int getMpiTimeRank() const { return mpi_time_rank_; }
295 
296  private:
297  /// \brief Beginning of DA timing window
298  const util::DateTime win_start_;
299 
300  /// \brief End of DA timing window
301  const util::DateTime win_end_;
302 
303  /// \brief MPI group communicator
304  const eckit::mpi::Comm & comm_;
305 
306  /// \brief MPI time communicator
307  const eckit::mpi::Comm & time_comm_;
308 
309  /// \brief new dimension scales for output file construction
311 
312  /// \brief maximum variable size for output file contruction
313  Dimensions_t max_var_size_;
314 
315  /// \brief group MPI rank number for output file construction
316  std::size_t mpi_rank_;
317 
318  /// \brief time MPI rank number of output file construction
320 };
321 
322 } // namespace ioda
323 
324 #endif // OBSSPACEPARAMETERS_H_
Convenience classes for constructing ObsSpaces and setting up new Dimension Scales.
Describe the dimensions of a ioda::Attribute or ioda::Variable.
oops::RequiredParameter< std::vector< float > > lats
latitude values
oops::RequiredParameter< std::vector< std::string > > datetimes
datetime values
oops::RequiredParameter< std::vector< float > > lons
longitude values
oops::RequiredParameter< float > latEnd
latitude range end
oops::RequiredParameter< float > lonStart
longitude range start
oops::RequiredParameter< float > latStart
latitude range start
oops::OptionalParameter< int > ranSeed
random seed
oops::RequiredParameter< float > lonEnd
longitude range end
oops::RequiredParameter< int > numObs
number of observations
Options in the 'generate' YAML section.
oops::Parameter< std::vector< float > > obsErrors
obs error estimates
oops::Parameter< ObsGroupingParameters > obsGrouping
options controlling obs record grouping
oops::OptionalParameter< EmbeddedObsGenerateRandomParameters > random
specification for generating using the random method
oops::OptionalParameter< EmbeddedObsGenerateListParameters > list
specification for generating using the list method
oops::Parameter< int > maxFrameSize
maximum frame size
oops::Parameter< std::vector< std::string > > nonMissingExtendedVars
number of model levels in target of the averaging function
oops::RequiredParameter< int > numModelLevels
number of model levels in target of the averaging function
oops::Parameter< bool > readFromSeparateFiles
oops::RequiredParameter< std::string > fileName
input obs file name
oops::RequiredParameter< std::string > fileName
output obs file name
Options controlling the ObsIoGenerateList class.
EmbeddedObsGenerateListParameters list
options shared by this class and the legacy implementation (LegacyObsGenerateParameters)
oops::Parameter< std::vector< float > > obsErrors
obs error estimates
Options controlling the ObsIoGenerateRandom class.
EmbeddedObsGenerateRandomParameters random
options shared by this class and the legacy implementation (LegacyObsGenerateParameters)
Base of classes storing the configuration parameters of ObsIo subclasses.
oops::RequiredPolymorphicParameter< ObsIoParametersBase, ObsIoFactory > obsIoInParameters
void deserialize(const eckit::Configuration &config)
deserialize the parameter sub groups
const eckit::mpi::Comm & time_comm_
MPI time communicator.
int obsPertSeed() const
return the associated perturbations seed
ObsSpaceParameters(const util::DateTime &winStart, const util::DateTime &winEnd, const eckit::mpi::Comm &comm, const eckit::mpi::Comm &timeComm)
Constructor.
NewDimensionScales_t new_dims_
new dimension scales for output file construction
int getMpiTimeRank() const
get the MPI rank number
const util::DateTime & windowEnd() const
return the end of the DA timing window
void setMaxVarSize(const Dimensions_t maxVarSize)
set the maximum variable size
ObsTopLevelParameters top_level_
sub groups of parameters
std::size_t mpi_rank_
group MPI rank number for output file construction
std::size_t getMpiRank() const
get the MPI rank number
NewDimensionScales_t getDimScales() const
get a new dimension scale
const util::DateTime win_start_
Beginning of DA timing window.
const eckit::mpi::Comm & comm_
MPI group communicator.
void setDimScale(const std::string &dimName, const Dimensions_t curSize, const Dimensions_t maxSize, const Dimensions_t chunkSize)
set a new dimension scale
Dimensions_t getMaxVarSize() const
get the maximum variable size
int mpi_time_rank_
time MPI rank number of output file construction
const eckit::mpi::Comm & timeComm() const
return the associated MPI time communicator
const util::DateTime & windowStart() const
return the start of the DA timing window
const eckit::mpi::Comm & comm() const
return the associated MPI group communicator
const util::DateTime win_end_
End of DA timing window.
Dimensions_t max_var_size_
maximum variable size for output file contruction
oops::OptionalParameter< ObsFileInParameters > obsInFile
Fill this section to read observations from a file.
oops::OptionalParameter< float > haloRadius
Halo distribution radius.
oops::Parameter< int > obsPertSeed
perturbation seed
oops::OptionalParameter< LegacyObsGenerateParameters > obsGenerate
Fill this section to generate observations on the fly.
oops::RequiredParameter< oops::Variables > simVars
simulated variables
void deserialize(util::CompositePath &path, const eckit::Configuration &config) override
oops::OptionalParameter< ObsIoParametersWrapper > source
Fill this section instead of obsdatain and generate to load observations from any other source.
oops::OptionalParameter< std::vector< float > > haloCenter
Halo distribution center.
oops::OptionalParameter< ObsExtendParameters > obsExtend
extend the ObsSpace with extra fixed-size records
oops::RequiredParameter< std::string > obsSpaceName
name of obs space
oops::OptionalParameter< ObsFileOutParameters > obsOutFile
output specification by writing to a file
oops::Parameter< std::string > distName
name of MPI distribution
const ObsIoParametersBase & obsIoInParameters() const
parameters indicating where to load data from
std::vector< std::shared_ptr< NewDimensionScale_Base > > NewDimensionScales_t
constexpr int DEFAULT_FRAME_SIZE