11 #ifndef OOPS_ASSIMILATION_COSTFUNCTION_H_
12 #define OOPS_ASSIMILATION_COSTFUNCTION_H_
18 #include <boost/noncopyable.hpp>
19 #include <boost/ptr_container/ptr_vector.hpp>
21 #include "eckit/config/LocalConfiguration.h"
22 #include "eckit/mpi/Comm.h"
38 #include "oops/util/DateTime.h"
39 #include "oops/util/dot_product.h"
40 #include "oops/util/Duration.h"
41 #include "oops/util/Logger.h"
53 template<
typename MODEL,
typename OBS>
class CostFunction :
private boost::noncopyable {
68 const eckit::Configuration & config = eckit::LocalConfiguration(),
75 const bool idModel =
false)
const = 0;
78 const bool idModel =
false)
const = 0;
117 std::unique_ptr<const CtrlVar_>
xb_;
118 std::unique_ptr<JbTotal_>
jb_;
128 template <
typename MODEL,
typename OBS>
138 const eckit::mpi::Comm &) = 0;
139 static std::map < std::string, CostFactory<MODEL, OBS> * > &
getMakers() {
140 static std::map < std::string, CostFactory<MODEL, OBS> * > makers_;
145 template<
class MODEL,
class OBS,
class FCT>
149 const eckit::mpi::Comm & comm)
override
150 {
return new FCT(config, comm);}
160 template <
typename MODEL,
typename OBS>
162 if (getMakers().find(name) != getMakers().end()) {
163 throw std::runtime_error(name +
" already registered in cost function factory.");
165 getMakers()[name] =
this;
170 template <
typename MODEL,
typename OBS>
172 const eckit::mpi::Comm & comm) {
173 std::string
id = config.getString(
"cost type");
174 Log::trace() <<
"Variational Assimilation Type=" <<
id << std::endl;
175 typename std::map<std::string, CostFactory<MODEL, OBS>*>::iterator j = getMakers().find(
id);
176 if (j == getMakers().end()) {
177 throw std::runtime_error(
id +
" does not exist in cost function factory.");
179 Log::trace() <<
"CostFactory::create found cost function type" << std::endl;
180 return (*j).second->make(config, comm);
187 template<
typename MODEL,
typename OBS>
194 template<
typename MODEL,
typename OBS>
196 Log::trace() <<
"CostFunction::setupTerms start" << std::endl;
200 jterms_.push_back(jo);
201 Log::trace() <<
"CostFunction::setupTerms Jo added" << std::endl;
205 jb_.reset(
new JbTotal_(*xb_, this->newJb(config, this->geometry(), *xb_),
206 config, this->geometry(), jo->
obspaces()));
207 Log::trace() <<
"CostFunction::setupTerms Jb added" << std::endl;
210 std::vector<eckit::LocalConfiguration> jcs;
211 config.get(
"constraints", jcs);
212 for (
size_t jj = 0; jj < jcs.size(); ++jj) {
214 jterms_.push_back(jc);
216 Log::trace() <<
"CostFunction::setupTerms done" << std::endl;
223 template<
typename MODEL,
typename OBS>
226 Log::trace() <<
"CostFunction::setupTerms start" << std::endl;
230 jterms_.push_back(jo);
231 Log::trace() <<
"CostFunction::setupTerms Jo added" << std::endl;
235 jb_.reset(
new JbTotal_(*xb_, this->newJb(config, this->geometry(), *xb_),
236 config, this->geometry(), jo->
obspaces()));
237 Log::trace() <<
"CostFunction::setupTerms Jb added" << std::endl;
240 std::vector<eckit::LocalConfiguration> jcs;
241 config.get(
"constraints", jcs);
242 for (
size_t jj = 0; jj < jcs.size(); ++jj) {
244 jterms_.push_back(jc);
246 Log::trace() <<
"CostFunction::setupTerms done" << std::endl;
251 template<
typename MODEL,
typename OBS>
253 const eckit::Configuration & config,
255 Log::trace() <<
"CostFunction::evaluate start" << std::endl;
258 jb_->initialize(fguess);
259 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
265 this->runNL(mfguess, pp);
269 costJb_ = jb_->finalize(mfguess);
272 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
273 costJoJc_ += jterms_[jj].finalize();
276 Log::test() <<
"CostFunction: Nonlinear J = " << zzz << std::endl;
277 Log::trace() <<
"CostFunction::evaluate done" << std::endl;
283 template<
typename MODEL,
typename OBS>
285 const eckit::Configuration & innerConf,
287 Log::trace() <<
"CostFunction::linearize start" << std::endl;
289 const eckit::LocalConfiguration resConf(innerConf,
"geometry");
290 const Geometry_ lowres(resConf, this->geometry().getComm(), this->geometry().timeComm());
294 JqTermTLAD_ * jq = jb_->initializeTraj(fguess, lowres, innerConf);
296 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
297 pptraj.
enrollProcessor(jterms_[jj].initializeTraj(fguess, lowres, innerConf));
301 this->doLinearize(lowres, innerConf, *xb_, fguess, post, pptraj);
304 double zzz = this->evaluate(fguess, innerConf, post);
307 jb_->finalizeTraj(jq);
308 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
309 jterms_[jj].finalizeTraj();
312 Log::trace() <<
"CostFunction::linearize done" << std::endl;
318 template<
typename MODEL,
typename OBS>
320 Log::trace() <<
"CostFunction::computeGradientFG start" << std::endl;
325 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
326 std::shared_ptr<const GeneralizedDepartures> tmp(jterms_[jj].newGradientFG());
330 this->runADJ(grad, costad, pp);
331 Log::info() <<
"CostFunction::computeGradientFG: gradient:" << grad << std::endl;
332 Log::trace() <<
"CostFunction::computeGradientFG done" << std::endl;
337 template<
typename MODEL,
typename OBS>
340 Log::trace() <<
"CostFunction::addIncrement start" << std::endl;
341 Log::info() <<
"CostFunction::addIncrement: First guess:" << xx << std::endl;
342 Log::info() <<
"CostFunction::addIncrement: Increment:" << dx << std::endl;
346 this->addIncr(xx, dx, post);
348 Log::info() <<
"CostFunction::addIncrement: Analysis: " << xx << std::endl;
349 Log::test() <<
"CostFunction::addIncrement: Analysis: " << xx << std::endl;
350 Log::trace() <<
"CostFunction::addIncrement done" << std::endl;
355 template<
typename MODEL,
typename OBS>
357 Log::trace() <<
"CostFunction::resetLinearization start" << std::endl;
358 for (
unsigned jj = 0; jj < jterms_.size(); ++jj) {
359 jterms_[jj].resetLinearization();
361 Log::trace() <<
"CostFunction::resetLinearization done" << std::endl;
368 #endif // OOPS_ASSIMILATION_COSTFUNCTION_H_