Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ModelEvaluator_Epetra.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Panzer: A partial differential equation assembly
4 // engine for strongly coupled complex multiphysics systems
5 //
6 // Copyright 2011 NTESS and the Panzer contributors.
7 // SPDX-License-Identifier: BSD-3-Clause
8 // *****************************************************************************
9 // @HEADER
10 
11 #include "PanzerDiscFE_config.hpp"
18 #include "Panzer_GlobalData.hpp"
22 
23 #include "Epetra_CrsMatrix.h"
24 #include "Epetra_MpiComm.h"
25 #include "Epetra_LocalMap.h"
26 
27 #include "Teuchos_ScalarTraits.hpp"
29 #include "Teuchos_TimeMonitor.hpp"
30 
31 #include "Thyra_EpetraOperatorWrapper.hpp"
32 #include "Thyra_EpetraThyraWrappers.hpp"
33 #include "Thyra_VectorStdOps.hpp"
34 #include "Thyra_ProductVectorBase.hpp"
35 #include "Thyra_SpmdVectorBase.hpp"
36 #include "Thyra_DefaultProductVector.hpp"
37 #include "Thyra_ProductVectorSpaceBase.hpp"
38 
39 #include <sstream>
40 
41 namespace {
42 
44 class EpetraLOF_EOpFactory : public Teuchos::AbstractFactory<Epetra_Operator> {
46 public:
47  EpetraLOF_EOpFactory(const panzer::BlockedEpetraLinearObjFactory<panzer::Traits,int> & lof)
48  : W_graph_(lof.getGraph(0,0)) {}
49 
51  { return Teuchos::rcp(new Epetra_CrsMatrix(::Copy,*W_graph_)); }
52 };
53 
54 }
55 
56 
61  const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
62  const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
63  const Teuchos::RCP<panzer::GlobalData>& global_data,
64  bool build_transient_support)
65  : t_init_(0.0)
66  , fmb_(fmb)
67  , responseLibrary_(rLibrary)
68  , p_names_(p_names)
69  , global_data_(global_data)
70  , build_transient_support_(build_transient_support)
71  , lof_(lof)
72  , oneTimeDirichletBeta_on_(false)
73  , oneTimeDirichletBeta_(0.0)
74 {
75  using Teuchos::rcp;
76  using Teuchos::rcp_dynamic_cast;
77 
79  ae_tm_.buildObjects(builder);
80 
81  // Setup parameters
82  this->initializeParameterVector(p_names_,p_values,global_data->pl);
83 
84  // try to determine the runtime linear object factory
85 
87  Teuchos::rcp_dynamic_cast<panzer::BlockedEpetraLinearObjFactory<panzer::Traits,int> >(lof);
88 
89  // initialize maps, x_dot_init, x0, p_init, g_map, and linear operator factory
90  if(ep_lof!=Teuchos::null)
91  initializeEpetraObjs(*ep_lof);
92  else {
93  TEUCHOS_ASSERT(false); // bad news!
94  }
95 }
96 
101  const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
102  const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
103  const Teuchos::RCP<panzer::GlobalData>& global_data,
104  bool build_transient_support)
105  : t_init_(0.0)
106  , fmb_(fmb)
107  , responseLibrary_(rLibrary)
108  , p_names_(p_names)
109  , global_data_(global_data)
110  , build_transient_support_(build_transient_support)
111  , lof_(lof)
112  , oneTimeDirichletBeta_on_(false)
113  , oneTimeDirichletBeta_(0.0)
114 {
115  using Teuchos::rcp;
116  using Teuchos::rcp_dynamic_cast;
117 
119  ae_tm_.buildObjects(builder);
120 
121  // Setup parameters
122  this->initializeParameterVector(p_names_,p_values,global_data->pl);
123 
124  // initailize maps, x_dot_init, x0, p_init, g_map, and linear operator factory
125  initializeEpetraObjs(*lof);
126 }
127 
129 {
130  using Teuchos::RCP;
131  using Teuchos::rcp;
132  using Teuchos::rcp_dynamic_cast;
133 
134  TEUCHOS_TEST_FOR_EXCEPTION(responseLibrary_==Teuchos::null,std::logic_error,
135  "panzer::ModelEvaluator_Epetra::initializeEpetraObjs: The response library "
136  "was not correctly initialized before calling initializeEpetraObjs.");
137 
138  map_x_ = lof.getMap(0);
139  x0_ = rcp(new Epetra_Vector(*map_x_));
140  x_dot_init_ = rcp(new Epetra_Vector(*map_x_));
141  x_dot_init_->PutScalar(0.0);
142 
143  // setup parameters (initialize vector from parameter library)
144  for (int i=0; i < parameter_vector_.size(); i++) {
145  RCP<Epetra_Map> local_map = rcp(new Epetra_LocalMap(static_cast<int>(parameter_vector_[i].size()), 0, map_x_->Comm())) ;
146  p_map_.push_back(local_map);
147 
148  RCP<Epetra_Vector> ep_vec = rcp(new Epetra_Vector(*local_map));
149  ep_vec->PutScalar(0.0);
150 
151  for (unsigned int j=0; j < parameter_vector_[i].size(); j++)
152  (*ep_vec)[j] = parameter_vector_[i][j].baseValue;
153 
154  p_init_.push_back(ep_vec);
155  }
156 
157  // Initialize the epetra operator factory
158  epetraOperatorFactory_ = Teuchos::rcp(new EpetraLOF_EOpFactory(lof));
159 }
160 
163  const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
164  const Teuchos::RCP<panzer::ParamLib>& parameter_library)
165 {
166  parameter_vector_.resize(p_names.size());
167  is_distributed_parameter_.resize(p_names.size(),false);
168  for (std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >::size_type p = 0;
169  p < p_names.size(); ++p) {
170 
171  // register all the scalar parameters, setting initial
172  for(int i=0;i<p_names[p]->size();i++)
173  registerScalarParameter((*p_names[p])[i],*parameter_library,(*p_values[p])[i]);
174 
175  parameter_library->fillVector<panzer::Traits::Residual>(*(p_names[p]), parameter_vector_[p]);
176 
177  for(int i=0;i<p_names[p]->size();i++) {
178  parameter_vector_[p][i].baseValue = (*p_values[p])[i];
179  parameter_vector_[p][i].family->setRealValueForAllTypes((*p_values[p])[i]);
180  }
181  }
182 }
183 
184 // Post-Construction methods to add parameters and responses
185 
187 addDistributedParameter(const std::string name,
188  const Teuchos::RCP<Epetra_Map>& global_map,
189  const Teuchos::RCP<Epetra_Import>& importer,
190  const Teuchos::RCP<Epetra_Vector>& ghosted_vector)
191 {
192  // Will push_back a new parameter entry
193  int index = static_cast<int>(p_map_.size());
194 
195  p_map_.push_back(global_map);
196  Teuchos::RCP<Epetra_Vector> ep_vec = Teuchos::rcp(new Epetra_Vector(*global_map));
197  ep_vec->PutScalar(0.0);
198  p_init_.push_back(ep_vec);
199 
202  tmp_names->push_back(name);
203  p_names_.push_back(tmp_names);
204 
205  is_distributed_parameter_.push_back(true);
206 
207  // NOTE: we do not add this parameter to the sacado parameter
208  // library in the global data object. That library is for scalars.
209  // We will need to do something different if we need sensitivities
210  // wrt distributed parameters.
211 
212  distributed_parameter_container_.push_back(std::make_tuple(name,index,importer,ghosted_vector));
213 
214  return index;
215 }
216 
217 // Overridden from EpetraExt::ModelEvaluator
218 
221 {
222  return map_x_;
223 }
224 
227 {
228  return map_x_;
229 }
230 
233 {
234  return x0_;
235 }
236 
239 {
240  return x_dot_init_;
241 }
242 
243 double
245 {
246  return t_init_;
247 }
248 
251 {
252  return epetraOperatorFactory_->create();
253 }
254 
257 {
258  return p_map_[l];
259 }
260 
263 {
264  return p_names_[l];
265 }
266 
269 {
270  return p_init_[l];
271 }
272 
275 {
276  return g_map_[l];
277 }
278 
281 {
282  InArgsSetup inArgs;
283  inArgs.setModelEvalDescription(this->description());
284  inArgs.setSupports(IN_ARG_x,true);
285  if (build_transient_support_) {
286  inArgs.setSupports(IN_ARG_x_dot,true);
287  inArgs.setSupports(IN_ARG_t,true);
288  inArgs.setSupports(IN_ARG_alpha,true);
289  inArgs.setSupports(IN_ARG_beta,true);
290  }
291  inArgs.set_Np(p_init_.size());
292 
293  return inArgs;
294 }
295 
298 {
299  OutArgsSetup outArgs;
300  outArgs.setModelEvalDescription(this->description());
301  outArgs.set_Np_Ng(p_init_.size(), g_map_.size());
302  outArgs.setSupports(OUT_ARG_f,true);
303  outArgs.setSupports(OUT_ARG_W,true);
304  outArgs.set_W_properties(
306  DERIV_LINEARITY_NONCONST
307  ,DERIV_RANK_FULL
308  ,true // supportsAdjoint
309  )
310  );
311 
312  // add in df/dp (if appropriate)
313  for(std::size_t i=0;i<p_init_.size();i++) {
314  if(!is_distributed_parameter_[i])
315  outArgs.setSupports(OUT_ARG_DfDp,i,EpetraExt::ModelEvaluator::DerivativeSupport(DERIV_MV_BY_COL));
316  }
317 
318  // add in dg/dx (if appropriate)
319  for(std::size_t i=0;i<g_names_.size();i++) {
320  typedef panzer::Traits::Jacobian RespEvalT;
321 
322  // check dg/dx and add it in if appropriate
323  Teuchos::RCP<panzer::ResponseBase> respJacBase = responseLibrary_->getResponse<RespEvalT>(g_names_[i]);
324  if(respJacBase!=Teuchos::null) {
325  // cast is guranteed to succeed because of check in addResponse
327 
328  // class must supoprt a derivative
329  if(resp->supportsDerivative())
330  outArgs.setSupports(OUT_ARG_DgDx,i,DerivativeSupport(DERIV_TRANS_MV_BY_ROW));
331  //outArgs.setSupports(OUT_ARG_DgDx,i,DerivativeSupport(DERIV_LINEAR_OP));
332  }
333  }
334 
335  return outArgs;
336 }
337 
340  const Teuchos::RCP<Thyra::VectorBase<double> > & f) const
341 {
342  using Teuchos::RCP;
343  using Teuchos::ArrayRCP;
344  using Teuchos::Array;
345  //using Teuchos::tuple;
346  using Teuchos::rcp_dynamic_cast;
347 
348  // if neccessary build a ghosted container
349  if(Teuchos::is_null(ghostedContainer_)) {
350  ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
351  lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
352  panzer::LinearObjContainer::F,*ghostedContainer_);
353  }
354 
356  ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
357  ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
358  ae_inargs.alpha = 0.0;
359  ae_inargs.beta = 1.0;
360  ae_inargs.evaluate_transient_terms = false;
361 
362  // this is the tempory target
363  lof_->initializeContainer(panzer::LinearObjContainer::F,*ae_inargs.container_);
364 
365  // here we are building a container, this operation is fast, simply allocating a struct
366  const RCP<panzer::ThyraObjContainer<double> > thGlobalContainer =
367  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(ae_inargs.container_,true);
368 
369  TEUCHOS_ASSERT(!Teuchos::is_null(thGlobalContainer));
370 
371  // Ghosted container objects are zeroed out below only if needed for
372  // a particular calculation. This makes it more efficient than
373  // zeroing out all objects in the container here.
374  const RCP<panzer::ThyraObjContainer<double> > thGhostedContainer =
375  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(ae_inargs.ghostedContainer_,true);
376  TEUCHOS_ASSERT(!Teuchos::is_null(thGhostedContainer));
377  Thyra::assign(thGhostedContainer->get_f_th().ptr(),0.0);
378 
379  // Set the solution vector (currently all targets require solution).
380  // In the future we may move these into the individual cases below.
381  // A very subtle (and fragile) point: A non-null pointer in global
382  // container triggers export operations during fill. Also, the
383  // introduction of the container is forcing us to cast away const on
384  // arguments that should be const. Another reason to redesign
385  // LinearObjContainer layers.
386  thGlobalContainer->set_x_th(x);
387 
388  // evaluate dirichlet boundary conditions
389  RCP<panzer::LinearObjContainer> counter = ae_tm_.getAsObject<panzer::Traits::Residual>()->evaluateOnlyDirichletBCs(ae_inargs);
390 
391  // allocate the result container
392  RCP<panzer::LinearObjContainer> result = lof_->buildLinearObjContainer(); // we use a new global container
393 
394  // stuff the evaluate boundary conditions into the f spot of the counter ... the x is already filled
395  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(counter)->set_f_th(thGlobalContainer->get_f_th());
396 
397  // stuff the vector that needs applied dirichlet conditions in the the f spot of the result LOC
398  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(result)->set_f_th(f);
399 
400  // use the linear object factory to apply the result
401  lof_->applyDirichletBCs(*counter,*result);
402 }
403 
405  const OutArgs& outArgs ) const
406 {
407  using Teuchos::RCP;
408  using Teuchos::rcp_dynamic_cast;
409 
410  evalModel_basic(inArgs,outArgs);
411 }
412 
414  const OutArgs& outArgs ) const
415 {
416  using Teuchos::RCP;
417  using Teuchos::rcp_dynamic_cast;
418 
419  // Transient or steady-state evaluation is determined by the x_dot
420  // vector. If this RCP is null, then we are doing a steady-state
421  // fill.
422  bool has_x_dot = false;
424  has_x_dot = nonnull(inArgs.get_x_dot());
425 
426  // Make sure construction built in transient support
427  TEUCHOS_TEST_FOR_EXCEPTION(has_x_dot && !build_transient_support_, std::runtime_error,
428  "ModelEvaluator was not built with transient support enabled!");
429 
430  //
431  // Get the output arguments
432  //
433  const RCP<Epetra_Vector> f_out = outArgs.get_f();
434  const RCP<Epetra_Operator> W_out = outArgs.get_W();
435  bool requiredResponses = required_basic_g(outArgs);
436  bool requiredSensitivities = required_basic_dfdp(outArgs);
437 
438  // see if the user wants us to do anything
439  if(Teuchos::is_null(f_out) && Teuchos::is_null(W_out) &&
440  !requiredResponses && !requiredSensitivities) {
441  return;
442  }
443 
444  // the user requested work from this method
445  // keep on moving
446 
447  // if neccessary build a ghosted container
448  if(Teuchos::is_null(ghostedContainer_)) {
449  ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
450  lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
453  panzer::LinearObjContainer::Mat, *ghostedContainer_);
454  }
455 
456  //
457  // Get the input arguments
458  //
459  const RCP<const Epetra_Vector> x = inArgs.get_x();
461 
463  ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
464  ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
465  ae_inargs.alpha = 0.0;
466  ae_inargs.beta = 1.0;
467  ae_inargs.evaluate_transient_terms = false;
468  if (build_transient_support_) {
469  x_dot = inArgs.get_x_dot();
470  ae_inargs.alpha = inArgs.get_alpha();
471  ae_inargs.beta = inArgs.get_beta();
472  ae_inargs.time = inArgs.get_t();
473  ae_inargs.evaluate_transient_terms = true;
474  }
475 
476  // handle application of the one time dirichlet beta in the
477  // assembly engine. Note that this has to be set explicitly
478  // each time because this badly breaks encapsulation. Essentially
479  // we must work around the model evaluator abstraction!
480  ae_inargs.apply_dirichlet_beta = false;
481  if(oneTimeDirichletBeta_on_) {
482  ae_inargs.dirichlet_beta = oneTimeDirichletBeta_;
483  ae_inargs.apply_dirichlet_beta = true;
484 
485  oneTimeDirichletBeta_on_ = false;
486  }
487 
488  // Set locally replicated scalar input parameters
489  for (int i=0; i<inArgs.Np(); i++) {
491  if ( nonnull(p) && !is_distributed_parameter_[i]) {
492  for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
493  parameter_vector_[i][j].baseValue = (*p)[j];
494  }
495  }
496  }
497 
498  for (Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
499  for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
500  parameter_vector_[i][j].family->setRealValueForAllTypes(parameter_vector_[i][j].baseValue);
501  }
502  }
503 
504  // Perform global to ghost and set distributed parameters
505  for (std::vector<std::tuple<std::string,int,Teuchos::RCP<Epetra_Import>,Teuchos::RCP<Epetra_Vector> > >::const_iterator i =
506  distributed_parameter_container_.begin(); i != distributed_parameter_container_.end(); ++i) {
507  // do export if parameter exists in inArgs
508  Teuchos::RCP<const Epetra_Vector> global_vec = inArgs.get_p(std::get<1>(*i));
509  if (nonnull(global_vec)) {
510  // Only import if the importer is nonnull
511  Teuchos::RCP<Epetra_Import> importer = std::get<2>(*i);
512  if (nonnull(importer))
513  std::get<3>(*i)->Import(*global_vec,*importer,Insert);
514  }
515 
516  // set in ae_inargs_ string lookup container
518  Teuchos::rcp(new panzer::EpetraLinearObjContainer(p_map_[std::get<1>(*i)],p_map_[std::get<1>(*i)]));
519  container->set_x(std::get<3>(*i));
520  ae_inargs.addGlobalEvaluationData(std::get<0>(*i),container);
521  }
522 
523  // here we are building a container, this operation is fast, simply allocating a struct
524  const RCP<panzer::EpetraLinearObjContainer> epGlobalContainer =
525  Teuchos::rcp_dynamic_cast<panzer::EpetraLinearObjContainer>(ae_inargs.container_);
526 
527  TEUCHOS_ASSERT(!Teuchos::is_null(epGlobalContainer));
528 
529  // Ghosted container objects are zeroed out below only if needed for
530  // a particular calculation. This makes it more efficient thatn
531  // zeroing out all objects in the container here.
532  const RCP<panzer::EpetraLinearObjContainer> epGhostedContainer =
533  Teuchos::rcp_dynamic_cast<panzer::EpetraLinearObjContainer>(ae_inargs.ghostedContainer_);
534 
535  // Set the solution vector (currently all targets require solution).
536  // In the future we may move these into the individual cases below.
537  // A very subtle (and fragile) point: A non-null pointer in global
538  // container triggers export operations during fill. Also, the
539  // introduction of the container is forcing us to cast away const on
540  // arguments that should be const. Another reason to redesign
541  // LinearObjContainer layers.
542  epGlobalContainer->set_x(Teuchos::rcp_const_cast<Epetra_Vector>(x));
543  if (has_x_dot)
544  epGlobalContainer->set_dxdt(Teuchos::rcp_const_cast<Epetra_Vector>(x_dot));
545 
546  if (!Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
547 
548  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f and J)");
549 
550  // Set the targets
551  epGlobalContainer->set_f(f_out);
552  epGlobalContainer->set_A(Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(W_out));
553 
554  // Zero values in ghosted container objects
555  epGhostedContainer->get_f()->PutScalar(0.0);
556  epGhostedContainer->get_A()->PutScalar(0.0);
557 
558  ae_tm_.getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
559  }
560  else if(!Teuchos::is_null(f_out) && Teuchos::is_null(W_out)) {
561 
562  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f)");
563 
564  epGlobalContainer->set_f(f_out);
565 
566  // Zero values in ghosted container objects
567  epGhostedContainer->get_f()->PutScalar(0.0);
568 
569  ae_tm_.getAsObject<panzer::Traits::Residual>()->evaluate(ae_inargs);
570 
571  f_out->Update(1.0, *(epGlobalContainer->get_f()), 0.0);
572  }
573  else if(Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
574 
575  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(J)");
576 
577  // this dummy nonsense is needed only for scattering dirichlet conditions
578  if (Teuchos::is_null(dummy_f_))
579  dummy_f_ = Teuchos::rcp(new Epetra_Vector(*(this->get_f_map())));
580  epGlobalContainer->set_f(dummy_f_);
581  epGlobalContainer->set_A(Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(W_out));
582 
583  // Zero values in ghosted container objects
584  epGhostedContainer->get_A()->PutScalar(0.0);
585 
586  ae_tm_.getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
587  }
588  // HACK: set A to null before calling responses to avoid touching the
589  // the Jacobian after it has been properly assembled. Should be fixed
590  // by using a modified version of ae_inargs instead.
591  epGlobalContainer->set_A(Teuchos::null);
592 
593  // evaluate responses...uses the stored assembly arguments and containers
594  if(requiredResponses) {
595  evalModel_basic_g(ae_inargs,inArgs,outArgs);
596 
597  // evaluate response derivatives
598  if(required_basic_dgdx(outArgs))
599  evalModel_basic_dgdx(ae_inargs,inArgs,outArgs);
600  }
601 
602  if(required_basic_dfdp(outArgs))
603  evalModel_basic_dfdp(ae_inargs,inArgs,outArgs);
604 
605  // TODO: Clearing all references prevented a seg-fault with Rythmos,
606  // which is no longer used. Check if it's still needed.
607  epGlobalContainer->set_x(Teuchos::null);
608  epGlobalContainer->set_dxdt(Teuchos::null);
609  epGlobalContainer->set_f(Teuchos::null);
610  epGlobalContainer->set_A(Teuchos::null);
611 
612  // forget previous containers
613  ae_inargs.container_ = Teuchos::null;
614  ae_inargs.ghostedContainer_ = Teuchos::null;
615 }
616 
617 void
619 evalModel_basic_g(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
620 {
621  // optional sanity check
622  // TEUCHOS_ASSERT(required_basic_g(outArgs));
623 
624  for(std::size_t i=0;i<g_names_.size();i++) {
625  Teuchos::RCP<Epetra_Vector> vec = outArgs.get_g(i);
626  if(vec!=Teuchos::null) {
627  std::string responseName = g_names_[i];
629  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Residual> >(responseLibrary_->getResponse<panzer::Traits::Residual>(responseName));
630  resp->setVector(vec);
631  }
632  }
633 
634  // evaluator responses
635  responseLibrary_->addResponsesToInArgs<panzer::Traits::Residual>(ae_inargs);
636  responseLibrary_->evaluate<panzer::Traits::Residual>(ae_inargs);
637 }
638 
639 void
641 evalModel_basic_dgdx(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
642 {
643  // optional sanity check
644  TEUCHOS_ASSERT(required_basic_dgdx(outArgs));
645 
646  for(std::size_t i=0;i<g_names_.size();i++) {
647  // get "Vector" out of derivative, if its something else, throw an exception
649  if(deriv.isEmpty())
650  continue;
651 
653 
654  if(vec!=Teuchos::null) {
655  std::string responseName = g_names_[i];
657  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Jacobian> >(responseLibrary_->getResponse<panzer::Traits::Jacobian>(responseName));
658  resp->setDerivative(vec);
659  }
660  }
661 
662  // evaluator responses
663  responseLibrary_->addResponsesToInArgs<panzer::Traits::Jacobian>(ae_inargs);
664  responseLibrary_->evaluate<panzer::Traits::Jacobian>(ae_inargs);
665 }
666 
667 void
669 evalModel_basic_dfdp(AssemblyEngineInArgs ae_inargs, const InArgs& /* inArgs */, const OutArgs& outArgs) const
670 {
671  using Teuchos::RCP;
672  using Teuchos::rcp_dynamic_cast;
673 
674  TEUCHOS_ASSERT(required_basic_dfdp(outArgs));
675 
676  // dynamic cast to blocked LOF for now
677  RCP<const Thyra::VectorSpaceBase<double> > glblVS = rcp_dynamic_cast<const ThyraObjFactory<double> >(lof_,true)->getThyraRangeSpace();;
678 
679  std::vector<std::string> activeParameters;
680 
681  // fill parameter vector containers
682  int totalParameterCount = 0;
683  for(Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
684  // have derivatives been requested?
686  if(deriv.isEmpty())
687  continue;
688 
689  // grab multivector, make sure its the right dimension
691  TEUCHOS_ASSERT(mVec->NumVectors()==int(parameter_vector_[i].size()));
692 
693  for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
694 
695  // build containers for each vector
697  RCP<LinearObjContainer> globalContainer = loc_pair->getGlobalLOC();
698 
699  // stuff target vector into global container
700  RCP<Epetra_Vector> vec = Teuchos::rcpFromRef(*(*mVec)(j));
701  RCP<panzer::ThyraObjContainer<double> > thGlobalContainer =
702  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<double> >(globalContainer);
703  thGlobalContainer->set_f_th(Thyra::create_Vector(vec,glblVS));
704 
705  // add container into in args object
706  std::string name = "PARAMETER_SENSITIVIES: "+(*p_names_[i])[j];
707  ae_inargs.addGlobalEvaluationData(name,loc_pair->getGhostedLOC());
708  ae_inargs.addGlobalEvaluationData(name+"_pair",loc_pair);
709 
710  activeParameters.push_back(name);
711  totalParameterCount++;
712  }
713  }
714 
715  // this communicates to the scatter evaluators so that the appropriate parameters are scattered
716  RCP<GlobalEvaluationData> ged_activeParameters = Teuchos::rcp(new ParameterList_GlobalEvaluationData(activeParameters));
717  ae_inargs.addGlobalEvaluationData("PARAMETER_NAMES",ged_activeParameters);
718 
719  int paramIndex = 0;
720  for (Teuchos::Array<panzer::ParamVec>::size_type i=0; i < parameter_vector_.size(); i++) {
721  // don't modify the parameter if its not needed
723  if(deriv.isEmpty()) {
724  // reinitialize values that should not have sensitivities computed (this is a precaution)
725  for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
726  Traits::FadType p = Traits::FadType(totalParameterCount, parameter_vector_[i][j].baseValue);
727  parameter_vector_[i][j].family->setValue<panzer::Traits::Tangent>(p);
728  }
729  continue;
730  }
731  else {
732  // loop over each parameter in the vector, initializing the AD type
733  for (unsigned int j=0; j < parameter_vector_[i].size(); j++) {
734  Traits::FadType p = Traits::FadType(totalParameterCount, parameter_vector_[i][j].baseValue);
735  p.fastAccessDx(paramIndex) = 1.0;
736  parameter_vector_[i][j].family->setValue<panzer::Traits::Tangent>(p);
737  paramIndex++;
738  }
739  }
740  }
741 
742  // make sure that the total parameter count and the total parameter index match up
743  TEUCHOS_ASSERT(paramIndex==totalParameterCount);
744 
745  if(totalParameterCount>0) {
746  ae_tm_.getAsObject<panzer::Traits::Tangent>()->evaluate(ae_inargs);
747  }
748 }
749 
751 {
752  // determine if any of the outArgs are not null!
753  bool activeGArgs = false;
754  for(int i=0;i<outArgs.Ng();i++)
755  activeGArgs |= (outArgs.get_g(i)!=Teuchos::null);
756 
757  return activeGArgs | required_basic_dgdx(outArgs);
758 }
759 
761 {
762  // determine if any of the outArgs are not null!
763  bool activeGArgs = false;
764  for(int i=0;i<outArgs.Ng();i++) {
765  // no derivatives are supported
766  if(outArgs.supports(OUT_ARG_DgDx,i).none())
767  continue;
768 
769  // this is basically a redundant computation
770  activeGArgs |= (!outArgs.get_DgDx(i).isEmpty());
771  }
772 
773  return activeGArgs;
774 }
775 
777 {
778  // determine if any of the outArgs are not null!
779  bool activeFPArgs = false;
780  for(int i=0;i<outArgs.Np();i++) {
781  // no derivatives are supported
782  if(outArgs.supports(OUT_ARG_DfDp,i).none())
783  continue;
784 
785  // this is basically a redundant computation
786  activeFPArgs |= (!outArgs.get_DfDp(i).isEmpty());
787  }
788 
789  return activeFPArgs;
790 }
791 
793 {
794  t_init_ = t;
795 }
796 
799 {
800 
801  using Teuchos::rcpFromRef;
802  using Teuchos::rcp_dynamic_cast;
803  using Teuchos::RCP;
804  using Teuchos::ArrayView;
805  using Teuchos::rcp_dynamic_cast;
806 
807  const int numVecs = x.NumVectors();
808 
809  TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
810  "epetraToThyra does not work with MV dimension != 1");
811 
812  const RCP<const Thyra::ProductVectorBase<double> > prodThyraVec =
813  Thyra::castOrCreateProductVectorBase(rcpFromRef(thyraVec));
814 
815  const Teuchos::ArrayView<double> epetraData(x[0], x.Map().NumMyElements());
816  // NOTE: See above!
817 
818  std::size_t offset = 0;
819  const int numBlocks = prodThyraVec->productSpace()->numBlocks();
820  for (int b = 0; b < numBlocks; ++b) {
821  const RCP<const Thyra::VectorBase<double> > vec_b = prodThyraVec->getVectorBlock(b);
823  rcp_dynamic_cast<const Thyra::SpmdVectorBase<double> >(vec_b, true);
824 
826  spmd_b->getLocalData(Teuchos::ptrFromRef(thyraData));
827 
828  for (Teuchos::ArrayRCP<const double>::size_type i=0; i < thyraData.size(); ++i) {
829  epetraData[i+offset] = thyraData[i];
830  }
831  offset += thyraData.size();
832  }
833 
834 }
835 
836 
839 {
840  using Teuchos::RCP;
841  using Teuchos::ArrayView;
842  using Teuchos::rcpFromPtr;
843  using Teuchos::rcp_dynamic_cast;
844 
845  const int numVecs = x.NumVectors();
846 
847  TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
848  "ModelEvaluator_Epetra::copyEpetraToThyra does not work with MV dimension != 1");
849 
850  const RCP<Thyra::ProductVectorBase<double> > prodThyraVec =
851  Thyra::castOrCreateNonconstProductVectorBase(rcpFromPtr(thyraVec));
852 
853  const Teuchos::ArrayView<const double> epetraData(x[0], x.Map().NumMyElements());
854  // NOTE: I tried using Epetra_MultiVector::operator()(int) to return an
855  // Epetra_Vector object but it has a defect when Reset(...) is called which
856  // results in a memory access error (see bug 4700).
857 
858  std::size_t offset = 0;
859  const int numBlocks = prodThyraVec->productSpace()->numBlocks();
860  for (int b = 0; b < numBlocks; ++b) {
861  const RCP<Thyra::VectorBase<double> > vec_b = prodThyraVec->getNonconstVectorBlock(b);
862  const RCP<Thyra::SpmdVectorBase<double> > spmd_b =
863  rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(vec_b, true);
864 
865  Teuchos::ArrayRCP<double> thyraData;
866  spmd_b->getNonconstLocalData(Teuchos::ptrFromRef(thyraData));
867 
868  for (Teuchos::ArrayRCP<double>::size_type i=0; i < thyraData.size(); ++i) {
869  thyraData[i] = epetraData[i+offset];
870  }
871  offset += thyraData.size();
872  }
873 
874 }
875 
876 
881  const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
882  const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
883  const Teuchos::RCP<panzer::GlobalData>& global_data,
884  bool build_transient_support)
885 {
886  using Teuchos::RCP;
887  using Teuchos::rcp_dynamic_cast;
888  using Teuchos::rcp;
889 
890  std::stringstream ss;
891  ss << "panzer::buildEpetraME: Linear object factory is incorrect type. Should be one of: ";
892 
894  = rcp_dynamic_cast<BlockedEpetraLinearObjFactory<panzer::Traits,int> >(lof);
895 
896  // if you can, build from an epetra linear object factory
897  if(ep_lof!=Teuchos::null)
898  return rcp(new ModelEvaluator_Epetra(fmb,rLibrary,ep_lof,p_names,p_values,global_data,build_transient_support));
899 
900  ss << "\"BlockedEpetraLinearObjFactory\", ";
901 
902  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,ss.str());
903 }
904 
906 setOneTimeDirichletBeta(const double & beta) const
907 {
908  oneTimeDirichletBeta_on_ = true;
909  oneTimeDirichletBeta_ = beta;
910 }
bool supports(EOutArgsMembers arg) const
void applyDirichletBCs(const Teuchos::RCP< Thyra::VectorBase< double > > &x, const Teuchos::RCP< Thyra::VectorBase< double > > &f) const
void set_W_properties(const DerivativeProperties &properties)
Evaluation< Epetra_Vector > get_g(int j) const
void set_f(const Teuchos::RCP< Epetra_Vector > &in)
Teuchos::RCP< const Epetra_Vector > get_p_init(int l) const
Teuchos::RCP< const Epetra_Vector > get_x_init() const
Derivative get_DfDp(int l) const
void setSupports(EOutArgsMembers arg, bool supports=true)
Teuchos::RCP< panzer::ParamLib > pl
Sacado scalar parameter library.
void copyThyraIntoEpetra(const Thyra::VectorBase< double > &thyraVec, Epetra_MultiVector &x) const
Teuchos::RCP< ModelEvaluator_Epetra > buildEpetraME(const Teuchos::RCP< FieldManagerBuilder > &fmb, const Teuchos::RCP< ResponseLibrary< panzer::Traits > > &rLibrary, const Teuchos::RCP< LinearObjFactory< panzer::Traits > > &lof, const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::GlobalData > &global_data, bool build_transient_support)
Teuchos::RCP< const Epetra_Vector > get_x_dot_init() const
Teuchos::RCP< const Epetra_Map > get_p_map(int l) const
Teuchos::RCP< Epetra_Operator > create_W() const
bool is_null(const std::shared_ptr< T > &p)
Teuchos::RCP< Epetra_Operator > get_W() const
void initializeEpetraObjs(panzer::BlockedEpetraLinearObjFactory< panzer::Traits, int > &lof)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const Epetra_Map > get_g_map(int l) const
Teuchos::RCP< LinearObjContainer > getGlobalLOC() const
size_type size() const
void setSupports(EInArgsMembers arg, bool supports=true)
void set_A(const Teuchos::RCP< Epetra_CrsMatrix > &in)
void evalModel_basic_dfdp(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
void evalModel_basic_dgdx(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
Teuchos::RCP< const Epetra_Vector > get_p(int l) const
Teuchos::RCP< panzer::LinearObjContainer > ghostedContainer_
bool required_basic_g(const OutArgs &outArgs) const
Are their required responses in the out args? g and DgDx.
Derivative get_DgDx(int j) const
const Teuchos::RCP< Epetra_CrsMatrix > get_A() const
void set_t_init(double t)
Set initial time value.
void set_dxdt(const Teuchos::RCP< Epetra_Vector > &in)
Teuchos::RCP< LinearObjContainer > getGhostedLOC() const
int PutScalar(double ScalarConstant)
Teuchos::RCP< panzer::LinearObjContainer > container_
ModelEvaluator_Epetra(const Teuchos::RCP< panzer::FieldManagerBuilder > &fmb, const Teuchos::RCP< panzer::ResponseLibrary< panzer::Traits > > &rLibrary, const Teuchos::RCP< panzer::LinearObjFactory< panzer::Traits > > &lof, const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::GlobalData > &global_data, bool build_transient_support)
void addGlobalEvaluationData(const std::string &key, const Teuchos::RCP< GlobalEvaluationData > &ged)
Teuchos::RCP< Epetra_MultiVector > getMultiVector() const
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we&#39;re performing.
virtual const Teuchos::RCP< Epetra_Map > getMap(int i) const
get the map from the matrix
void setModelEvalDescription(const std::string &modelEvalDescription)
Teuchos::RCP< const Epetra_Map > get_x_map() const
Ordinal size_type
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
int addDistributedParameter(const std::string name, const Teuchos::RCP< Epetra_Map > &global_map, const Teuchos::RCP< Epetra_Import > &importer, const Teuchos::RCP< Epetra_Vector > &ghosted_vector)
Ptr< T > ptr() const
Teuchos::RCP< const Epetra_Vector > get_x_dot() const
bool supports(EInArgsMembers arg) const
const Teuchos::RCP< Epetra_Vector > get_f() const
void setModelEvalDescription(const std::string &modelEvalDescription)
void initializeParameterVector(const std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > &p_names, const std::vector< Teuchos::RCP< Teuchos::Array< double > > > &p_values, const Teuchos::RCP< panzer::ParamLib > &parameter_library)
PANZER_FADTYPE FadType
panzer::AssemblyEngine_TemplateManager< panzer::Traits > ae_tm_
bool nonnull(const boost::shared_ptr< T > &p)
void evalModel(const InArgs &inArgs, const OutArgs &outArgs) const
void set_x(const Teuchos::RCP< Epetra_Vector > &in)
size_type size() const
virtual obj_ptr_t create() const =0
bool required_basic_dfdp(const OutArgs &outArgs) const
Are derivatives of the residual with respect to the parameters in the out args? DfDp.
void evalModel_basic(const InArgs &inArgs, const OutArgs &outArgs) const
for evaluation and handling of normal quantities, x,f,W, etc
std::vector< Teuchos::RCP< Teuchos::Array< std::string > > > p_names_
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< const Epetra_Map > get_f_map() const
void evalModel_basic_g(AssemblyEngineInArgs ae_inargs, const InArgs &inArgs, const OutArgs &outArgs) const
Evaluation< Epetra_Vector > get_f() const
void copyEpetraIntoThyra(const Epetra_MultiVector &x, const Teuchos::Ptr< Thyra::VectorBase< double > > &thyraVec) const
void registerScalarParameter(const std::string name, panzer::ParamLib &pl, double realValue)
Teuchos::RCP< const Epetra_Vector > get_x() const
bool required_basic_dgdx(const OutArgs &outArgs) const
Are their required responses in the out args? DgDx.
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
void setOneTimeDirichletBeta(const double &beta) const