Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterResidual_Epetra_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_EPETRA_IMPL_HPP
12 #define PANZER_SCATTER_RESIDUAL_EPETRA_IMPL_HPP
13 
14 #include "Teuchos_RCP.hpp"
15 #include "Teuchos_Assert.hpp"
16 
17 #include "Phalanx_DataLayout.hpp"
18 
19 #include "Epetra_Map.h"
20 #include "Epetra_Vector.h"
21 #include "Epetra_CrsMatrix.h"
22 
23 #include "Panzer_GlobalIndexer.hpp"
24 #include "Panzer_PureBasis.hpp"
30 
31 #include "Phalanx_DataLayout_MDALayout.hpp"
32 
33 #include "Teuchos_FancyOStream.hpp"
34 
35 // **********************************************************************
36 // Specialization: Residual
37 // **********************************************************************
38 
39 template<typename TRAITS,typename LO,typename GO>
42  const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
43  const Teuchos::ParameterList& p,
44  bool useDiscreteAdjoint)
45  : globalIndexer_(indexer)
46  , globalDataKey_("Residual Scatter Container")
47  , useDiscreteAdjoint_(useDiscreteAdjoint)
48 {
49  std::string scatterName = p.get<std::string>("Scatter Name");
50  scatterHolder_ =
52 
53  // get names to be evaluated
54  const std::vector<std::string>& names =
55  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
56 
57  // grab map from evaluated names to field names
58  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
59 
61  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
62 
63  // build the vector of fields that this is dependent on
64  scatterFields_.resize(names.size());
65  for (std::size_t eq = 0; eq < names.size(); ++eq) {
66  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
67 
68  // tell the field manager that we depend on this field
69  this->addDependentField(scatterFields_[eq]);
70  }
71 
72  // this is what this evaluator provides
73  this->addEvaluatedField(*scatterHolder_);
74 
75  if (p.isType<std::string>("Global Data Key"))
76  globalDataKey_ = p.get<std::string>("Global Data Key");
77 
78  this->setName(scatterName+" Scatter Residual");
79 }
80 
81 // **********************************************************************
82 template<typename TRAITS,typename LO,typename GO>
84 postRegistrationSetup(typename TRAITS::SetupData /* d */,
85  PHX::FieldManager<TRAITS>& /* fm */)
86 {
87  fieldIds_.resize(scatterFields_.size());
88  // load required field numbers for fast use
89  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
90  // get field ID from DOF manager
91  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
92  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
93  }
94 }
95 
96 // **********************************************************************
97 template<typename TRAITS,typename LO,typename GO>
99 preEvaluate(typename TRAITS::PreEvalData d)
100 {
101  // extract linear object container
102  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
103 
104  if(epetraContainer_==Teuchos::null) {
105  // extract linear object container
106  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
107  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
108  }
109 }
110 
111 // **********************************************************************
112 template<typename TRAITS,typename LO,typename GO>
114 evaluateFields(typename TRAITS::EvalData workset)
115 {
116  // for convenience pull out some objects from workset
117  std::string blockId = this->wda(workset).block_id;
118  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
119 
120  Teuchos::RCP<Epetra_Vector> r = epetraContainer_->get_f();
121 
122  // NOTE: A reordering of these loops will likely improve performance
123  // The "getGIDFieldOffsets may be expensive. However the
124  // "getElementGIDs" can be cheaper. However the lookup for LIDs
125  // may be more expensive!
126 
127  // scatter operation for each cell in workset
128  auto LIDs = globalIndexer_->getLIDs();
129  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
130  Kokkos::deep_copy(LIDs_h, LIDs);
131  // loop over each field to be scattered
132  for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
133  int fieldNum = fieldIds_[fieldIndex];
134  auto field = PHX::as_view(scatterFields_[fieldIndex]);
135  auto field_h = Kokkos::create_mirror_view(field);
136  Kokkos::deep_copy(field_h, field);
137 
138  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
139  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
140  std::size_t cellLocalId = localCellIds[worksetCellIndex];
141 
142  // loop over basis functions
143  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
144  int offset = elmtOffset[basis];
145  int lid = LIDs_h(cellLocalId, offset);
146  (*r)[lid] += field_h(worksetCellIndex,basis);
147  }
148  }
149  }
150 }
151 
152 // **********************************************************************
153 // Specialization: Tangent
154 // **********************************************************************
155 
156 template<typename TRAITS,typename LO,typename GO>
159  const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
160  const Teuchos::ParameterList& p,
161  bool /* useDiscreteAdjoint */)
162  : globalIndexer_(indexer)
163 {
164  std::string scatterName = p.get<std::string>("Scatter Name");
165  scatterHolder_ =
167 
168  // get names to be evaluated
169  const std::vector<std::string>& names =
170  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
171 
172  // grab map from evaluated names to field names
173  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
174 
176  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
177 
178  // build the vector of fields that this is dependent on
179  scatterFields_.resize(names.size());
180  for (std::size_t eq = 0; eq < names.size(); ++eq) {
181  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
182 
183  // tell the field manager that we depend on this field
184  this->addDependentField(scatterFields_[eq]);
185  }
186 
187  // this is what this evaluator provides
188  this->addEvaluatedField(*scatterHolder_);
189 
190  this->setName(scatterName+" Scatter Tangent");
191 }
192 
193 // **********************************************************************
194 template<typename TRAITS,typename LO,typename GO>
196 postRegistrationSetup(typename TRAITS::SetupData /* d */,
197  PHX::FieldManager<TRAITS>& /* fm */)
198 {
199  fieldIds_.resize(scatterFields_.size());
200  // load required field numbers for fast use
201  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
202  // get field ID from DOF manager
203  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
204  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
205  }
206 }
207 
208 // **********************************************************************
209 template<typename TRAITS,typename LO,typename GO>
211 preEvaluate(typename TRAITS::PreEvalData d)
212 {
213  using Teuchos::RCP;
214  using Teuchos::rcp_dynamic_cast;
215 
216  // this is the list of parameters and their names that this scatter has to account for
217  std::vector<std::string> activeParameters =
218  rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters();
219 
220  dfdp_vectors_.clear();
221  for(std::size_t i=0;i<activeParameters.size();i++) {
222  RCP<Epetra_Vector> vec = rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(activeParameters[i]),true)->get_f();
223  dfdp_vectors_.push_back(vec);
224  }
225 }
226 
227 // **********************************************************************
228 template<typename TRAITS,typename LO,typename GO>
230 evaluateFields(typename TRAITS::EvalData workset)
231 {
232  // for convenience pull out some objects from workset
233  std::string blockId = this->wda(workset).block_id;
234  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
235 
236  // NOTE: A reordering of these loops will likely improve performance
237  // The "getGIDFieldOffsets may be expensive. However the
238  // "getElementGIDs" can be cheaper. However the lookup for LIDs
239  // may be more expensive!
240 
241  // loop over each field to be scattered
242  auto LIDs = globalIndexer_->getLIDs();
243  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
244  Kokkos::deep_copy(LIDs_h, LIDs);
245  for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
246  int fieldNum = fieldIds_[fieldIndex];
247  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
248  auto scatterField_h = Kokkos::create_mirror_view(scatterFields_[fieldIndex].get_static_view());
249  Kokkos::deep_copy(scatterField_h, scatterFields_[fieldIndex].get_static_view());
250  // scatter operation for each cell in workset
251  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
252  std::size_t cellLocalId = localCellIds[worksetCellIndex];
253 
254  auto LIDs = globalIndexer_->getElementLIDs(cellLocalId);
255  // loop over basis functions
256  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
257  int offset = elmtOffset[basis];
258  int lid = LIDs_h(cellLocalId, offset);
259 
260  // scatter the sensitivity vectors
261  ScalarT value = scatterField_h(worksetCellIndex,basis);
262  for(int d=0;d<value.size();d++)
263  (*dfdp_vectors_[d])[lid] += value.fastAccessDx(d);
264  }
265  }
266  }
267 }
268 
269 // **********************************************************************
270 // Specialization: Jacobian
271 // **********************************************************************
272 
273 template<typename TRAITS,typename LO,typename GO>
277  const Teuchos::ParameterList& p,
278  bool useDiscreteAdjoint)
279  : globalIndexer_(indexer)
280  , colGlobalIndexer_(cIndexer)
281  , globalDataKey_("Residual Scatter Container")
282  , useDiscreteAdjoint_(useDiscreteAdjoint)
283 {
284  std::string scatterName = p.get<std::string>("Scatter Name");
285  scatterHolder_ =
287 
288  // get names to be evaluated
289  const std::vector<std::string>& names =
290  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
291 
292  // grab map from evaluated names to field names
293  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
294 
296  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
297 
298  // build the vector of fields that this is dependent on
299  scatterFields_.resize(names.size());
300  for (std::size_t eq = 0; eq < names.size(); ++eq) {
301  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
302 
303  // tell the field manager that we depend on this field
304  this->addDependentField(scatterFields_[eq]);
305  }
306 
307  // this is what this evaluator provides
308  this->addEvaluatedField(*scatterHolder_);
309 
310  if (p.isType<std::string>("Global Data Key"))
311  globalDataKey_ = p.get<std::string>("Global Data Key");
312  if (p.isType<bool>("Use Discrete Adjoint"))
313  useDiscreteAdjoint = p.get<bool>("Use Discrete Adjoint");
314 
315  // discrete adjoint does not work with non-square matrices
316  if(useDiscreteAdjoint)
317  { TEUCHOS_ASSERT(colGlobalIndexer_==globalIndexer_); }
318 
319  this->setName(scatterName+" Scatter Residual Epetra (Jacobian)");
320 }
321 
322 // **********************************************************************
323 template<typename TRAITS,typename LO,typename GO>
325 postRegistrationSetup(typename TRAITS::SetupData /* d */,
326  PHX::FieldManager<TRAITS>& /* fm */)
327 {
328  // globalIndexer_ = d.globalIndexer_;
329 
330  fieldIds_.resize(scatterFields_.size());
331  // load required field numbers for fast use
332  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
333  // get field ID from DOF manager
334  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
335  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
336  }
337 }
338 
339 // **********************************************************************
340 template<typename TRAITS,typename LO,typename GO>
342 preEvaluate(typename TRAITS::PreEvalData d)
343 {
344  // extract linear object container
345  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
346 
347  if(epetraContainer_==Teuchos::null) {
348  // extract linear object container
349  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
350  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
351  }
352 }
353 
354 // **********************************************************************
355 template<typename TRAITS,typename LO,typename GO>
357 evaluateFields(typename TRAITS::EvalData workset)
358 {
359  std::vector<double> jacRow;
360 
361  bool useColumnIndexer = colGlobalIndexer_!=Teuchos::null;
362 
363  // for convenience pull out some objects from workset
364  std::string blockId = this->wda(workset).block_id;
365  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
366 
367  Teuchos::RCP<Epetra_Vector> r = epetraContainer_->get_f();
368  Teuchos::RCP<Epetra_CrsMatrix> Jac = epetraContainer_->get_A();
369 
371  colGlobalIndexer = useColumnIndexer ? colGlobalIndexer_ : globalIndexer_;
372 
373  // NOTE: A reordering of these loops will likely improve performance
374  // The "getGIDFieldOffsets" may be expensive. However the
375  // "getElementGIDs" can be cheaper. However the lookup for LIDs
376  // may be more expensive!
377 
378  // scatter operation for each cell in workset
379  auto LIDs = globalIndexer_->getLIDs();
380  auto colLIDs = colGlobalIndexer->getLIDs();
381  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
382  auto colLIDs_h = Kokkos::create_mirror_view(colLIDs);
383  Kokkos::deep_copy(LIDs_h, LIDs);
384  Kokkos::deep_copy(colLIDs_h, colLIDs);
385  std::vector<typename decltype(scatterFields_[0].get_static_view())::HostMirror> scatterFields_h;
386  for ( std::size_t i=0; i< scatterFields_.size(); ++i) {
387  scatterFields_h.push_back(Kokkos::create_mirror_view(scatterFields_[i].get_static_view()));
388  Kokkos::deep_copy(scatterFields_h[i], scatterFields_[i].get_static_view());
389  }
390 
391  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
392  std::size_t cellLocalId = localCellIds[worksetCellIndex];
393 
394  std::vector<int> cLIDs;
395  for (int i(0); i < static_cast<int>(colLIDs_h.extent(1)); ++i)
396  cLIDs.push_back(colLIDs_h(cellLocalId, i));
397  if (Teuchos::nonnull(workset.other)) {
398  const std::size_t other_cellLocalId = workset.other->cell_local_ids[worksetCellIndex];
399  for (int i(0); i < static_cast<int>(colLIDs_h.extent(1)); ++i)
400  cLIDs.push_back(colLIDs_h(other_cellLocalId, i));
401  }
402 
403  // loop over each field to be scattered
404  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
405  int fieldNum = fieldIds_[fieldIndex];
406  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
407 
408  // loop over the basis functions (currently they are nodes)
409  for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) {
410  const ScalarT scatterField = (scatterFields_h[fieldIndex])(worksetCellIndex,rowBasisNum);
411  int rowOffset = elmtOffset[rowBasisNum];
412  int row = LIDs_h(cellLocalId,rowOffset);
413 
414  // Sum residual
415  if(r!=Teuchos::null)
416  r->SumIntoMyValue(row,0,scatterField.val());
417 
418  // Sum Jacobian
419  if(useDiscreteAdjoint_) {
420  // loop over the sensitivity indices: all DOFs on a cell
421  jacRow.resize(scatterField.size());
422 
423  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
424  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex);
425 
426  for(std::size_t c=0;c<cLIDs.size();c++) {
427  int err = Jac->SumIntoMyValues(cLIDs[c], 1, &jacRow[c],&row);
429  }
430  }
431  else {
432  int err = Jac->SumIntoMyValues(
433  row,
434  std::min(cLIDs.size(), static_cast<size_t>(scatterField.size())),
435  scatterField.dx(),
436  panzer::ptrFromStlVector(cLIDs));
437 
439  }
440  } // end rowBasisNum
441  } // end fieldIndex
442  }
443 }
444 
445 // **********************************************************************
446 
447 #endif
T & get(const std::string &name, T def_value)
bool nonnull(const std::shared_ptr< T > &p)
const Kokkos::View< const panzer::LocalOrdinal **, Kokkos::LayoutRight, PHX::Device > getLIDs() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
T * ptrFromStlVector(std::vector< T > &v)
Pushes residual values into the residual vector for a Newton-based solve.
int SumIntoMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
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
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)