Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterResidual_Tpetra_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_SCATTER_RESIDUAL_TPETRA_IMPL_HPP
12 #define PANZER_SCATTER_RESIDUAL_TPETRA_IMPL_HPP
13 
14 #include "Teuchos_RCP.hpp"
15 #include "Teuchos_Assert.hpp"
16 
17 #include "Phalanx_DataLayout.hpp"
18 
19 #include "Panzer_GlobalIndexer.hpp"
20 #include "Panzer_PureBasis.hpp"
25 
26 #include "Phalanx_DataLayout_MDALayout.hpp"
27 
28 #include "Teuchos_FancyOStream.hpp"
29 
30 #include "Tpetra_Vector.hpp"
31 #include "Tpetra_Map.hpp"
32 #include "Tpetra_CrsMatrix.hpp"
33 
34 // **********************************************************************
35 // Specialization: Residual
36 // **********************************************************************
37 
38 template<typename TRAITS,typename LO,typename GO,typename NodeT>
41  const Teuchos::ParameterList& p)
42  : globalIndexer_(indexer)
43  , globalDataKey_("Residual Scatter Container")
44 {
45  std::string scatterName = p.get<std::string>("Scatter Name");
46  scatterHolder_ =
48 
49  // get names to be evaluated
50  const std::vector<std::string>& names =
51  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
52 
53  // grab map from evaluated names to field names
54  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
55 
57  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
58 
59  // build the vector of fields that this is dependent on
60  scatterFields_.resize(names.size());
61  scratch_offsets_.resize(names.size());
62  for (std::size_t eq = 0; eq < names.size(); ++eq) {
63  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
64 
65  // tell the field manager that we depend on this field
66  this->addDependentField(scatterFields_[eq]);
67  }
68 
69  // this is what this evaluator provides
70  this->addEvaluatedField(*scatterHolder_);
71 
72  if (p.isType<std::string>("Global Data Key"))
73  globalDataKey_ = p.get<std::string>("Global Data Key");
74 
75  this->setName(scatterName+" Scatter Residual");
76 }
77 
78 // **********************************************************************
79 template<typename TRAITS,typename LO,typename GO,typename NodeT>
81 postRegistrationSetup(typename TRAITS::SetupData d,
82  PHX::FieldManager<TRAITS>& /* fm */)
83 {
84  fieldIds_.resize(scatterFields_.size());
85  const Workset & workset_0 = (*d.worksets_)[0];
86  std::string blockId = this->wda(workset_0).block_id;
87 
88 
89  // load required field numbers for fast use
90  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
91  // get field ID from DOF manager
92  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
93  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
94 
95  const std::vector<int> & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldIds_[fd]);
96  scratch_offsets_[fd] = PHX::View<int*>("offsets",offsets.size());
97  Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(offsets.data(), offsets.size()));
98  }
99  scratch_lids_ = PHX::View<LO**>("lids",scatterFields_[0].extent(0),
100  globalIndexer_->getElementBlockGIDCount(blockId));
101 
102 }
103 
104 // **********************************************************************
105 template<typename TRAITS,typename LO,typename GO,typename NodeT>
107 preEvaluate(typename TRAITS::PreEvalData d)
108 {
110 
111  // extract linear object container
112  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
113 
114  if(tpetraContainer_==Teuchos::null) {
115  // extract linear object container
116  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
117  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
118  }
119 }
120 
121 
122 // **********************************************************************
123 // Specialization: Tangent
124 // **********************************************************************
125 
126 template<typename TRAITS,typename LO,typename GO,typename NodeT>
129  const Teuchos::ParameterList& p)
130  : globalIndexer_(indexer)
131  , globalDataKey_("Residual Scatter Container")
132 {
133 
134  std::string scatterName = p.get<std::string>("Scatter Name");
135  scatterHolder_ =
137 
138  // get names to be evaluated
139  const std::vector<std::string>& names =
140  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
141 
142  // grab map from evaluated names to field names
143  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
144 
146  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
147 
148  // build the vector of fields that this is dependent on
149  scatterFields_.resize(names.size());
150  scratch_offsets_.resize(names.size());
151  for (std::size_t eq = 0; eq < names.size(); ++eq) {
152  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
153 
154  // tell the field manager that we depend on this field
155  this->addDependentField(scatterFields_[eq]);
156  }
157 
158  // this is what this evaluator provides
159  this->addEvaluatedField(*scatterHolder_);
160 
161  if (p.isType<std::string>("Global Data Key"))
162  globalDataKey_ = p.get<std::string>("Global Data Key");
163 
164  this->setName(scatterName+" Scatter Tangent");
165 }
166 
167 // **********************************************************************
168 template<typename TRAITS,typename LO,typename GO,typename NodeT>
170 postRegistrationSetup(typename TRAITS::SetupData d,
171  PHX::FieldManager<TRAITS>& /* fm */)
172 {
173  fieldIds_.resize(scatterFields_.size());
174  const Workset & workset_0 = (*d.worksets_)[0];
175  std::string blockId = this->wda(workset_0).block_id;
176 
177  // load required field numbers for fast use
178  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
179  // get field ID from DOF manager
180  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
181  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
182 
183  const std::vector<int> & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldIds_[fd]);
184  scratch_offsets_[fd] = PHX::View<int*>("offsets",offsets.size());
185  Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(offsets.data(), offsets.size()));
186  }
187  scratch_lids_ = PHX::View<LO**>("lids",scatterFields_[0].extent(0),
188  globalIndexer_->getElementBlockGIDCount(blockId));
189 }
190 
191 // **********************************************************************
192 template<typename TRAITS,typename LO,typename GO,typename NodeT>
194 preEvaluate(typename TRAITS::PreEvalData d)
195 {
196  using Teuchos::RCP;
197  using Teuchos::rcp_dynamic_cast;
198 
200 
201  // this is the list of parameters and their names that this scatter has to account for
202  std::vector<std::string> activeParameters =
203  rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters();
204 
205  dfdpFieldsVoV_.initialize("ScatterResidual_Tpetra<Tangent>::dfdpFieldsVoV_",activeParameters.size());
206 
207  for(std::size_t i=0;i<activeParameters.size();i++) {
209  rcp_dynamic_cast<LOC>(d.gedc->getDataObject(activeParameters[i]),true)->get_f();
210  auto dfdp_view = vec->getLocalViewDevice(Tpetra::Access::ReadWrite);
211 
212  dfdpFieldsVoV_.addView(dfdp_view,i);
213  }
214 
215  dfdpFieldsVoV_.syncHostToDevice();
216 
217  // extract linear object container
218  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
219 
220  if(tpetraContainer_==Teuchos::null) {
221  // extract linear object container
222  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
223  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
224  }
225 }
226 
227 // **********************************************************************
228 // Specialization: Jacobian
229 // **********************************************************************
230 
231 template<typename TRAITS,typename LO,typename GO,typename NodeT>
234  const Teuchos::ParameterList& p)
235  : globalIndexer_(indexer)
236  , globalDataKey_("Residual Scatter Container")
237  , my_derivative_size_(0)
238  , other_derivative_size_(0)
239 {
240  std::string scatterName = p.get<std::string>("Scatter Name");
241  scatterHolder_ =
243 
244  // get names to be evaluated
245  const std::vector<std::string>& names =
246  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
247 
248  // grab map from evaluated names to field names
249  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
250 
252  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
253 
254  // build the vector of fields that this is dependent on
255  scatterFields_.resize(names.size());
256  scratch_offsets_.resize(names.size());
257  for (std::size_t eq = 0; eq < names.size(); ++eq) {
258  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
259 
260  // tell the field manager that we depend on this field
261  this->addDependentField(scatterFields_[eq]);
262  }
263 
264  // this is what this evaluator provides
265  this->addEvaluatedField(*scatterHolder_);
266 
267  if (p.isType<std::string>("Global Data Key"))
268  globalDataKey_ = p.get<std::string>("Global Data Key");
269 
270  this->setName(scatterName+" Scatter Residual (Jacobian)");
271 }
272 
273 // **********************************************************************
274 template<typename TRAITS,typename LO,typename GO,typename NodeT>
276 postRegistrationSetup(typename TRAITS::SetupData d,
277  PHX::FieldManager<TRAITS>& /* fm */)
278 {
279  fieldIds_.resize(scatterFields_.size());
280 
281  const Workset & workset_0 = (*d.worksets_)[0];
282  std::string blockId = this->wda(workset_0).block_id;
283 
284  // load required field numbers for fast use
285  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
286  // get field ID from DOF manager
287  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
288  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
289 
290  int fieldNum = fieldIds_[fd];
291  const std::vector<int> & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
292  scratch_offsets_[fd] = PHX::View<int*>("offsets",offsets.size());
293  Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(offsets.data(), offsets.size()));
294  }
295 
296  my_derivative_size_ = globalIndexer_->getElementBlockGIDCount(blockId);
297  if (Teuchos::nonnull(workset_0.other)) {
298  auto otherBlockId = workset_0.other->block_id;
299  other_derivative_size_ = globalIndexer_->getElementBlockGIDCount(otherBlockId);
300  }
302  "lids", scatterFields_[0].extent(0), my_derivative_size_ + other_derivative_size_ );
303  scratch_vals_ = Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device>(
304  "vals", scatterFields_[0].extent(0), my_derivative_size_ + other_derivative_size_ );
305 }
306 
307 // **********************************************************************
308 template<typename TRAITS,typename LO,typename GO,typename NodeT>
310 preEvaluate(typename TRAITS::PreEvalData d)
311 {
313 
314  // extract linear object container
315  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
316 
317  if(tpetraContainer_==Teuchos::null) {
318  // extract linear object container
319  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
320  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
321  }
322 }
323 
324 
325 // **********************************************************************
326 namespace panzer {
327 namespace {
328 
329 template <typename ScalarT,typename LO,typename GO,typename NodeT,typename LocalMatrixT>
330 class ScatterResidual_Jacobian_Functor {
331 public:
332  typedef typename PHX::Device execution_space;
334 
337  LocalMatrixT jac; // Kokkos jacobian type
338 
340  Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device> vals;
341  PHX::View<const int*> offsets; // how to get a particular field
343 
344 
345  KOKKOS_INLINE_FUNCTION
346  void operator()(const unsigned int cell) const
347  {
348  int numIds = lids.extent(1);
349 
350  // loop over the basis functions (currently they are nodes)
351  for(std::size_t basis=0; basis < offsets.extent(0); basis++) {
352  typename FieldType::array_type::reference_type scatterField = field(cell,basis);
353  int offset = offsets(basis);
354  LO lid = lids(cell,offset);
355 
356  // Sum residual
357  if(fillResidual)
358  Kokkos::atomic_add(&r_data(lid,0), scatterField.val());
359 
360  // loop over the sensitivity indices: all DOFs on a cell
361  for(int sensIndex=0;sensIndex<numIds;++sensIndex)
362  vals(cell,sensIndex) = scatterField.fastAccessDx(sensIndex);
363 
364  // Sum Jacobian
365  jac.sumIntoValues(lid, &lids(cell,0), numIds, &vals(cell,0), true, true);
366  } // end basis
367  }
368 };
369 
370 template <typename ScalarT,typename LO,typename GO,typename NodeT>
371 class ScatterResidual_Residual_Functor {
372 public:
373  typedef typename PHX::Device execution_space;
375 
377 
378  PHX::View<const LO**> lids; // local indices for unknowns
379  PHX::View<const int*> offsets; // how to get a particular field
381 
382  KOKKOS_INLINE_FUNCTION
383  void operator()(const unsigned int cell) const
384  {
385 
386  // loop over the basis functions (currently they are nodes)
387  for(std::size_t basis=0; basis < offsets.extent(0); basis++) {
388  int offset = offsets(basis);
389  LO lid = lids(cell,offset);
390  Kokkos::atomic_add(&r_data(lid,0), field(cell,basis));
391 
392  } // end basis
393  }
394 };
395 
396 template <typename ScalarT,typename LO,typename GO,typename NodeT>
397 class ScatterResidual_Tangent_Functor {
398 public:
399  typedef typename PHX::Device execution_space;
401 
402  bool fillResidual;
404 
405  Kokkos::View<const LO**> lids; // local indices for unknowns.
406  PHX::View<const int*> offsets; // how to get a particular field
408  double num_params;
409 
411 
412  KOKKOS_INLINE_FUNCTION
413  void operator()(const unsigned int cell) const
414  {
415 
416  // loop over the basis functions (currently they are nodes)
417  for(std::size_t basis=0; basis < offsets.extent(0); basis++) {
418  typename FieldType::array_type::reference_type scatterField = field(cell,basis);
419  int offset = offsets(basis);
420  LO lid = lids(cell,offset);
421 
422  // Sum residual
423  if(fillResidual)
424  Kokkos::atomic_add(&r_data(lid,0), scatterField.val());
425 
426  // loop over the tangents
427  for(int i_param=0; i_param<num_params; i_param++)
428  dfdp_fields(i_param)(lid,0) += scatterField.fastAccessDx(i_param);
429 
430  } // end basis
431  }
432 };
433 
434 }
435 }
436 
437 // **********************************************************************
438 template<typename TRAITS,typename LO,typename GO,typename NodeT>
440 evaluateFields(typename TRAITS::EvalData workset)
441 {
443 
444  // for convenience pull out some objects from workset
445  std::string blockId = this->wda(workset).block_id;
446 
447  Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->get_f();
448 
449  globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
450 
451  ScatterResidual_Residual_Functor<ScalarT,LO,GO,NodeT> functor;
452  functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
453  functor.lids = scratch_lids_;
454 
455  // for each field, do a parallel for loop
456  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
457  functor.offsets = scratch_offsets_[fieldIndex];
458  functor.field = scatterFields_[fieldIndex];
459 
460  Kokkos::parallel_for(workset.num_cells,functor);
461  }
462 }
463 
464 // **********************************************************************
465 template<typename TRAITS,typename LO,typename GO,typename NodeT>
467 evaluateFields(typename TRAITS::EvalData workset)
468 {
470 
471  typedef typename LOC::CrsMatrixType::local_matrix_device_type LocalMatrixT;
472 
473  // for convenience pull out some objects from workset
474  std::string blockId = this->wda(workset).block_id;
475 
476  Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->get_f();
477  Teuchos::RCP<typename LOC::CrsMatrixType> Jac = tpetraContainer_->get_A();
478 
479  // Cache scratch lids. For interface bc problems the derivative
480  // dimension extent spans two cells. Use subviews to get the self
481  // lids and the other lids.
482  if (Teuchos::nonnull(workset.other)) {
483  auto my_scratch_lids = Kokkos::subview(scratch_lids_,Kokkos::ALL,std::make_pair(0,my_derivative_size_));
484  globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,my_scratch_lids);
485  auto other_scratch_lids = Kokkos::subview(scratch_lids_,Kokkos::ALL,std::make_pair(my_derivative_size_,my_derivative_size_ + other_derivative_size_));
486  globalIndexer_->getElementLIDs(workset.other->cell_local_ids_k,other_scratch_lids);
487  }
488  else {
489  globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
490  }
491 
492  ScatterResidual_Jacobian_Functor<ScalarT,LO,GO,NodeT,LocalMatrixT> functor;
493  functor.fillResidual = (r!=Teuchos::null);
494  if(functor.fillResidual)
495  functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
496  functor.jac = Jac->getLocalMatrixDevice();
497  functor.lids = scratch_lids_;
498  functor.vals = scratch_vals_;
499 
500  // for each field, do a parallel for loop
501  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
502  functor.offsets = scratch_offsets_[fieldIndex];
503  functor.field = scatterFields_[fieldIndex];
504 
505  Kokkos::parallel_for(workset.num_cells,functor);
506  }
507 
508 }
509 
510 // **********************************************************************
511 template<typename TRAITS,typename LO,typename GO,typename NodeT>
513 evaluateFields(typename TRAITS::EvalData workset)
514 {
516 
517  // for convenience pull out some objects from workset
518  std::string blockId = this->wda(workset).block_id;
519 
520  Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->get_f();
521 
522  globalIndexer_->getElementLIDs(this->wda(workset).getLocalCellIDs(),scratch_lids_);
523 
524  ScatterResidual_Tangent_Functor<ScalarT,LO,GO,NodeT> functor;
525  functor.fillResidual = (r!=Teuchos::null);
526  if(functor.fillResidual)
527  functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
528  functor.lids = scratch_lids_;
529  functor.dfdp_fields = dfdpFieldsVoV_.getViewDevice();
530 
531  // for each field, do a parallel for loop
532  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
533  functor.offsets = scratch_offsets_[fieldIndex];
534  functor.field = scatterFields_[fieldIndex];
535  functor.num_params = Kokkos::dimension_scalar(scatterFields_[fieldIndex].get_view())-1;
536 
537  Kokkos::parallel_for(workset.num_cells,functor);
538  }
539 }
540 
541 // **********************************************************************
542 
543 #endif
T & get(const std::string &name, T def_value)
bool nonnull(const std::shared_ptr< T > &p)
FieldType
The type of discretization to use for a field pattern.
PHX::View< const int * > offsets
Kokkos::View< const LO **, Kokkos::LayoutRight, PHX::Device > lids
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< WorksetDetails > other
Kokkos::View< Kokkos::View< double **, Kokkos::LayoutLeft, PHX::Device > * > dfdp_fields
Kokkos::View< typename Sacado::ScalarType< ScalarT >::type **, Kokkos::LayoutRight, PHX::Device > vals
Kokkos::View< double **, Kokkos::LayoutLeft, PHX::Device > r_data
std::string block_id
DEPRECATED - use: getElementBlock()
Pushes residual values into the residual vector for a Newton-based solve.
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
bool isType(const std::string &name) const