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  // We also need storage for the number of tangent fields associated with
309  // each gatherField
310 
311  if (has_tangent_fields_) {
312 
313  size_t inner_vector_max_size = 0;
314  for (std::size_t fd = 0; fd < tangentFields_.size(); ++fd)
315  inner_vector_max_size = std::max(inner_vector_max_size,tangentFields_[fd].size());
316  tangentFieldsVoV_.initialize("GatherSolution_BlockedTpetra<Tangent>::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size);
317 
318  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
319  for (std::size_t i=0; i<tangentFields_[fd].size(); ++i) {
320  tangentFieldsVoV_.addView(tangentFields_[fd][i].get_static_view(),fd,i);
321  }
322  }
323 
324  tangentFieldsVoV_.syncHostToDevice();
325  }
326 
327  indexerNames_.clear(); // Don't need this anymore
328 }
329 
330 // **********************************************************************
331 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
333 preEvaluate(typename TRAITS::PreEvalData d)
334 {
335  // extract linear object container
336  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
337 }
338 
339 // **********************************************************************
340 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
342 evaluateFields(typename TRAITS::EvalData workset)
343 {
344  using Teuchos::RCP;
345  using Teuchos::ArrayRCP;
346  using Teuchos::ptrFromRef;
347  using Teuchos::rcp_dynamic_cast;
348 
349  using Thyra::VectorBase;
350  using Thyra::SpmdVectorBase;
352 
353  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
354  out.setShowProcRank(true);
355  out.setOutputToRootOnly(-1);
356 
357  const PHX::View<const int*> & localCellIds = this->wda(workset).getLocalCellIDs();
358 
359  Teuchos::RCP<ProductVectorBase<double> > blockedSolution;
360  if (useTimeDerivativeSolutionVector_)
361  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
362  else
363  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
364 
365  // Loop over fields to gather
366  int currentWorksetLIDSubBlock = -1;
367  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
368  // workset LIDs only change if in different sub blocks
369  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
370  const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
371  const std::string blockId = this->wda(workset).block_id;
372  const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
373  blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
374  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
375  }
376 
377  const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
378  const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealT,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),true))->getTpetraVector());
379  const auto kokkosSolution = subblockSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
380 
381  // Class data fields for lambda capture
382  const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
383  const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
384  const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
385 
386  if (has_tangent_fields_) {
387  const int numTangents = tangentFields_[fieldIndex].size();
388  const auto tangentFieldsDevice = tangentFieldsVoV_.getViewDevice();
389  const auto kokkosTangents = Kokkos::subview(tangentFieldsDevice,fieldIndex,Kokkos::ALL());
390  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
391  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
392  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
393  fieldValues(cell,basis).zero();
394  fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
395  for (int i_tangent=0; i_tangent<numTangents; ++i_tangent)
396  fieldValues(cell,basis).fastAccessDx(i_tangent) = kokkosTangents(i_tangent)(cell,basis);
397  }
398  });
399  } else {
400  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
401  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
402  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
403  fieldValues(cell,basis).zero();
404  fieldValues(cell,basis) = kokkosSolution(rowLID,0);
405  }
406  });
407  }
408  }
409 
410 }
411 
412 // **********************************************************************
413 // Specialization: Jacobian
414 // **********************************************************************
415 
416 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
420  const Teuchos::ParameterList& p)
421  : globalIndexer_(indexer)
422 {
423  GatherSolution_Input input;
424  input.setParameterList(p);
425 
426  const std::vector<std::string> & names = input.getDofNames();
428 
429  indexerNames_ = input.getIndexerNames();
430  useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
431  globalDataKey_ = input.getGlobalDataKey();
432 
433  disableSensitivities_ = !input.firstSensitivitiesAvailable();
434 
435  gatherFields_.resize(names.size());
436  for (std::size_t fd = 0; fd < names.size(); ++fd) {
437  PHX::MDField<ScalarT,Cell,NODE> f(names[fd],basis->functional);
438  gatherFields_[fd] = f;
439  this->addEvaluatedField(gatherFields_[fd]);
440  }
441 
442  // figure out what the first active name is
443  std::string firstName = "<none>";
444  if(names.size()>0)
445  firstName = names[0];
446 
447  // print out convenience
448  if(disableSensitivities_) {
449  std::string n = "GatherSolution (BlockedTpetra, No Sensitivities): "+firstName+" (Jacobian)";
450  this->setName(n);
451  }
452  else {
453  std::string n = "GatherSolution (BlockedTpetra): "+firstName+" ("+PHX::print<EvalT>()+") ";
454  this->setName(n);
455  }
456 }
457 
458 // **********************************************************************
459 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
461 postRegistrationSetup(typename TRAITS::SetupData d,
462  PHX::FieldManager<TRAITS>& /* fm */)
463 {
464  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
465 
466  const Workset & workset_0 = (*d.worksets_)[0];
467  const std::string blockId = this->wda(workset_0).block_id;
468 
469  fieldIds_.resize(gatherFields_.size());
470  fieldOffsets_.resize(gatherFields_.size());
471  productVectorBlockIndex_.resize(gatherFields_.size());
472  int maxElementBlockGIDCount = -1;
473  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
474 
475  const std::string fieldName = indexerNames_[fd];
476  const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
477  productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
478  const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
479  fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName); // Field number in the sub-global-indexer
480 
481  const std::vector<int>& offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
482  fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
483  auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
484  for (std::size_t i=0; i < offsets.size(); ++i)
485  hostOffsets(i) = offsets[i];
486  Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
487  maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
488  }
489 
490  // We will use one workset lid view for all fields, but has to be
491  // sized big enough to hold the largest elementBlockGIDCount in the
492  // ProductVector.
493  worksetLIDs_ = PHX::View<LO**>("ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
494  gatherFields_[0].extent(0),
495  maxElementBlockGIDCount);
496 
497  // Compute the block offsets
498  const auto& blockGlobalIndexers = globalIndexer_->getFieldDOFManagers();
499  const int numBlocks = static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
500  blockOffsets_ = PHX::View<LO*>("GatherSolution_BlockedTpetra(Jacobian):blockOffsets_",
501  numBlocks+1); // Number of blocks, plus a sentinel
502  const auto hostBlockOffsets = Kokkos::create_mirror_view(blockOffsets_);
503  for (int blk=0;blk<numBlocks;++blk) {
504  int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk);
505  hostBlockOffsets(blk) = blockOffset;
506  }
507  hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
508  Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
509 
510  indexerNames_.clear(); // Don't need this anymore
511 }
512 
513 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
515 preEvaluate(typename TRAITS::PreEvalData d)
516 {
517  // extract linear object container
518  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
519 }
520 
521 // **********************************************************************
522 template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
524 evaluateFields(typename TRAITS::EvalData workset)
525 {
526  using Teuchos::RCP;
527  using Teuchos::rcp_dynamic_cast;
528  using Thyra::VectorBase;
530 
531  const auto& localCellIds = this->wda(workset).cell_local_ids_k;
532 
533  RealType seedValue = RealType(0.0);
534  RCP<ProductVectorBase<double>> blockedSolution;
535  if (useTimeDerivativeSolutionVector_) {
536  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
537  seedValue = workset.alpha;
538  }
539  else {
540  blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
541  seedValue = workset.beta;
542  }
543 
544  // turn off sensitivies: this may be faster if we don't expand the term
545  // but I suspect not because anywhere it is used the full complement of
546  // sensitivies will be needed anyway.
547  if(disableSensitivities_)
548  seedValue = 0.0;
549 
550  // Loop over fields to gather
551  int currentWorksetLIDSubBlock = -1;
552  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
553  // workset LIDs only change if in different sub blocks
554  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
555  const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
556  const std::string blockId = this->wda(workset).block_id;
557  const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
558  blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
559  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
560  }
561 
562  const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
563  const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),true))->getTpetraVector());
564  const auto kokkosSolution = subblockSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
565 
566  // Class data fields for lambda capture
567  const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
568  const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
569  const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
570  const PHX::View<const LO*> blockOffsets = blockOffsets_;
571  auto blockOffsets_h = Kokkos::create_mirror_view(blockOffsets);
572  Kokkos::deep_copy(blockOffsets_h, blockOffsets);
573  const int blockStart = blockOffsets_h(blockRowIndex);
574 
575  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
576  for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
577  const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
578  fieldValues(cell,basis).zero();
579  fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
580  fieldValues(cell,basis).fastAccessDx(blockStart+fieldOffsets(basis)) = seedValue;
581  }
582  });
583 
584  }
585 }
586 
587 // **********************************************************************
588 
589 #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;