Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterDirichletResidual_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_DIRICHLET_RESIDUAL_EPETRA_IMPL_HPP
12 #define PANZER_SCATTER_DIRICHLET_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"
29 
30 #include "Phalanx_DataLayout_MDALayout.hpp"
31 
32 #include "Teuchos_FancyOStream.hpp"
33 
34 // **********************************************************************
35 // Specialization: Residual
36 // **********************************************************************
37 
38 
39 template<typename TRAITS,typename LO,typename GO>
42  const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
43  const Teuchos::ParameterList& p)
44  : globalIndexer_(indexer)
45  , globalDataKey_("Residual Scatter Container")
46 {
47  std::string scatterName = p.get<std::string>("Scatter Name");
48  scatterHolder_ =
50 
51  // get names to be evaluated
52  const std::vector<std::string>& names =
53  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
54 
55  // grab map from evaluated names to field names
56  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
57 
58  // determine if we are scattering an initial condition
59  scatterIC_ = p.isParameter("Scatter Initial Condition") ? p.get<bool>("Scatter Initial Condition") : false;
60 
61  Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
62  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional :
63  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
64  if (!scatterIC_) {
65  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
66  local_side_id_ = p.get<int>("Local Side ID");
67  }
68 
69  // build the vector of fields that this is dependent on
70  scatterFields_.resize(names.size());
71  for (std::size_t eq = 0; eq < names.size(); ++eq) {
72  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
73 
74  // tell the field manager that we depend on this field
75  this->addDependentField(scatterFields_[eq]);
76  }
77 
78  checkApplyBC_ = p.isParameter("Check Apply BC") ? p.get<bool>("Check Apply BC") : false;
79  if (checkApplyBC_) {
80  applyBC_.resize(names.size());
81  for (std::size_t eq = 0; eq < names.size(); ++eq) {
82  applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
83  this->addDependentField(applyBC_[eq]);
84  }
85  }
86 
87  // this is what this evaluator provides
88  this->addEvaluatedField(*scatterHolder_);
89 
90  if (p.isType<std::string>("Global Data Key"))
91  globalDataKey_ = p.get<std::string>("Global Data Key");
92 
93  this->setName(scatterName+" Scatter Residual");
94 }
95 
96 // **********************************************************************
97 template<typename TRAITS,typename LO,typename GO>
99 postRegistrationSetup(typename TRAITS::SetupData /* d */,
100  PHX::FieldManager<TRAITS>& /* fm */)
101 {
102  fieldIds_.resize(scatterFields_.size());
103 
104  // load required field numbers for fast use
105  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
106  // get field ID from DOF manager
107  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
108  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
109  }
110 
111  // get the number of nodes (Should be renamed basis)
112  num_nodes = scatterFields_[0].extent(1);
113 }
114 
115 // **********************************************************************
116 template<typename TRAITS,typename LO,typename GO>
118 preEvaluate(typename TRAITS::PreEvalData d)
119 {
120  // extract linear object container
121  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
122 
123  if(epetraContainer_==Teuchos::null) {
124  // extract linear object container
125  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
126  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
127 
128  dirichletCounter_ = Teuchos::null;
129  }
130  else {
131  // extract dirichlet counter from container
133  = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject("Dirichlet Counter"),true);
134 
135  dirichletCounter_ = epetraContainer->get_f();
136  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
137  }
138 }
139 
140 // **********************************************************************
141 template<typename TRAITS,typename LO,typename GO>
143 evaluateFields(typename TRAITS::EvalData workset)
144 {
145  // for convenience pull out some objects from workset
146  std::string blockId = this->wda(workset).block_id;
147  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
148 
149  Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
150  Teuchos::RCP<Epetra_Vector> r = (!scatterIC_) ?
151  epetraContainer->get_f() :
152  epetraContainer->get_x();
153  // NOTE: A reordering of these loops will likely improve performance
154  // The "getGIDFieldOffsets may be expensive. However the
155  // "getElementGIDs" can be cheaper. However the lookup for LIDs
156  // may be more expensive!
157 
158  // scatter operation for each cell in workset
159  auto LIDs = globalIndexer_->getLIDs();
160  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
161  Kokkos::deep_copy(LIDs_h, LIDs);
162 
163 
164  // loop over each field to be scattered
165  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
166  int fieldNum = fieldIds_[fieldIndex];
167  auto field = PHX::as_view(scatterFields_[fieldIndex]);
168  auto field_h = Kokkos::create_mirror_view(field);
169  Kokkos::deep_copy(field_h, field);
170 
171  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
172  std::size_t cellLocalId = localCellIds[worksetCellIndex];
173 
174  if (!scatterIC_) {
175  // this call "should" get the right ordering according to the Intrepid2 basis
176  const std::pair<std::vector<int>,std::vector<int> > & indicePair
177  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
178  const std::vector<int> & elmtOffset = indicePair.first;
179  const std::vector<int> & basisIdMap = indicePair.second;
180 
181  // loop over basis functions
182  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
183  int offset = elmtOffset[basis];
184  int lid = LIDs_h(cellLocalId, offset);
185  if(lid<0) // not on this processor!
186  continue;
187 
188  int basisId = basisIdMap[basis];
189 
190  if (checkApplyBC_)
191  if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
192  continue;
193 
194  (*r)[lid] = field_h(worksetCellIndex,basisId);
195 
196  // record that you set a dirichlet condition
197  if(dirichletCounter_!=Teuchos::null)
198  (*dirichletCounter_)[lid] = 1.0;
199  }
200  } else {
201  // this call "should" get the right ordering according to the Intrepid2 basis
202  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
203 
204  // loop over basis functions
205  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
206  int offset = elmtOffset[basis];
207  int lid = LIDs_h(cellLocalId, offset);
208  if(lid<0) // not on this processor!
209  continue;
210 
211  (*r)[lid] = field_h(worksetCellIndex,basis);
212 
213  // record that you set a dirichlet condition
214  if(dirichletCounter_!=Teuchos::null)
215  (*dirichletCounter_)[lid] = 1.0;
216  }
217  }
218  }
219  }
220 }
221 
222 // **********************************************************************
223 // Specialization: Tangent
224 // **********************************************************************
225 
226 
227 template<typename TRAITS,typename LO,typename GO>
230  const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
231  const Teuchos::ParameterList& p)
232  : globalIndexer_(indexer)
233  , globalDataKey_("Residual Scatter Container")
234 {
235  std::string scatterName = p.get<std::string>("Scatter Name");
236  scatterHolder_ =
238 
239  // get names to be evaluated
240  const std::vector<std::string>& names =
241  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
242 
243  // grab map from evaluated names to field names
244  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
245 
246  // determine if we are scattering an initial condition
247  scatterIC_ = p.isParameter("Scatter Initial Condition") ? p.get<bool>("Scatter Initial Condition") : false;
248 
249  Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
250  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional :
251  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
252  if (!scatterIC_) {
253  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
254  local_side_id_ = p.get<int>("Local Side ID");
255  }
256 
257  // build the vector of fields that this is dependent on
258  scatterFields_.resize(names.size());
259  for (std::size_t eq = 0; eq < names.size(); ++eq) {
260  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
261 
262  // tell the field manager that we depend on this field
263  this->addDependentField(scatterFields_[eq]);
264  }
265 
266  checkApplyBC_ = p.isParameter("Check Apply BC") ? p.get<bool>("Check Apply BC") : false;
267  if (checkApplyBC_) {
268  applyBC_.resize(names.size());
269  for (std::size_t eq = 0; eq < names.size(); ++eq) {
270  applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
271  this->addDependentField(applyBC_[eq]);
272  }
273  }
274 
275  // this is what this evaluator provides
276  this->addEvaluatedField(*scatterHolder_);
277 
278  if (p.isType<std::string>("Global Data Key"))
279  globalDataKey_ = p.get<std::string>("Global Data Key");
280 
281  this->setName(scatterName+" Scatter Tangent");
282 }
283 
284 // **********************************************************************
285 template<typename TRAITS,typename LO,typename GO>
287 postRegistrationSetup(typename TRAITS::SetupData /* d */,
288  PHX::FieldManager<TRAITS>& /* fm */)
289 {
290  fieldIds_.resize(scatterFields_.size());
291 
292  // load required field numbers for fast use
293  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
294  // get field ID from DOF manager
295  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
296  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
297  }
298 
299  // get the number of nodes (Should be renamed basis)
300  num_nodes = scatterFields_[0].extent(1);
301 }
302 
303 // **********************************************************************
304 template<typename TRAITS,typename LO,typename GO>
306 preEvaluate(typename TRAITS::PreEvalData d)
307 {
308  // extract linear object container
309  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
310 
311  if(epetraContainer_==Teuchos::null) {
312  // extract linear object container
313  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
314  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
315 
316  dirichletCounter_ = Teuchos::null;
317  }
318  else {
319  // extract dirichlet counter from container
321  = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject("Dirichlet Counter"),true);
322 
323  dirichletCounter_ = epetraContainer->get_f();
324  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
325  }
326 
327  using Teuchos::RCP;
328  using Teuchos::rcp_dynamic_cast;
329 
330  // this is the list of parameters and their names that this scatter has to account for
331  std::vector<std::string> activeParameters =
332  rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters();
333 
334  // ETP 02/03/16: This code needs to be updated to properly handle scatterIC_
335  TEUCHOS_ASSERT(!scatterIC_);
336  dfdp_vectors_.clear();
337  for(std::size_t i=0;i<activeParameters.size();i++) {
338  RCP<Epetra_Vector> vec = rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(activeParameters[i]),true)->get_f();
339  dfdp_vectors_.push_back(vec);
340  }
341 }
342 
343 // **********************************************************************
344 template<typename TRAITS,typename LO,typename GO>
346 evaluateFields(typename TRAITS::EvalData workset)
347 {
348  // for convenience pull out some objects from workset
349  std::string blockId = this->wda(workset).block_id;
350  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
351 
352  Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
353  Teuchos::RCP<Epetra_Vector> r = (!scatterIC_) ?
354  epetraContainer->get_f() :
355  epetraContainer->get_x();
356  // NOTE: A reordering of these loops will likely improve performance
357  // The "getGIDFieldOffsets may be expensive. However the
358  // "getElementGIDs" can be cheaper. However the lookup for LIDs
359  // may be more expensive!
360 
361  // loop over each field to be scattered
362  auto LIDs = globalIndexer_->getLIDs();
363  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
364  Kokkos::deep_copy(LIDs_h, LIDs);
365  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
366  int fieldNum = fieldIds_[fieldIndex];
367  auto scatterField_h = Kokkos::create_mirror_view(scatterFields_[fieldIndex].get_static_view());
368  Kokkos::deep_copy(scatterField_h, scatterFields_[fieldIndex].get_static_view());
369 
370  // scatter operation for each cell in workset
371  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
372  std::size_t cellLocalId = localCellIds[worksetCellIndex];
373 
374  if (!scatterIC_) {
375  // this call "should" get the right ordering according to the Intrepid2 basis
376  const std::pair<std::vector<int>,std::vector<int> > & indicePair
377  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
378  const std::vector<int> & elmtOffset = indicePair.first;
379  const std::vector<int> & basisIdMap = indicePair.second;
380 
381  // loop over basis functions
382  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
383  int offset = elmtOffset[basis];
384  int lid = LIDs_h(cellLocalId, offset);
385  if(lid<0) // not on this processor!
386  continue;
387 
388  int basisId = basisIdMap[basis];
389 
390  if (checkApplyBC_)
391  if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
392  continue;
393 
394  ScalarT value = scatterField_h(worksetCellIndex,basisId);
395  // (*r)[lid] = (scatterFields_[fieldIndex])(worksetCellIndex,basisId).val();
396 
397  // then scatter the sensitivity vectors
398  if(value.size()==0)
399  for(std::size_t d=0;d<dfdp_vectors_.size();d++)
400  (*dfdp_vectors_[d])[lid] = 0.0;
401  else
402  for(int d=0;d<value.size();d++) {
403  (*dfdp_vectors_[d])[lid] = value.fastAccessDx(d);
404  }
405 
406  // record that you set a dirichlet condition
407  if(dirichletCounter_!=Teuchos::null)
408  (*dirichletCounter_)[lid] = 1.0;
409  }
410  } else {
411  // this call "should" get the right ordering according to the Intrepid2 basis
412  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
413 
414  // loop over basis functions
415  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
416  int offset = elmtOffset[basis];
417  int lid = LIDs_h(cellLocalId, offset);
418  if(lid<0) // not on this processor!
419  continue;
420 
421  ScalarT value = scatterField_h(worksetCellIndex,basis);
422  // (*r)[lid] = (scatterFields_[fieldIndex])(worksetCellIndex,basis).val();
423 
424  // then scatter the sensitivity vectors
425  if(value.size()==0)
426  for(std::size_t d=0;d<dfdp_vectors_.size();d++)
427  (*dfdp_vectors_[d])[lid] = 0.0;
428  else
429  for(int d=0;d<value.size();d++) {
430  (*dfdp_vectors_[d])[lid] = value.fastAccessDx(d);
431  }
432 
433  // record that you set a dirichlet condition
434  if(dirichletCounter_!=Teuchos::null)
435  (*dirichletCounter_)[lid] = 1.0;
436  }
437  }
438  }
439  }
440 }
441 
442 // **********************************************************************
443 // Specialization: Jacobian
444 // **********************************************************************
445 
446 template<typename TRAITS,typename LO,typename GO>
450  const Teuchos::ParameterList& p)
451  : globalIndexer_(indexer)
452  , colGlobalIndexer_(cIndexer)
453  , globalDataKey_("Residual Scatter Container")
454  , preserveDiagonal_(false)
455 {
456  std::string scatterName = p.get<std::string>("Scatter Name");
457  scatterHolder_ =
459 
460  // get names to be evaluated
461  const std::vector<std::string>& names =
462  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
463 
464  // grab map from evaluated names to field names
465  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
466 
468  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional;
469 
470  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
471  local_side_id_ = p.get<int>("Local Side ID");
472 
473  // build the vector of fields that this is dependent on
474  scatterFields_.resize(names.size());
475  for (std::size_t eq = 0; eq < names.size(); ++eq) {
476  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
477 
478  // tell the field manager that we depend on this field
479  this->addDependentField(scatterFields_[eq]);
480  }
481 
482  checkApplyBC_ = p.get<bool>("Check Apply BC");
483  if (checkApplyBC_) {
484  applyBC_.resize(names.size());
485  for (std::size_t eq = 0; eq < names.size(); ++eq) {
486  applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
487  this->addDependentField(applyBC_[eq]);
488  }
489  }
490 
491  // this is what this evaluator provides
492  this->addEvaluatedField(*scatterHolder_);
493 
494  if (p.isType<std::string>("Global Data Key"))
495  globalDataKey_ = p.get<std::string>("Global Data Key");
496 
497  if (p.isType<bool>("Preserve Diagonal"))
498  preserveDiagonal_ = p.get<bool>("Preserve Diagonal");
499 
500  this->setName(scatterName+" Scatter Residual (Jacobian)");
501 }
502 
503 // **********************************************************************
504 template<typename TRAITS,typename LO,typename GO>
506 postRegistrationSetup(typename TRAITS::SetupData /* d */,
507  PHX::FieldManager<TRAITS>& /* fm */)
508 {
509  fieldIds_.resize(scatterFields_.size());
510 
511  // load required field numbers for fast use
512  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
513  // get field ID from DOF manager
514  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
515  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
516  }
517 
518  // get the number of nodes (Should be renamed basis)
519  num_nodes = scatterFields_[0].extent(1);
520  num_eq = scatterFields_.size();
521 }
522 
523 // **********************************************************************
524 template<typename TRAITS,typename LO,typename GO>
526 preEvaluate(typename TRAITS::PreEvalData d)
527 {
528  // extract linear object container
529  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
530 
531  if(epetraContainer_==Teuchos::null) {
532  // extract linear object container
533  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
534  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc,true);
535 
536  dirichletCounter_ = Teuchos::null;
537  }
538  else {
539  // extract dirichlet counter from container
540  Teuchos::RCP<GlobalEvaluationData> dataContainer = d.gedc->getDataObject("Dirichlet Counter");
541  Teuchos::RCP<EpetraLinearObjContainer> epetraContainer = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(dataContainer,true);
542 
543  dirichletCounter_ = epetraContainer->get_f();
544  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
545  }
546 }
547 
548 // **********************************************************************
549 template<typename TRAITS,typename LO,typename GO>
551 evaluateFields(typename TRAITS::EvalData workset)
552 {
554  int gidCount(0);
555  bool useColumnIndexer = colGlobalIndexer_!=Teuchos::null;
557  colGlobalIndexer = useColumnIndexer ? colGlobalIndexer_ : globalIndexer_;
558 
559  // for convenience pull out some objects from workset
560  std::string blockId = this->wda(workset).block_id;
561  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
562 
563  Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
564  TEUCHOS_ASSERT(epetraContainer!=Teuchos::null);
565  Teuchos::RCP<Epetra_Vector> r = epetraContainer->get_f();
566  Teuchos::RCP<Epetra_CrsMatrix> Jac = epetraContainer->get_A();
567  // NOTE: A reordering of these loops will likely improve performance
568  // The "getGIDFieldOffsets may be expensive. However the
569  // "getElementGIDs" can be cheaper. However the lookup for LIDs
570  // may be more expensive!
571 
572  // scatter operation for each cell in workset
573 
574  auto LIDs = globalIndexer_->getLIDs();
575  auto colLIDs = colGlobalIndexer->getLIDs();
576  auto LIDs_h = Kokkos::create_mirror_view(LIDs);
577  auto colLIDs_h = Kokkos::create_mirror_view(colLIDs);
578  Kokkos::deep_copy(LIDs_h, LIDs);
579  Kokkos::deep_copy(colLIDs_h, colLIDs);
580 
581  std::vector<typename decltype(scatterFields_[0].get_static_view())::HostMirror> scatterFields_h;
582  for ( std::size_t i=0; i< scatterFields_.size(); ++i) {
583  scatterFields_h.push_back(Kokkos::create_mirror_view(scatterFields_[i].get_static_view()));
584  Kokkos::deep_copy(scatterFields_h[i], scatterFields_[i].get_static_view());
585  }
586 
587  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
588  std::size_t cellLocalId = localCellIds[worksetCellIndex];
589 
590  gidCount = colGlobalIndexer->getElementBlockGIDCount(blockId);
591 
592  // loop over each field to be scattered
593  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
594  int fieldNum = fieldIds_[fieldIndex];
595 
596  // this call "should" get the right ordering according to the Intrepid2 basis
597  const std::pair<std::vector<int>,std::vector<int> > & indicePair
598  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
599  const std::vector<int> & elmtOffset = indicePair.first;
600  const std::vector<int> & basisIdMap = indicePair.second;
601 
602  // loop over basis functions
603  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
604  int offset = elmtOffset[basis];
605  int row = LIDs_h(cellLocalId, offset);
606  if(row<0) // not on this processor
607  continue;
608 
609  int basisId = basisIdMap[basis];
610 
611  if (checkApplyBC_)
612  if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
613  continue;
614 
615  // zero out matrix row
616  {
617  int numEntries = 0;
618  int * rowIndices = 0;
619  double * rowValues = 0;
620 
621  Jac->ExtractMyRowView(row,numEntries,rowValues,rowIndices);
622 
623  for(int i=0;i<numEntries;i++) {
624  if(preserveDiagonal_) {
625  if(row!=rowIndices[i])
626  rowValues[i] = 0.0;
627  }
628  else
629  rowValues[i] = 0.0;
630  }
631  }
632 
633  // int gid = GIDs[offset];
634  const ScalarT scatterField = (scatterFields_h[fieldIndex])(worksetCellIndex,basisId);
635 
636  if(r!=Teuchos::null)
637  (*r)[row] = scatterField.val();
638  if(dirichletCounter_!=Teuchos::null) {
639  // std::cout << "Writing " << row << " " << dirichletCounter_->MyLength() << std::endl;
640  (*dirichletCounter_)[row] = 1.0; // mark row as dirichlet
641  }
642 
643  // loop over the sensitivity indices: all DOFs on a cell
644  std::vector<double> jacRow(scatterField.size(),0.0);
645 
646  if(!preserveDiagonal_) {
647  int err = Jac->ReplaceMyValues(row, gidCount, scatterField.dx(),
648  &colLIDs_h(cellLocalId,0));
649  TEUCHOS_ASSERT(err==0);
650  }
651  }
652  }
653  }
654 }
655 
656 // **********************************************************************
657 
658 #endif
const Teuchos::RCP< Epetra_Vector > get_x() const
T & get(const std::string &name, T def_value)
bool is_null(const std::shared_ptr< T > &p)
virtual int getElementBlockGIDCount(const std::size_t &blockIndex) const =0
How any GIDs are associate with each element in a particular element block.
const Kokkos::View< const panzer::LocalOrdinal **, Kokkos::LayoutRight, PHX::Device > getLIDs() const
const Teuchos::RCP< Epetra_CrsMatrix > get_A() const
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const Teuchos::RCP< Epetra_Vector > get_f() const
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)
int ReplaceMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
Pushes residual values into the residual vector for a Newton-based solve.