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