OOPS
DualVector.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_ASSIMILATION_DUALVECTOR_H_
12 #define OOPS_ASSIMILATION_DUALVECTOR_H_
13 
14 #include <memory>
15 #include <utility>
16 #include <vector>
17 
19 #include "oops/base/Departures.h"
22 #include "oops/util/dot_product.h"
23 
24 namespace oops {
25 
26 /// Container of dual space vectors for all terms of the cost function.
27 /*!
28  * Contains dual space vectors for all terms of the cost function,
29  * that is Departures for Jo, an Increment_ for Jc, a ControlIncrement
30  * for Jb and Jq.
31  */
32 
33 // -----------------------------------------------------------------------------
34 template<typename MODEL, typename OBS> class DualVector {
38 
39  public:
40  DualVector(): dxjb_(), dxjo_(), dxjc_(), ijo_(), ijc_(), size_(0) {}
41  DualVector(const DualVector &);
43 
44 // Access increment
45  void dx(CtrlInc_ * dx) {dxjb_.reset(dx);}
46  const CtrlInc_ & dx() const {return *dxjb_;}
47  CtrlInc_ & dx() {return *dxjb_;}
48 
49 // Store and retrieve other elements (takes ownership)
50  void append(std::unique_ptr<GeneralizedDepartures> &&);
51  std::shared_ptr<const GeneralizedDepartures> getv(const unsigned) const;
52 
53 // Linear algebra
54  DualVector & operator=(const DualVector &);
55  DualVector & operator+=(const DualVector &);
56  DualVector & operator-=(const DualVector &);
57  DualVector & operator*=(const double);
58  void zero();
59  void axpy(const double, const DualVector &);
60  double dot_product_with(const DualVector &) const;
61 
62 // Clear everything
63  void clear();
64 
65  private:
66  bool compatible(const DualVector & other) const;
67 
68  std::unique_ptr<CtrlInc_> dxjb_;
69  std::vector<std::shared_ptr<Departures_> > dxjo_;
70  std::vector<std::shared_ptr<Increment_> > dxjc_;
71  std::vector<unsigned> ijo_;
72  std::vector<unsigned> ijc_;
73  unsigned size_;
74 };
75 
76 // =============================================================================
77 
78 template<typename MODEL, typename OBS>
80  : dxjb_(), dxjo_(), dxjc_(),
81  ijo_(other.ijo_), ijc_(other.ijc_), size_(other.size_)
82 {
83  if (other.dxjb_ != 0) {
84  dxjb_.reset(new CtrlInc_(*other.dxjb_));
85  }
86  for (unsigned jj = 0; jj < other.dxjo_.size(); ++jj) {
87  std::shared_ptr<Departures_> pd(new Departures_(*other.dxjo_[jj]));
88  dxjo_.push_back(pd);
89  }
90  for (unsigned jj = 0; jj < other.dxjc_.size(); ++jj) {
91  std::shared_ptr<Increment_> pi(new Increment_(*other.dxjc_[jj]));
92  dxjc_.push_back(pi);
93  }
94 }
95 // -----------------------------------------------------------------------------
96 template<typename MODEL, typename OBS>
98  dxjb_.reset();
99  dxjo_.clear();
100  dxjc_.clear();
101  ijo_.clear();
102  ijc_.clear();
103  size_ = 0;
104 }
105 // -----------------------------------------------------------------------------
106 template<typename MODEL, typename OBS>
107 void DualVector<MODEL, OBS>::append(std::unique_ptr<GeneralizedDepartures> && uv) {
108 // Since there is no duck-typing in C++, we do it manually.
109  std::shared_ptr<GeneralizedDepartures> sv = std::move(uv);
110  std::shared_ptr<Increment_> si = std::dynamic_pointer_cast<Increment_>(sv);
111  if (si != nullptr) {
112  dxjc_.push_back(si);
113  ijc_.push_back(size_);
114  }
115  std::shared_ptr<Departures_> sd = std::dynamic_pointer_cast<Departures_>(sv);
116  if (sd != nullptr) {
117  dxjo_.push_back(sd);
118  ijo_.push_back(size_);
119  }
120  ASSERT(si != nullptr || sd != nullptr);
121  ++size_;
122 }
123 // -----------------------------------------------------------------------------
124 template<typename MODEL, typename OBS>
125 std::shared_ptr<const GeneralizedDepartures>
126 DualVector<MODEL, OBS>::getv(const unsigned ii) const {
127  ASSERT(ii < size_);
128  std::shared_ptr<const GeneralizedDepartures> pv;
129  for (unsigned jj = 0; jj < ijo_.size(); ++jj) {
130  if (ijo_[jj] == ii) pv = dxjo_[jj];
131  }
132  for (unsigned jj = 0; jj < ijc_.size(); ++jj) {
133  if (ijc_[jj] == ii) pv = dxjc_[jj];
134  }
135  ASSERT(pv != 0);
136  return pv;
137 }
138 // -----------------------------------------------------------------------------
139 template<typename MODEL, typename OBS>
141  ASSERT(this->compatible(rhs));
142  if (dxjb_ != 0) {
143  *dxjb_ = *rhs.dxjb_;
144  }
145  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
146  *dxjo_[jj] = *rhs.dxjo_[jj];
147  }
148  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
149  *dxjc_[jj] = *rhs.dxjc_[jj];
150  }
151  return *this;
152 }
153 // -----------------------------------------------------------------------------
154 template<typename MODEL, typename OBS>
156  ASSERT(this->compatible(rhs));
157  if (dxjb_ != 0) {
158  *dxjb_ += *rhs.dxjb_;
159  }
160  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
161  *dxjo_[jj] += *rhs.dxjo_[jj];
162  }
163  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
164  *dxjc_[jj] += *rhs.dxjc_[jj];
165  }
166  return *this;
167 }
168 // -----------------------------------------------------------------------------
169 template<typename MODEL, typename OBS>
171  ASSERT(this->compatible(rhs));
172  if (dxjb_ != 0) {
173  *dxjb_ -= *rhs.dxjb_;
174  }
175  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
176  *dxjo_[jj] -= *rhs.dxjo_[jj];
177  }
178  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
179  *dxjc_[jj] -= *rhs.dxjc_[jj];
180  }
181  return *this;
182 }
183 // -----------------------------------------------------------------------------
184 template<typename MODEL, typename OBS>
186  if (dxjb_ != 0) {
187  *dxjb_ *= zz;
188  }
189  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
190  *dxjo_[jj] *= zz;
191  }
192  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
193  *dxjc_[jj] *= zz;
194  }
195  return *this;
196 }
197 // -----------------------------------------------------------------------------
198 template<typename MODEL, typename OBS>
200  if (dxjb_ != 0) {
201  dxjb_->zero();
202  }
203  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
204  dxjo_[jj]->zero();
205  }
206  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
207  dxjc_[jj]->zero();
208  }
209 }
210 // -----------------------------------------------------------------------------
211 template<typename MODEL, typename OBS>
212 void DualVector<MODEL, OBS>::axpy(const double zz, const DualVector & rhs) {
213  ASSERT(this->compatible(rhs));
214  if (dxjb_ != 0) {
215  dxjb_->axpy(zz, *rhs.dxjb_);
216  }
217  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
218  dxjo_[jj]->axpy(zz, *rhs.dxjo_[jj]);
219  }
220  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
221  dxjc_[jj]->axpy(zz, *rhs.dxjc_[jj]);
222  }
223 }
224 // -----------------------------------------------------------------------------
225 template<typename MODEL, typename OBS>
227  ASSERT(this->compatible(x2));
228  double zz = 0.0;
229  if (dxjb_ != 0) {
230  zz += dot_product(*dxjb_, *x2.dxjb_);
231  }
232  for (unsigned jj = 0; jj < dxjo_.size(); ++jj) {
233  zz += dot_product(*dxjo_[jj], *x2.dxjo_[jj]);
234  }
235  for (unsigned jj = 0; jj < dxjc_.size(); ++jj) {
236  zz += dot_product(*dxjc_[jj], *x2.dxjc_[jj]);
237  }
238  return zz;
239 }
240 // -----------------------------------------------------------------------------
241 template<typename MODEL, typename OBS>
243  bool lcheck = (dxjb_ == 0) == (other.dxjb_ == 0)
244  && (dxjo_.size() == other.dxjo_.size())
245  && (dxjc_.size() == other.dxjc_.size());
246  return lcheck;
247 }
248 // -----------------------------------------------------------------------------
249 } // namespace oops
250 
251 #endif // OOPS_ASSIMILATION_DUALVECTOR_H_
oops::DualVector::operator+=
DualVector & operator+=(const DualVector &)
Definition: DualVector.h:155
oops::DualVector::operator-=
DualVector & operator-=(const DualVector &)
Definition: DualVector.h:170
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::DualVector::clear
void clear()
Definition: DualVector.h:97
oops::DualVector::ijo_
std::vector< unsigned > ijo_
Definition: DualVector.h:71
oops::DualVector::dx
CtrlInc_ & dx()
Definition: DualVector.h:47
oops::DualVector::axpy
void axpy(const double, const DualVector &)
Definition: DualVector.h:212
oops::DualVector::dxjb_
std::unique_ptr< CtrlInc_ > dxjb_
Definition: DualVector.h:68
oops::DualVector
Container of dual space vectors for all terms of the cost function.
Definition: DualVector.h:34
oops::DualVector::dx
void dx(CtrlInc_ *dx)
Definition: DualVector.h:45
oops::DualVector::dxjc_
std::vector< std::shared_ptr< Increment_ > > dxjc_
Definition: DualVector.h:70
oops::ControlIncrement
Definition: ControlIncrement.h:46
oops::DualVector::append
void append(std::unique_ptr< GeneralizedDepartures > &&)
Definition: DualVector.h:107
Departures.h
oops::DualVector::size_
unsigned size_
Definition: DualVector.h:73
oops::DualVector::operator=
DualVector & operator=(const DualVector &)
Definition: DualVector.h:140
oops::DualVector::zero
void zero()
Definition: DualVector.h:199
oops::Departures
Difference between two observation vectors.
Definition: oops/base/Departures.h:44
oops::DualVector::~DualVector
~DualVector()
Definition: DualVector.h:42
oops::DualVector::dxjo_
std::vector< std::shared_ptr< Departures_ > > dxjo_
Definition: DualVector.h:69
oops::DualVector::operator*=
DualVector & operator*=(const double)
Definition: DualVector.h:185
oops::DualVector::Departures_
Departures< OBS > Departures_
Definition: DualVector.h:37
oops::DualVector::ijc_
std::vector< unsigned > ijc_
Definition: DualVector.h:72
oops::DualVector::getv
std::shared_ptr< const GeneralizedDepartures > getv(const unsigned) const
Definition: DualVector.h:126
oops::DualVector::compatible
bool compatible(const DualVector &other) const
Definition: DualVector.h:242
oops::DualVector::DualVector
DualVector()
Definition: DualVector.h:40
GeneralizedDepartures.h
oops::DualVector::CtrlInc_
ControlIncrement< MODEL, OBS > CtrlInc_
Definition: DualVector.h:36
ControlIncrement.h
oops::DualVector::dx
const CtrlInc_ & dx() const
Definition: DualVector.h:46
oops::Increment
Increment Class: Difference between two states.
Definition: CostJbState.h:27
oops::DualVector::dot_product_with
double dot_product_with(const DualVector &) const
Definition: DualVector.h:226
oops::DualVector::Increment_
Increment< MODEL > Increment_
Definition: DualVector.h:35
qg_constants_mod::pi
real(kind_real), parameter, public pi
Pi.
Definition: qg_constants_mod.F90:22
Increment.h