IODA
ObsVector.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2017-2019 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 #include "ioda/ObsVector.h"
9 
10 #include <math.h>
11 #include <limits>
12 
13 #include "eckit/config/LocalConfiguration.h"
14 #include "eckit/mpi/Comm.h"
15 #include "ioda/ObsSpace.h"
16 #include "oops/base/Variables.h"
17 #include "oops/util/abor1_cpp.h"
18 #include "oops/util/Logger.h"
19 #include "oops/util/missingValues.h"
20 #include "oops/util/Random.h"
21 
22 namespace ioda {
23 // -----------------------------------------------------------------------------
25  const std::string & name, const bool fail)
26  : obsdb_(obsdb), obsvars_(obsdb.obsvariables()),
27  nvars_(obsvars_.variables().size()), nlocs_(obsdb_.nlocs()),
28  values_(nlocs_ * nvars_),
29  missing_(util::missingValue(missing_)) {
30  oops::Log::trace() << "ObsVector::ObsVector " << name << std::endl;
31  if (!name.empty()) this->read(name, fail);
32 }
33 // -----------------------------------------------------------------------------
35  : obsdb_(other.obsdb_), obsvars_(other.obsvars_), nvars_(other.nvars_),
36  nlocs_(other.nlocs_), values_(nlocs_ * nvars_), missing_(other.missing_) {
37  values_ = other.values_;
38  oops::Log::trace() << "ObsVector copied " << std::endl;
39 }
40 // -----------------------------------------------------------------------------
41 ObsVector::ObsVector(ObsSpace & obsdb, const ObsVector & other)
42  : obsdb_(obsdb), obsvars_(other.obsvars_), nvars_(other.nvars_),
43  nlocs_(obsdb.localobs().size()), values_(nlocs_ * nvars_), missing_(other.missing_) {
44  for (size_t ii = 0; ii < nlocs_; ++ii) {
45  for (size_t vv = 0; vv < nvars_; ++vv) {
46  values_[ii*nvars_ + vv] = other.values_[obsdb.localobs()[ii]*nvars_ + vv];
47  }
48  }
49  oops::Log::trace() << "Local ObsVector copied " << std::endl;
50 }
51 // -----------------------------------------------------------------------------
53 }
54 // -----------------------------------------------------------------------------
56  values_ = rhs.values_;
57  return *this;
58 }
59 // -----------------------------------------------------------------------------
60 ObsVector & ObsVector::operator*= (const double & zz) {
61  for (size_t jj = 0; jj < values_.size() ; ++jj) {
62  if (values_[jj] != missing_) {
63  values_[jj] = zz * values_[jj];
64  }
65  }
66  return *this;
67 }
68 // -----------------------------------------------------------------------------
70  const size_t nn = values_.size();
71  ASSERT(rhs.values_.size() == nn);
72  for (size_t jj = 0; jj < nn ; ++jj) {
73  if (values_[jj] == missing_ || rhs.values_[jj] == missing_) {
74  values_[jj] = missing_;
75  } else {
76  values_[jj] += rhs.values_[jj];
77  }
78  }
79  return *this;
80 }
81 // -----------------------------------------------------------------------------
83  const size_t nn = values_.size();
84  ASSERT(rhs.values_.size() == nn);
85  for (size_t jj = 0; jj < nn ; ++jj) {
86  if (values_[jj] == missing_ || rhs.values_[jj] == missing_) {
87  values_[jj] = missing_;
88  } else {
89  values_[jj] -= rhs.values_[jj];
90  }
91  }
92  return *this;
93 }
94 // -----------------------------------------------------------------------------
96  const size_t nn = values_.size();
97  ASSERT(rhs.values_.size() == nn);
98  for (size_t jj = 0; jj < nn ; ++jj) {
99  if (values_[jj] == missing_ || rhs.values_[jj] == missing_) {
100  values_[jj] = missing_;
101  } else {
102  values_[jj] *= rhs.values_[jj];
103  }
104  }
105  return *this;
106 }
107 // -----------------------------------------------------------------------------
109  const size_t nn = values_.size();
110  ASSERT(rhs.values_.size() == nn);
111  for (size_t jj = 0; jj < nn ; ++jj) {
112  if (values_[jj] == missing_ || rhs.values_[jj] == missing_) {
113  values_[jj] = missing_;
114  } else {
115  values_[jj] /= rhs.values_[jj];
116  }
117  }
118  return *this;
119 }
120 // -----------------------------------------------------------------------------
122  for (size_t jj = 0; jj < values_.size() ; ++jj) {
123  values_[jj] = 0.0;
124  }
125 }
126 // -----------------------------------------------------------------------------
127 void ObsVector::axpy(const double & zz, const ObsVector & rhs) {
128  const size_t nn = values_.size();
129  ASSERT(rhs.values_.size() == nn);
130  for (size_t jj = 0; jj < nn ; ++jj) {
131  if (values_[jj] == missing_ || rhs.values_[jj] == missing_) {
132  values_[jj] = missing_;
133  } else {
134  values_[jj] += zz * rhs.values_[jj];
135  }
136  }
137 }
138 // -----------------------------------------------------------------------------
140  for (size_t jj = 0; jj < values_.size() ; ++jj) {
141  if (values_[jj] != missing_) {
142  values_[jj] = 1.0 / values_[jj];
143  }
144  }
145 }
146 // -----------------------------------------------------------------------------
148  util::NormalDistribution<double> x(values_.size(), 0.0, 1.0, this->getSeed());
149  for (size_t jj = 0; jj < values_.size() ; ++jj) {
150  values_[jj] = x[jj];
151  }
152 }
153 // -----------------------------------------------------------------------------
154 double ObsVector::dot_product_with(const ObsVector & other) const {
155  const size_t nn = values_.size();
156  ASSERT(other.values_.size() == nn);
157  double zz = 0.0;
158  for (size_t jj = 0; jj < nn ; ++jj) {
159  if (values_[jj] != missing_ && other.values_[jj] != missing_) {
160  zz += values_[jj] * other.values_[jj];
161  }
162  }
163  if (obsdb_.isDistributed()) {
164  obsdb_.comm().allReduceInPlace(zz, eckit::mpi::sum());
165  }
166  return zz;
167 }
168 // -----------------------------------------------------------------------------
169 double ObsVector::rms() const {
170  double zrms = 0.0;
171  int nobs = 0;
172  for (size_t jj = 0; jj < values_.size() ; ++jj) {
173  if (values_[jj] != missing_) {
174  zrms += values_[jj] * values_[jj];
175  ++nobs;
176  }
177  }
178  if (obsdb_.isDistributed()) {
179  obsdb_.comm().allReduceInPlace(zrms, eckit::mpi::sum());
180  obsdb_.comm().allReduceInPlace(nobs, eckit::mpi::sum());
181  }
182  if (nobs > 0) zrms = sqrt(zrms / static_cast<double>(nobs));
183  return zrms;
184 }
185 // -----------------------------------------------------------------------------
186 void ObsVector::read(const std::string & name, const bool fail) {
187  oops::Log::trace() << "ObsVector::read, name = " << name << std::endl;
188 
189  // Read in the variables stored in obsvars_ from the group given by "name".
190  //
191  // We want to construct the vector in the order of all variable values for the
192  // first location, then all variable values for the second location, etc. This
193  // means that a single variable gets its values spread out across the vector
194  // in intervals the size of nvars_, and that the starting point for each variable
195  // in the vector is given by the index of the variable name in varnames_.
196 
197  std::size_t nlocs = obsdb_.nlocs();
198  std::vector<double> tmp(nlocs);
199  for (std::size_t jv = 0; jv < nvars_; ++jv) {
200  if (fail || obsdb_.has(name, obsvars_.variables()[jv])) {
201  obsdb_.get_db(name, obsvars_.variables()[jv], tmp);
202 
203  for (std::size_t jj = 0; jj < nlocs; ++jj) {
204  std::size_t ivec = jv + (jj * nvars_);
205  values_[ivec] = tmp[jj];
206  }
207  }
208  }
209 }
210 // -----------------------------------------------------------------------------
211 void ObsVector::save(const std::string & name) const {
212  oops::Log::trace() << "ObsVector::save, name = " << name << std::endl;
213 
214  // As noted in the read method, the order is all variables at the first location,
215  // then all variables at the next location, etc.
216  std::size_t nlocs = obsdb_.nlocs();
217  std::size_t ivec;
218  for (std::size_t jv = 0; jv < nvars_; ++jv) {
219  std::vector<double> tmp(nlocs);
220  for (std::size_t jj = 0; jj < tmp.size(); ++jj) {
221  ivec = jv + (jj * nvars_);
222  tmp[jj] = values_[ivec];
223  }
224 
225  obsdb_.put_db(name, obsvars_.variables()[jv], tmp);
226  }
227 }
228 // -----------------------------------------------------------------------------
229 Eigen::VectorXd ObsVector::packEigen() const {
230  Eigen::VectorXd vec(nobs());
231  size_t ii = 0;
232  for (const double & val : values_) {
233  if (val != missing_) {
234  vec(ii++) = val;
235  }
236  }
237  return vec;
238 }
239 // -----------------------------------------------------------------------------
240 void ObsVector::mask(const ObsDataVector<int> & flags) {
241  oops::Log::trace() << "ObsVector::mask" << std::endl;
242  ASSERT(values_.size() == flags.nvars() * flags.nlocs());
243  size_t ii = 0;
244  for (size_t jv = 0; jv < flags.nvars(); ++jv) {
245  for (size_t jj = 0; jj < flags.nlocs(); ++jj) {
246  if (flags[jv][jj] > 0) values_[ii] = missing_;
247  ++ii;
248  }
249  }
250 }
251 // -----------------------------------------------------------------------------
252 unsigned int ObsVector::nobs() const {
253  int nobs = 0;
254  for (size_t jj = 0; jj < values_.size() ; ++jj) {
255  if (values_[jj] != missing_) ++nobs;
256  }
257  if (obsdb_.isDistributed()) {
258  obsdb_.comm().allReduceInPlace(nobs, eckit::mpi::sum());
259  }
260  return nobs;
261 }
262 // -----------------------------------------------------------------------------
263 const double & ObsVector::toFortran() const {
264  return values_[0];
265 }
266 // -----------------------------------------------------------------------------
268  return values_[0];
269 }
270 // -----------------------------------------------------------------------------
271 void ObsVector::print(std::ostream & os) const {
272  double zmin = std::numeric_limits<double>::max();
273  double zmax = std::numeric_limits<double>::lowest();
274  double zrms = 0.0;
275  int nobs = 0;
276  for (size_t jj = 0; jj < values_.size() ; ++jj) {
277  if (values_[jj] != missing_) {
278  if (values_[jj] < zmin) zmin = values_[jj];
279  if (values_[jj] > zmax) zmax = values_[jj];
280  zrms += values_[jj] * values_[jj];
281  ++nobs;
282  }
283  }
284  if (obsdb_.isDistributed()) {
285  obsdb_.comm().allReduceInPlace(zmin, eckit::mpi::min());
286  obsdb_.comm().allReduceInPlace(zmax, eckit::mpi::max());
287  obsdb_.comm().allReduceInPlace(zrms, eckit::mpi::sum());
288  obsdb_.comm().allReduceInPlace(nobs, eckit::mpi::sum());
289  }
290  if (nobs > 0) {
291  zrms = sqrt(zrms / static_cast<double>(nobs));
292  os << obsdb_.obsname() << " nobs= " << nobs << " Min="
293  << zmin << ", Max=" << zmax << ", RMS=" << zrms << std::endl;
294  } else {
295  os << obsdb_.obsname() << ": No observations." << std::endl;
296  }
297 }
298 // -----------------------------------------------------------------------------
299 } // namespace ioda
ioda::ObsSpace::get_db
void get_db(const std::string &group, const std::string &name, std::vector< int > &vdata) const
Definition: ObsSpace.cc:167
ioda::ObsVector::invert
void invert()
Definition: ObsVector.cc:139
ioda::ObsVector::~ObsVector
~ObsVector()
Definition: ObsVector.cc:52
ioda::ObsVector::rms
double rms() const
Definition: ObsVector.cc:169
ioda::ObsDataVector::nlocs
size_t nlocs() const
Definition: ObsDataVector.h:62
ioda::ObsVector::obsdb_
ObsSpace & obsdb_
Associate ObsSpace object.
Definition: src/ObsVector.h:84
ioda::ObsVector::obsvars_
oops::Variables obsvars_
Variables.
Definition: src/ObsVector.h:87
ioda::ObsSpace::has
bool has(const std::string &, const std::string &) const
Definition: ObsSpace.cc:282
ObsSpace.h
ioda::ObsVector::ObsVector
ObsVector(ObsSpace &, const std::string &name="", const bool fail=true)
Definition: ObsVector.cc:24
ioda::ObsVector::operator=
ObsVector & operator=(const ObsVector &)
Definition: ObsVector.cc:55
ioda::ObsVector::save
void save(const std::string &) const
Definition: ObsVector.cc:211
ioda::ObsSpace::comm
const eckit::mpi::Comm & comm() const
Definition: src/ObsSpace.h:103
ioda::ObsVector::mask
void mask(const ObsDataVector< int > &)
Definition: ObsVector.cc:240
ioda
Definition: IodaUtils.cc:13
ioda::ObsVector::print
void print(std::ostream &) const
Definition: ObsVector.cc:271
ioda::ObsVector::operator/=
ObsVector & operator/=(const ObsVector &)
Definition: ObsVector.cc:108
ioda::ObsVector::missing_
const double missing_
Missing data mark.
Definition: src/ObsVector.h:97
ioda::ObsVector
ObsVector class to handle vectors in observation space for IODA.
Definition: src/ObsVector.h:34
ioda::ObsVector::values_
std::vector< double > values_
Vector data.
Definition: src/ObsVector.h:94
ioda::ObsVector::nobs
unsigned int nobs() const
Definition: ObsVector.cc:252
ioda::ObsVector::random
void random()
Definition: ObsVector.cc:147
ioda::ObsSpace::isDistributed
bool isDistributed() const
Definition: src/ObsSpace.h:109
ioda::ObsVector::toFortran
const double & toFortran() const
Definition: ObsVector.cc:263
ioda::ObsSpace::localobs
const std::vector< std::size_t > & localobs() const
Definition: src/ObsSpace.h:94
ioda::ObsSpace::nlocs
std::size_t nlocs() const
Definition: ObsSpace.cc:344
ioda::ObsSpace::obsname
const std::string & obsname() const
Definition: src/ObsSpace.h:97
ioda::ObsVector::dot_product_with
double dot_product_with(const ObsVector &) const
Definition: ObsVector.cc:154
ioda::ObsVector::axpy
void axpy(const double &, const ObsVector &)
Definition: ObsVector.cc:127
ioda::ObsSpace::put_db
void put_db(const std::string &group, const std::string &name, const std::vector< int > &vdata)
Definition: ObsSpace.cc:242
ioda::ObsVector::operator*=
ObsVector & operator*=(const double &)
Definition: ObsVector.cc:60
ioda::ObsVector::operator+=
ObsVector & operator+=(const ObsVector &)
Definition: ObsVector.cc:69
ioda::ObsVector::nvars_
std::size_t nvars_
Number of variables.
Definition: src/ObsVector.h:90
ioda::ObsDataVector
ObsDataVector<DATATYPE> handles vectors of data of type DATATYPE in observation space.
Definition: ObsDataVector.h:41
ObsVector.h
ioda::ObsDataVector::nvars
size_t nvars() const
Definition: ObsDataVector.h:61
ioda::ObsVector::packEigen
Eigen::VectorXd packEigen() const
Definition: ObsVector.cc:229
ioda::ObsSpace
Observation Space View.
Definition: src/ObsSpace.h:35
ioda::ObsVector::read
void read(const std::string &, const bool fail=true)
Definition: ObsVector.cc:186
ioda::ObsVector::zero
void zero()
Definition: ObsVector.cc:121
ioda::ObsVector::nlocs
std::size_t nlocs() const
Definition: src/ObsVector.h:70
ioda::ObsVector::nlocs_
std::size_t nlocs_
Definition: src/ObsVector.h:91
ioda::ObsVector::operator-=
ObsVector & operator-=(const ObsVector &)
Definition: ObsVector.cc:82