FV3 Bundle
CostFctWeak.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_COSTFCTWEAK_H_
12 #define OOPS_ASSIMILATION_COSTFCTWEAK_H_
13 
14 #include <map>
15 
16 #include "eckit/config/LocalConfiguration.h"
25 #include "oops/base/StateInfo.h"
26 #include "oops/base/Variables.h"
29 #include "oops/interface/Model.h"
30 #include "oops/interface/State.h"
31 #include "oops/util/DateTime.h"
32 #include "oops/util/Duration.h"
33 #include "oops/util/Logger.h"
34 
35 namespace oops {
36 
37 /// Weak Constraint 4D-Var Cost Function
38 /*!
39  * General weak constraint constraint 4D-Var cost function.
40  */
41 
42 // -----------------------------------------------------------------------------
43 
44 template<typename MODEL> class CostFctWeak : public CostFunction<MODEL> {
53 
54  public:
55  CostFctWeak(const eckit::Configuration &, const Geometry_ &, const Model_ &);
57 
60  const bool idModel = false) const override;
63  const bool idModel = false) const override;
64  void zeroAD(CtrlInc_ &) const override;
65 
66  void runTLM(CtrlInc_ &, const bool idModel = false) const;
67  void runADJ(CtrlInc_ &, const bool idModel = false) const;
68  void runNL(CtrlVar_ &, PostProcessor<State_> &) const override;
69 
70  private:
71  void addIncr(CtrlVar_ &, const CtrlInc_ &, PostProcessor<Increment_> &) const override;
72 
73  CostJbJq<MODEL> * newJb(const eckit::Configuration &, const Geometry_ &,
74  const CtrlVar_ &) const override;
75  CostJo<MODEL> * newJo(const eckit::Configuration &) const override;
76  CostTermBase<MODEL> * newJc(const eckit::Configuration &, const Geometry_ &) const override;
77  void doLinearize(const Geometry_ &, const eckit::Configuration &,
78  const CtrlVar_ &, const CtrlVar_ &) override;
79 
80  util::Duration windowLength_;
81  util::DateTime windowBegin_;
82  util::DateTime windowEnd_;
83  util::Duration windowSub_;
84  unsigned int nsubwin_;
85  bool tlforcing_;
87  boost::scoped_ptr<ChangeVar_> an2model_;
88 };
89 
90 // =============================================================================
91 
92 template<typename MODEL>
93 CostFctWeak<MODEL>::CostFctWeak(const eckit::Configuration & config,
94  const Geometry_ & resol, const Model_ & model)
95  : CostFunction<MODEL>::CostFunction(config, resol, model),
96  tlforcing_(false), ctlvars_(config), an2model_()
97 {
98  windowLength_ = util::Duration(config.getString("window_length"));
99  windowBegin_ = util::DateTime(config.getString("window_begin"));
101  windowSub_ = util::Duration(config.getString("window_sub"));
102 
103  nsubwin_ = windowLength_.toSeconds() / windowSub_.toSeconds();
104  ASSERT(windowLength_.toSeconds() == windowSub_.toSeconds()*nsubwin_);
105 
106  if (config.has("tlforcing")) {
107  if (config.getString("tlforcing") == "on") tlforcing_ = true;
108  }
109 
110  this->setupTerms(config);
111  Log::trace() << "CostFctWeak constructed" << std::endl;
112 }
113 
114 // -----------------------------------------------------------------------------
115 
116 template <typename MODEL>
117 CostJbJq<MODEL> * CostFctWeak<MODEL>::newJb(const eckit::Configuration & jbConf,
118  const Geometry_ & resol,
119  const CtrlVar_ & xb) const {
120  return new CostJbJq<MODEL>(jbConf, resol, ctlvars_, windowSub_, xb.state(), tlforcing_);
121 }
122 
123 // -----------------------------------------------------------------------------
124 
125 template <typename MODEL>
126 CostJo<MODEL> * CostFctWeak<MODEL>::newJo(const eckit::Configuration & joConf) const {
127  return new CostJo<MODEL>(joConf, windowBegin_, windowEnd_, util::Duration(0), true);
128 }
129 
130 // -----------------------------------------------------------------------------
131 
132 template <typename MODEL>
133 CostTermBase<MODEL> * CostFctWeak<MODEL>::newJc(const eckit::Configuration & jcConf,
134  const Geometry_ & resol) const {
135  const eckit::LocalConfiguration jcdfi(jcConf, "jcdfi");
136  const util::DateTime vt(windowBegin_ + windowLength_/2);
137  return new CostJcDFI<MODEL>(jcdfi, resol, vt, windowLength_);
138 }
139 
140 // -----------------------------------------------------------------------------
141 
142 template <typename MODEL>
144  PostProcessor<State_> & post) const {
145  State_ xm(xx.state()[0].geometry(), CostFct_::getModel().variables(), windowBegin_);
146  for (unsigned int jsub = 0; jsub < nsubwin_; ++jsub) {
147  util::DateTime bgn(windowBegin_ + jsub*windowSub_);
148  util::DateTime end(bgn + windowSub_);
149 
150  ASSERT(xx.state()[jsub].validTime() == bgn);
151  xm = xx.state()[jsub];
152  CostFct_::getModel().forecast(xm, xx.modVar(), windowSub_, post);
153  xx.state()[jsub] = xm;
154  ASSERT(xx.state()[jsub].validTime() == end);
155  }
156 }
157 
158 // -----------------------------------------------------------------------------
159 
160 template<typename MODEL>
162  const eckit::Configuration & innerConf,
163  const CtrlVar_ & bg, const CtrlVar_ & fg) {
164  Log::trace() << "CostFctWeak::doLinearize start" << std::endl;
165  eckit::LocalConfiguration conf(innerConf, "linearmodel");
166  an2model_.reset(LinearVariableChangeFactory<MODEL>::create(bg.state()[0], fg.state()[0],
167  resol, conf));
168  an2model_->setInputVariables(ctlvars_);
169  an2model_->setOutputVariables(CostFct_::getTLM().variables());
170  Log::trace() << "CostFctWeak::doLinearize done" << std::endl;
171 }
172 
173 // -----------------------------------------------------------------------------
174 
175 template <typename MODEL>
179  const bool idModel) const {
180  Increment_ dxmodel(dx.state()[0].geometry(), CostFct_::getTLM().variables(), windowBegin_);
181 
182  for (int jsub = dx.state().first(); jsub <= dx.state().last(); ++jsub) {
183  util::DateTime bgn(windowBegin_ + jsub*windowSub_);
184  util::DateTime end(bgn + windowSub_);
185 
186  ASSERT(dx.state()[jsub].validTime() == bgn);
187  if (tlforcing_ && jsub > 0) dx.state()[jsub] += dx.state()[jsub-1];
188  an2model_->multiply(dx.state()[jsub], dxmodel);
189  CostFct_::getTLM(jsub).forecastTL(dxmodel, dx.modVar(), windowSub_, post, cost, idModel);
190  an2model_->multiplyInverse(dxmodel, dx.state()[jsub]);
191  ASSERT(dx.state()[jsub].validTime() == end);
192  }
193 }
194 
195 // -----------------------------------------------------------------------------
196 
197 template <typename MODEL>
198 void CostFctWeak<MODEL>::runTLM(CtrlInc_ & dx, const bool idModel) const {
201  ASSERT(!tlforcing_);
202  Increment_ dxmodel(dx.state()[0].geometry(), CostFct_::getTLM().variables(), windowBegin_);
203 
204  for (int jsub = dx.state().first(); jsub <= dx.state().last(); ++jsub) {
205  util::DateTime bgn(windowBegin_ + jsub*windowSub_);
206  util::DateTime end(bgn + windowSub_);
207  ASSERT(dx.state()[jsub].validTime() == bgn);
208 
209  if (idModel) {
210  dx.state()[jsub].updateTime(windowSub_);
211  } else {
212  an2model_->multiply(dx.state()[jsub], dxmodel);
213  CostFct_::getTLM(jsub).forecastTL(dxmodel, dx.modVar(), windowSub_, post, cost);
214  an2model_->multiplyInverse(dxmodel, dx.state()[jsub]);
215  }
216 
217  ASSERT(dx.state()[jsub].validTime() == end);
218  }
219 
220  dx.state().shift_forward();
221 }
222 
223 // -----------------------------------------------------------------------------
224 
225 template <typename MODEL>
227  for (int jsub = dx.state().first(); jsub <= dx.state().last(); ++jsub) {
228  util::DateTime end(windowBegin_ + (jsub+1)*windowSub_);
229  dx.state()[jsub].zero(end);
230  }
231  dx.modVar().zero();
232  dx.obsVar().zero();
233 }
234 
235 // -----------------------------------------------------------------------------
236 
237 template <typename MODEL>
241  const bool idModel) const {
242  Increment_ dxmodel(dx.state()[0].geometry(), CostFct_::getTLM().variables(), windowEnd_);
243  for (int jsub = dx.state().last(); jsub >= dx.state().first(); --jsub) {
244  util::DateTime bgn(windowBegin_ + jsub*windowSub_);
245  util::DateTime end(bgn + windowSub_);
246 
247  ASSERT(dx.state()[jsub].validTime() == end);
248  an2model_->multiplyInverseAD(dx.state()[jsub], dxmodel);
249  CostFct_::getTLM(jsub).forecastAD(dxmodel, dx.modVar(), windowSub_, post, cost, idModel);
250  an2model_->multiplyAD(dxmodel, dx.state()[jsub]);
251  if (tlforcing_ && jsub > 0) dx.state()[jsub-1] += dx.state()[jsub];
252  ASSERT(dx.state()[jsub].validTime() == bgn);
253  }
254 }
255 
256 // -----------------------------------------------------------------------------
257 
258 template <typename MODEL>
259 void CostFctWeak<MODEL>::runADJ(CtrlInc_ & dx, const bool idModel) const {
262  ASSERT(!tlforcing_);
263  Increment_ dxmodel(dx.state()[0].geometry(), CostFct_::getTLM().variables(), windowEnd_);
264 
265  dx.state().shift_backward();
266 
267  for (int jsub = dx.state().last(); jsub >= dx.state().first(); --jsub) {
268  util::DateTime bgn(windowBegin_ + jsub*windowSub_);
269  util::DateTime end(bgn + windowSub_);
270  ASSERT(dx.state()[jsub].validTime() == end);
271 
272  if (idModel) {
273  dx.state()[jsub].updateTime(-windowSub_);
274  } else {
275  an2model_->multiplyInverseAD(dx.state()[jsub], dxmodel);
276  CostFct_::getTLM(jsub).forecastAD(dxmodel, dx.modVar(), windowSub_, post, cost);
277  an2model_->multiplyAD(dxmodel, dx.state()[jsub]);
278  }
279 
280  ASSERT(dx.state()[jsub].validTime() == bgn);
281  }
282 }
283 
284 // -----------------------------------------------------------------------------
285 
286 template<typename MODEL>
288  PostProcessor<Increment_> & post) const {
289  if (tlforcing_) {
290  Increment_ xi(dx.state()[0]);
291  Increment_ dxmodel(dx.state()[0].geometry(), CostFct_::getTLM().variables(), windowBegin_);
292  for (unsigned int jsub = 0; jsub < nsubwin_; ++jsub) {
293  if (jsub > 0) xi += dx.state()[jsub];
294  xx.state()[jsub] += xi;
295  if (jsub < nsubwin_-1) {
296  an2model_->multiply(xi, dxmodel);
297  CostFct_::getTLM(jsub).forecastTL(dxmodel, dx.modVar(), windowSub_, post);
298  an2model_->multiplyInverse(dxmodel, xi);
299  }
300  }
301  } else {
302  for (unsigned int jsub = 0; jsub < nsubwin_; ++jsub) {
303  xx.state()[jsub] += dx.state()[jsub];
304  }
305  }
306 }
307 
308 // -----------------------------------------------------------------------------
309 
310 } // namespace oops
311 
312 #endif // OOPS_ASSIMILATION_COSTFCTWEAK_H_
CostJo< MODEL > * newJo(const eckit::Configuration &) const override
Definition: CostFctWeak.h:126
State4D_ & state()
Get state control variable.
util::Duration windowSub_
Definition: CostFctWeak.h:83
void zeroAD(CtrlInc_ &) const override
Definition: CostFctWeak.h:226
boost::scoped_ptr< ChangeVar_ > an2model_
Definition: CostFctWeak.h:87
util::Duration windowLength_
Definition: CostFctWeak.h:80
int first() const
Definition: Increment4D.h:78
ObsAuxIncr_ & obsVar()
Get augmented observation control variable.
ModelAuxIncr_ & modVar()
Get augmented model control variable.
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT end
void addIncr(CtrlVar_ &, const CtrlInc_ &, PostProcessor< Increment_ > &) const override
Definition: CostFctWeak.h:287
Definition: conf.py:1
Jb + Jq Cost Function.
Definition: CostJbJq.h:45
unsigned int nsubwin_
Definition: CostFctWeak.h:84
State< MODEL > State_
Definition: CostFctWeak.h:50
CostFunction< MODEL > CostFct_
Definition: CostFctWeak.h:48
Cost Function.
Definition: CostFunction.h:56
Encapsulates the model state.
integer(long), parameter false
Jc DFI Cost Function.
Definition: CostJcDFI.h:45
Control variable.
LinearVariableChangeBase< MODEL > ChangeVar_
Definition: CostFctWeak.h:52
Geometry< MODEL > Geometry_
Definition: CostFctWeak.h:49
The namespace for the main oops code.
ModelAux_ & modVar()
Get augmented model control variable.
void runTLM(CtrlInc_ &, PostProcessorTLAD< MODEL > &, PostProcessor< Increment_ >, const bool idModel=false) const override
Definition: CostFctWeak.h:176
CostFctWeak(const eckit::Configuration &, const Geometry_ &, const Model_ &)
Definition: CostFctWeak.h:93
real, dimension(:,:,:), allocatable vt
Weak Constraint 4D-Var Cost Function.
Definition: CostFctWeak.h:44
Increment4D_ & state()
Get state control variable.
Model< MODEL > Model_
Definition: CostFctWeak.h:51
void runADJ(CtrlInc_ &, PostProcessorTLAD< MODEL > &, PostProcessor< Increment_ >, const bool idModel=false) const override
Definition: CostFctWeak.h:238
void doLinearize(const Geometry_ &, const eckit::Configuration &, const CtrlVar_ &, const CtrlVar_ &) override
Definition: CostFctWeak.h:161
const Variables ctlvars_
Definition: CostFctWeak.h:86
real(fp), parameter xb
Definition: ufo_aod_mod.F90:41
void runNL(CtrlVar_ &, PostProcessor< State_ > &) const override
Definition: CostFctWeak.h:143
LinearVariableChangeFactory Factory.
Control model post processing.
Base class for generic variable transform.
Encapsulates the nonlinear forecast model.
int last() const
Definition: Increment4D.h:79
CostJbJq< MODEL > * newJb(const eckit::Configuration &, const Geometry_ &, const CtrlVar_ &) const override
Definition: CostFctWeak.h:117
Increment Class: Difference between two states.
Jo Cost Function.
Definition: CostJo.h:54
Base Class for Cost Function Terms.
Definition: CostTermBase.h:37
Geometry_ geometry() const
Get geometry.
Definition: Increment4D.h:73
Increment< MODEL > Increment_
Definition: CostFctWeak.h:45
ControlVariable< MODEL > CtrlVar_
Definition: CostFctWeak.h:47
Control model post processing.
Definition: PostProcessor.h:31
ControlIncrement< MODEL > CtrlInc_
Definition: CostFctWeak.h:46
void setupTerms(const eckit::Configuration &)
Definition: CostFunction.h:212
util::DateTime windowBegin_
Definition: CostFctWeak.h:81
void shift_forward()
To be removed.
Definition: Increment4D.h:250
CostTermBase< MODEL > * newJc(const eckit::Configuration &, const Geometry_ &) const override
Definition: CostFctWeak.h:133
util::DateTime windowEnd_
Definition: CostFctWeak.h:82