IODA Bundle
oops/src/oops/interface/ObsVector.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_INTERFACE_OBSVECTOR_H_
12 #define OOPS_INTERFACE_OBSVECTOR_H_
13 
14 #include <Eigen/Dense>
15 #include <math.h>
16 #include <memory>
17 #include <ostream>
18 #include <string>
19 #include <utility>
20 
23 #include "oops/util/gatherPrint.h"
24 #include "oops/util/Logger.h"
25 #include "oops/util/ObjectCounter.h"
26 #include "oops/util/Printable.h"
27 #include "oops/util/Timer.h"
28 
29 namespace eckit {
30  class Configuration;
31 }
32 
33 namespace util {
34  class DateTime;
35 }
36 
37 namespace oops {
38 
39 // -----------------------------------------------------------------------------
40 
41 template <typename OBS>
42 class ObsVector : public util::Printable,
43  private util::ObjectCounter<ObsVector<OBS> > {
44  typedef typename OBS::ObsVector ObsVector_;
45 
46  public:
47  static const std::string classname() {return "oops::ObsVector";}
48 
49  /// Creates vector from \p obsspace. If \p name is specified, reads the
50  /// specified \p name variable from \p obsspace. Otherwise, zero vector is created.
51  explicit ObsVector(const ObsSpace<OBS> & obsspace, const std::string name = "");
52 
53  /// Wraps an existing ObsVector_.
54  ///
55  /// \param obsvector The vector to wrap.
56  /// \param timeComm Time communicator.
57  ObsVector(std::unique_ptr<ObsVector_> obsvector, const eckit::mpi::Comm &timeComm);
58 
59  ObsVector(const ObsVector &);
60  ~ObsVector();
61 
62 /// Interfacing
63  ObsVector_ & obsvector() {return *data_;}
64  const ObsVector_ & obsvector() const {return *data_;}
65 
66 // Linear algebra
67  ObsVector & operator = (const ObsVector &);
68  ObsVector & operator*= (const double &);
69  ObsVector & operator+= (const ObsVector &);
70  ObsVector & operator-= (const ObsVector &);
71  ObsVector & operator*= (const ObsVector &);
72  ObsVector & operator/= (const ObsVector &);
73 
74  /// Pack observations local to this MPI task into an Eigen vector
75  /// (excluding vector elements that are masked out: where \p mask is a missing value)
76  Eigen::VectorXd packEigen(const ObsVector & mask) const;
77  /// Number of non-masked out observations local to this MPI task
78  /// (size of an Eigen vector returned by `packEigen`)
79  size_t packEigenSize(const ObsVector & mask) const;
80 
81  void zero();
82  /// Set this ObsVector to ones (used in tests)
83  void ones();
84  void axpy(const double &, const ObsVector &);
85  void invert();
86  void random();
87  double dot_product_with(const ObsVector &) const;
88  double rms() const;
89  /// Mask out elements of the vector where \p mask is > 0
90  void mask(const ObsDataVector<OBS, int> & mask);
91  /// Mask out elements of the vector where \p mask is a missing value
92  void mask(const ObsVector & mask);
94 
95 // I/O
96  void save(const std::string &) const;
97  void read(const std::string &);
98 
99  /// number of non-masked out observations (across all MPI tasks)
100  unsigned int nobs() const;
101 
102  private:
103  void print(std::ostream &) const;
104  std::unique_ptr<ObsVector_> data_;
105  const eckit::mpi::Comm & commTime_;
106 };
107 
108 // -----------------------------------------------------------------------------
109 template <typename OBS>
110 ObsVector<OBS>::ObsVector(const ObsSpace<OBS> & os, const std::string name)
111  : data_(), commTime_(os.timeComm()) {
112  Log::trace() << "ObsVector<OBS>::ObsVector starting " << name << std::endl;
113  util::Timer timer(classname(), "ObsVector");
114  data_.reset(new ObsVector_(os.obsspace(), name));
115  this->setObjectSize(data_->size() * sizeof(double));
116  Log::trace() << "ObsVector<OBS>::ObsVector done" << std::endl;
117 }
118 // -----------------------------------------------------------------------------
119 template <typename OBS>
120 ObsVector<OBS>::ObsVector(std::unique_ptr<ObsVector_> obsvector, const eckit::mpi::Comm &timeComm)
121  : data_(std::move(obsvector)), commTime_(timeComm) {
122  Log::trace() << "ObsVector<OBS>::ObsVector starting " << std::endl;
123  util::Timer timer(classname(), "ObsVector");
124  this->setObjectSize(data_->size() * sizeof(double));
125  Log::trace() << "ObsVector<OBS>::ObsVector done" << std::endl;
126 }
127 // -----------------------------------------------------------------------------
128 template <typename OBS>
129 ObsVector<OBS>::ObsVector(const ObsVector & other): data_(), commTime_(other.commTime_) {
130  Log::trace() << "ObsVector<OBS>::ObsVector starting" << std::endl;
131  util::Timer timer(classname(), "ObsVector");
132  data_.reset(new ObsVector_(*other.data_));
133  this->setObjectSize(data_->size() * sizeof(double));
134  Log::trace() << "ObsVector<OBS>::ObsVector done" << std::endl;
135 }
136 // -----------------------------------------------------------------------------
137 template <typename OBS>
139  Log::trace() << "ObsVector<OBS>::~ObsVector starting" << std::endl;
140  util::Timer timer(classname(), "~ObsVector");
141  data_.reset();
142  Log::trace() << "ObsVector<OBS>::~ObsVector done" << std::endl;
143 }
144 // -----------------------------------------------------------------------------
145 template <typename OBS>
147  Log::trace() << "ObsVector<OBS>::operator= starting" << std::endl;
148  util::Timer timer(classname(), "operator=");
149 
150  *data_ = *rhs.data_;
151 
152  Log::trace() << "ObsVector<OBS>::operator= done" << std::endl;
153  return *this;
154 }
155 // -----------------------------------------------------------------------------
156 template <typename OBS>
158  Log::trace() << "ObsVector<OBS>::operator*= starting" << std::endl;
159  util::Timer timer(classname(), "operator*=");
160 
161  *data_ *= zz;
162 
163  Log::trace() << "ObsVector<OBS>::operator*= done" << std::endl;
164  return *this;
165 }
166 // -----------------------------------------------------------------------------
167 template <typename OBS>
169  Log::trace() << "ObsVector<OBS>::operator+= starting" << std::endl;
170  util::Timer timer(classname(), "operator+=");
171 
172  *data_ += *rhs.data_;
173 
174  Log::trace() << "ObsVector<OBS>::operator+= done" << std::endl;
175  return *this;
176 }
177 // -----------------------------------------------------------------------------
178 template <typename OBS>
180  Log::trace() << "ObsVector<OBS>::operator-= starting" << std::endl;
181  util::Timer timer(classname(), "operator-=");
182 
183  *data_ -= *rhs.data_;
184 
185  Log::trace() << "ObsVector<OBS>::operator-= done" << std::endl;
186  return *this;
187 }
188 // -----------------------------------------------------------------------------
189 template <typename OBS>
191  Log::trace() << "ObsVector<OBS>::operator*= starting" << std::endl;
192  util::Timer timer(classname(), "operator*=");
193 
194  *data_ *= *rhs.data_;
195 
196  Log::trace() << "ObsVector<OBS>::operator*= done" << std::endl;
197  return *this;
198 }
199 // -----------------------------------------------------------------------------
200 template <typename OBS>
202  Log::trace() << "ObsVector<OBS>::operator/= starting" << std::endl;
203  util::Timer timer(classname(), "operator/=");
204 
205  *data_ /= *rhs.data_;
206 
207  Log::trace() << "ObsVector<OBS>::operator/= done" << std::endl;
208  return *this;
209 }
210 // -----------------------------------------------------------------------------
211 template <typename OBS>
213  Log::trace() << "ObsVector<OBS>::zero starting" << std::endl;
214  util::Timer timer(classname(), "zero");
215 
216  data_->zero();
217 
218  Log::trace() << "ObsVector<OBS>::zero done" << std::endl;
219 }
220 // -----------------------------------------------------------------------------
221 template <typename OBS>
223  Log::trace() << "ObsVector<OBS>::ones starting" << std::endl;
224  util::Timer timer(classname(), "ones");
225 
226  data_->ones();
227 
228  Log::trace() << "ObsVector<OBS>::ones done" << std::endl;
229 }
230 // -----------------------------------------------------------------------------
231 template <typename OBS>
232 void ObsVector<OBS>::axpy(const double & zz, const ObsVector & rhs) {
233  Log::trace() << "ObsVector<OBS>::axpy starting" << std::endl;
234  util::Timer timer(classname(), "axpy");
235 
236  data_->axpy(zz, *rhs.data_);
237 
238  Log::trace() << "ObsVector<OBS>::axpy done" << std::endl;
239 }
240 // -----------------------------------------------------------------------------
241 template <typename OBS>
243  Log::trace() << "ObsVector<OBS>::invert starting" << std::endl;
244  util::Timer timer(classname(), "invert");
245 
246  data_->invert();
247 
248  Log::trace() << "ObsVector<OBS>::invert done" << std::endl;
249 }
250 // -----------------------------------------------------------------------------
251 template <typename OBS>
253  Log::trace() << "ObsVector<OBS>::random starting" << std::endl;
254  util::Timer timer(classname(), "random");
255 
256  data_->random();
257 
258  Log::trace() << "ObsVector<OBS>::random done" << std::endl;
259 }
260 // -----------------------------------------------------------------------------
261 template <typename OBS>
262 double ObsVector<OBS>::dot_product_with(const ObsVector & other) const {
263  Log::trace() << "ObsVector<OBS>::dot_product starting" << std::endl;
264  util::Timer timer(classname(), "dot_product");
265 
266  double zz = data_->dot_product_with(*other.data_);
267  commTime_.allReduceInPlace(zz, eckit::mpi::Operation::SUM);
268 
269  Log::trace() << "ObsVector<OBS>::dot_product done" << std::endl;
270  return zz;
271 }
272 // -----------------------------------------------------------------------------
273 template <typename OBS>
275  Log::trace() << "ObsVector<OBS>::mask starting" << std::endl;
276  util::Timer timer(classname(), "mask");
277  data_->mask(qc.obsdatavector());
278  Log::trace() << "ObsVector<OBS>::mask done" << std::endl;
279 }
280 // -----------------------------------------------------------------------------
281 template <typename OBS>
282 void ObsVector<OBS>::mask(const ObsVector & mask) {
283  Log::trace() << "ObsVector<OBS>::mask(ObsVector) starting" << std::endl;
284  util::Timer timer(classname(), "mask(ObsVector)");
285  data_->mask(mask.obsvector());
286  Log::trace() << "ObsVector<OBS>::mask(ObsVector) done" << std::endl;
287 }
288 // -----------------------------------------------------------------------------
289 template <typename OBS>
291  Log::trace() << "ObsVector<OBS>::operator= starting" << std::endl;
292  util::Timer timer(classname(), "operator=");
293  *data_ = rhs.obsdatavector();
294  Log::trace() << "ObsVector<OBS>::operator= done" << std::endl;
295  return *this;
296 }
297 // -----------------------------------------------------------------------------
298 template <typename OBS>
299 double ObsVector<OBS>::rms() const {
300  Log::trace() << "ObsVector<OBS>::rms starting" << std::endl;
301  util::Timer timer(classname(), "rms");
302 
303  double zz = 0.0;
304  size_t ntot = this->nobs();
305  if (ntot > 0) {
306  zz = data_->rms();
307  double zzz = zz * zz * static_cast<double>(data_->nobs());
308  commTime_.allReduceInPlace(zzz, eckit::mpi::Operation::SUM);
309  zzz /= static_cast<double>(ntot);
310  zz = std::sqrt(zzz);
311  }
312 
313  Log::trace() << "ObsVector<OBS>::rms done" << std::endl;
314  return zz;
315 }
316 // -----------------------------------------------------------------------------
317 template <typename OBS>
318 unsigned int ObsVector<OBS>::nobs() const {
319  int nobs = data_->nobs();
320  commTime_.allReduceInPlace(nobs, eckit::mpi::Operation::SUM);
321  return nobs;
322 }
323 // -----------------------------------------------------------------------------
324 template <typename OBS>
325 void ObsVector<OBS>::print(std::ostream & os) const {
326  Log::trace() << "ObsVector<OBS>::print starting" << std::endl;
327  util::Timer timer(classname(), "print");
328  if (commTime_.size() > 1) {
329  gatherPrint(os, *data_, commTime_);
330  } else {
331  os << *data_;
332  }
333  Log::trace() << "ObsVector<OBS>::print done" << std::endl;
334 }
335 // -----------------------------------------------------------------------------
336 template <typename OBS>
337 void ObsVector<OBS>::save(const std::string & name) const {
338  Log::trace() << "ObsVector<OBS>::save starting " << name << std::endl;
339  util::Timer timer(classname(), "save");
340 
341  data_->save(name);
342 
343  Log::trace() << "ObsVector<OBS>::save done" << std::endl;
344 }
345 // -----------------------------------------------------------------------------
346 template <typename OBS>
347 Eigen::VectorXd ObsVector<OBS>::packEigen(const ObsVector & mask) const {
348  Log::trace() << "ObsVector<OBS>::packEigen starting " << std::endl;
349  util::Timer timer(classname(), "packEigen");
350 
351  Eigen::VectorXd vec = data_->packEigen(mask.obsvector());
352 
353  Log::trace() << "ObsVector<OBS>::packEigen done" << std::endl;
354  return vec;
355 }
356 // -----------------------------------------------------------------------------
357 template <typename OBS>
358 size_t ObsVector<OBS>::packEigenSize(const ObsVector & mask) const {
359  Log::trace() << "ObsVector<OBS>::packEigenSize starting " << std::endl;
360  util::Timer timer(classname(), "packEigenSize");
361 
362  size_t len = data_->packEigenSize(mask.obsvector());
363 
364  Log::trace() << "ObsVector<OBS>::packEigen done" << std::endl;
365  return len;
366 }
367 // -----------------------------------------------------------------------------
368 template <typename OBS>
369 void ObsVector<OBS>::read(const std::string & name) {
370  Log::trace() << "ObsVector<OBS>::read starting " << name << std::endl;
371  util::Timer timer(classname(), "read");
372 
373  data_->read(name);
374 
375  Log::trace() << "ObsVector<OBS>::read done" << std::endl;
376 }
377 // -----------------------------------------------------------------------------
378 
379 } // namespace oops
380 
381 #endif // OOPS_INTERFACE_OBSVECTOR_H_
ObsDataVec_ & obsdatavector()
Interfacing.
ObsSpace_ & obsspace() const
Interfacing.
unsigned int nobs() const
number of non-masked out observations (across all MPI tasks)
void axpy(const double &, const ObsVector &)
const ObsVector_ & obsvector() const
void ones()
Set this ObsVector to ones (used in tests)
const eckit::mpi::Comm & commTime_
void save(const std::string &) const
void mask(const ObsDataVector< OBS, int > &mask)
Mask out elements of the vector where mask is > 0.
std::unique_ptr< ObsVector_ > data_
void print(std::ostream &) const
ObsVector & operator-=(const ObsVector &)
void read(const std::string &)
ObsVector_ & obsvector()
Interfacing.
size_t packEigenSize(const ObsVector &mask) const
Eigen::VectorXd packEigen(const ObsVector &mask) const
double dot_product_with(const ObsVector &) const
ObsVector & operator*=(const double &)
ObsVector & operator+=(const ObsVector &)
ObsVector(const ObsSpace< OBS > &obsspace, const std::string name="")
ObsVector & operator/=(const ObsVector &)
static const std::string classname()
ObsVector & operator=(const ObsVector &)
The namespace for the main oops code.
Definition: encode.cc:30