Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_GatherTangent_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_TANGENT_BLOCKED_TPETRA_IMPL_HPP
12 #define PANZER_GATHER_TANGENT_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  : globalIndexer_(indexer)
38  , useTimeDerivativeSolutionVector_(false)
39  , globalDataKey_("Tangent Gather Container")
40 {
41  const std::vector<std::string>& names =
42  *(p.get< Teuchos::RCP< std::vector<std::string> > >("DOF Names"));
43 
45 
48 
49  gatherFields_.resize(names.size());
50  for (std::size_t fd = 0; fd < names.size(); ++fd) {
51  gatherFields_[fd] =
52  PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->functional);
53  this->addEvaluatedField(gatherFields_[fd]);
54  // If blockedContainer_ is null, the evalaution is a no-op. In this
55  // case we need to preserve zero initial value. Do this by not
56  // sharing.
57  this->addUnsharedField(gatherFields_[fd].fieldTag().clone());
58  }
59 
60  if (p.isType<bool>("Use Time Derivative Solution Vector"))
61  useTimeDerivativeSolutionVector_ = p.get<bool>("Use Time Derivative Solution Vector");
62 
63  if (p.isType<std::string>("Global Data Key"))
64  globalDataKey_ = p.get<std::string>("Global Data Key");
65 
66  this->setName("Gather Tangent");
67 }
68 
69 // **********************************************************************
70 template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
72 postRegistrationSetup(typename TRAITS::SetupData d,
73  PHX::FieldManager<TRAITS>& /* fm */)
74 {
75  TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_->size());
76 
77  const Workset & workset_0 = (*d.worksets_)[0];
78  const std::string blockId = this->wda(workset_0).block_id;
79 
80  fieldIds_.resize(gatherFields_.size());
81  fieldOffsets_.resize(gatherFields_.size());
82  fieldGlobalIndexers_.resize(gatherFields_.size());
83  productVectorBlockIndex_.resize(gatherFields_.size());
84  int maxElementBlockGIDCount = -1;
85  for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
86  // get field ID from DOF manager
87  const std::string& fieldName = (*indexerNames_)[fd];
88  const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
89  productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
90  fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
91  fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer
92 
93  const std::vector<int>& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
94  fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size());
95  auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
96  for(std::size_t i=0; i < offsets.size(); ++i)
97  hostFieldOffsets(i) = offsets[i];
98  Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets);
99 
100  maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
101  }
102 
103  // We will use one workset lid view for all fields, but has to be
104  // sized big enough to hold the largest elementBlockGIDCount in the
105  // ProductVector.
106  worksetLIDs_ = PHX::View<LO**>("GatherSolution_BlockedTpetra(Residual):worksetLIDs",
107  gatherFields_[0].extent(0),
108  maxElementBlockGIDCount);
109 
110  indexerNames_ = Teuchos::null; // Don't need this anymore
111 }
112 
113 // **********************************************************************
114 template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
116 preEvaluate(typename TRAITS::PreEvalData d)
117 {
118  // try to extract linear object container
119  if (d.gedc->containsDataObject(globalDataKey_)) {
120  Teuchos::RCP<GlobalEvaluationData> ged = d.gedc->getDataObject(globalDataKey_);
122  Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(ged);
123 
124  if(loc_pair!=Teuchos::null) {
126  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(loc,true);
127  }
128 
129  if(blockedContainer_==Teuchos::null) {
130  blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(ged,true);
131  }
132  }
133 }
134 
135 // **********************************************************************
136 template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
138 evaluateFields(typename TRAITS::EvalData workset)
139 {
140  using Teuchos::RCP;
141  using Teuchos::rcp_dynamic_cast;
142  using Thyra::VectorBase;
144 
145  // If blockedContainer_ was not initialized, then no global evaluation data
146  // container was set, in which case this evaluator becomes a no-op
147  if (blockedContainer_ == Teuchos::null) return;
148 
149  const PHX::View<const int*>& localCellIds = this->wda(workset).cell_local_ids_k;
150 
151  RCP<ProductVectorBase<ScalarT>> thyraBlockSolution;
152  if (useTimeDerivativeSolutionVector_)
153  thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),true);
154  else
155  thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),true);
156 
157  // Loop over gathered fields
158  int currentWorksetLIDSubBlock = -1;
159  for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
160  // workset LIDs only change for different sub blocks
161  if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
162  const std::string blockId = this->wda(workset).block_id;
163  const int num_dofs = fieldGlobalIndexers_[fieldIndex]->getElementBlockGIDCount(blockId);
164  fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
165  currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
166  }
167 
168  const auto& tpetraSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<ScalarT,LO,GO,NodeT>>(thyraBlockSolution->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),true))->getTpetraVector());
169  const auto& kokkosSolution = tpetraSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
170 
171  // Class data fields for lambda capture
172  const auto& fieldOffsets = fieldOffsets_[fieldIndex];
173  const auto& worksetLIDs = worksetLIDs_;
174  const auto& fieldValues = gatherFields_[fieldIndex];
175 
176  Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
177  for(int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
178  const int lid = worksetLIDs(cell,fieldOffsets(basis));
179  fieldValues(cell,basis) = kokkosSolution(lid,0);
180  }
181  });
182  }
183 
184 }
185 
186 // **********************************************************************
187 
188 #endif
Teuchos::RCP< std::vector< std::string > > indexerNames_
virtual Teuchos::RCP< CloneableEvaluator > clone(const Teuchos::ParameterList &pl) const
T & get(const std::string &name, T def_value)
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
Teuchos::RCP< LinearObjContainer > getGhostedLOC() const
PHX::View< const int * > offsets
std::string block_id
DEPRECATED - use: getElementBlock()
std::vector< PHX::MDField< ScalarT, Cell, NODE > > gatherFields_
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)