Panzer Version of the Day
Loading...
Searching...
No Matches
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
19#include "Panzer_PureBasis.hpp"
20#include "Panzer_TpetraLinearObjFactory.hpp"
26
27#include "Teuchos_FancyOStream.hpp"
28
29#include "Thyra_SpmdVectorBase.hpp"
30#include "Thyra_ProductVectorBase.hpp"
31
32#include "Tpetra_Map.hpp"
33
34template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
37 const Teuchos::RCP<const BlockedDOFManager> & indexer,
38 const Teuchos::ParameterList& p)
39 : globalIndexer_(indexer)
40 , useTimeDerivativeSolutionVector_(false)
41 , globalDataKey_("Tangent Gather Container")
42{
43 const std::vector<std::string>& names =
44 *(p.get< Teuchos::RCP< std::vector<std::string> > >("DOF Names"));
45
46 indexerNames_ = p.get< Teuchos::RCP< std::vector<std::string> > >("Indexer Names");
47
48 Teuchos::RCP<panzer::PureBasis> basis =
49 p.get< Teuchos::RCP<panzer::PureBasis> >("Basis");
50
51 gatherFields_.resize(names.size());
52 for (std::size_t fd = 0; fd < names.size(); ++fd) {
53 gatherFields_[fd] =
54 PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->functional);
55 this->addEvaluatedField(gatherFields_[fd]);
56 // If blockedContainer_ is null, the evalaution is a no-op. In this
57 // case we need to preserve zero initial value. Do this by not
58 // sharing.
59 this->addUnsharedField(gatherFields_[fd].fieldTag().clone());
60 }
61
62 if (p.isType<bool>("Use Time Derivative Solution Vector"))
63 useTimeDerivativeSolutionVector_ = p.get<bool>("Use Time Derivative Solution Vector");
64
65 if (p.isType<std::string>("Global Data Key"))
66 globalDataKey_ = p.get<std::string>("Global Data Key");
67
68 this->setName("Gather Tangent");
69}
70
71// **********************************************************************
72template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
74postRegistrationSetup(typename TRAITS::SetupData d,
76{
77 TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_->size());
78
79 const Workset & workset_0 = (*d.worksets_)[0];
80 const std::string blockId = this->wda(workset_0).block_id;
81
82 fieldIds_.resize(gatherFields_.size());
83 fieldOffsets_.resize(gatherFields_.size());
84 fieldGlobalIndexers_.resize(gatherFields_.size());
85 productVectorBlockIndex_.resize(gatherFields_.size());
86 int maxElementBlockGIDCount = -1;
87 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
88 // get field ID from DOF manager
89 const std::string& fieldName = (*indexerNames_)[fd];
90 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
91 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
92 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
93 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer
94
95 const std::vector<int>& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
96 fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size());
97 auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
98 for(std::size_t i=0; i < offsets.size(); ++i)
99 hostFieldOffsets(i) = offsets[i];
100 Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets);
101
102 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
103 }
104
105 // We will use one workset lid view for all fields, but has to be
106 // sized big enough to hold the largest elementBlockGIDCount in the
107 // ProductVector.
108 worksetLIDs_ = PHX::View<LO**>("GatherSolution_BlockedTpetra(Residual):worksetLIDs",
109 gatherFields_[0].extent(0),
110 maxElementBlockGIDCount);
111
112 indexerNames_ = Teuchos::null; // Don't need this anymore
113}
114
115// **********************************************************************
116template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
118preEvaluate(typename TRAITS::PreEvalData d)
119{
120 using Teuchos::RCP;
121 using Teuchos::rcp_dynamic_cast;
123
124 if (!d.gedc->containsDataObject(globalDataKey_))
125 return;
126
127 RCP<GlobalEvaluationData> ged = d.gedc->getDataObject(globalDataKey_);
128
129 // try to extract a linear object container, possibly wrapped in a LOCPair
130 {
131 RCP<const ContainerType> blockedContainer = rcp_dynamic_cast<const ContainerType>(ged);
132 RCP<LOCPair_GlobalEvaluationData> loc_pair =
133 rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(ged);
134
135 if(loc_pair!=Teuchos::null)
136 blockedContainer = rcp_dynamic_cast<const ContainerType>(loc_pair->getGhostedLOC(),true);
137
138 if(blockedContainer!=Teuchos::null) {
139 blockedContainer_ = blockedContainer;
140 return;
141 }
142 }
143
144 // otherwise it must be a blocked read-only ghosted vector, which is what the
145 // model evaluator hands out for the tangent gather containers (throws if not)
146 xBvRoGed_ = rcp_dynamic_cast<BVROGED>(ged,true);
147}
148
149// **********************************************************************
150template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
152evaluateFields(typename TRAITS::EvalData workset)
153{
154 using Teuchos::RCP;
155 using Teuchos::rcp_dynamic_cast;
156 using Thyra::VectorBase;
158
159 // If neither source was initialized, then no global evaluation data
160 // container was set, in which case this evaluator becomes a no-op
161 if (blockedContainer_ == Teuchos::null && xBvRoGed_ == Teuchos::null) return;
162
163 const PHX::View<const int*>& localCellIds = this->wda(workset).cell_local_ids_k;
164
165 RCP<ProductVectorBase<ScalarT>> thyraBlockSolution;
166 if (blockedContainer_ != Teuchos::null) {
167 if (useTimeDerivativeSolutionVector_)
168 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),true);
169 else
170 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),true);
171 }
172
173 // Loop over gathered fields
174 int currentWorksetLIDSubBlock = -1;
175 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
176 // workset LIDs only change for different sub blocks
177 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
178 const std::string blockId = this->wda(workset).block_id;
179 const int num_dofs = fieldGlobalIndexers_[fieldIndex]->getElementBlockGIDCount(blockId);
180 fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
181 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
182 }
183
184 // Pull the ghosted sub-block vector from whichever source preEvaluate() found
185 const int blockIndex = productVectorBlockIndex_[fieldIndex];
186 RCP<const VectorType> tpetraSolution;
187 if (thyraBlockSolution != Teuchos::null) {
188 tpetraSolution = rcp_dynamic_cast<Thyra::TpetraVector<ScalarT,LO,GO,NodeT>>(
189 thyraBlockSolution->getNonconstVectorBlock(blockIndex),true)->getConstTpetraVector();
190 }
191 else {
193 tpetraSolution = rcp_dynamic_cast<TVROGED>(xBvRoGed_->getGEDBlock(blockIndex),true)
195 }
196 const auto& kokkosSolution = tpetraSolution->getLocalViewDevice(Tpetra::Access::ReadOnly);
197
198 // Class data fields for lambda capture
199 const auto& fieldOffsets = fieldOffsets_[fieldIndex];
200 const auto& worksetLIDs = worksetLIDs_;
201 const auto& fieldValues = gatherFields_[fieldIndex];
202
203 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
204 for(int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
205 const int lid = worksetLIDs(cell,fieldOffsets(basis));
206 fieldValues(cell,basis) = kokkosSolution(lid,0);
207 }
208 });
209 }
210
211}
212
213// **********************************************************************
214
215#endif
PHX::View< const int * > offsets
This class encapsulates the needs of a gather operation to do a halo exchange for blocked vectors.
std::vector< PHX::MDField< ScalarT, Cell, NODE > > gatherFields_
Teuchos::RCP< std::vector< std::string > > indexerNames_
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
virtual Teuchos::RCP< CloneableEvaluator > clone(const Teuchos::ParameterList &pl) const
Teuchos::RCP< VectorType > getGhostedVector_Tpetra() const
Get the ghosted vector (Tpetra version)
std::string block_id
DEPRECATED - use: getElementBlock()