Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_GatherSolution_Tpetra_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef PANZER_GATHER_SOLUTION_TPETRA_IMPL_HPP
44 #define PANZER_GATHER_SOLUTION_TPETRA_IMPL_HPP
45 
46 #include "Teuchos_Assert.hpp"
47 #include "Phalanx_DataLayout.hpp"
48 
49 #include "Panzer_GlobalIndexer.hpp"
50 #include "Panzer_PureBasis.hpp"
56 #include "Panzer_DOFManager.hpp"
57 
58 #include "Teuchos_FancyOStream.hpp"
59 
60 #include "Tpetra_Vector.hpp"
61 #include "Tpetra_Map.hpp"
62 
63 // **********************************************************************
64 // Specialization: Residual
65 // **********************************************************************
66 
67 template<typename TRAITS,typename LO,typename GO,typename NodeT>
71  const Teuchos::ParameterList& p)
72  : globalIndexer_(indexer)
73  , has_tangent_fields_(false)
74 {
75  typedef std::vector< std::vector<std::string> > vvstring;
76 
78  input.setParameterList(p);
79 
80  const std::vector<std::string> & names = input.getDofNames();
82  const vvstring & tangent_field_names = input.getTangentNames();
83 
84  indexerNames_ = input.getIndexerNames();
85  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
86  globalDataKey_ = input.getGlobalDataKey();
87 
88  // allocate fields
89  gatherFields_.resize(names.size());
90  for (std::size_t fd = 0; fd < names.size(); ++fd) {
91  gatherFields_[fd] =
93  this->addEvaluatedField(gatherFields_[fd]);
94  }
95 
96  // Setup dependent tangent fields if requested
97  if (tangent_field_names.size()>0) {
98  TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
99 
100  has_tangent_fields_ = true;
101  tangentFields_.resize(gatherFields_.size());
102  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
103  tangentFields_[fd].resize(tangent_field_names[fd].size());
104  for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
105  tangentFields_[fd][i] =
106  PHX::MDField<const ScalarT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
107  this->addDependentField(tangentFields_[fd][i]);
108  }
109  }
110  }
111 
112  // figure out what the first active name is
113  std::string firstName = "<none>";
114  if(names.size()>0)
115  firstName = names[0];
116 
117  std::string n = "GatherSolution (Tpetra): "+firstName+" (Residual)";
118  this->setName(n);
119 }
120 
121 // **********************************************************************
122 template<typename TRAITS,typename LO,typename GO,typename NodeT>
124 postRegistrationSetup(typename TRAITS::SetupData d,
125  PHX::FieldManager<TRAITS>& /* fm */)
126 {
127  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
128 
129  fieldIds_.resize(gatherFields_.size());
130 
131  const Workset & workset_0 = (*d.worksets_)[0];
132  std::string blockId = this->wda(workset_0).block_id;
133  scratch_offsets_.resize(gatherFields_.size());
134 
135  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
136  const std::string& fieldName = indexerNames_[fd];
137  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
138 
139  int fieldNum = fieldIds_[fd];
140  const std::vector<int> & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
141  scratch_offsets_[fd] = PHX::View<int*>("offsets",offsets.size());
142  Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(offsets.data(), offsets.size()));
143  }
144 
145  scratch_lids_ = PHX::View<LO**>("lids",gatherFields_[0].extent(0),
146  globalIndexer_->getElementBlockGIDCount(blockId));
147 
148  indexerNames_.clear(); // Don't need this anymore
149 }
150 
151 // **********************************************************************
152 template<typename TRAITS,typename LO,typename GO,typename NodeT>
154 preEvaluate(typename TRAITS::PreEvalData d)
155 {
157 
158  // extract linear object container
159  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
160 
161  if(tpetraContainer_==Teuchos::null) {
162  // extract linear object container
163  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
164  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
165  }
166 }
167 
168 // **********************************************************************
169 template<typename TRAITS,typename LO,typename GO,typename NodeT>
171 evaluateFields(typename TRAITS::EvalData workset)
172 {
174 
175  // for convenience pull out some objects from workset
176  std::string blockId = this->wda(workset).block_id;
177  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
178 
180  if (useTimeDerivativeSolutionVector_)
181  x = tpetraContainer_->get_dxdt();
182  else
183  x = tpetraContainer_->get_x();
184 
185  auto x_data = x->getLocalViewDevice(Tpetra::Access::ReadOnly);
186 
187  globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
188 
189  // NOTE: A reordering of these loops will likely improve performance
190  // The "getGIDFieldOffsets may be expensive. However the
191  // "getElementGIDs" can be cheaper. However the lookup for LIDs
192  // may be more expensive!
193 
194  // gather operation for each cell in workset
195 
196  auto lids = scratch_lids_;
197  for (std::size_t fieldIndex=0; fieldIndex<gatherFields_.size();fieldIndex++) {
198  auto offsets = scratch_offsets_[fieldIndex];
199  auto gather_field = gatherFields_[fieldIndex].get_static_view();
200 
201  Kokkos::parallel_for(localCellIds.size(), KOKKOS_LAMBDA (std::size_t worksetCellIndex) {
202  // loop over basis functions and fill the fields
203  for(std::size_t basis=0;basis<offsets.extent(0);basis++) {
204  int offset = offsets(basis);
205  LO lid = lids(worksetCellIndex,offset);
206 
207  // set the value and seed the FAD object
208  gather_field(worksetCellIndex,basis) = x_data(lid,0);
209  }
210  });
211  }
212 }
213 
214 // **********************************************************************
215 // Specialization: Tangent
216 // **********************************************************************
217 
218 template<typename TRAITS,typename LO,typename GO,typename NodeT>
222  const Teuchos::ParameterList& p)
223  : globalIndexer_(indexer)
224  , has_tangent_fields_(false)
225 {
226  typedef std::vector< std::vector<std::string> > vvstring;
227 
228  GatherSolution_Input input;
229  input.setParameterList(p);
230 
231  const std::vector<std::string> & names = input.getDofNames();
233  const vvstring & tangent_field_names = input.getTangentNames();
234 
235  indexerNames_ = input.getIndexerNames();
236  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
237  globalDataKey_ = input.getGlobalDataKey();
238 
239  // allocate fields
240  gatherFields_.resize(names.size());
241  for (std::size_t fd = 0; fd < names.size(); ++fd) {
242  gatherFields_[fd] =
244  this->addEvaluatedField(gatherFields_[fd]);
245  // Don't allow for sharing so that we can avoid zeroing out the
246  // off-diagonal values of the FAD derivative array.
247  this->addUnsharedField(gatherFields_[fd].fieldTag().clone());
248  }
249 
250  // Setup dependent tangent fields if requested
251  if (tangent_field_names.size()>0) {
252  TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
253 
254  has_tangent_fields_ = true;
255  tangentFields_.resize(gatherFields_.size());
256  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
257  tangentFields_[fd].resize(tangent_field_names[fd].size());
258  for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
259  tangentFields_[fd][i] =
260  PHX::MDField<const RealT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
261  this->addDependentField(tangentFields_[fd][i]);
262  }
263  }
264  }
265 
266  // figure out what the first active name is
267  std::string firstName = "<none>";
268  if(names.size()>0)
269  firstName = names[0];
270 
271  std::string n = "GatherSolution (Tpetra): "+firstName+" (Tangent)";
272  this->setName(n);
273 }
274 
275 // **********************************************************************
276 template<typename TRAITS,typename LO,typename GO,typename NodeT>
278 postRegistrationSetup(typename TRAITS::SetupData /* d */,
279  PHX::FieldManager<TRAITS>& /* fm */)
280 {
281  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
282 
283  fieldIds_.resize(gatherFields_.size());
284 
285  // Original implementation of tangentFields used vector of
286  // vectors. The inner vectors could have different sizes for each
287  // [fd]. With UVM removal, we need to use a rank 2 view of views. So
288  // we need an extra vector to carry around the inner vector sizes.
289  tangentInnerVectorSizes_ = PHX::View<size_t*>("tangentInnerVectorSizes_",gatherFields_.size());
290  auto tangentInnerVectorSizes_host = Kokkos::create_mirror_view(tangentInnerVectorSizes_);
291  size_t inner_vector_max_size = 0;
292  for (std::size_t fd = 0; fd < tangentFields_.size(); ++fd) {
293  inner_vector_max_size = std::max(inner_vector_max_size,tangentFields_[fd].size());
294  tangentInnerVectorSizes_host(fd) = tangentFields_[fd].size();
295  }
296  Kokkos::deep_copy(tangentInnerVectorSizes_,tangentInnerVectorSizes_host);
297 
298  gatherFieldsVoV_.initialize("GatherSolution_Teptra<Tangent>::gatherFieldsVoV_",gatherFields_.size());
299  tangentFieldsVoV_.initialize("GatherSolution_Teptra<Tangent>::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size);
300 
301  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
302  const std::string& fieldName = indexerNames_[fd];
303  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
304  gatherFieldsVoV_.addView(gatherFields_[fd].get_static_view(),fd);
305 
306  if (has_tangent_fields_) {
307  for (std::size_t i=0; i<tangentFields_[fd].size(); ++i) {
308  tangentFieldsVoV_.addView(tangentFields_[fd][i].get_static_view(),fd,i);
309  }
310  }
311  }
312 
313  gatherFieldsVoV_.syncHostToDevice();
314  tangentFieldsVoV_.syncHostToDevice();
315 
316  indexerNames_.clear(); // Don't need this anymore
317 }
318 
319 // **********************************************************************
320 template<typename TRAITS,typename LO,typename GO,typename NodeT>
322 preEvaluate(typename TRAITS::PreEvalData d)
323 {
325 
326  // extract linear object container
327  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
328 
329  if(tpetraContainer_==Teuchos::null) {
330  // extract linear object container
331  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
332  tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
333  }
334 }
335 
336 // **********************************************************************
337 template<typename TRAITS,typename LO,typename GO,typename NodeT>
339 evaluateFields(typename TRAITS::EvalData workset)
340 {
342 
343  // for convenience pull out some objects from workset
344  std::string blockId = this->wda(workset).block_id;
345 
347  if (useTimeDerivativeSolutionVector_)
348  x = tpetraContainer_->get_dxdt();
349  else
350  x = tpetraContainer_->get_x();
351 
352  typedef typename PHX::MDField<ScalarT,Cell,NODE>::array_type::reference_type reference_type;
353  auto cellLocalIdsKokkos = this->wda(workset).getLocalCellIDs();
354  auto lids = globalIndexer_->getLIDs();
355  auto gidFieldOffsetsVoV = Teuchos::rcp_dynamic_cast<const panzer::DOFManager>(globalIndexer_,true)->getGIDFieldOffsetsKokkos(blockId,fieldIds_);
356  auto gidFieldOffsets = gidFieldOffsetsVoV.getViewDevice();
357  auto gatherFieldsDevice = gatherFieldsVoV_.getViewDevice();
358  auto x_view = x->getLocalViewDevice(Tpetra::Access::ReadOnly);
359  auto tangentInnerVectorSizes = this->tangentInnerVectorSizes_;
360 
361  if (has_tangent_fields_) {
362  auto tangentFieldsDevice = tangentFieldsVoV_.getViewDevice();
363  Kokkos::parallel_for("GatherSolutionTpetra<Tangent>",cellLocalIdsKokkos.extent(0),KOKKOS_LAMBDA(const int worksetCellIndex) {
364  for (size_t fieldIndex = 0; fieldIndex < gidFieldOffsets.extent(0); ++fieldIndex) {
365  for(size_t basis=0;basis<gidFieldOffsets(fieldIndex).extent(0);basis++) {
366  int offset = gidFieldOffsets(fieldIndex)(basis);
367  LO lid = lids(cellLocalIdsKokkos(worksetCellIndex),offset);
368  auto gf_ref = (gatherFieldsDevice[fieldIndex])(worksetCellIndex,basis);
369  gf_ref.val() = x_view(lid,0);
370  for (std::size_t i=0; i<tangentInnerVectorSizes(fieldIndex); ++i) {
371  gf_ref.fastAccessDx(i) = tangentFieldsDevice(fieldIndex,i)(worksetCellIndex,basis);
372  }
373  }
374  }
375  });
376  }
377  else {
378  Kokkos::parallel_for("GatherSolutionTpetra<Tangent>",cellLocalIdsKokkos.extent(0),KOKKOS_LAMBDA(const int worksetCellIndex) {
379  for (size_t fieldIndex = 0; fieldIndex < gidFieldOffsets.extent(0); ++fieldIndex) {
380  for(size_t basis=0;basis<gidFieldOffsets(fieldIndex).extent(0);basis++) {
381  int offset = gidFieldOffsets(fieldIndex)(basis);
382  LO lid = lids(cellLocalIdsKokkos(worksetCellIndex),offset);
383  reference_type gf_ref = (gatherFieldsDevice[fieldIndex])(worksetCellIndex,basis);
384  gf_ref.val() = x_view(lid,0);
385  }
386  }
387  });
388  }
389 }
390 
391 // **********************************************************************
392 // Specialization: Jacobian
393 // **********************************************************************
394 
395 template<typename TRAITS,typename LO,typename GO,typename NodeT>
399  const Teuchos::ParameterList& p)
400  : globalIndexer_(indexer)
401 {
402  // typedef std::vector< std::vector<std::string> > vvstring;
403 
404  GatherSolution_Input input;
405  input.setParameterList(p);
406 
407  const std::vector<std::string> & names = input.getDofNames();
409  //const vvstring & tangent_field_names = input.getTangentNames();
410 
411  indexerNames_ = input.getIndexerNames();
412  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
413  globalDataKey_ = input.getGlobalDataKey();
414 
415  gatherSeedIndex_ = input.getGatherSeedIndex();
416  sensitivitiesName_ = input.getSensitivitiesName();
417  disableSensitivities_ = !input.firstSensitivitiesAvailable();
418 
419  gatherFields_.resize(names.size());
420  scratch_offsets_.resize(names.size());
421  for (std::size_t fd = 0; fd < names.size(); ++fd) {
422  PHX::MDField<ScalarT,Cell,NODE> f(names[fd],basis->functional);
423  gatherFields_[fd] = f;
424  this->addEvaluatedField(gatherFields_[fd]);
425  // Don't allow for sharing so that we can avoid zeroing out the
426  // off-diagonal values of the FAD derivative array.
427  this->addUnsharedField(gatherFields_[fd].fieldTag().clone());
428  }
429 
430  // figure out what the first active name is
431  std::string firstName = "<none>";
432  if(names.size()>0)
433  firstName = names[0];
434 
435  // print out convenience
436  if(disableSensitivities_) {
437  std::string n = "GatherSolution (Tpetra, No Sensitivities): "+firstName+" (Jacobian)";
438  this->setName(n);
439  }
440  else {
441  std::string n = "GatherSolution (Tpetra): "+firstName+" (Jacobian) ";
442  this->setName(n);
443  }
444 }
445 
446 // **********************************************************************
447 template<typename TRAITS,typename LO,typename GO,typename NodeT>
449 postRegistrationSetup(typename TRAITS::SetupData d,
450  PHX::FieldManager<TRAITS>& /* fm */)
451 {
452  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
453 
454  fieldIds_.resize(gatherFields_.size());
455 
456  const Workset & workset_0 = (*d.worksets_)[0];
457  std::string blockId = this->wda(workset_0).block_id;
458 
459  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
460  // get field ID from DOF manager
461  const std::string& fieldName = indexerNames_[fd];
462  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
463 
464  int fieldNum = fieldIds_[fd];
465  const std::vector<int> & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
466  scratch_offsets_[fd] = PHX::View<int*>("offsets",offsets.size());
467  Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(offsets.data(), offsets.size()));
468  }
469 
470  scratch_lids_ = PHX::View<LO**>("lids",gatherFields_[0].extent(0),
471  globalIndexer_->getElementBlockGIDCount(blockId));
472 
473  indexerNames_.clear(); // Don't need this anymore
474 }
475 
476 // **********************************************************************
477 template<typename TRAITS,typename LO,typename GO,typename NodeT>
479 preEvaluate(typename TRAITS::PreEvalData d)
480 {
481  using Teuchos::RCP;
482  using Teuchos::rcp;
483  using Teuchos::rcp_dynamic_cast;
484 
487 
488  // manage sensitivities
490  if(!disableSensitivities_) {
491  if(d.first_sensitivities_name==sensitivitiesName_)
492  applySensitivities_ = true;
493  else
494  applySensitivities_ = false;
495  }
496  else
497  applySensitivities_ = false;
498 
500 
502 
503  // first try refactored ReadOnly container
504  std::string post = useTimeDerivativeSolutionVector_ ? " - Xdot" : " - X";
505  if(d.gedc->containsDataObject(globalDataKey_+post)) {
506  ged = d.gedc->getDataObject(globalDataKey_+post);
507 
508  RCP<RO_GED> ro_ged = rcp_dynamic_cast<RO_GED>(ged,true);
509 
510  x_vector = ro_ged->getGhostedVector_Tpetra();
511 
512  return;
513  }
514 
515  ged = d.gedc->getDataObject(globalDataKey_);
516 
517  // try to extract linear object container
518  {
519  RCP<LOC> tpetraContainer = rcp_dynamic_cast<LOC>(ged);
520  RCP<LOCPair_GlobalEvaluationData> loc_pair = rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(ged);
521 
522  if(loc_pair!=Teuchos::null) {
523  Teuchos::RCP<LinearObjContainer> loc = loc_pair->getGhostedLOC();
524  // extract linear object container
525  tpetraContainer = rcp_dynamic_cast<LOC>(loc);
526  }
527 
528  if(tpetraContainer!=Teuchos::null) {
529  if (useTimeDerivativeSolutionVector_)
530  x_vector = tpetraContainer->get_dxdt();
531  else
532  x_vector = tpetraContainer->get_x();
533 
534  return; // epetraContainer was found
535  }
536  }
537 
538  // try to extract an EpetraVector_ReadOnly object (this is the last resort!, it throws if not found)
539  {
540  RCP<RO_GED> ro_ged = rcp_dynamic_cast<RO_GED>(ged,true);
541 
542  x_vector = ro_ged->getGhostedVector_Tpetra();
543  }
544 }
545 
546 // **********************************************************************
547 template<typename TRAITS,typename LO,typename GO,typename NodeT>
549 evaluateFields(typename TRAITS::EvalData workset)
550 {
551  // for convenience pull out some objects from workset
552  std::string blockId = this->wda(workset).block_id;
553 
554  double seed_value = 0.0;
555  if (useTimeDerivativeSolutionVector_) {
556  seed_value = workset.alpha;
557  }
558  else if (gatherSeedIndex_<0) {
559  seed_value = workset.beta;
560  }
561  else if(!useTimeDerivativeSolutionVector_) {
562  seed_value = workset.gather_seeds[gatherSeedIndex_];
563  }
564  else {
565  TEUCHOS_ASSERT(false);
566  }
567 
568  // turn off sensitivies: this may be faster if we don't expand the term
569  // but I suspect not because anywhere it is used the full complement of
570  // sensitivies will be needed anyway.
571  if(!applySensitivities_)
572  seed_value = 0.0;
573 
574  // Interface worksets handle DOFs from two element blocks. The
575  // derivative offset for the other element block must be shifted by
576  // the derivative side of my element block.
577  functor_data.dos = 0;
578  if (this->wda.getDetailsIndex() == 1)
579  {
580  // Get the DOF count for my element block.
581  functor_data.dos = globalIndexer_->getElementBlockGIDCount(workset.details(0).block_id);
582  }
583 
584  // switch to a faster assembly
585  bool use_seed = true;
586  if(seed_value==0.0)
587  use_seed = false;
588 
589  globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
590 
591  // now setup the fuctor_data, and run the parallel_for loop
593 
594  functor_data.x_data = x_vector->getLocalViewDevice(Tpetra::Access::ReadOnly);
595  functor_data.seed_value = seed_value;
596  functor_data.lids = scratch_lids_;
597 
598  // loop over the fields to be gathered
599  for(std::size_t fieldIndex=0;
600  fieldIndex<gatherFields_.size();fieldIndex++) {
601 
602  // setup functor data
603  functor_data.offsets = scratch_offsets_[fieldIndex];
604  functor_data.field = gatherFields_[fieldIndex];
605 
606  if(use_seed)
607  Kokkos::parallel_for(workset.num_cells,*this);
608  else
609  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device,NoSeed>(0,workset.num_cells),*this);
610  }
612 }
613 
614 // **********************************************************************
615 template<typename TRAITS,typename LO,typename GO,typename NodeT>
616 KOKKOS_INLINE_FUNCTION
618 operator()(const int worksetCellIndex) const
619 {
620  // loop over basis functions and fill the fields
621  for(std::size_t basis=0;basis<functor_data.offsets.extent(0);basis++) {
622  int offset = functor_data.offsets(basis);
623  LO lid = functor_data.lids(worksetCellIndex,offset);
624 
625  // set the value and seed the FAD object
626  if (functor_data.dos == 0)
627  functor_data.field(worksetCellIndex,basis).val() = functor_data.x_data(lid,0);
628  else // Interface conditions need to zero out derivative array
629  functor_data.field(worksetCellIndex,basis) = ScalarT(functor_data.x_data(lid,0));
630 
631  functor_data.field(worksetCellIndex,basis).fastAccessDx(functor_data.dos + offset) = functor_data.seed_value;
632  }
633 }
634 
635 // **********************************************************************
636 template<typename TRAITS,typename LO,typename GO,typename NodeT>
637 KOKKOS_INLINE_FUNCTION
639 operator()(const NoSeed,const int worksetCellIndex) const
640 {
641  // loop over basis functions and fill the fields
642  for(std::size_t basis=0;basis<functor_data.offsets.extent(0);basis++) {
643  int offset = functor_data.offsets(basis);
644  LO lid = functor_data.lids(worksetCellIndex,offset);
645 
646  // set the value and seed the FAD object
647  functor_data.field(worksetCellIndex,basis).val() = functor_data.x_data(lid,0);
648  }
649 }
650 
651 // **********************************************************************
652 
653 #endif
const std::vector< std::vector< std::string > > & getTangentNames() const
Get the name of the tangent fields (tangent only)
const std::vector< std::string > & getDofNames() const
The names of the DOFs to be gathered (all types)
void setParameterList(const Teuchos::ParameterList &pl)
std::string getGlobalDataKey() const
Name of the global evaluation data container to use for the source vector (all types) ...
Teuchos::RCP< const PureBasis > getBasis() const
Basis definiting layout of dof names (all types)
PHX::View< const int * > offsets
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
int getGatherSeedIndex() const
What index to use for initializing the seed (Jacobian and Hessian)
Gathers solution values from the Newton solution vector into the nodal fields of the field manager...
bool firstSensitivitiesAvailable()
Are first derivative sensitivities enabled or disabled? (Jacobian and Hessian)
bool useTimeDerivativeSolutionVector() const
Gather a time derivative vector? (all types)
std::string block_id
DEPRECATED - use: getElementBlock()
const std::vector< std::string > & getIndexerNames() const
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< PHX::DataLayout > functional
&lt;Cell,Basis&gt; or &lt;Cell,Basis&gt;
Kokkos::View< const LO **, Kokkos::LayoutRight, PHX::Device > lids
std::string getSensitivitiesName() const
The name of the sensitivities. Enables sensitivities at &quot;preEvaluate&quot; time (Jacobian and Hessian) ...