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