Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_GatherSolution_BlockedTpetra_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_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
12 #define PANZER_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
13 
14 #include "Teuchos_Assert.hpp"
15 #include "Phalanx_DataLayout.hpp"
16 
17 #include "Panzer_GlobalIndexer.hpp"
19 #include "Panzer_PureBasis.hpp"
20 #include "Panzer_TpetraLinearObjFactory.hpp"
24 
25 #include "Teuchos_FancyOStream.hpp"
26 
27 #include "Thyra_SpmdVectorBase.hpp"
28 #include "Thyra_ProductVectorBase.hpp"
29 
30 #include "Tpetra_Map.hpp"
31 
32 template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
36  const Teuchos::ParameterList& p)
37 {
38  const std::vector<std::string>& names =
39  *(p.get< Teuchos::RCP< std::vector<std::string> > >("DOF Names"));
40 
43 
44  for (std::size_t fd = 0; fd < names.size(); ++fd) {
46  this->addEvaluatedField(field.fieldTag());
47  }
48 
49  this->setName("Gather Solution");
50 }
51 
52 // **********************************************************************
53 // Specialization: Residual
54 // **********************************************************************
55 
56 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
60  const Teuchos::ParameterList& p)
61  : globalIndexer_(indexer)
62  , has_tangent_fields_(false)
63 {
64  typedef std::vector< std::vector<std::string> > vvstring;
65 
67  input.setParameterList(p);
68 
69  const std::vector<std::string> & names = input.getDofNames();
71  const vvstring & tangent_field_names = input.getTangentNames();
72 
73  indexerNames_ = input.getIndexerNames();
74  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
75  globalDataKey_ = input.getGlobalDataKey();
76 
77  // allocate fields
78  gatherFields_.resize(names.size());
79  for (std::size_t fd = 0; fd < names.size(); ++fd) {
80  gatherFields_[fd] =
82  this->addEvaluatedField(gatherFields_[fd]);
83  }
84 
85  // Setup dependent tangent fields if requested
86  if (tangent_field_names.size()>0) {
87  TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
88 
89  has_tangent_fields_ = true;
90  tangentFields_.resize(gatherFields_.size());
91  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
92  tangentFields_[fd].resize(tangent_field_names[fd].size());
93  for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
94  tangentFields_[fd][i] =
95  PHX::MDField<const ScalarT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
96  this->addDependentField(tangentFields_[fd][i]);
97  }
98  }
99  }
100 
101  // figure out what the first active name is
102  std::string firstName = "<none>";
103  if(names.size()>0)
104  firstName = names[0];
105 
106  std::string n = "GatherSolution (BlockedTpetra): "+firstName+" (Residual)";
107  this->setName(n);
108 }
109 
110 // **********************************************************************
111 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
113 postRegistrationSetup(typename TRAITS::SetupData d,
114  PHX::FieldManager<TRAITS>& /* fm */)
115 {
116  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
117 
118  const Workset & workset_0 = (*d.worksets_)[0];
119  const std::string blockId = this->wda(workset_0).block_id;
120 
121  fieldIds_.resize(gatherFields_.size());
122  fieldOffsets_.resize(gatherFields_.size());
123  fieldGlobalIndexers_.resize(gatherFields_.size());
124  productVectorBlockIndex_.resize(gatherFields_.size());
125  int maxElementBlockGIDCount = -1;
126  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
127  // get field ID from DOF manager
128  const std::string& fieldName = indexerNames_[fd];
129  const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
130  productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
131  fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
132  fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer
133 
134  const std::vector<int>& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
135  fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size());
136  auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
137  for(std::size_t i=0; i < offsets.size(); ++i)
138  hostFieldOffsets(i) = offsets[i];
139  Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets);
140 
141  maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
142  }
143 
144  // We will use one workset lid view for all fields, but has to be
145  // sized big enough to hold the largest elementBlockGIDCount in the
146  // ProductVector.
147  worksetLIDs_ = PHX::View<LO**>("GatherSolution_BlockedTpetra(Residual):worksetLIDs",
148  gatherFields_[0].extent(0),
149  maxElementBlockGIDCount);
150 
151  indexerNames_.clear(); // Don't need this anymore
152 }
153 
154 // **********************************************************************
155 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
157 preEvaluate(typename TRAITS::PreEvalData d)
158 {
159  // extract linear object container
160  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
161 }
162 
163 // **********************************************************************
164 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
166 evaluateFields(typename TRAITS::EvalData workset)
167 {
168  using Teuchos::RCP;
169  using Teuchos::rcp_dynamic_cast;
170  using Thyra::VectorBase;
172 
173  const PHX::View<const int*>& localCellIds = this->wda(workset).cell_local_ids_k;
174 
175  RCP<ProductVectorBase<ScalarT>> thyraBlockSolution;
176  if (useTimeDerivativeSolutionVector_)
177  thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),true);
178  else
179  thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),true);
180 
181  // Loop over gathered fields
182  int currentWorksetLIDSubBlock = -1;
183  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
184  // workset LIDs only change for different sub blocks
185  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
186  const std::string blockId = this->wda(workset).block_id;
187  const int num_dofs = fieldGlobalIndexers_[fieldIndex]->getElementBlockGIDCount(blockId);
188  fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
189  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
190  }
191 
192  const auto& tpetraSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<ScalarT,LO,GO,NodeT>>(thyraBlockSolution->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),true))->getTpetraVector());
193  const auto& kokkosSolution = tpetraSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
194 
195  // Class data fields for lambda capture
196  const auto& fieldOffsets = fieldOffsets_[fieldIndex];
197  const auto& worksetLIDs = worksetLIDs_;
198  const auto& fieldValues = gatherFields_[fieldIndex];
199 
200  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
201  for(int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
202  const int lid = worksetLIDs(cell,fieldOffsets(basis));
203  fieldValues(cell,basis) = kokkosSolution(lid,0);
204  }
205  });
206  }
207 
208 }
209 
210 // **********************************************************************
211 // Specialization: Tangent
212 // **********************************************************************
213 
214 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
218  const Teuchos::ParameterList& p)
219  : globalIndexer_(indexer)
220  , has_tangent_fields_(false)
221 {
222  typedef std::vector< std::vector<std::string> > vvstring;
223 
224  GatherSolution_Input input;
225  input.setParameterList(p);
226 
227  const std::vector<std::string> & names = input.getDofNames();
229  const vvstring & tangent_field_names = input.getTangentNames();
230 
231  indexerNames_ = input.getIndexerNames();
232  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
233  globalDataKey_ = input.getGlobalDataKey();
234 
235  // allocate fields
236  gatherFields_.resize(names.size());
237  for (std::size_t fd = 0; fd < names.size(); ++fd) {
238  gatherFields_[fd] =
240  this->addEvaluatedField(gatherFields_[fd]);
241  }
242 
243  // Setup dependent tangent fields if requested
244  if (tangent_field_names.size()>0) {
245  TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
246 
247  has_tangent_fields_ = true;
248  tangentFields_.resize(gatherFields_.size());
249  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
250  tangentFields_[fd].resize(tangent_field_names[fd].size());
251  for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
252  tangentFields_[fd][i] =
253  PHX::MDField<const RealT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
254  this->addDependentField(tangentFields_[fd][i]);
255  }
256  }
257  }
258 
259  // figure out what the first active name is
260  std::string firstName = "<none>";
261  if(names.size()>0)
262  firstName = names[0];
263 
264  std::string n = "GatherSolution (BlockedTpetra): "+firstName+" (Tangent)";
265  this->setName(n);
266 }
267 
268 // **********************************************************************
269 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
271 postRegistrationSetup(typename TRAITS::SetupData d,
272  PHX::FieldManager<TRAITS>& /* fm */)
273 {
274  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
275 
276  const Workset & workset_0 = (*d.worksets_)[0];
277  const std::string blockId = this->wda(workset_0).block_id;
278 
279  fieldIds_.resize(gatherFields_.size());
280  fieldOffsets_.resize(gatherFields_.size());
281  productVectorBlockIndex_.resize(gatherFields_.size());
282  int maxElementBlockGIDCount = -1;
283  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
284 
285  const std::string fieldName = indexerNames_[fd];
286  const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
287  productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
288  const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
289  fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName); // Field number in the sub-global-indexer
290 
291  const std::vector<int>& offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
292  fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Tangent):fieldOffsets",offsets.size());
293  auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
294  for (std::size_t i=0; i < offsets.size(); ++i)
295  hostOffsets(i) = offsets[i];
296  Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
297  maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
298  }
299 
300  // We will use one workset lid view for all fields, but has to be
301  // sized big enough to hold the largest elementBlockGIDCount in the
302  // ProductVector.
303  worksetLIDs_ = PHX::View<LO**>("ScatterResidual_BlockedTpetra(Tangent):worksetLIDs",
304  gatherFields_[0].extent(0),
305  maxElementBlockGIDCount);
306 
307  // Set up storage for tangentFields using view of views
308  if (has_tangent_fields_) {
309 
310  size_t inner_vector_max_size = 0;
311  for (std::size_t fd = 0; fd < tangentFields_.size(); ++fd)
312  inner_vector_max_size = std::max(inner_vector_max_size,tangentFields_[fd].size());
313  tangentFieldsVoV_.initialize("GatherSolution_BlockedTpetra<Tangent>::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size);
314 
315  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
316  for (std::size_t i=0; i<tangentFields_[fd].size(); ++i) {
317  tangentFieldsVoV_.addView(tangentFields_[fd][i].get_static_view(),fd,i);
318  }
319  }
320 
321  tangentFieldsVoV_.syncHostToDevice();
322  }
323 
324  indexerNames_.clear(); // Don't need this anymore
325 }
326 
327 // **********************************************************************
328 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
330 preEvaluate(typename TRAITS::PreEvalData d)
331 {
332  // extract linear object container
333  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
334 }
335 
336 // **********************************************************************
337 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
339 evaluateFields(typename TRAITS::EvalData workset)
340 {
341  using Teuchos::RCP;
342  using Teuchos::ArrayRCP;
343  using Teuchos::ptrFromRef;
344  using Teuchos::rcp_dynamic_cast;
345 
346  using Thyra::VectorBase;
347  using Thyra::SpmdVectorBase;
349 
350  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
351  out.setShowProcRank(true);
352  out.setOutputToRootOnly(-1);
353 
354  const PHX::View<const int*> & localCellIds = this->wda(workset).getLocalCellIDs();
355 
356  Teuchos::RCP<ProductVectorBase<double> > blockedSolution;
357  if (useTimeDerivativeSolutionVector_)
358  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
359  else
360  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
361 
362  // Loop over fields to gather
363  int currentWorksetLIDSubBlock = -1;
364  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
365  // workset LIDs only change if in different sub blocks
366  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
367  const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
368  const std::string blockId = this->wda(workset).block_id;
369  const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
370  blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
371  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
372  }
373 
374  const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
375  const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealT,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),true))->getTpetraVector());
376  const auto kokkosSolution = subblockSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
377 
378  // Class data fields for lambda capture
379  const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
380  const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
381  const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
382 
383  if (has_tangent_fields_) {
384  const int numTangents = tangentFields_[fieldIndex].size();
385  const auto tangentFieldsDevice = tangentFieldsVoV_.getViewDevice();
386  const auto kokkosTangents = Kokkos::subview(tangentFieldsDevice,fieldIndex,Kokkos::ALL());
387  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
388  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
389  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
390  fieldValues(cell,basis).zero();
391  fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
392  for (int i_tangent=0; i_tangent<numTangents; ++i_tangent)
393  fieldValues(cell,basis).fastAccessDx(i_tangent) = kokkosTangents(i_tangent)(cell,basis);
394  }
395  });
396  } else {
397  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
398  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
399  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
400  fieldValues(cell,basis).zero();
401  fieldValues(cell,basis) = kokkosSolution(rowLID,0);
402  }
403  });
404  }
405  }
406 
407 }
408 
409 // **********************************************************************
410 // Specialization: Jacobian
411 // **********************************************************************
412 
413 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
417  const Teuchos::ParameterList& p)
418  : globalIndexer_(indexer)
419 {
420  GatherSolution_Input input;
421  input.setParameterList(p);
422 
423  const std::vector<std::string> & names = input.getDofNames();
425 
426  indexerNames_ = input.getIndexerNames();
427  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
428  globalDataKey_ = input.getGlobalDataKey();
429 
430  disableSensitivities_ = !input.firstSensitivitiesAvailable();
431 
432  gatherFields_.resize(names.size());
433  for (std::size_t fd = 0; fd < names.size(); ++fd) {
434  PHX::MDField<ScalarT,Cell,NODE> f(names[fd],basis->functional);
435  gatherFields_[fd] = f;
436  this->addEvaluatedField(gatherFields_[fd]);
437  }
438 
439  // figure out what the first active name is
440  std::string firstName = "<none>";
441  if(names.size()>0)
442  firstName = names[0];
443 
444  // print out convenience
445  if(disableSensitivities_) {
446  std::string n = "GatherSolution (BlockedTpetra, No Sensitivities): "+firstName+" (Jacobian)";
447  this->setName(n);
448  }
449  else {
450  std::string n = "GatherSolution (BlockedTpetra): "+firstName+" ("+PHX::print<EvalT>()+") ";
451  this->setName(n);
452  }
453 }
454 
455 // **********************************************************************
456 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
458 postRegistrationSetup(typename TRAITS::SetupData d,
459  PHX::FieldManager<TRAITS>& /* fm */)
460 {
461  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
462 
463  const Workset & workset_0 = (*d.worksets_)[0];
464  const std::string blockId = this->wda(workset_0).block_id;
465 
466  fieldIds_.resize(gatherFields_.size());
467  fieldOffsets_.resize(gatherFields_.size());
468  productVectorBlockIndex_.resize(gatherFields_.size());
469  int maxElementBlockGIDCount = -1;
470  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
471 
472  const std::string fieldName = indexerNames_[fd];
473  const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
474  productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
475  const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
476  fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName); // Field number in the sub-global-indexer
477 
478  const std::vector<int>& offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
479  fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
480  auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
481  for (std::size_t i=0; i < offsets.size(); ++i)
482  hostOffsets(i) = offsets[i];
483  Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
484  maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
485  }
486 
487  // We will use one workset lid view for all fields, but has to be
488  // sized big enough to hold the largest elementBlockGIDCount in the
489  // ProductVector.
490  worksetLIDs_ = PHX::View<LO**>("ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
491  gatherFields_[0].extent(0),
492  maxElementBlockGIDCount);
493 
494  // Compute the block offsets
495  const auto& blockGlobalIndexers = globalIndexer_->getFieldDOFManagers();
496  const int numBlocks = static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
497  blockOffsets_ = PHX::View<LO*>("GatherSolution_BlockedTpetra(Jacobian):blockOffsets_",
498  numBlocks+1); // Number of blocks, plus a sentinel
499  const auto hostBlockOffsets = Kokkos::create_mirror_view(blockOffsets_);
500  for (int blk=0;blk<numBlocks;++blk) {
501  int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk);
502  hostBlockOffsets(blk) = blockOffset;
503  }
504  hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
505  Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
506 
507  indexerNames_.clear(); // Don't need this anymore
508 }
509 
510 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
512 preEvaluate(typename TRAITS::PreEvalData d)
513 {
514  // extract linear object container
515  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
516 }
517 
518 // **********************************************************************
519 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
521 evaluateFields(typename TRAITS::EvalData workset)
522 {
523  using Teuchos::RCP;
524  using Teuchos::rcp_dynamic_cast;
525  using Thyra::VectorBase;
527 
528  const auto& localCellIds = this->wda(workset).cell_local_ids_k;
529 
530  RealType seedValue = RealType(0.0);
531  RCP<ProductVectorBase<double>> blockedSolution;
532  if (useTimeDerivativeSolutionVector_) {
533  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
534  seedValue = workset.alpha;
535  }
536  else {
537  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
538  seedValue = workset.beta;
539  }
540 
541  // turn off sensitivies: this may be faster if we don't expand the term
542  // but I suspect not because anywhere it is used the full complement of
543  // sensitivies will be needed anyway.
544  if(disableSensitivities_)
545  seedValue = 0.0;
546 
547  // Loop over fields to gather
548  int currentWorksetLIDSubBlock = -1;
549  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
550  // workset LIDs only change if in different sub blocks
551  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
552  const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
553  const std::string blockId = this->wda(workset).block_id;
554  const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
555  blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
556  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
557  }
558 
559  const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
560  const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),true))->getTpetraVector());
561  const auto kokkosSolution = subblockSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
562 
563  // Class data fields for lambda capture
564  const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
565  const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
566  const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
567  const PHX::View<const LO*> blockOffsets = blockOffsets_;
568  auto blockOffsets_h = Kokkos::create_mirror_view(blockOffsets);
569  Kokkos::deep_copy(blockOffsets_h, blockOffsets);
570  const int blockStart = blockOffsets_h(blockRowIndex);
571 
572  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
573  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
574  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
575  fieldValues(cell,basis).zero();
576  fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
577  fieldValues(cell,basis).fastAccessDx(blockStart+fieldOffsets(basis)) = seedValue;
578  }
579  });
580 
581  }
582 }
583 
584 // **********************************************************************
585 
586 #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)
GatherSolution_BlockedTpetra(const Teuchos::RCP< const BlockedDOFManager > &indexer)
void setParameterList(const Teuchos::ParameterList &pl)
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
T & get(const std::string &name, T def_value)
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
bool firstSensitivitiesAvailable()
Are first derivative sensitivities enabled or disabled? (Jacobian and Hessian)
bool useTimeDerivativeSolutionVector() const
Gather a time derivative vector? (all types)
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
virtual void preEvaluate(typename Traits::PreEvalData d)=0
std::string block_id
DEPRECATED - use: getElementBlock()
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...
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;