Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ModelEvaluator_impl.hpp
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 #ifndef __Panzer_ModelEvaluator_impl_hpp__
12 #define __Panzer_ModelEvaluator_impl_hpp__
13 
14 #include "Teuchos_DefaultComm.hpp"
15 #include "Teuchos_ArrayRCP.hpp"
16 
17 #include "PanzerDiscFE_config.hpp"
18 #include "Panzer_Traits.hpp"
25 #include "Panzer_GlobalData.hpp"
33 
34 #include "Thyra_TpetraThyraWrappers.hpp"
35 #include "Thyra_SpmdVectorBase.hpp"
36 #include "Thyra_DefaultSpmdVector.hpp"
37 #include "Thyra_DefaultSpmdVectorSpace.hpp"
38 #include "Thyra_DefaultMultiVectorProductVectorSpace.hpp"
39 #include "Thyra_DefaultMultiVectorProductVector.hpp"
40 #include "Thyra_MultiVectorStdOps.hpp"
41 #include "Thyra_VectorStdOps.hpp"
42 
43 // For writing out residuals/Jacobians
44 #include "Thyra_ProductVectorBase.hpp"
45 #include "Thyra_BlockedLinearOpBase.hpp"
46 #include "Thyra_TpetraVector.hpp"
47 #include "Thyra_TpetraLinearOp.hpp"
48 #include "Tpetra_CrsMatrix.hpp"
49 
50 // Constructors/Initializers/Accessors
51 
52 template<typename Scalar>
57  const std::vector<Teuchos::RCP<Teuchos::Array<std::string> > >& p_names,
58  const std::vector<Teuchos::RCP<Teuchos::Array<double> > >& p_values,
59  const Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> > & solverFactory,
60  const Teuchos::RCP<panzer::GlobalData>& global_data,
61  bool build_transient_support,
62  double t_init)
63  : t_init_(t_init)
64  , num_me_parameters_(0)
65  , do_fd_dfdp_(false)
66  , fd_perturb_size_(1e-7)
67  , require_in_args_refresh_(true)
68  , require_out_args_refresh_(true)
69  , responseLibrary_(rLibrary)
70  , global_data_(global_data)
71  , build_transient_support_(build_transient_support)
72  , lof_(lof)
73  , solverFactory_(solverFactory)
74  , oneTimeDirichletBeta_on_(false)
75  , oneTimeDirichletBeta_(0.0)
76  , build_volume_field_managers_(true)
77  , build_bc_field_managers_(true)
78  , active_evaluation_types_(Sacado::mpl::size<panzer::Traits::EvalTypes>::value, true)
79  , write_matrix_count_(0)
80 {
81  using Teuchos::RCP;
82  using Teuchos::rcp;
83  using Teuchos::rcp_dynamic_cast;
84  using Teuchos::tuple;
85  using Thyra::VectorBase;
86  using Thyra::createMember;
87 
88  TEUCHOS_ASSERT(lof_!=Teuchos::null);
89 
91  ae_tm_.buildObjects(builder);
92 
93  //
94  // Build x, f spaces
95  //
96 
97  // dynamic cast to blocked LOF for now
98  RCP<const ThyraObjFactory<Scalar> > tof = rcp_dynamic_cast<const ThyraObjFactory<Scalar> >(lof,true);
99 
100  x_space_ = tof->getThyraDomainSpace();
101  f_space_ = tof->getThyraRangeSpace();
102 
103  //
104  // Setup parameters
105  //
106  for(std::size_t i=0;i<p_names.size();i++)
107  addParameter(*(p_names[i]),*(p_values[i]));
108 
109  // now that the vector spaces are setup we can allocate the nominal values
110  // (i.e. initial conditions)
112 }
113 
114 template<typename Scalar>
117  const Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> > & solverFactory,
118  const Teuchos::RCP<panzer::GlobalData>& global_data,
119  bool build_transient_support,double t_init)
120  : t_init_(t_init)
121  , num_me_parameters_(0)
122  , do_fd_dfdp_(false)
123  , fd_perturb_size_(1e-7)
124  , require_in_args_refresh_(true)
125  , require_out_args_refresh_(true)
126  , global_data_(global_data)
127  , build_transient_support_(build_transient_support)
128  , lof_(lof)
129  , solverFactory_(solverFactory)
130  , oneTimeDirichletBeta_on_(false)
131  , oneTimeDirichletBeta_(0.0)
132  , build_volume_field_managers_(true)
133  , build_bc_field_managers_(true)
134  , active_evaluation_types_(Sacado::mpl::size<panzer::Traits::EvalTypes>::value, true)
135  , write_matrix_count_(0)
136 {
137  using Teuchos::RCP;
138  using Teuchos::rcp_dynamic_cast;
139 
140  TEUCHOS_ASSERT(lof_!=Teuchos::null);
141 
142  //
143  // Build x, f spaces
144  //
145 
146  // dynamic cast to blocked LOF for now
147  RCP<const ThyraObjFactory<Scalar> > tof = rcp_dynamic_cast<const ThyraObjFactory<Scalar> >(lof_,true);
148 
149  x_space_ = tof->getThyraDomainSpace();
150  f_space_ = tof->getThyraRangeSpace();
151 
152  // now that the vector spaces are setup we can allocate the nominal values
153  // (i.e. initial conditions)
155 
156  // allocate a response library so that responses can be added, it will be initialized in "setupModel"
158 }
159 
160 template<typename Scalar>
163 {
164  TEUCHOS_ASSERT(false);
165 }
166 
167 // Public functions overridden from ModelEvaulator
168 
169 template<typename Scalar>
172 {
173  return x_space_;
174 }
175 
176 
177 template<typename Scalar>
180 {
181  return f_space_;
182 }
183 
184 template<typename Scalar>
187 {
188  TEUCHOS_TEST_FOR_EXCEPTION(!(i>=0 && i<num_me_parameters_),std::runtime_error,
189  "panzer::ModelEvaluator::get_p_names: Requested parameter index out of range.");
190 
191  if (i < Teuchos::as<int>(parameters_.size()))
192  return parameters_[i]->names;
193  else if (i < Teuchos::as<int>(parameters_.size()+tangent_space_.size())) {
195  int param_index = i-parameters_.size();
196  std::ostringstream ss;
197  ss << "TANGENT VECTOR: " << param_index;
198  names->push_back(ss.str());
199  return names;
200  }
201  else if (build_transient_support_ && i < Teuchos::as<int>(parameters_.size()+2*tangent_space_.size())) {
203  int param_index = i-parameters_.size()-tangent_space_.size();
204  std::ostringstream ss;
205  ss << "TIME DERIVATIVE TANGENT VECTOR: " << param_index;
206  names->push_back(ss.str());
207  return names;
208  }
209 
210  return Teuchos::null;
211 }
212 
213 template<typename Scalar>
216 {
217  TEUCHOS_TEST_FOR_EXCEPTION(!(i>=0 && i<num_me_parameters_),std::runtime_error,
218  "panzer::ModelEvaluator::get_p_space: Requested parameter index out of range.");
219 
220  if (i < Teuchos::as<int>(parameters_.size()))
221  return parameters_[i]->space;
222  else if (i < Teuchos::as<int>(parameters_.size()+tangent_space_.size()))
223  return tangent_space_[i-parameters_.size()];
224  else if (build_transient_support_ && i < Teuchos::as<int>(parameters_.size()+2*tangent_space_.size()))
225  return tangent_space_[i-parameters_.size()-tangent_space_.size()];
226 
227  return Teuchos::null;
228 }
229 
230 template<typename Scalar>
233 {
234  TEUCHOS_TEST_FOR_EXCEPTION(!(i>=0 && i<Teuchos::as<int>(responses_.size())),std::runtime_error,
235  "panzer::ModelEvaluator::get_g_names: Requested response index out of range.");
236 
237  return Teuchos::ArrayView<const std::string>(&(responses_[i]->name),1);
238 }
239 
240 template<typename Scalar>
241 const std::string &
243 {
244  TEUCHOS_ASSERT(i>=0 &&
245  static_cast<typename std::vector<Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > >::size_type>(i)<responses_.size());
246 
247  return responses_[i]->name;
248 }
249 
250 template<typename Scalar>
253 {
254  TEUCHOS_ASSERT(i>=0 &&
255  static_cast<typename std::vector<Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > >::size_type>(i)<responses_.size());
256 
257  return responses_[i]->space;
258 }
259 
260 template<typename Scalar>
261 Thyra::ModelEvaluatorBase::InArgs<Scalar>
263 {
264  return getNominalValues();
265 }
266 
267 template<typename Scalar>
268 Thyra::ModelEvaluatorBase::InArgs<Scalar>
270 {
271  using Teuchos::RCP;
272  using Teuchos::rcp_dynamic_cast;
273 
274  if(require_in_args_refresh_) {
275  typedef Thyra::ModelEvaluatorBase MEB;
276 
277  //
278  // Refresh nominal values, this is primarily adding
279  // new parameters.
280  //
281 
282  MEB::InArgsSetup<Scalar> nomInArgs;
283  nomInArgs = nominalValues_;
284  nomInArgs.setSupports(nominalValues_);
285 
286  // setup parameter support
287  nomInArgs.set_Np(num_me_parameters_);
288  for(std::size_t p=0;p<parameters_.size();p++) {
289  // setup nominal in arguments
290  nomInArgs.set_p(p,parameters_[p]->initial_value);
291 
292  // We explicitly do not set nominal values for tangent parameters
293  // as these are parameters that should be hidden from client code
294  }
295 
296  nominalValues_ = nomInArgs;
297  }
298 
299  // refresh no longer required
300  require_in_args_refresh_ = false;
301 
302  return nominalValues_;
303 }
304 
305 template<typename Scalar>
306 void
308 {
309  typedef Thyra::ModelEvaluatorBase MEB;
310 
311  //
312  // Setup nominal values
313  //
314 
315  MEB::InArgsSetup<Scalar> nomInArgs;
316  nomInArgs.setModelEvalDescription(this->description());
317  nomInArgs.setSupports(MEB::IN_ARG_x);
318  Teuchos::RCP<Thyra::VectorBase<Scalar> > x_nom = Thyra::createMember(x_space_);
319  Thyra::assign(x_nom.ptr(),0.0);
320  nomInArgs.set_x(x_nom);
321  if(build_transient_support_) {
322  nomInArgs.setSupports(MEB::IN_ARG_x_dot,true);
323  nomInArgs.setSupports(MEB::IN_ARG_t,true);
324  nomInArgs.setSupports(MEB::IN_ARG_alpha,true);
325  nomInArgs.setSupports(MEB::IN_ARG_beta,true);
326  nomInArgs.setSupports(MEB::IN_ARG_step_size,true);
327  nomInArgs.setSupports(MEB::IN_ARG_stage_number,true);
328 
329  Teuchos::RCP<Thyra::VectorBase<Scalar> > x_dot_nom = Thyra::createMember(x_space_);
330  Thyra::assign(x_dot_nom.ptr(),0.0);
331  nomInArgs.set_x_dot(x_dot_nom);
332  nomInArgs.set_t(t_init_);
333  nomInArgs.set_alpha(0.0); // these have no meaning initially!
334  nomInArgs.set_beta(0.0);
335  //TODO: is this needed?
336  nomInArgs.set_step_size(0.0);
337  nomInArgs.set_stage_number(1.0);
338  }
339 
340  // setup parameter support -- for each scalar parameter we support the parameter itself and tangent vectors for x, xdot
341  nomInArgs.set_Np(num_me_parameters_);
342  std::size_t v_index = 0;
343  for(std::size_t p=0;p<parameters_.size();p++) {
344  nomInArgs.set_p(p,parameters_[p]->initial_value);
345  if (!parameters_[p]->is_distributed) {
346  Teuchos::RCP<Thyra::VectorBase<Scalar> > v_nom_x = Thyra::createMember(*tangent_space_[v_index]);
347  Thyra::assign(v_nom_x.ptr(),0.0);
348  nomInArgs.set_p(v_index+parameters_.size(),v_nom_x);
349  if (build_transient_support_) {
350  Teuchos::RCP<Thyra::VectorBase<Scalar> > v_nom_xdot = Thyra::createMember(*tangent_space_[v_index]);
351  Thyra::assign(v_nom_xdot.ptr(),0.0);
352  nomInArgs.set_p(v_index+parameters_.size()+tangent_space_.size(),v_nom_xdot);
353  }
354  ++v_index;
355  }
356  }
357 
358  nominalValues_ = nomInArgs;
359 }
360 
361 template <typename Scalar>
363 buildVolumeFieldManagers(const bool value)
364 {
365  build_volume_field_managers_ = value;
366 }
367 
368 template <typename Scalar>
370 buildBCFieldManagers(const bool value)
371 {
372  build_bc_field_managers_ = value;
373 }
374 
375 template <typename Scalar>
378  const std::vector<Teuchos::RCP<panzer::PhysicsBlock> >& physicsBlocks,
379  const std::vector<panzer::BC> & bcs,
380  const panzer::EquationSetFactory & eqset_factory,
381  const panzer::BCStrategyFactory& bc_factory,
384  const Teuchos::ParameterList& closure_models,
385  const Teuchos::ParameterList& user_data,
386  bool writeGraph,const std::string & graphPrefix,
387  const Teuchos::ParameterList& me_params)
388 {
389  // First: build residual assembly engine
391  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::ModelEvaluator::setupModel()",setupModel);
392 
393  {
394  // 1. build Field manager builder
396 
398  {
399  PANZER_FUNC_TIME_MONITOR_DIFF("allocate FieldManagerBuilder",allocFMB);
401  fmb->setActiveEvaluationTypes(active_evaluation_types_);
402  }
403  {
404  PANZER_FUNC_TIME_MONITOR_DIFF("fmb->setWorksetContainer()",setupWorksets);
405  fmb->setWorksetContainer(wc);
406  }
407  if (build_volume_field_managers_) {
408  PANZER_FUNC_TIME_MONITOR_DIFF("fmb->setupVolumeFieldManagers()",setupVolumeFieldManagers);
409  fmb->setupVolumeFieldManagers(physicsBlocks,volume_cm_factory,closure_models,*lof_,user_data);
410  }
411  if (build_bc_field_managers_) {
412  PANZER_FUNC_TIME_MONITOR_DIFF("fmb->setupBCFieldManagers()",setupBCFieldManagers);
413  fmb->setupBCFieldManagers(bcs,physicsBlocks,eqset_factory,bc_cm_factory,bc_factory,closure_models,*lof_,user_data);
414  }
415 
416  // Print Phalanx DAGs
417  if (writeGraph){
418  if (build_volume_field_managers_)
419  fmb->writeVolumeGraphvizDependencyFiles(graphPrefix, physicsBlocks);
420  if (build_bc_field_managers_)
421  fmb->writeBCGraphvizDependencyFiles(graphPrefix+"BC_");
422  }
423 
424  {
425  PANZER_FUNC_TIME_MONITOR_DIFF("AssemblyEngine_TemplateBuilder::buildObjects()",AETM_BuildObjects);
426  panzer::AssemblyEngine_TemplateBuilder builder(fmb,lof_);
427  ae_tm_.buildObjects(builder);
428  }
429  }
430 
431  // Second: build the responses
433 
434  {
435  PANZER_FUNC_TIME_MONITOR_DIFF("build response library",buildResponses);
436 
437  responseLibrary_->initialize(wc,lof_->getRangeGlobalIndexer(),lof_);
438 
439  buildResponses(physicsBlocks,eqset_factory,volume_cm_factory,closure_models,user_data,writeGraph,graphPrefix+"Responses_");
440  buildDistroParamDfDp_RL(wc,physicsBlocks,bcs,eqset_factory,bc_factory,volume_cm_factory,closure_models,user_data,writeGraph,graphPrefix+"Response_DfDp_");
441  buildDistroParamDgDp_RL(wc,physicsBlocks,bcs,eqset_factory,bc_factory,volume_cm_factory,closure_models,user_data,writeGraph,graphPrefix+"Response_DgDp_");
442 
443  do_fd_dfdp_ = false;
444  fd_perturb_size_ = 1.0e-7;
445  if (me_params.isParameter("FD Forward Sensitivities"))
446  do_fd_dfdp_ = me_params.get<bool>("FD Forward Sensitivities");
447  if (me_params.isParameter("FD Perturbation Size"))
448  fd_perturb_size_ = me_params.get<double>("FD Perturbation Size");
449  }
450 }
451 
452 template <typename Scalar>
454 setupAssemblyInArgs(const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
455  panzer::AssemblyEngineInArgs & ae_inargs) const
456 {
457  using Teuchos::RCP;
458  using Teuchos::rcp;
459  using Teuchos::rcp_dynamic_cast;
460  using Teuchos::rcp_const_cast;
461  typedef Thyra::ModelEvaluatorBase MEB;
462 
463  // if neccessary build a ghosted container
464  if(Teuchos::is_null(ghostedContainer_)) {
465  ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
466  lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
469  panzer::LinearObjContainer::Mat, *ghostedContainer_);
470  }
471 
472  bool is_transient = false;
473  if (inArgs.supports(MEB::IN_ARG_x_dot ))
474  is_transient = !Teuchos::is_null(inArgs.get_x_dot());
475 
476  if(Teuchos::is_null(xContainer_))
477  xContainer_ = lof_->buildReadOnlyDomainContainer();
478  if(Teuchos::is_null(xdotContainer_) && is_transient)
479  xdotContainer_ = lof_->buildReadOnlyDomainContainer();
480 
481  const RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x();
482  RCP<const Thyra::VectorBase<Scalar> > x_dot; // possibly empty, but otherwise uses x_dot
483 
484  // Make sure construction built in transient support
485  TEUCHOS_TEST_FOR_EXCEPTION(is_transient && !build_transient_support_, std::runtime_error,
486  "ModelEvaluator was not built with transient support enabled!");
487 
488  ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
489  ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
490  ae_inargs.alpha = 0.0;
491  ae_inargs.beta = 1.0;
492  ae_inargs.evaluate_transient_terms = false;
493  if (build_transient_support_) {
494  x_dot = inArgs.get_x_dot();
495  ae_inargs.alpha = inArgs.get_alpha();
496  ae_inargs.beta = inArgs.get_beta();
497  ae_inargs.time = inArgs.get_t();
498 
499  ae_inargs.step_size= inArgs.get_step_size();
500  ae_inargs.stage_number = inArgs.get_stage_number();
501  ae_inargs.evaluate_transient_terms = true;
502  }
503 
504  // this member is handled in the individual functions
505  ae_inargs.apply_dirichlet_beta = false;
506 
507  // Set input parameters
508  int num_param_vecs = parameters_.size();
509  for (int i=0; i<num_param_vecs; i++) {
510 
511  RCP<const Thyra::VectorBase<Scalar> > paramVec = inArgs.get_p(i);
512  if ( paramVec!=Teuchos::null && !parameters_[i]->is_distributed) {
513  // non distributed parameters
514 
516  rcp_dynamic_cast<const Thyra::SpmdVectorBase<Scalar> >(paramVec,true)->getLocalData(Teuchos::ptrFromRef(p_data));
517 
518  for (unsigned int j=0; j < parameters_[i]->scalar_value.size(); j++) {
519  parameters_[i]->scalar_value[j].baseValue = p_data[j];
520  parameters_[i]->scalar_value[j].family->setRealValueForAllTypes(parameters_[i]->scalar_value[j].baseValue);
521  }
522  }
523  else if ( paramVec!=Teuchos::null && parameters_[i]->is_distributed) {
524  // distributed parameters
525 
526  std::string key = (*parameters_[i]->names)[0];
527  RCP<GlobalEvaluationData> ged = distrParamGlobalEvaluationData_.getDataObject(key);
528 
529  TEUCHOS_ASSERT(ged!=Teuchos::null);
530 
531  // cast to a LOCPair throwing an exception if the cast doesn't work.
532  RCP<LOCPair_GlobalEvaluationData> loc_pair_ged = rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(ged);
534  if(loc_pair_ged!=Teuchos::null) {
535  // cast to a ThyraObjContainer throwing an exception if the cast doesn't work.
536  RCP<ThyraObjContainer<Scalar> > th_ged = rcp_dynamic_cast<ThyraObjContainer<Scalar> >(loc_pair_ged->getGlobalLOC(),true);
537  th_ged->set_x_th(Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(paramVec));
538  }
539  else {
540  TEUCHOS_ASSERT(ro_ged!=Teuchos::null);
541  ro_ged->setOwnedVector(paramVec);
542  }
543  }
544  }
545 
546  ae_inargs.addGlobalEvaluationData(distrParamGlobalEvaluationData_);
547 
548  // here we are building a container, this operation is fast, simply allocating a struct
549  const RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
550  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.container_);
551 
552  TEUCHOS_ASSERT(!Teuchos::is_null(thGlobalContainer));
553 
554  // Ghosted container objects are zeroed out below only if needed for
555  // a particular calculation. This makes it more efficient than
556  // zeroing out all objects in the container here.
557  // const RCP<panzer::ThyraObjContainer<Scalar> > thGhostedContainer =
558  // Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.ghostedContainer_);
559 
560  // Set the solution vector (currently all targets require solution).
561  // In the future we may move these into the individual cases below.
562  // A very subtle (and fragile) point: A non-null pointer in global
563  // container triggers export operations during fill. Also, the
564  // introduction of the container is forcing us to cast away const on
565  // arguments that should be const. Another reason to redesign
566  // LinearObjContainer layers.
567  thGlobalContainer->set_x_th(Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(x));
568  xContainer_->setOwnedVector(x);
569  ae_inargs.addGlobalEvaluationData("Solution Gather Container - X",xContainer_);
570 
571  if (is_transient) {
572  thGlobalContainer->set_dxdt_th(Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(x_dot));
573  xdotContainer_->setOwnedVector(x_dot);
574  ae_inargs.addGlobalEvaluationData("Solution Gather Container - Xdot",xdotContainer_);
575  }
576 
577  // Add tangent vectors for x and xdot to GlobalEvaluationData, one for each
578  // scalar parameter vector and parameter within that vector.
579  // Note: The keys for the global evaluation data containers for the tangent
580  // vectors are constructed in EquationSet_AddFieldDefaultImpl::
581  // buildAndRegisterGatherAndOrientationEvaluators().
582  int vIndex(0);
583  for (int i(0); i < num_param_vecs; ++i)
584  {
585  using std::string;
587  using Thyra::VectorBase;
589  if (not parameters_[i]->is_distributed)
590  {
591  auto dxdp = rcp_const_cast<VectorBase<Scalar>>
592  (inArgs.get_p(vIndex + num_param_vecs));
593  if (not dxdp.is_null())
594  {
595  // We need to cast away const because the object container requires
596  // non-const vectors.
597  auto dxdpBlock = rcp_dynamic_cast<ProductVectorBase<Scalar>>(dxdp);
598  int numParams(parameters_[i]->scalar_value.size());
599  for (int j(0); j < numParams; ++j)
600  {
601  RCP<ROVGED> dxdpContainer = lof_->buildReadOnlyDomainContainer();
602  dxdpContainer->setOwnedVector(dxdpBlock->getNonconstVectorBlock(j));
603  string name("X TANGENT GATHER CONTAINER: " +
604  (*parameters_[i]->names)[j]);
605  ae_inargs.addGlobalEvaluationData(name, dxdpContainer);
606  } // end loop over the parameters
607  } // end if (not dxdp.is_null())
608  if (build_transient_support_)
609  {
610  // We need to cast away const because the object container requires
611  // non-const vectors.
612  auto dxdotdp = rcp_const_cast<VectorBase<Scalar>>
613  (inArgs.get_p(vIndex + num_param_vecs + tangent_space_.size()));
614  if (not dxdotdp.is_null())
615  {
616  auto dxdotdpBlock =
617  rcp_dynamic_cast<ProductVectorBase<Scalar>>(dxdotdp);
618  int numParams(parameters_[i]->scalar_value.size());
619  for (int j(0); j < numParams; ++j)
620  {
621  RCP<ROVGED> dxdotdpContainer = lof_->buildReadOnlyDomainContainer();
622  dxdotdpContainer->setOwnedVector(
623  dxdotdpBlock->getNonconstVectorBlock(j));
624  string name("DXDT TANGENT GATHER CONTAINER: " +
625  (*parameters_[i]->names)[j]);
626  ae_inargs.addGlobalEvaluationData(name, dxdotdpContainer);
627  } // end loop over the parameters
628  } // end if (not dxdotdp.is_null())
629  } // end if (build_transient_support_)
630  ++vIndex;
631  } // end if (not parameters_[i]->is_distributed)
632  } // end loop over the parameter vectors
633 } // end of setupAssemblyInArgs()
634 
635 // Private functions overridden from ModelEvaulatorDefaultBase
636 
637 
638 template <typename Scalar>
639 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
641 {
642  typedef Thyra::ModelEvaluatorBase MEB;
643 
644  if(require_out_args_refresh_) {
645  MEB::OutArgsSetup<Scalar> outArgs;
646  outArgs.setModelEvalDescription(this->description());
647  outArgs.set_Np_Ng(num_me_parameters_, responses_.size());
648  outArgs.setSupports(MEB::OUT_ARG_f);
649  outArgs.setSupports(MEB::OUT_ARG_W_op);
650 
651  // add in dg/dx (if appropriate)
652  for(std::size_t i=0;i<responses_.size();i++) {
653  typedef panzer::Traits::Jacobian RespEvalT;
654 
655  // check dg/dx and add it in if appropriate
657  = responseLibrary_->getResponse<RespEvalT>(responses_[i]->name);
658  if(respJacBase!=Teuchos::null) {
659  // cast is guranteed to succeed because of check in addResponse
661  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<RespEvalT> >(respJacBase);
662 
663  // class must supppot a derivative
664  if(resp->supportsDerivative()) {
665  outArgs.setSupports(MEB::OUT_ARG_DgDx,i,MEB::DerivativeSupport(MEB::DERIV_MV_GRADIENT_FORM));
666 
667 
668  for(std::size_t p=0;p<parameters_.size();p++) {
669  if(parameters_[p]->is_distributed && parameters_[p]->global_indexer!=Teuchos::null)
670  outArgs.setSupports(MEB::OUT_ARG_DgDp,i,p,MEB::DerivativeSupport(MEB::DERIV_MV_GRADIENT_FORM));
671  if(!parameters_[p]->is_distributed)
672  outArgs.setSupports(MEB::OUT_ARG_DgDp,i,p,MEB::DerivativeSupport(MEB::DERIV_MV_JACOBIAN_FORM));
673  }
674  }
675  }
676  }
677 
678  // setup parameter support
679  for(std::size_t p=0;p<parameters_.size();p++) {
680 
681  if(!parameters_[p]->is_distributed)
682  outArgs.setSupports(MEB::OUT_ARG_DfDp,p,MEB::DerivativeSupport(MEB::DERIV_MV_BY_COL));
683  else if(parameters_[p]->is_distributed && parameters_[p]->global_indexer!=Teuchos::null)
684  outArgs.setSupports(MEB::OUT_ARG_DfDp,p,MEB::DerivativeSupport(MEB::DERIV_LINEAR_OP));
685  }
686 
687  prototypeOutArgs_ = outArgs;
688  }
689 
690  // we don't need to build it anymore
691  require_out_args_refresh_ = false;
692 
693  return prototypeOutArgs_;
694 }
695 
696 template <typename Scalar>
699 create_W_op() const
700 {
701  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::create_W_op");
703  = Teuchos::rcp_dynamic_cast<const ThyraObjFactory<Scalar> >(lof_,true);
704 
705  return tof->getThyraMatrix();
706 }
707 
708 template <typename Scalar>
712 {
713  return solverFactory_;
714 }
715 
716 template <typename Scalar>
719 create_DfDp_op(int p) const
720 {
721  using Teuchos::RCP;
722  using Teuchos::rcp_dynamic_cast;
723 
724  typedef Thyra::ModelEvaluatorBase MEB;
725 
726  // The code below uses prototypeOutArgs_, so we need to make sure it is
727  // initialized before using it. This happens through createOutArgs(),
728  // however it may be allowable to call create_DfDp_op() before
729  // createOutArgs() is called. Thus we do this here if prototypeOutArgs_
730  // needs to be initialized.
731  //
732  // Previously this was handled in the TEUCHOS_ASSERT below through the call
733  // to Np(), however it isn't a good idea to include code in asserts that is
734  // required for proper execution (the asserts may be removed in an optimized
735  // build, for example).
736  if(require_out_args_refresh_) {
737  this->createOutArgs();
738  }
739 
740  TEUCHOS_ASSERT(0<=p && p<Teuchos::as<int>(parameters_.size()));
741 
742  // assert that DfDp is supported
743  const ParameterObject & po = *parameters_[p];
744 
745  if(po.is_distributed && po.global_indexer!=Teuchos::null) {
746  TEUCHOS_ASSERT(prototypeOutArgs_.supports(MEB::OUT_ARG_DfDp,p).supports(MEB::DERIV_LINEAR_OP));
747 
748  // for a distributed parameter, figure it out from the
749  // response library
750  RCP<Response_Residual<Traits::Jacobian> > response_jacobian
751  = rcp_dynamic_cast<Response_Residual<Traits::Jacobian> >(po.dfdp_rl->template getResponse<Traits::Jacobian>("RESIDUAL"));
752 
753  return response_jacobian->allocateJacobian();
754  }
755  else if(!po.is_distributed) {
756  TEUCHOS_ASSERT(prototypeOutArgs_.supports(MEB::OUT_ARG_DfDp,p).supports(MEB::DERIV_MV_BY_COL));
757 
758  // this is a scalar parameter (its easy to create!)
759  return Thyra::createMember(*get_f_space());
760  }
761 
762  // shourld never get here
763  TEUCHOS_ASSERT(false);
764 
765  return Teuchos::null;
766 }
767 
768 template <typename Scalar>
770 addParameter(const std::string & name,const Scalar & initialValue)
771 {
772  Teuchos::Array<std::string> tmp_names;
773  tmp_names.push_back(name);
774 
775  Teuchos::Array<Scalar> tmp_values;
776  tmp_values.push_back(initialValue);
777 
778  return addParameter(tmp_names,tmp_values);
779 }
780 
781 template <typename Scalar>
784  const Teuchos::Array<Scalar> & initialValues)
785 {
786  using Teuchos::RCP;
787  using Teuchos::rcp;
788  using Teuchos::rcp_dynamic_cast;
789  using Teuchos::ptrFromRef;
790 
791  TEUCHOS_ASSERT(names.size()==initialValues.size());
792 
793  int parameter_index = parameters_.size();
794 
795  // Create parameter object
796  RCP<ParameterObject> param = createScalarParameter(names,initialValues);
797  parameters_.push_back(param);
798 
799  // Create vector space for parameter tangent vector
801  Thyra::multiVectorProductVectorSpace(x_space_, param->names->size());
802  tangent_space_.push_back(tan_space);
803 
804  // The number of model evaluator parameters is the number of model parameters (parameters_.size()) plus a tangent
805  // vector for each scalar parameter (tangent_space_.size()) plus a tangent vector for xdot for each scalar parameter.
806  num_me_parameters_ += 2;
807  if (build_transient_support_)
808  ++num_me_parameters_;
809 
810  require_in_args_refresh_ = true;
811  require_out_args_refresh_ = true;
812  this->resetDefaultBase();
813 
814  return parameter_index;
815 }
816 
817 template <typename Scalar>
819 addDistributedParameter(const std::string & key,
820  const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > & vs,
822  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & initial,
824 {
825  distrParamGlobalEvaluationData_.addDataObject(key,ged);
826 
827  int parameter_index = parameters_.size();
828  parameters_.push_back(createDistributedParameter(key,vs,initial,ugi));
829  ++num_me_parameters_;
830 
831  require_in_args_refresh_ = true;
832  require_out_args_refresh_ = true;
833  this->resetDefaultBase();
834 
835  return parameter_index;
836 }
837 
838 template <typename Scalar>
840 addNonParameterGlobalEvaluationData(const std::string & key,
842 {
843  nonParamGlobalEvaluationData_.addDataObject(key,ged);
844 }
845 
846 template <typename Scalar>
848 addFlexibleResponse(const std::string & responseName,
849  const std::vector<WorksetDescriptor> & wkst_desc,
851 {
852  // add a basic response, use x global indexer to define it
853  builder->setDerivativeInformation(lof_);
854 
855  int respIndex = addResponse(responseName,wkst_desc,*builder);
856 
857  // set the builder for this response
858  responses_[respIndex]->builder = builder;
859 
860  return respIndex;
861 }
862 
863 
864 template <typename Scalar>
867  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & f) const
868 {
869  using Teuchos::RCP;
870  using Teuchos::ArrayRCP;
871  using Teuchos::Array;
872  using Teuchos::tuple;
873  using Teuchos::rcp_dynamic_cast;
874 
875  // if neccessary build a ghosted container
876  if(Teuchos::is_null(ghostedContainer_)) {
877  ghostedContainer_ = lof_->buildGhostedLinearObjContainer();
878  lof_->initializeGhostedContainer(panzer::LinearObjContainer::X |
879  panzer::LinearObjContainer::F,*ghostedContainer_);
880  }
881 
883  ae_inargs.container_ = lof_->buildLinearObjContainer(); // we use a new global container
884  ae_inargs.ghostedContainer_ = ghostedContainer_; // we can reuse the ghosted container
885  ae_inargs.alpha = 0.0;
886  ae_inargs.beta = 1.0;
887  //TODO: is this really needed?
888  ae_inargs.step_size = 0.0;
889  ae_inargs.stage_number = 1.0;
890  ae_inargs.evaluate_transient_terms = false;
891  ae_inargs.addGlobalEvaluationData(nonParamGlobalEvaluationData_);
892  ae_inargs.addGlobalEvaluationData(distrParamGlobalEvaluationData_);
893 
894  // this is the tempory target
895  lof_->initializeContainer(panzer::LinearObjContainer::F,*ae_inargs.container_);
896 
897  // here we are building a container, this operation is fast, simply allocating a struct
898  const RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
899  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.container_);
900 
901  TEUCHOS_ASSERT(!Teuchos::is_null(thGlobalContainer));
902 
903  // Ghosted container objects are zeroed out below only if needed for
904  // a particular calculation. This makes it more efficient than
905  // zeroing out all objects in the container here.
906  const RCP<panzer::ThyraObjContainer<Scalar> > thGhostedContainer =
907  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.ghostedContainer_);
908  Thyra::assign(thGhostedContainer->get_f_th().ptr(),0.0);
909 
910  // Set the solution vector (currently all targets require solution).
911  // In the future we may move these into the individual cases below.
912  // A very subtle (and fragile) point: A non-null pointer in global
913  // container triggers export operations during fill. Also, the
914  // introduction of the container is forcing us to cast away const on
915  // arguments that should be const. Another reason to redesign
916  // LinearObjContainer layers.
917  thGlobalContainer->set_x_th(x);
918 
919  // evaluate dirichlet boundary conditions
921  = ae_tm_.template getAsObject<panzer::Traits::Residual>()->evaluateOnlyDirichletBCs(ae_inargs);
922 
923  // allocate the result container
924  RCP<panzer::LinearObjContainer> result = lof_->buildLinearObjContainer(); // we use a new global container
925 
926  // stuff the evaluate boundary conditions into the f spot of the counter ... the x is already filled
927  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(counter)->set_f_th(
928  thGlobalContainer->get_f_th());
929 
930  // stuff the vector that needs applied dirichlet conditions in the the f spot of the result LOC
931  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(result)->set_f_th(f);
932 
933  // use the linear object factory to apply the result
934  lof_->applyDirichletBCs(*counter,*result);
935 }
936 
937 template <typename Scalar>
939 evalModel_D2gDx2(int respIndex,
940  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
941  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_x,
942  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & D2gDx2) const
943 {
944 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
945 
946  // set model parameters from supplied inArgs
947  setParameters(inArgs);
948 
949  {
950  std::string responseName = responses_[respIndex]->name;
952  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Hessian> >(
953  responseLibrary_->getResponse<panzer::Traits::Hessian>(responseName));
954  resp->setDerivative(D2gDx2);
955  }
956 
957  // setup all the assembly in arguments (this is parameters and
958  // x/x_dot). At this point with the exception of the one time dirichlet
959  // beta that is all thats neccessary.
961  setupAssemblyInArgs(inArgs,ae_inargs);
962 
963  ae_inargs.beta = 1.0;
964 
965  auto deltaXContainer = lof_->buildReadOnlyDomainContainer();
966  deltaXContainer->setOwnedVector(delta_x);
967  ae_inargs.addGlobalEvaluationData("DELTA_Solution Gather Container",deltaXContainer);
968 
969  // evaluate responses
970  responseLibrary_->addResponsesToInArgs<panzer::Traits::Hessian>(ae_inargs);
971  responseLibrary_->evaluate<panzer::Traits::Hessian>(ae_inargs);
972 
973  // reset parameters back to nominal values
974  resetParameters();
975 #else
976  (void)respIndex;
977  (void)inArgs;
978  (void)delta_x;
979  (void)D2gDx2;
980  TEUCHOS_ASSERT(false);
981 #endif
982 }
983 
984 template <typename Scalar>
986 evalModel_D2gDxDp(int respIndex,
987  int pIndex,
988  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
989  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_p,
990  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & D2gDxDp) const
991 {
992 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
993 
994  // set model parameters from supplied inArgs
995  setParameters(inArgs);
996 
997  {
998  std::string responseName = responses_[respIndex]->name;
1000  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Hessian> >(
1001  responseLibrary_->getResponse<panzer::Traits::Hessian>(responseName));
1002  resp->setDerivative(D2gDxDp);
1003  }
1004 
1005  // setup all the assembly in arguments (this is parameters and
1006  // x/x_dot). At this point with the exception of the one time dirichlet
1007  // beta that is all thats neccessary.
1008  panzer::AssemblyEngineInArgs ae_inargs;
1009  setupAssemblyInArgs(inArgs,ae_inargs);
1010 
1011  ae_inargs.beta = 1.0;
1012  ae_inargs.second_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1013 
1014  auto deltaPContainer = parameters_[pIndex]->dfdp_rl->getLinearObjFactory()->buildReadOnlyDomainContainer();
1015  deltaPContainer->setOwnedVector(delta_p);
1016  ae_inargs.addGlobalEvaluationData("DELTA_"+(*parameters_[pIndex]->names)[0],deltaPContainer);
1017 
1018  // evaluate responses
1019  responseLibrary_->addResponsesToInArgs<panzer::Traits::Hessian>(ae_inargs);
1020  responseLibrary_->evaluate<panzer::Traits::Hessian>(ae_inargs);
1021 
1022  // reset parameters back to nominal values
1023  resetParameters();
1024 #else
1025  (void)respIndex;
1026  (void)pIndex;
1027  (void)inArgs;
1028  (void)delta_p;
1029  (void)D2gDxDp;
1030  TEUCHOS_ASSERT(false);
1031 #endif
1032 }
1033 
1034 template <typename Scalar>
1036 evalModel_D2gDp2(int respIndex,
1037  int pIndex,
1038  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1039  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_p,
1040  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & D2gDp2) const
1041 {
1042 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1043 
1044  // set model parameters from supplied inArgs
1045  setParameters(inArgs);
1046 
1047  ResponseLibrary<Traits> & rLibrary = *parameters_[pIndex]->dgdp_rl;
1048 
1049  {
1050  std::string responseName = responses_[respIndex]->name;
1052  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Hessian> >(
1053  rLibrary.getResponse<panzer::Traits::Hessian>(responseName));
1054  resp->setDerivative(D2gDp2);
1055  }
1056 
1057  // setup all the assembly in arguments (this is parameters and
1058  // x/x_dot). At this point with the exception of the one time dirichlet
1059  // beta that is all thats neccessary.
1060  panzer::AssemblyEngineInArgs ae_inargs;
1061  setupAssemblyInArgs(inArgs,ae_inargs);
1062 
1063  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
1064  // gather seeds
1065  ae_inargs.first_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1066  ae_inargs.second_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1067 
1068  auto deltaPContainer = parameters_[pIndex]->dfdp_rl->getLinearObjFactory()->buildReadOnlyDomainContainer();
1069  deltaPContainer->setOwnedVector(delta_p);
1070  ae_inargs.addGlobalEvaluationData("DELTA_"+(*parameters_[pIndex]->names)[0],deltaPContainer);
1071 
1072  // evaluate responses
1073  rLibrary.addResponsesToInArgs<panzer::Traits::Hessian>(ae_inargs);
1074  rLibrary.evaluate<panzer::Traits::Hessian>(ae_inargs);
1075 
1076  // reset parameters back to nominal values
1077  resetParameters();
1078 #else
1079  (void)respIndex;
1080  (void)pIndex;
1081  (void)inArgs;
1082  (void)delta_p;
1083  (void)D2gDp2;
1084  TEUCHOS_ASSERT(false);
1085 #endif
1086 }
1087 
1088 template <typename Scalar>
1090 evalModel_D2gDpDx(int respIndex,
1091  int pIndex,
1092  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1093  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_x,
1094  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & D2gDpDx) const
1095 {
1096 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1097 
1098  // set model parameters from supplied inArgs
1099  setParameters(inArgs);
1100 
1101  ResponseLibrary<Traits> & rLibrary = *parameters_[pIndex]->dgdp_rl;
1102 
1103  {
1104  std::string responseName = responses_[respIndex]->name;
1106  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Hessian> >(
1107  rLibrary.getResponse<panzer::Traits::Hessian>(responseName));
1108  resp->setDerivative(D2gDpDx);
1109  }
1110 
1111  // setup all the assembly in arguments (this is parameters and
1112  // x/x_dot). At this point with the exception of the one time dirichlet
1113  // beta that is all thats neccessary.
1114  panzer::AssemblyEngineInArgs ae_inargs;
1115  setupAssemblyInArgs(inArgs,ae_inargs);
1116 
1117  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
1118  // gather seeds
1119  ae_inargs.first_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1120  ae_inargs.second_sensitivities_name = "";
1121 
1122  auto deltaXContainer = lof_->buildReadOnlyDomainContainer();
1123  deltaXContainer->setOwnedVector(delta_x);
1124  ae_inargs.addGlobalEvaluationData("DELTA_Solution Gather Container",deltaXContainer);
1125 
1126  // evaluate responses
1127  rLibrary.addResponsesToInArgs<panzer::Traits::Hessian>(ae_inargs);
1128  rLibrary.evaluate<panzer::Traits::Hessian>(ae_inargs);
1129 
1130  // reset parameters back to nominal values
1131  resetParameters();
1132 #else
1133  (void)respIndex;
1134  (void)pIndex;
1135  (void)inArgs;
1136  (void)delta_x;
1137  (void)D2gDpDx;
1138  TEUCHOS_ASSERT(false);
1139 #endif
1140 }
1141 
1142 template <typename Scalar>
1144 evalModel_D2fDx2(const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1145  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_x,
1146  const Teuchos::RCP<Thyra::LinearOpBase<Scalar> > & D2fDx2) const
1147 {
1148 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1149 
1150  using Teuchos::RCP;
1151  using Teuchos::ArrayRCP;
1152  using Teuchos::Array;
1153  using Teuchos::tuple;
1154  using Teuchos::rcp_dynamic_cast;
1155 
1156  typedef Thyra::ModelEvaluatorBase MEB;
1157 
1158  // Transient or steady-state evaluation is determined by the x_dot
1159  // vector. If this RCP is null, then we are doing a steady-state
1160  // fill.
1161  bool is_transient = false;
1162  if (inArgs.supports(MEB::IN_ARG_x_dot ))
1163  is_transient = !Teuchos::is_null(inArgs.get_x_dot());
1164 
1165  // Make sure construction built in transient support
1166  TEUCHOS_TEST_FOR_EXCEPTION(is_transient && !build_transient_support_, std::runtime_error,
1167  "ModelEvaluator was not built with transient support enabled!");
1168 
1169  //
1170  // Get the output arguments
1171  //
1172  const RCP<Thyra::LinearOpBase<Scalar> > W_out = D2fDx2;
1173 
1174  // setup all the assembly in arguments (this is parameters and
1175  // x/x_dot). At this point with the exception of the one time dirichlet
1176  // beta that is all thats neccessary.
1177  panzer::AssemblyEngineInArgs ae_inargs;
1178  setupAssemblyInArgs(inArgs,ae_inargs);
1179 
1180  auto deltaXContainer = lof_->buildReadOnlyDomainContainer();
1181  deltaXContainer->setOwnedVector(delta_x);
1182  ae_inargs.addGlobalEvaluationData("DELTA_Solution Gather Container",deltaXContainer);
1183 
1184  // set model parameters from supplied inArgs
1185  setParameters(inArgs);
1186 
1187  // handle application of the one time dirichlet beta in the
1188  // assembly engine. Note that this has to be set explicitly
1189  // each time because this badly breaks encapsulation. Essentially
1190  // we must work around the model evaluator abstraction!
1191  if(oneTimeDirichletBeta_on_) {
1192  ae_inargs.dirichlet_beta = oneTimeDirichletBeta_;
1193  ae_inargs.apply_dirichlet_beta = true;
1194 
1195  oneTimeDirichletBeta_on_ = false;
1196  }
1197 
1198  // here we are building a container, this operation is fast, simply allocating a struct
1199  const RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
1200  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.container_);
1201  const RCP<panzer::ThyraObjContainer<Scalar> > thGhostedContainer =
1202  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.ghostedContainer_);
1203 
1204  {
1205  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(D2fDx2)");
1206 
1207  // this dummy nonsense is needed only for scattering dirichlet conditions
1208  RCP<Thyra::VectorBase<Scalar> > dummy_f = Thyra::createMember(f_space_);
1209  thGlobalContainer->set_f_th(dummy_f);
1210  thGlobalContainer->set_A_th(W_out);
1211 
1212  // Zero values in ghosted container objects
1213  thGhostedContainer->initializeMatrix(0.0);
1214 
1215  ae_tm_.template getAsObject<panzer::Traits::Hessian>()->evaluate(ae_inargs);
1216  }
1217 
1218  // HACK: set A to null before calling responses to avoid touching the
1219  // the Jacobian after it has been properly assembled. Should be fixed
1220  // by using a modified version of ae_inargs instead.
1221  thGlobalContainer->set_A_th(Teuchos::null);
1222 
1223  // TODO: Clearing all references prevented a seg-fault with Rythmos,
1224  // which is no longer used. Check if it's still needed.
1225  thGlobalContainer->set_x_th(Teuchos::null);
1226  thGlobalContainer->set_dxdt_th(Teuchos::null);
1227  thGlobalContainer->set_f_th(Teuchos::null);
1228  thGlobalContainer->set_A_th(Teuchos::null);
1229 
1230  // reset parameters back to nominal values
1231  resetParameters();
1232 #else
1233  (void)inArgs;
1234  (void)delta_x;
1235  (void)D2fDx2;
1236  TEUCHOS_ASSERT(false);
1237 #endif
1238 }
1239 
1240 template <typename Scalar>
1243  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1244  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_p,
1245  const Teuchos::RCP<Thyra::LinearOpBase<Scalar> > & D2fDxDp) const
1246 {
1247 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1248 
1249  using Teuchos::RCP;
1250  using Teuchos::ArrayRCP;
1251  using Teuchos::Array;
1252  using Teuchos::tuple;
1253  using Teuchos::rcp_dynamic_cast;
1254 
1255  typedef Thyra::ModelEvaluatorBase MEB;
1256 
1257  // Transient or steady-state evaluation is determined by the x_dot
1258  // vector. If this RCP is null, then we are doing a steady-state
1259  // fill.
1260  bool is_transient = false;
1261  if (inArgs.supports(MEB::IN_ARG_x_dot ))
1262  is_transient = !Teuchos::is_null(inArgs.get_x_dot());
1263 
1264  // Make sure construction built in transient support
1265  TEUCHOS_TEST_FOR_EXCEPTION(is_transient && !build_transient_support_, std::runtime_error,
1266  "ModelEvaluator was not built with transient support enabled!");
1267 
1268  //
1269  // Get the output arguments
1270  //
1271  const RCP<Thyra::LinearOpBase<Scalar> > W_out = D2fDxDp;
1272 
1273  // setup all the assembly in arguments (this is parameters and
1274  // x/x_dot). At this point with the exception of the one time dirichlet
1275  // beta that is all thats neccessary.
1276  panzer::AssemblyEngineInArgs ae_inargs;
1277  setupAssemblyInArgs(inArgs,ae_inargs);
1278 
1279  ae_inargs.second_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1280 
1281  auto deltaPContainer = parameters_[pIndex]->dfdp_rl->getLinearObjFactory()->buildReadOnlyDomainContainer();
1282  deltaPContainer->setOwnedVector(delta_p);
1283  ae_inargs.addGlobalEvaluationData("DELTA_"+(*parameters_[pIndex]->names)[0],deltaPContainer);
1284 
1285  // set model parameters from supplied inArgs
1286  setParameters(inArgs);
1287 
1288  // handle application of the one time dirichlet beta in the
1289  // assembly engine. Note that this has to be set explicitly
1290  // each time because this badly breaks encapsulation. Essentially
1291  // we must work around the model evaluator abstraction!
1292  if(oneTimeDirichletBeta_on_) {
1293  ae_inargs.dirichlet_beta = oneTimeDirichletBeta_;
1294  ae_inargs.apply_dirichlet_beta = true;
1295 
1296  oneTimeDirichletBeta_on_ = false;
1297  }
1298 
1299  // here we are building a container, this operation is fast, simply allocating a struct
1300  const RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
1301  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.container_);
1302  const RCP<panzer::ThyraObjContainer<Scalar> > thGhostedContainer =
1303  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.ghostedContainer_);
1304 
1305  {
1306  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(D2fDxDp)");
1307 
1308  // this dummy nonsense is needed only for scattering dirichlet conditions
1309  RCP<Thyra::VectorBase<Scalar> > dummy_f = Thyra::createMember(f_space_);
1310  thGlobalContainer->set_f_th(dummy_f);
1311  thGlobalContainer->set_A_th(W_out);
1312 
1313  // Zero values in ghosted container objects
1314  thGhostedContainer->initializeMatrix(0.0);
1315 
1316  ae_tm_.template getAsObject<panzer::Traits::Hessian>()->evaluate(ae_inargs);
1317  }
1318 
1319  // HACK: set A to null before calling responses to avoid touching the
1320  // the Jacobian after it has been properly assembled. Should be fixed
1321  // by using a modified version of ae_inargs instead.
1322  thGlobalContainer->set_A_th(Teuchos::null);
1323 
1324  // TODO: Clearing all references prevented a seg-fault with Rythmos,
1325  // which is no longer used. Check if it's still needed.
1326  thGlobalContainer->set_x_th(Teuchos::null);
1327  thGlobalContainer->set_dxdt_th(Teuchos::null);
1328  thGlobalContainer->set_f_th(Teuchos::null);
1329  thGlobalContainer->set_A_th(Teuchos::null);
1330 
1331  // reset parameters back to nominal values
1332  resetParameters();
1333 #else
1334  (void)pIndex;
1335  (void)inArgs;
1336  (void)delta_p;
1337  (void)D2fDxDp;
1338  TEUCHOS_ASSERT(false);
1339 #endif
1340 }
1341 
1342 template <typename Scalar>
1345  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1346  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_x,
1347  const Teuchos::RCP<Thyra::LinearOpBase<Scalar> > & D2fDpDx) const
1348 {
1349 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1350  using Teuchos::RCP;
1351  using Teuchos::rcp_dynamic_cast;
1352  using Teuchos::null;
1353 
1354  // parameter is not distributed
1355  TEUCHOS_ASSERT(parameters_[pIndex]->is_distributed);
1356 
1357  // parameter is distributed but has no global indexer.
1358  // thus the user doesn't want sensitivities!
1359  TEUCHOS_ASSERT(parameters_[pIndex]->dfdp_rl!=null);
1360 
1361  ResponseLibrary<Traits> & rLibrary = *parameters_[pIndex]->dfdp_rl;
1362 
1363  // get the response and tell it to fill the derivative operator
1364  RCP<Response_Residual<Traits::Hessian> > response_hessian =
1365  rcp_dynamic_cast<Response_Residual<Traits::Hessian> >(rLibrary.getResponse<Traits::Hessian>("RESIDUAL"));
1366  response_hessian->setHessian(D2fDpDx);
1367 
1368  // setup all the assembly in arguments (this is parameters and x/x_dot).
1369  // make sure the correct seeding is performed
1370  panzer::AssemblyEngineInArgs ae_inargs;
1371  setupAssemblyInArgs(inArgs,ae_inargs);
1372 
1373  auto deltaXContainer = lof_->buildReadOnlyDomainContainer();
1374  deltaXContainer->setOwnedVector(delta_x);
1375  ae_inargs.addGlobalEvaluationData("DELTA_Solution Gather Container",deltaXContainer);
1376 
1377  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
1378  // gather seeds
1379  ae_inargs.first_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1380  ae_inargs.second_sensitivities_name = "";
1381 
1382  rLibrary.addResponsesToInArgs<Traits::Hessian>(ae_inargs);
1383  rLibrary.evaluate<Traits::Hessian>(ae_inargs);
1384 #else
1385  (void)pIndex;
1386  (void)inArgs;
1387  (void)delta_x;
1388  (void)D2fDpDx;
1389  TEUCHOS_ASSERT(false);
1390 #endif
1391 }
1392 
1393 template <typename Scalar>
1395 evalModel_D2fDp2(int pIndex,
1396  const Thyra::ModelEvaluatorBase::InArgs<Scalar> & inArgs,
1397  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & delta_p,
1398  const Teuchos::RCP<Thyra::LinearOpBase<Scalar> > & D2fDp2) const
1399 {
1400 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
1401  using Teuchos::RCP;
1402  using Teuchos::rcp_dynamic_cast;
1403  using Teuchos::null;
1404 
1405  // parameter is not distributed
1406  TEUCHOS_ASSERT(parameters_[pIndex]->is_distributed);
1407 
1408  // parameter is distributed but has no global indexer.
1409  // thus the user doesn't want sensitivities!
1410  TEUCHOS_ASSERT(parameters_[pIndex]->dfdp_rl!=null);
1411 
1412  ResponseLibrary<Traits> & rLibrary = *parameters_[pIndex]->dfdp_rl;
1413 
1414  // get the response and tell it to fill the derivative operator
1415  RCP<Response_Residual<Traits::Hessian> > response_hessian =
1416  rcp_dynamic_cast<Response_Residual<Traits::Hessian> >(rLibrary.getResponse<Traits::Hessian>("RESIDUAL"));
1417  response_hessian->setHessian(D2fDp2);
1418 
1419  // setup all the assembly in arguments (this is parameters and x/x_dot).
1420  // make sure the correct seeding is performed
1421  panzer::AssemblyEngineInArgs ae_inargs;
1422  setupAssemblyInArgs(inArgs,ae_inargs);
1423 
1424  auto deltaPContainer = parameters_[pIndex]->dfdp_rl->getLinearObjFactory()->buildReadOnlyDomainContainer();
1425  deltaPContainer->setOwnedVector(delta_p);
1426  ae_inargs.addGlobalEvaluationData("DELTA_"+(*parameters_[pIndex]->names)[0],deltaPContainer);
1427 
1428  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
1429  // gather seeds
1430  ae_inargs.first_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1431  ae_inargs.second_sensitivities_name = (*parameters_[pIndex]->names)[0]; // distributed parameters have one name!
1432 
1433  rLibrary.addResponsesToInArgs<Traits::Hessian>(ae_inargs);
1434  rLibrary.evaluate<Traits::Hessian>(ae_inargs);
1435 #else
1436  (void)pIndex;
1437  (void)inArgs;
1438  (void)delta_p;
1439  (void)D2fDp2;
1440  TEUCHOS_ASSERT(false);
1441 #endif
1442 }
1443 
1444 template <typename Scalar>
1446 evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1447  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1448 {
1449  evalModelImpl_basic(inArgs,outArgs);
1450 
1451  // evaluate responses...uses the stored assembly arguments and containers
1452  if(required_basic_g(outArgs))
1453  evalModelImpl_basic_g(inArgs,outArgs);
1454 
1455  // evaluate response derivatives
1456  if(required_basic_dgdx(outArgs))
1457  evalModelImpl_basic_dgdx(inArgs,outArgs);
1458 
1459  // evaluate response derivatives to scalar parameters
1460  if(required_basic_dgdp_scalar(outArgs))
1461  evalModelImpl_basic_dgdp_scalar(inArgs,outArgs);
1462 
1463  // evaluate response derivatives to distributed parameters
1464  if(required_basic_dgdp_distro(outArgs))
1465  evalModelImpl_basic_dgdp_distro(inArgs,outArgs);
1466 
1467  if(required_basic_dfdp_scalar(outArgs)) {
1468  if (do_fd_dfdp_)
1469  evalModelImpl_basic_dfdp_scalar_fd(inArgs,outArgs);
1470  else
1471  evalModelImpl_basic_dfdp_scalar(inArgs,outArgs);
1472  }
1473 
1474  if(required_basic_dfdp_distro(outArgs))
1475  evalModelImpl_basic_dfdp_distro(inArgs,outArgs);
1476 }
1477 
1478 template <typename Scalar>
1480 evalModelImpl_basic(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1481  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1482 {
1483  using Teuchos::RCP;
1484  using Teuchos::ArrayRCP;
1485  using Teuchos::Array;
1486  using Teuchos::tuple;
1487  using Teuchos::rcp_dynamic_cast;
1488 
1489  typedef Thyra::ModelEvaluatorBase MEB;
1490 
1491  // Transient or steady-state evaluation is determined by the x_dot
1492  // vector. If this RCP is null, then we are doing a steady-state
1493  // fill.
1494  bool is_transient = false;
1495  if (inArgs.supports(MEB::IN_ARG_x_dot ))
1496  is_transient = !Teuchos::is_null(inArgs.get_x_dot());
1497 
1498  // Make sure construction built in transient support
1499  TEUCHOS_TEST_FOR_EXCEPTION(is_transient && !build_transient_support_, std::runtime_error,
1500  "ModelEvaluator was not built with transient support enabled!");
1501 
1502  //
1503  // Get the output arguments
1504  //
1505  const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
1506  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
1507 
1508  // see if the user wants us to do anything
1509  if(Teuchos::is_null(f_out) && Teuchos::is_null(W_out) ) {
1510  return;
1511  }
1512 
1513  // setup all the assembly in arguments (this is parameters and
1514  // x/x_dot). At this point with the exception of the one time dirichlet
1515  // beta that is all thats neccessary.
1516  panzer::AssemblyEngineInArgs ae_inargs;
1517  setupAssemblyInArgs(inArgs,ae_inargs);
1518 
1519  // set model parameters from supplied inArgs
1520  setParameters(inArgs);
1521 
1522  // handle application of the one time dirichlet beta in the
1523  // assembly engine. Note that this has to be set explicitly
1524  // each time because this badly breaks encapsulation. Essentially
1525  // we must work around the model evaluator abstraction!
1526  if(oneTimeDirichletBeta_on_) {
1527  ae_inargs.dirichlet_beta = oneTimeDirichletBeta_;
1528  ae_inargs.apply_dirichlet_beta = true;
1529 
1530  oneTimeDirichletBeta_on_ = false;
1531  }
1532 
1533  // here we are building a container, this operation is fast, simply allocating a struct
1534  const RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
1535  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.container_);
1536  const RCP<panzer::ThyraObjContainer<Scalar> > thGhostedContainer =
1537  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(ae_inargs.ghostedContainer_);
1538 
1539  if (!Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
1540  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f and J)");
1541 
1542  // only add auxiliary global data if Jacobian is being formed
1543  ae_inargs.addGlobalEvaluationData(nonParamGlobalEvaluationData_);
1544 
1545  // Set the targets
1546  thGlobalContainer->set_f_th(f_out);
1547  thGlobalContainer->set_A_th(W_out);
1548 
1549  // Zero values in ghosted container objects
1550  Thyra::assign(thGhostedContainer->get_f_th().ptr(),0.0);
1551  thGhostedContainer->initializeMatrix(0.0);
1552 
1553  ae_tm_.template getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
1554  }
1555  else if(!Teuchos::is_null(f_out) && Teuchos::is_null(W_out)) {
1556 
1557  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(f)");
1558 
1559  // don't add auxiliary global data if Jacobian is not computed.
1560  // this leads to zeroing of aux ops in special cases.
1561 
1562  thGlobalContainer->set_f_th(f_out);
1563 
1564  // Zero values in ghosted container objects
1565  Thyra::assign(thGhostedContainer->get_f_th().ptr(),0.0);
1566 
1567  ae_tm_.template getAsObject<panzer::Traits::Residual>()->evaluate(ae_inargs);
1568  }
1569  else if(Teuchos::is_null(f_out) && !Teuchos::is_null(W_out)) {
1570 
1571  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(J)");
1572 
1573  // only add auxiliary global data if Jacobian is being formed
1574  ae_inargs.addGlobalEvaluationData(nonParamGlobalEvaluationData_);
1575 
1576  // this dummy nonsense is needed only for scattering dirichlet conditions
1577  RCP<Thyra::VectorBase<Scalar> > dummy_f = Thyra::createMember(f_space_);
1578  thGlobalContainer->set_f_th(dummy_f);
1579  thGlobalContainer->set_A_th(W_out);
1580 
1581  // Zero values in ghosted container objects
1582  thGhostedContainer->initializeMatrix(0.0);
1583 
1584  ae_tm_.template getAsObject<panzer::Traits::Jacobian>()->evaluate(ae_inargs);
1585  }
1586 
1587  // HACK: set A to null before calling responses to avoid touching the
1588  // the Jacobian after it has been properly assembled. Should be fixed
1589  // by using a modified version of ae_inargs instead.
1590  thGlobalContainer->set_A_th(Teuchos::null);
1591 
1592  // TODO: Clearing all references prevented a seg-fault with Rythmos,
1593  // which is no longer used. Check if it's still needed.
1594  thGlobalContainer->set_x_th(Teuchos::null);
1595  thGlobalContainer->set_dxdt_th(Teuchos::null);
1596  thGlobalContainer->set_f_th(Teuchos::null);
1597  thGlobalContainer->set_A_th(Teuchos::null);
1598 
1599  // reset parameters back to nominal values
1600  resetParameters();
1601 
1602  const bool writeToFile = false;
1603  if (writeToFile && nonnull(W_out)) {
1604  const auto check_blocked = Teuchos::rcp_dynamic_cast<::Thyra::BlockedLinearOpBase<double> >(W_out,false);
1605  if (check_blocked) {
1606  const int numBlocks = check_blocked->productDomain()->numBlocks();
1607  const int rangeBlocks = check_blocked->productRange()->numBlocks();
1608  TEUCHOS_ASSERT(numBlocks == rangeBlocks); // not true for optimization
1609  for (int row=0; row < numBlocks; ++row) {
1610  for (int col=0; col < numBlocks; ++col) {
1611  using LO = panzer::LocalOrdinal;
1612  using GO = panzer::GlobalOrdinal;
1613  using NodeT = panzer::TpetraNodeType;
1614  const auto thyraTpetraOperator = Teuchos::rcp_dynamic_cast<::Thyra::TpetraLinearOp<double,LO,GO,NodeT>>(check_blocked->getNonconstBlock(row,col),true);
1615  const auto tpetraCrsMatrix = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<double,LO,GO,NodeT>>(thyraTpetraOperator->getTpetraOperator(),true);
1616  tpetraCrsMatrix->print(std::cout);
1617  std::stringstream ss;
1618  ss << "W_out_" << write_matrix_count_ << ".rank_" << tpetraCrsMatrix->getMap()->getComm()->getRank() << ".block_" << row << "_" << col << ".txt";
1619  std::fstream fs(ss.str().c_str(),std::fstream::out|std::fstream::trunc);
1620  Teuchos::FancyOStream fos(Teuchos::rcpFromRef(fs));
1621  tpetraCrsMatrix->describe(fos,Teuchos::VERB_EXTREME);
1622  fs.close();
1623  }
1624  }
1625  }
1626  else {
1627  using LO = panzer::LocalOrdinal;
1628  using GO = panzer::GlobalOrdinal;
1629  using NodeT = panzer::TpetraNodeType;
1630  const auto thyraTpetraOperator = Teuchos::rcp_dynamic_cast<::Thyra::TpetraLinearOp<double,LO,GO,NodeT>>(W_out,true);
1631  const auto tpetraCrsMatrix = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<double,LO,GO,NodeT>>(thyraTpetraOperator->getTpetraOperator(),true);
1632  tpetraCrsMatrix->print(std::cout);
1633  std::stringstream ss;
1634  ss << "W_out_" << write_matrix_count_ << ".rank_" << tpetraCrsMatrix->getMap()->getComm()->getRank() << ".txt";
1635  std::fstream fs(ss.str().c_str(),std::fstream::out|std::fstream::trunc);
1636  Teuchos::FancyOStream fos(Teuchos::rcpFromRef(fs));
1637  tpetraCrsMatrix->describe(fos,Teuchos::VERB_EXTREME);
1638  fs.close();
1639  }
1640  ++write_matrix_count_;
1641  }
1642 
1643 }
1644 
1645 template <typename Scalar>
1647 evalModelImpl_basic_g(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1648  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1649 {
1650  // optional sanity check
1651  // TEUCHOS_ASSERT(required_basic_g(outArgs));
1652 
1653  // setup all the assembly in arguments (this is parameters and
1654  // x/x_dot). At this point with the exception of the one time dirichlet
1655  // beta that is all thats neccessary.
1656  panzer::AssemblyEngineInArgs ae_inargs;
1657  setupAssemblyInArgs(inArgs,ae_inargs);
1658 
1659  // set model parameters from supplied inArgs
1660  setParameters(inArgs);
1661 
1662  for(std::size_t i=0;i<responses_.size();i++) {
1663  Teuchos::RCP<Thyra::VectorBase<Scalar> > vec = outArgs.get_g(i);
1664  if(vec!=Teuchos::null) {
1665  std::string responseName = responses_[i]->name;
1667  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Residual> >(
1668  responseLibrary_->getResponse<panzer::Traits::Residual>(responseName));
1669  resp->setVector(vec);
1670  }
1671  }
1672 
1673  // evaluator responses
1674  responseLibrary_->addResponsesToInArgs<panzer::Traits::Residual>(ae_inargs);
1675  responseLibrary_->evaluate<panzer::Traits::Residual>(ae_inargs);
1676 
1677  // reset parameters back to nominal values
1678  resetParameters();
1679 }
1680 
1681 template <typename Scalar>
1682 void
1684 evalModelImpl_basic_dgdx(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1685  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1686 {
1687  typedef Thyra::ModelEvaluatorBase MEB;
1688 
1689  // optional sanity check
1690  TEUCHOS_ASSERT(required_basic_dgdx(outArgs));
1691 
1692  // set model parameters from supplied inArgs
1693  setParameters(inArgs);
1694 
1695  for(std::size_t i=0;i<responses_.size();i++) {
1696  // get "Vector" out of derivative, if its something else, throw an exception
1697  MEB::Derivative<Scalar> deriv = outArgs.get_DgDx(i);
1698  if(deriv.isEmpty())
1699  continue;
1700 
1701  Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > vec = deriv.getMultiVector();
1702 
1703  if(vec!=Teuchos::null) {
1704 
1705  std::string responseName = responses_[i]->name;
1707  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Jacobian> >(
1708  responseLibrary_->getResponse<panzer::Traits::Jacobian>(responseName));
1709  resp->setDerivative(vec);
1710  }
1711  }
1712 
1713  // setup all the assembly in arguments (this is parameters and
1714  // x/x_dot). At this point with the exception of the one time dirichlet
1715  // beta that is all thats neccessary.
1716  panzer::AssemblyEngineInArgs ae_inargs;
1717  setupAssemblyInArgs(inArgs,ae_inargs);
1718 
1719  // evaluate responses
1720  responseLibrary_->addResponsesToInArgs<panzer::Traits::Jacobian>(ae_inargs);
1721  responseLibrary_->evaluate<panzer::Traits::Jacobian>(ae_inargs);
1722 
1723  // reset parameters back to nominal values
1724  resetParameters();
1725 }
1726 
1727 template <typename Scalar>
1728 void
1730 evalModelImpl_basic_dgdp_scalar(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1731  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1732 {
1733  using Teuchos::RCP;
1734  using Teuchos::rcp;
1735  using Teuchos::rcp_dynamic_cast;
1736 
1737  typedef Thyra::ModelEvaluatorBase MEB;
1738 
1739  // optional sanity check
1740  TEUCHOS_ASSERT(required_basic_dgdp_scalar(outArgs));
1741 
1742  // First find all of the active parameters for all responses
1743  std::vector<std::string> activeParameterNames;
1744  std::vector<int> activeParameters;
1745  int totalParameterCount = 0;
1746  for(std::size_t j=0; j<parameters_.size(); j++) {
1747 
1748  // skip non-scalar parameters
1749  if(parameters_[j]->is_distributed)
1750  continue;
1751 
1752  bool is_active = false;
1753  for(std::size_t i=0;i<responses_.size(); i++) {
1754 
1755  MEB::Derivative<Scalar> deriv = outArgs.get_DgDp(i,j);
1756  if(deriv.isEmpty())
1757  continue;
1758 
1759  Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > vec = deriv.getMultiVector();
1760  if(vec!=Teuchos::null) {
1761  // get the response and tell it to fill the derivative vector
1762  std::string responseName = responses_[i]->name;
1765  responseLibrary_->getResponse<panzer::Traits::Tangent>(responseName));
1766  resp->setVector(vec);
1767  is_active = true;
1768  }
1769  }
1770 
1771  if (is_active) {
1772  for (std::size_t k=0; k<parameters_[j]->scalar_value.size(); k++) {
1773  std::string name = "PARAMETER_SENSITIVIES: "+(*parameters_[j]->names)[k];
1774  activeParameterNames.push_back(name);
1775  totalParameterCount++;
1776  }
1777  activeParameters.push_back(j);
1778  }
1779  }
1780 
1781  // setup all the assembly in arguments
1782  panzer::AssemblyEngineInArgs ae_inargs;
1783  setupAssemblyInArgs(inArgs,ae_inargs);
1784 
1785  // add active parameter names to assembly in-args
1786  RCP<panzer::GlobalEvaluationData> ged_activeParameters =
1787  rcp(new panzer::ParameterList_GlobalEvaluationData(activeParameterNames));
1788  ae_inargs.addGlobalEvaluationData("PARAMETER_NAMES",ged_activeParameters);
1789 
1790  // Initialize Fad components of all active parameters
1791  int paramIndex = 0;
1792  for (std::size_t ap=0; ap<activeParameters.size(); ++ap) {
1793  const int j = activeParameters[ap];
1794  for (unsigned int k=0; k < parameters_[j]->scalar_value.size(); k++) {
1795  panzer::Traits::FadType p(totalParameterCount, parameters_[j]->scalar_value[k].baseValue);
1796  p.fastAccessDx(paramIndex) = 1.0;
1797  parameters_[j]->scalar_value[k].family->template setValue<panzer::Traits::Tangent>(p);
1798  paramIndex++;
1799  }
1800  }
1801 
1802  // make sure that the total parameter count and the total parameter index match up
1803  TEUCHOS_ASSERT(paramIndex==totalParameterCount);
1804 
1805  // evaluate response tangent
1806  if(totalParameterCount>0) {
1807  responseLibrary_->addResponsesToInArgs<Traits::Tangent>(ae_inargs);
1808  responseLibrary_->evaluate<Traits::Tangent>(ae_inargs);
1809  }
1810 }
1811 
1812 template <typename Scalar>
1813 void
1815 evalModelImpl_basic_dgdp_distro(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1816  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1817 {
1818  typedef Thyra::ModelEvaluatorBase MEB;
1819 
1820  // optional sanity check
1821  TEUCHOS_ASSERT(required_basic_dgdp_distro(outArgs));
1822 
1823  // loop over parameters, and then build a dfdp_rl only if they are distributed
1824  // and the user has provided the UGI. Note that this may be overly expensive if they
1825  // don't actually want those sensitivites because memory will be allocated unneccesarily.
1826  // It would be good to do this "just in time", but for now this is sufficient.
1827  for(std::size_t p=0;p<parameters_.size();p++) {
1828 
1829  // parameter is not distributed, a different path is
1830  // taken for those to compute dfdp
1831  if(!parameters_[p]->is_distributed)
1832  continue;
1833 
1834  ResponseLibrary<Traits> & rLibrary = *parameters_[p]->dgdp_rl;
1835 
1836  for(std::size_t r=0;r<responses_.size();r++) {
1837  // have derivatives been requested?
1838  MEB::Derivative<Scalar> deriv = outArgs.get_DgDp(r,p);
1839  if(deriv.isEmpty())
1840  continue;
1841 
1842  Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > vec = deriv.getMultiVector();
1843 
1844  if(vec!=Teuchos::null) {
1845 
1846  // get the response and tell it to fill the derivative vector
1847  std::string responseName = responses_[r]->name;
1849  = Teuchos::rcp_dynamic_cast<panzer::ResponseMESupportBase<panzer::Traits::Jacobian> >(
1850  rLibrary.getResponse<panzer::Traits::Jacobian>(responseName));
1851 
1852  resp->setDerivative(vec);
1853  }
1854  }
1855 
1856  // setup all the assembly in arguments (this is parameters and x/x_dot).
1857  // make sure the correct seeding is performed
1858  panzer::AssemblyEngineInArgs ae_inargs;
1859  setupAssemblyInArgs(inArgs,ae_inargs);
1860 
1861  ae_inargs.first_sensitivities_name = (*parameters_[p]->names)[0]; // distributed parameters have one name!
1862  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
1863  // gather seeds
1864 
1865  // evaluate responses
1866  rLibrary.addResponsesToInArgs<Traits::Jacobian>(ae_inargs);
1867  rLibrary.evaluate<Traits::Jacobian>(ae_inargs);
1868  }
1869 }
1870 
1871 template <typename Scalar>
1872 void
1874 evalModelImpl_basic_dfdp_scalar(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1875  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1876 {
1877  using Teuchos::RCP;
1878  using Teuchos::rcp_dynamic_cast;
1879 
1880  typedef Thyra::ModelEvaluatorBase MEB;
1881 
1882  TEUCHOS_ASSERT(required_basic_dfdp_scalar(outArgs));
1883 
1884  // setup all the assembly in arguments (this is parameters and
1885  // x/x_dot). At this point with the exception of the one time dirichlet
1886  // beta that is all thats neccessary.
1887  panzer::AssemblyEngineInArgs ae_inargs;
1888  setupAssemblyInArgs(inArgs,ae_inargs);
1889 
1890  // First: Fill the output vectors from the input arguments structure. Put them
1891  // in the global evaluation data container so they are correctly communicated.
1893 
1894  std::vector<std::string> activeParameters;
1895 
1896  int totalParameterCount = 0;
1897  for(std::size_t i=0; i < parameters_.size(); i++) {
1898  // skip non-scalar parameters
1899  if(parameters_[i]->is_distributed)
1900  continue;
1901 
1902  // have derivatives been requested?
1903  MEB::Derivative<Scalar> deriv = outArgs.get_DfDp(i);
1904  if(deriv.isEmpty())
1905  continue;
1906 
1907  // grab multivector, make sure its the right dimension
1908  Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > mVec = deriv.getMultiVector();
1909  TEUCHOS_ASSERT(mVec->domain()->dim()==Teuchos::as<int>(parameters_[i]->scalar_value.size()));
1910 
1911  for (std::size_t j=0; j < parameters_[i]->scalar_value.size(); j++) {
1912 
1913  // build containers for each vector
1916  RCP<LinearObjContainer> globalContainer = loc_pair->getGlobalLOC();
1917 
1918  // stuff target vector into global container
1919  RCP<Thyra::VectorBase<Scalar> > vec = mVec->col(j);
1920  RCP<panzer::ThyraObjContainer<Scalar> > thGlobalContainer =
1921  Teuchos::rcp_dynamic_cast<panzer::ThyraObjContainer<Scalar> >(globalContainer);
1922  thGlobalContainer->set_f_th(vec);
1923 
1924  // add container into in args object
1925  std::string name = "PARAMETER_SENSITIVIES: "+(*parameters_[i]->names)[j];
1926  ae_inargs.addGlobalEvaluationData(name,loc_pair->getGhostedLOC());
1927  ae_inargs.addGlobalEvaluationData(name+"_pair",loc_pair);
1928 
1929  activeParameters.push_back(name);
1930  totalParameterCount++;
1931  }
1932  }
1933 
1934  // Second: For all parameters that require derivative sensitivities, put in a name
1935  // so that the scatter can realize which sensitivity vectors it needs to fill
1937 
1938  RCP<GlobalEvaluationData> ged_activeParameters
1939  = Teuchos::rcp(new ParameterList_GlobalEvaluationData(activeParameters));
1940  ae_inargs.addGlobalEvaluationData("PARAMETER_NAMES",ged_activeParameters);
1941 
1942  // Third: Now seed all the parameters in the parameter vector so that derivatives
1943  // can be properly computed.
1945 
1946  int paramIndex = 0;
1947  for(std::size_t i=0; i < parameters_.size(); i++) {
1948  // skip non-scalar parameters
1949  if(parameters_[i]->is_distributed)
1950  continue;
1951 
1952  // don't modify the parameter if its not needed
1953  MEB::Derivative<Scalar> deriv = outArgs.get_DfDp(i);
1954  if(deriv.isEmpty()) {
1955  // reinitialize values that should not have sensitivities computed (this is a precaution)
1956  for (unsigned int j=0; j < parameters_[i]->scalar_value.size(); j++) {
1957  Traits::FadType p = Traits::FadType(totalParameterCount,
1958  parameters_[i]->scalar_value[j].baseValue);
1959  parameters_[i]->scalar_value[j].family->template setValue<panzer::Traits::Tangent>(p);
1960  }
1961  continue;
1962  }
1963  else {
1964  // loop over each parameter in the vector, initializing the AD type
1965  for (unsigned int j=0; j < parameters_[i]->scalar_value.size(); j++) {
1966  Traits::FadType p = Traits::FadType(totalParameterCount,
1967  parameters_[i]->scalar_value[j].baseValue);
1968  p.fastAccessDx(paramIndex) = 1.0;
1969  parameters_[i]->scalar_value[j].family->template setValue<panzer::Traits::Tangent>(p);
1970  paramIndex++;
1971  }
1972  }
1973  }
1974 
1975  // make sure that the total parameter count and the total parameter index match up
1976  TEUCHOS_ASSERT(paramIndex==totalParameterCount);
1977 
1978  // Fourth: Actually evaluate the residual's sensitivity to the parameters
1980 
1981  if(totalParameterCount>0) {
1982  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(df/dp)");
1983  ae_tm_.getAsObject<panzer::Traits::Tangent>()->evaluate(ae_inargs);
1984  }
1985 }
1986 
1987 template <typename Scalar>
1988 void
1990 evalModelImpl_basic_dfdp_scalar_fd(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
1991  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
1992 {
1993  PANZER_FUNC_TIME_MONITOR("panzer::ModelEvaluator::evalModel(df/dp)");
1994 
1995  using Teuchos::RCP;
1996  using Teuchos::rcp_dynamic_cast;
1997 
1998  typedef Thyra::ModelEvaluatorBase MEB;
1999 
2000  TEUCHOS_ASSERT(required_basic_dfdp_scalar(outArgs));
2001 
2002  // First evaluate the model without df/dp for the base point
2003  // Maybe it would be better to set all outArgs and then remove the df/dp ones,
2004  // but I couldn't get that to work.
2005  MEB::OutArgs<Scalar> outArgs_base = this->createOutArgs();
2006  if (outArgs.get_f() == Teuchos::null)
2007  outArgs_base.set_f(Thyra::createMember(this->get_f_space()));
2008  else
2009  outArgs_base.set_f(outArgs.get_f());
2010  outArgs_base.set_W_op(outArgs.get_W_op());
2011  this->evalModel(inArgs, outArgs_base);
2012  RCP<const Thyra::VectorBase<Scalar> > f = outArgs_base.get_f();
2013  RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x();
2015  if (inArgs.supports(MEB::IN_ARG_x_dot))
2016  x_dot = inArgs.get_x_dot();
2017 
2018  // Create in/out args for FD calculation
2019  RCP<Thyra::VectorBase<Scalar> > fd = Thyra::createMember(this->get_f_space());
2020  MEB::OutArgs<Scalar> outArgs_fd = this->createOutArgs();
2021  outArgs_fd.set_f(fd);
2022 
2023  RCP<Thyra::VectorBase<Scalar> > xd = Thyra::createMember(this->get_x_space());
2025  if (x_dot != Teuchos::null)
2026  xd_dot = Thyra::createMember(this->get_x_space());
2027  MEB::InArgs<Scalar> inArgs_fd = this->createInArgs();
2028  inArgs_fd.setArgs(inArgs); // This sets all inArgs that we don't override below
2029  inArgs_fd.set_x(xd);
2030  if (x_dot != Teuchos::null)
2031  inArgs_fd.set_x_dot(xd_dot);
2032 
2033  const double h = fd_perturb_size_;
2034  for(std::size_t i=0; i < parameters_.size(); i++) {
2035 
2036  // skip non-scalar parameters
2037  if(parameters_[i]->is_distributed)
2038  continue;
2039 
2040  // have derivatives been requested?
2041  MEB::Derivative<Scalar> deriv = outArgs.get_DfDp(i);
2042  if(deriv.isEmpty())
2043  continue;
2044 
2045  // grab multivector, make sure its the right dimension
2046  RCP<Thyra::MultiVectorBase<Scalar> > dfdp = deriv.getMultiVector();
2047  TEUCHOS_ASSERT(dfdp->domain()->dim()==Teuchos::as<int>(parameters_[i]->scalar_value.size()));
2048 
2049  // Get parameter vector and tangent vectors
2050  RCP<const Thyra::VectorBase<Scalar> > p = inArgs.get_p(i);
2051  RCP<const Thyra::VectorBase<Scalar> > dx_v = inArgs.get_p(i+parameters_.size());
2053  rcp_dynamic_cast<const Thyra::DefaultMultiVectorProductVector<Scalar> >(dx_v,true)->getMultiVector();
2056  if (x_dot != Teuchos::null) {
2057  dx_dot_v =inArgs.get_p(i+parameters_.size()+tangent_space_.size());
2058  dx_dot =
2059  rcp_dynamic_cast<const Thyra::DefaultMultiVectorProductVector<Scalar> >(dx_dot_v,true)->getMultiVector();
2060  }
2061 
2062  // Create perturbed parameter vector
2063  RCP<Thyra::VectorBase<Scalar> > pd = Thyra::createMember(this->get_p_space(i));
2064  inArgs_fd.set_p(i,pd);
2065 
2066  for (std::size_t j=0; j < parameters_[i]->scalar_value.size(); j++) {
2067 
2068  // Perturb parameter vector
2069  Thyra::copy(*p, pd.ptr());
2070  Thyra::set_ele(j, Thyra::get_ele(*p,j)+h, pd.ptr());
2071 
2072  // Perturb state vectors using tangents
2073  Thyra::V_VpStV(xd.ptr(), *x, h, *(dx)->col(j));
2074  if (x_dot != Teuchos::null)
2075  Thyra::V_VpStV(xd_dot.ptr(), *x_dot, h, *(dx_dot)->col(j));
2076 
2077  // Evaluate perturbed residual
2078  Thyra::assign(fd.ptr(), 0.0);
2079  this->evalModel(inArgs_fd, outArgs_fd);
2080 
2081  // FD calculation
2082  Thyra::V_StVpStV(dfdp->col(j).ptr(), 1.0/h, *fd, -1.0/h, *f);
2083 
2084  // Reset parameter back to un-perturbed value
2085  parameters_[i]->scalar_value[j].family->setRealValueForAllTypes(Thyra::get_ele(*p,j));
2086 
2087  }
2088  }
2089 }
2090 
2091 template <typename Scalar>
2092 void
2094 evalModelImpl_basic_dfdp_distro(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
2095  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2096 {
2097  using Teuchos::RCP;
2098  using Teuchos::rcp_dynamic_cast;
2099  using Teuchos::null;
2100 
2101  typedef Thyra::ModelEvaluatorBase MEB;
2102 
2103  TEUCHOS_ASSERT(required_basic_dfdp_distro(outArgs));
2104 
2105  // loop over parameters, and then build a dfdp_rl only if they are distributed
2106  // and the user has provided the UGI. Note that this may be overly expensive if they
2107  // don't actually want those sensitivites because memory will be allocated unneccesarily.
2108  // It would be good to do this "just in time", but for now this is sufficient.
2109  for(std::size_t p=0;p<parameters_.size();p++) {
2110 
2111  // parameter is not distributed, a different path is
2112  // taken for those to compute dfdp
2113  if(!parameters_[p]->is_distributed)
2114  continue;
2115 
2116  // parameter is distributed but has no global indexer.
2117  // thus the user doesn't want sensitivities!
2118  if(parameters_[p]->dfdp_rl==null)
2119  continue;
2120 
2121  // have derivatives been requested?
2122  MEB::Derivative<Scalar> deriv = outArgs.get_DfDp(p);
2123  if(deriv.isEmpty())
2124  continue;
2125 
2126  ResponseLibrary<Traits> & rLibrary = *parameters_[p]->dfdp_rl;
2127 
2128  // get the response and tell it to fill the derivative operator
2129  RCP<Response_Residual<Traits::Jacobian> > response_jacobian =
2130  rcp_dynamic_cast<Response_Residual<Traits::Jacobian> >(rLibrary.getResponse<Traits::Jacobian>("RESIDUAL"));
2131  response_jacobian->setJacobian(deriv.getLinearOp());
2132 
2133  // setup all the assembly in arguments (this is parameters and x/x_dot).
2134  // make sure the correct seeding is performed
2135  panzer::AssemblyEngineInArgs ae_inargs;
2136  setupAssemblyInArgs(inArgs,ae_inargs);
2137 
2138  ae_inargs.first_sensitivities_name = (*parameters_[p]->names)[0]; // distributed parameters have one name!
2139  ae_inargs.gather_seeds.push_back(1.0); // this assumes that gather point is always the zero index of
2140  // gather seeds
2141  rLibrary.addResponsesToInArgs<Traits::Jacobian>(ae_inargs);
2142 
2143  rLibrary.evaluate<Traits::Jacobian>(ae_inargs);
2144  }
2145 }
2146 
2147 template <typename Scalar>
2149 required_basic_g(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2150 {
2151  // determine if any of the outArgs are not null!
2152  bool activeGArgs = false;
2153  for(int i=0;i<outArgs.Ng();i++)
2154  activeGArgs |= (outArgs.get_g(i)!=Teuchos::null);
2155 
2156  return activeGArgs | required_basic_dgdx(outArgs);
2157 }
2158 
2159 template <typename Scalar>
2161 required_basic_dgdx(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2162 {
2163  typedef Thyra::ModelEvaluatorBase MEB;
2164 
2165  // determine if any of the outArgs are not null!
2166  bool activeGArgs = false;
2167  for(int i=0;i<outArgs.Ng();i++) {
2168  // no derivatives are supported
2169  if(outArgs.supports(MEB::OUT_ARG_DgDx,i).none())
2170  continue;
2171 
2172  // this is basically a redundant computation
2173  activeGArgs |= (!outArgs.get_DgDx(i).isEmpty());
2174  }
2175 
2176  return activeGArgs;
2177 }
2178 
2179 template <typename Scalar>
2181 required_basic_dgdp_scalar(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2182 {
2183  typedef Thyra::ModelEvaluatorBase MEB;
2184 
2185  // determine if any of the outArgs are not null!
2186  bool activeGArgs = false;
2187  for(int i=0;i<outArgs.Ng();i++) {
2188  for(int p=0;p<Teuchos::as<int>(parameters_.size());p++) {
2189 
2190  // only look at scalar parameters
2191  if(parameters_[p]->is_distributed)
2192  continue;
2193 
2194  // no derivatives are supported
2195  if(outArgs.supports(MEB::OUT_ARG_DgDp,i,p).none())
2196  continue;
2197 
2198  activeGArgs |= (!outArgs.get_DgDp(i,p).isEmpty());
2199  }
2200  }
2201 
2202  return activeGArgs;
2203 }
2204 
2205 template <typename Scalar>
2207 required_basic_dgdp_distro(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2208 {
2209  typedef Thyra::ModelEvaluatorBase MEB;
2210 
2211  // determine if any of the outArgs are not null!
2212  bool activeGArgs = false;
2213  for(int i=0;i<outArgs.Ng();i++) {
2214  for(int p=0;p<Teuchos::as<int>(parameters_.size());p++) {
2215 
2216  // only look at distributed parameters
2217  if(!parameters_[p]->is_distributed)
2218  continue;
2219 
2220  // no derivatives are supported
2221  if(outArgs.supports(MEB::OUT_ARG_DgDp,i,p).none())
2222  continue;
2223 
2224  activeGArgs |= (!outArgs.get_DgDp(i,p).isEmpty());
2225  }
2226  }
2227 
2228  return activeGArgs;
2229 }
2230 
2231 template <typename Scalar>
2233 required_basic_dfdp_scalar(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2234 {
2235  typedef Thyra::ModelEvaluatorBase MEB;
2236 
2237  // determine if any of the outArgs are not null!
2238  bool activeFPArgs = false;
2239  for(int i=0;i<Teuchos::as<int>(parameters_.size());i++) {
2240 
2241  // this is for scalar parameters only
2242  if(parameters_[i]->is_distributed)
2243  continue;
2244 
2245  // no derivatives are supported
2246  if(outArgs.supports(MEB::OUT_ARG_DfDp,i).none())
2247  continue;
2248 
2249  // this is basically a redundant computation
2250  activeFPArgs |= (!outArgs.get_DfDp(i).isEmpty());
2251  }
2252 
2253  return activeFPArgs;
2254 }
2255 
2256 template <typename Scalar>
2258 required_basic_dfdp_distro(const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
2259 {
2260  typedef Thyra::ModelEvaluatorBase MEB;
2261 
2262  // determine if any of the outArgs are not null!
2263  bool activeFPArgs = false;
2264  for(int i=0;i<Teuchos::as<int>(parameters_.size());i++) {
2265 
2266  // this is for scalar parameters only
2267  if(!parameters_[i]->is_distributed)
2268  continue;
2269 
2270  // no derivatives are supported
2271  if(outArgs.supports(MEB::OUT_ARG_DfDp,i).none())
2272  continue;
2273 
2274  // this is basically a redundant computation
2275  activeFPArgs |= (!outArgs.get_DfDp(i).isEmpty());
2276  }
2277 
2278  return activeFPArgs;
2279 }
2280 
2281 template <typename Scalar>
2285  const std::vector<Teuchos::RCP<panzer::PhysicsBlock> >& physicsBlocks,
2286  const std::vector<panzer::BC> & bcs,
2287  const panzer::EquationSetFactory & eqset_factory,
2288  const panzer::BCStrategyFactory& bc_factory,
2290  const Teuchos::ParameterList& closure_models,
2291  const Teuchos::ParameterList& user_data,
2292  const bool write_graphviz_file,
2293  const std::string& graphviz_file_prefix)
2294 {
2295  using Teuchos::RCP;
2296  using Teuchos::rcp;
2297  using Teuchos::null;
2298 
2299  // loop over parameters, and then build a dfdp_rl only if they are distributed
2300  // and the user has provided the UGI. Note that this may be overly expensive if they
2301  // don't actually want those sensitivites because memory will be allocated unneccesarily.
2302  // It would be good to do this "just in time", but for now this is sufficient.
2303  for(std::size_t p=0;p<parameters_.size();p++) {
2304  // parameter is not distributed, a different path is
2305  // taken for those to compute dfdp
2306  if(!parameters_[p]->is_distributed)
2307  continue;
2308 
2309  // parameter is distributed but has no global indexer.
2310  // thus the user doesn't want sensitivities!
2311  if(parameters_[p]->global_indexer==null)
2312  continue;
2313 
2314  // build the linear object factory that has the correct sizing for
2315  // the sensitivity matrix (parameter sized domain, residual sized range)
2317  parameters_[p]->global_indexer);
2318 
2319  // the user wants global sensitivities, hooray! Build and setup the response library
2320  RCP<ResponseLibrary<Traits> > rLibrary
2321  = Teuchos::rcp(new ResponseLibrary<Traits>(wc,lof_->getRangeGlobalIndexer(),
2322  param_lof,true));
2323  rLibrary->buildResidualResponseEvaluators(physicsBlocks,eqset_factory,bcs,bc_factory,
2324  cm_factory,closure_models,user_data,
2325  write_graphviz_file,graphviz_file_prefix);
2326 
2327  // make sure parameter response library is correct
2328  parameters_[p]->dfdp_rl = rLibrary;
2329  }
2330 }
2331 
2332 template <typename Scalar>
2336  const std::vector<Teuchos::RCP<panzer::PhysicsBlock> >& physicsBlocks,
2337  const std::vector<panzer::BC>& /* bcs */,
2338  const panzer::EquationSetFactory & eqset_factory,
2339  const panzer::BCStrategyFactory& /* bc_factory */,
2341  const Teuchos::ParameterList& closure_models,
2342  const Teuchos::ParameterList& user_data,
2343  const bool write_graphviz_file,
2344  const std::string& graphviz_file_prefix)
2345 {
2346  using Teuchos::RCP;
2347  using Teuchos::rcp;
2348  using Teuchos::null;
2349 
2350  // loop over parameters, and then build a dfdp_rl only if they are distributed
2351  // and the user has provided the UGI. Note that this may be overly expensive if they
2352  // don't actually want those sensitivites because memory will be allocated unneccesarily.
2353  // It would be good to do this "just in time", but for now this is sufficient.
2354  for(std::size_t p=0;p<parameters_.size();p++) {
2355  // parameter is not distributed, a different path is
2356  // taken for those to compute dfdp
2357  if(!parameters_[p]->is_distributed)
2358  continue;
2359 
2360  // parameter is distributed but has no global indexer.
2361  // thus the user doesn't want sensitivities!
2362  if(parameters_[p]->global_indexer==null)
2363  continue;
2364 
2365  // extract the linear object factory that has the correct sizing for
2366  // the sensitivity vector
2367  RCP<const LinearObjFactory<Traits> > param_lof = parameters_[p]->dfdp_rl->getLinearObjFactory();
2368  RCP<const GlobalIndexer > param_ugi = parameters_[p]->global_indexer;
2369 
2370  // the user wants global sensitivities, hooray! Build and setup the response library
2371  RCP<ResponseLibrary<Traits> > rLibrary
2372  = Teuchos::rcp(new ResponseLibrary<Traits>(wc,lof_->getRangeGlobalIndexer(), lof_));
2373 
2374 
2375  // build evaluators for all flexible responses
2376  for(std::size_t r=0;r<responses_.size();r++) {
2377  // only responses with a builder are non null!
2378  if(responses_[r]->builder==Teuchos::null)
2379  continue;
2380 
2381  // set the current derivative information in the builder
2382  // responses_[r]->builder->setDerivativeInformationBase(param_lof,param_ugi);
2383  responses_[r]->builder->setDerivativeInformation(param_lof);
2384 
2385  // add the response
2386  rLibrary->addResponse(responses_[r]->name,
2387  responses_[r]->wkst_desc,
2388  *responses_[r]->builder);
2389  }
2390 
2391  rLibrary->buildResponseEvaluators(physicsBlocks,eqset_factory,
2392  cm_factory,closure_models,user_data,
2393  write_graphviz_file,graphviz_file_prefix);
2394 
2395  // make sure parameter response library is correct
2396  parameters_[p]->dgdp_rl = rLibrary;
2397  }
2398 }
2399 
2400 template <typename Scalar>
2402 setOneTimeDirichletBeta(const Scalar & beta) const
2403 {
2404  oneTimeDirichletBeta_on_ = true;
2405  oneTimeDirichletBeta_ = beta;
2406 }
2407 
2408 template <typename Scalar>
2412  const Teuchos::Array<Scalar> & in_values) const
2413 {
2414  using Teuchos::RCP;
2415  using Teuchos::rcp;
2416  using Teuchos::rcp_dynamic_cast;
2417  using Teuchos::ptrFromRef;
2418 
2419  TEUCHOS_ASSERT(in_names.size()==in_values.size());
2420 
2421  // Check that the parameters are valid (i.e., they already exist in the parameter library)
2422  // std::size_t np = in_names.size();
2423  // for(std::size_t i=0;i<np;i++)
2424  // TEUCHOS_TEST_FOR_EXCEPTION(!global_data_->pl->isParameter(in_names[i]),
2425  // std::logic_error,
2426  // "Parameter \"" << in_names[i] << "\" does not exist in parameter library!");
2427 
2428  RCP<ParameterObject> paramObj = rcp(new ParameterObject);
2429 
2430  paramObj->names = rcp(new Teuchos::Array<std::string>(in_names));
2431  paramObj->is_distributed = false;
2432 
2433  // register all the scalar parameters, setting initial
2434  for(int i=0;i<in_names.size();i++)
2435  registerScalarParameter(in_names[i],*global_data_->pl,in_values[i]);
2436 
2437  paramObj->scalar_value = panzer::ParamVec();
2438  global_data_->pl->fillVector<panzer::Traits::Residual>(*paramObj->names, paramObj->scalar_value);
2439 
2440  // build initial condition vector
2441  paramObj->space =
2442  Thyra::locallyReplicatedDefaultSpmdVectorSpace<Scalar>(
2443  rcp(new Teuchos::MpiComm<long int>(lof_->getComm().getRawMpiComm())),paramObj->names->size());
2444 
2445  // fill vector with parameter values
2447  RCP<Thyra::VectorBase<Scalar> > initial_value = Thyra::createMember(paramObj->space);
2448  RCP<Thyra::SpmdVectorBase<Scalar> > vec = rcp_dynamic_cast<Thyra::SpmdVectorBase<Scalar> >(initial_value);
2449  vec->getNonconstLocalData(ptrFromRef(data));
2450  for (unsigned int i=0; i < paramObj->scalar_value.size(); i++)
2451  data[i] = in_values[i];
2452 
2453  paramObj->initial_value = initial_value;
2454 
2455  return paramObj;
2456 }
2457 
2458 template <typename Scalar>
2461 createDistributedParameter(const std::string & key,
2462  const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > & vs,
2463  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & initial,
2464  const Teuchos::RCP<const GlobalIndexer> & ugi) const
2465 {
2466  using Teuchos::RCP;
2467  using Teuchos::rcp;
2468 
2469  RCP<ParameterObject> paramObj = rcp(new ParameterObject);
2470 
2471  paramObj->is_distributed = true;
2472  paramObj->names = rcp(new Teuchos::Array<std::string>());
2473  paramObj->names->push_back(key);
2474  paramObj->space = vs;
2475  paramObj->initial_value = initial;
2476 
2477  paramObj->global_indexer = ugi;
2478 
2479  return paramObj;
2480 }
2481 
2482 template <typename Scalar>
2483 void
2485 setParameters(const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs) const
2486 {
2487  for(std::size_t i=0; i < parameters_.size(); i++) {
2488 
2489  // skip non-scalar parameters (for now)
2490  if(parameters_[i]->is_distributed)
2491  continue;
2492 
2493  // set parameter values for given parameter vector for all evaluation types
2494  Teuchos::RCP<const Thyra::VectorBase<Scalar> > p = inArgs.get_p(i);
2495  if (p != Teuchos::null) {
2496  for (unsigned int j=0; j < parameters_[i]->scalar_value.size(); j++) {
2497  parameters_[i]->scalar_value[j].family->setRealValueForAllTypes(Thyra::get_ele(*p,j));
2498  }
2499  }
2500 
2501  }
2502 }
2503 
2504 template <typename Scalar>
2505 void
2508 {
2509  for(std::size_t i=0; i < parameters_.size(); i++) {
2510 
2511  // skip non-scalar parameters (for now)
2512  if(parameters_[i]->is_distributed)
2513  continue;
2514 
2515  // Reset each parameter back to its nominal
2516  for (unsigned int j=0; j < parameters_[i]->scalar_value.size(); j++) {
2517  parameters_[i]->scalar_value[j].family->setRealValueForAllTypes(Thyra::get_ele(*(parameters_[i]->initial_value),j));
2518  }
2519 
2520  }
2521 }
2522 
2523 #endif // __Panzer_ModelEvaluator_impl_hpp__
Teuchos::RCP< const LinearObjFactory< panzer::Traits > > cloneWithNewDomain(const LinearObjFactory< panzer::Traits > &lof, const Teuchos::RCP< const GlobalIndexer > &dUgi)
Clone a linear object factory, but using a different domain.
Interface for constructing a BCStrategy_TemplateManager.
void setupVolumeFieldManagers(const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &cm_factory, const Teuchos::ParameterList &closure_models, const LinearObjFactory< panzer::Traits > &lo_factory, const Teuchos::ParameterList &user_data)
Allocates and initializes an equation set template manager.
virtual void evalModelImpl_basic_dgdp_distro(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int i) const override
Teuchos::RCP< panzer::ResponseLibrary< panzer::Traits > > dfdp_rl
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const override
Teuchos::RCP< const GlobalIndexer > global_indexer
void evalModel_D2gDp2(int rIndex, int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &D2gDp2) const
void initializeNominalValues() const
Initialize the nominal values with good starting conditions.
int addDistributedParameter(const std::string &name, const Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > &vs, const Teuchos::RCP< GlobalEvaluationData > &ged, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &initial, const Teuchos::RCP< const GlobalIndexer > &ugi=Teuchos::null)
void addResponsesToInArgs(panzer::AssemblyEngineInArgs &input_args) const
int addFlexibleResponse(const std::string &responseName, const std::vector< WorksetDescriptor > &wkst_desc, const Teuchos::RCP< ResponseMESupportBuilderBase > &builder)
T & get(const std::string &name, T def_value)
void evalModel_D2gDx2(int rIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &D2gDx2) const
bool is_null(const std::shared_ptr< T > &p)
void evalModel_D2fDp2(int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::LinearOpBase< Scalar > > &D2fDp2) const
void writeVolumeGraphvizDependencyFiles(std::string filename_prefix, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const override
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< ParameterObject > createScalarParameter(const Teuchos::Array< std::string > &names, const Teuchos::Array< Scalar > &in_values) const
panzer::AssemblyEngine_TemplateManager< panzer::Traits > ae_tm_
void buildDistroParamDgDp_RL(const Teuchos::RCP< panzer::WorksetContainer > &wc, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const std::vector< panzer::BC > &bcs, const panzer::EquationSetFactory &eqset_factory, const panzer::BCStrategyFactory &bc_factory, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &cm_factory, const Teuchos::ParameterList &closure_models, const Teuchos::ParameterList &user_data, const bool write_graphviz_file=false, const std::string &graphviz_file_prefix="")
Teuchos::RCP< LinearObjContainer > getGlobalLOC() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_DfDp_op(int i) const override
void evalModel_D2fDxDp(int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_p, const Teuchos::RCP< Thyra::LinearOpBase< Scalar > > &D2fDxDp) const
void setupAssemblyInArgs(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, panzer::AssemblyEngineInArgs &ae_inargs) const
void buildVolumeFieldManagers(const bool value)
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const override
void writeBCGraphvizDependencyFiles(std::string filename_prefix) const
void evalModel_D2gDpDx(int rIndex, int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &D2gDpDx) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int i) const override
void setOneTimeDirichletBeta(const Scalar &beta) const
virtual void evalModelImpl_basic(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Evaluate a simple model, meaning a residual and a jacobian, no fancy stochastic galerkin or multipoin...
void evalModel_D2fDx2(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::LinearOpBase< Scalar > > &D2fDx2) const
bool required_basic_g(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Does this set of out args require a simple response?
Sacado::ScalarParameterVector< panzer::EvaluationTraits > ParamVec
Teuchos::RCP< panzer::LinearObjContainer > ghostedContainer_
virtual void evalModelImpl_basic_dgdx(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
bool required_basic_dgdp_distro(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Are their required responses in the out args? DgDp.
Teuchos::RCP< Epetra_MultiVector > getMultiVector(const std::string &modelEvalDescription, const ModelEvaluator::Derivative &deriv, const std::string &derivName, const ModelEvaluator::EDerivativeMultiVectorOrientation mvOrientation)
const std::string & get_g_name(int i) const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const override
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > x_space_
void setParameters(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs) const
void evaluate(const panzer::AssemblyEngineInArgs &input_args)
Teuchos::RCP< LinearObjContainer > getGhostedLOC() const
Teuchos::RCP< panzer::LinearObjContainer > container_
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > f_space_
Teuchos::ArrayView< const std::string > get_g_names(int i) const override
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const override
void addGlobalEvaluationData(const std::string &key, const Teuchos::RCP< GlobalEvaluationData > &ged)
void setWorksetContainer(const Teuchos::RCP< WorksetContainer > &wc)
bool isParameter(const std::string &name) const
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const override
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 void evalModelImpl_basic_g(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Construct a simple response dicatated by this set of out args.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< ParameterObject > createDistributedParameter(const std::string &key, const Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > &vs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &initial, const Teuchos::RCP< const GlobalIndexer > &ugi) const
Teuchos::RCP< const panzer::LinearObjFactory< panzer::Traits > > lof_
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int i) const override
bool required_basic_dgdp_scalar(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Are their required responses in the out args? DgDp.
Ptr< T > ptr() const
bool required_basic_dgdx(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Are their required responses in the out args? DgDx.
virtual void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const override
virtual void setDerivativeInformation(const Teuchos::RCP< const panzer::LinearObjFactory< panzer::Traits > > &linearObjFactory)=0
Teuchos::RCP< ResponseBase > getResponse(const std::string &responseName) const
virtual void evalModelImpl_basic_dfdp_distro(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
virtual void evalModelImpl_basic_dfdp_scalar(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
void buildDistroParamDfDp_RL(const Teuchos::RCP< panzer::WorksetContainer > &wc, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const std::vector< panzer::BC > &bcs, const panzer::EquationSetFactory &eqset_factory, const panzer::BCStrategyFactory &bc_factory, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &cm_factory, const Teuchos::ParameterList &closure_models, const Teuchos::ParameterList &user_data, const bool write_graphviz_file=false, const std::string &graphviz_file_prefix="")
void setupModel(const Teuchos::RCP< panzer::WorksetContainer > &wc, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const std::vector< panzer::BC > &bcs, const panzer::EquationSetFactory &eqset_factory, const panzer::BCStrategyFactory &bc_factory, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &volume_cm_factory, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &bc_cm_factory, const Teuchos::ParameterList &closure_models, const Teuchos::ParameterList &user_data, bool writeGraph=false, const std::string &graphPrefix="", const Teuchos::ParameterList &me_params=Teuchos::ParameterList())
virtual void evalModelImpl_basic_dfdp_scalar_fd(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
PANZER_FADTYPE FadType
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const override
bool nonnull(const boost::shared_ptr< T > &p)
void push_back(const value_type &x)
size_type size() const
Teuchos::RCP< panzer::ResponseLibrary< panzer::Traits > > responseLibrary_
void addNonParameterGlobalEvaluationData(const std::string &name, const Teuchos::RCP< GlobalEvaluationData > &ged)
bool required_basic_dfdp_scalar(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Are derivatives of the residual with respect to the scalar parameters in the out args? DfDp.
void evalModel_D2fDpDx(int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_x, const Teuchos::RCP< Thyra::LinearOpBase< Scalar > > &D2fDpDx) const
void evalModel_D2gDxDp(int rIndex, int pIndex, const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &delta_p, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &D2gDxDp) const
void setupBCFieldManagers(const std::vector< panzer::BC > &bcs, const std::vector< Teuchos::RCP< panzer::PhysicsBlock > > &physicsBlocks, const panzer::EquationSetFactory &eqset_factory, const panzer::ClosureModelFactory_TemplateManager< panzer::Traits > &cm_factory, const panzer::BCStrategyFactory &bc_factory, const Teuchos::ParameterList &closure_models, const LinearObjFactory< panzer::Traits > &lo_factory, const Teuchos::ParameterList &user_data)
void applyDirichletBCs(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &f) const
#define TEUCHOS_ASSERT(assertion_test)
bool required_basic_dfdp_distro(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Are derivatives of the residual with respect to the distributed parameters in the out args...
Tpetra::KokkosCompat::KokkosDeviceWrapperNode< PHX::Device > TpetraNodeType
void registerScalarParameter(const std::string name, panzer::ParamLib &pl, double realValue)
void setActiveEvaluationTypes(const std::vector< bool > &aet)
Set a vector of active evaluation types to allocate.
virtual void evalModelImpl_basic_dgdp_scalar(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
void buildBCFieldManagers(const bool value)
int addParameter(const std::string &name, const Scalar &initial)