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