43 #ifndef PANZER_GATHER_SOLUTION_BLOCKED_EPETRA_IMPL_HPP
44 #define PANZER_GATHER_SOLUTION_BLOCKED_EPETRA_IMPL_HPP
46 #include "Teuchos_Assert.hpp"
47 #include "Phalanx_DataLayout.hpp"
52 #include "Panzer_TpetraLinearObjFactory.hpp"
57 #include "Teuchos_FancyOStream.hpp"
59 #include "Thyra_SpmdVectorBase.hpp"
60 #include "Thyra_ProductVectorBase.hpp"
62 #include "Tpetra_Map.hpp"
64 template <
typename EvalT,
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
70 const std::vector<std::string>& names =
76 for (std::size_t fd = 0; fd < names.size(); ++fd) {
77 PHX::MDField<ScalarT,Cell,NODE>
field = PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->
functional);
78 this->addEvaluatedField(field.fieldTag());
81 this->setName(
"Gather Solution");
88 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
93 : globalIndexer_(indexer)
94 , has_tangent_fields_(false)
96 typedef std::vector< std::vector<std::string> > vvstring;
101 const std::vector<std::string> & names = input.
getDofNames();
110 gatherFields_.resize(names.size());
111 for (std::size_t fd = 0; fd < names.size(); ++fd) {
113 PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->
functional);
114 this->addEvaluatedField(gatherFields_[fd]);
118 if (tangent_field_names.size()>0) {
119 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
121 has_tangent_fields_ =
true;
122 tangentFields_.resize(gatherFields_.size());
123 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
124 tangentFields_[fd].resize(tangent_field_names[fd].size());
125 for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
126 tangentFields_[fd][i] =
127 PHX::MDField<const ScalarT,Cell,NODE>(tangent_field_names[fd][i],basis->
functional);
128 this->addDependentField(tangentFields_[fd][i]);
134 std::string firstName =
"<none>";
136 firstName = names[0];
138 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" (Residual)";
143 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
150 const Workset & workset_0 = (*d.worksets_)[0];
151 const std::string blockId = this->wda(workset_0).
block_id;
153 fieldIds_.resize(gatherFields_.size());
154 fieldOffsets_.resize(gatherFields_.size());
155 fieldGlobalIndexers_.resize(gatherFields_.size());
156 productVectorBlockIndex_.resize(gatherFields_.size());
157 int maxElementBlockGIDCount = -1;
158 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
160 const std::string& fieldName = indexerNames_[fd];
161 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
162 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
163 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
164 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName);
166 const std::vector<int>&
offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
167 fieldOffsets_[fd] = Kokkos::View<int*,PHX::Device>(
"GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size());
168 auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
169 for(std::size_t i=0; i < offsets.size(); ++i)
170 hostFieldOffsets(i) = offsets[i];
171 Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets);
172 PHX::Device::fence();
174 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
180 worksetLIDs_ = Kokkos::View<LO**,PHX::Device>(
"GatherSolution_BlockedTpetra(Residual):worksetLIDs",
181 gatherFields_[0].extent(0),
182 maxElementBlockGIDCount);
184 indexerNames_.clear();
188 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
193 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
197 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
202 using Teuchos::rcp_dynamic_cast;
206 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
209 if (useTimeDerivativeSolutionVector_)
210 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),
true);
212 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),
true);
215 int currentWorksetLIDSubBlock = -1;
216 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
218 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
219 fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_);
220 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
223 const auto& tpetraSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<ScalarT,LO,GO,NodeT>>(thyraBlockSolution->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
224 const auto& kokkosSolution = tpetraSolution.template getLocalView<PHX::mem_space>();
227 const auto& fieldOffsets = fieldOffsets_[fieldIndex];
228 const auto& worksetLIDs = worksetLIDs_;
229 const auto& fieldValues = gatherFields_[fieldIndex];
231 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
232 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
233 const int lid = worksetLIDs(cell,fieldOffsets(basis));
234 fieldValues(cell,basis) = kokkosSolution(lid,0);
245 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
250 : gidIndexer_(indexer)
251 , has_tangent_fields_(false)
253 typedef std::vector< std::vector<std::string> > vvstring;
258 const std::vector<std::string> & names = input.
getDofNames();
267 gatherFields_.resize(names.size());
268 for (std::size_t fd = 0; fd < names.size(); ++fd) {
270 PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->
functional);
271 this->addEvaluatedField(gatherFields_[fd]);
275 if (tangent_field_names.size()>0) {
276 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
278 has_tangent_fields_ =
true;
279 tangentFields_.resize(gatherFields_.size());
280 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
281 tangentFields_[fd].resize(tangent_field_names[fd].size());
282 for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
283 tangentFields_[fd][i] =
284 PHX::MDField<const ScalarT,Cell,NODE>(tangent_field_names[fd][i],basis->
functional);
285 this->addDependentField(tangentFields_[fd][i]);
291 std::string firstName =
"<none>";
293 firstName = names[0];
295 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" (Tangent)";
300 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
307 fieldIds_.resize(gatherFields_.size());
309 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
311 const std::string& fieldName = indexerNames_[fd];
312 fieldIds_[fd] = gidIndexer_->getFieldNum(fieldName);
315 indexerNames_.clear();
319 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
324 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
328 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
334 using Teuchos::ptrFromRef;
335 using Teuchos::rcp_dynamic_cast;
338 using Thyra::SpmdVectorBase;
345 std::vector<std::pair<int,GO> > GIDs;
346 std::vector<LO> LIDs;
349 std::string blockId = this->wda(workset).block_id;
350 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
353 if (useTimeDerivativeSolutionVector_)
354 x = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
356 x = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
359 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
360 LO cellLocalId = localCellIds[worksetCellIndex];
362 gidIndexer_->getElementGIDs(cellLocalId,GIDs,blockId);
365 LIDs.resize(GIDs.size());
366 for(std::size_t i=0;i<GIDs.size();i++) {
370 LIDs[i] = x_map->getLocalElement(GIDs[i].second);
375 for (std::size_t fieldIndex=0; fieldIndex<gatherFields_.size();fieldIndex++) {
376 int fieldNum = fieldIds_[fieldIndex];
377 int indexerId = gidIndexer_->getFieldBlock(fieldNum);
381 block_x->getLocalData(ptrFromRef(local_x));
383 const std::vector<int> & elmtOffset = gidIndexer_->getGIDFieldOffsets(blockId,fieldNum);
386 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
387 int offset = elmtOffset[basis];
388 int lid = LIDs[offset];
390 if (!has_tangent_fields_)
391 (gatherFields_[fieldIndex])(worksetCellIndex,basis) = local_x[lid];
393 (gatherFields_[fieldIndex])(worksetCellIndex,basis).val() = local_x[lid];
394 for (std::size_t i=0; i<tangentFields_[fieldIndex].size(); ++i)
395 (gatherFields_[fieldIndex])(worksetCellIndex,basis).fastAccessDx(i) =
396 tangentFields_[fieldIndex][i](worksetCellIndex,basis).val();
407 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
412 : globalIndexer_(indexer)
417 const std::vector<std::string> & names = input.
getDofNames();
426 gatherFields_.resize(names.size());
427 for (std::size_t fd = 0; fd < names.size(); ++fd) {
428 PHX::MDField<ScalarT,Cell,NODE> f(names[fd],basis->
functional);
429 gatherFields_[fd] = f;
430 this->addEvaluatedField(gatherFields_[fd]);
434 std::string firstName =
"<none>";
436 firstName = names[0];
439 if(disableSensitivities_) {
440 std::string n =
"GatherSolution (BlockedTpetra, No Sensitivities): "+firstName+
" (Jacobian)";
444 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" ("+PHX::typeAsString<EvalT>()+
") ";
450 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
457 const Workset & workset_0 = (*d.worksets_)[0];
458 const std::string blockId = this->wda(workset_0).
block_id;
460 fieldIds_.resize(gatherFields_.size());
461 fieldOffsets_.resize(gatherFields_.size());
462 productVectorBlockIndex_.resize(gatherFields_.size());
463 int maxElementBlockGIDCount = -1;
464 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
466 const std::string fieldName = indexerNames_[fd];
467 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
468 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
469 const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
470 fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName);
472 const std::vector<int>&
offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
473 fieldOffsets_[fd] = Kokkos::View<int*,PHX::Device>(
"GatherSolution_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
474 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
475 for (std::size_t i=0; i < offsets.size(); ++i)
476 hostOffsets(i) = offsets[i];
477 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
478 maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
479 PHX::Device::fence();
485 worksetLIDs_ = Kokkos::View<LO**,PHX::Device>(
"ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
486 gatherFields_[0].extent(0),
487 maxElementBlockGIDCount);
490 const auto& blockGlobalIndexers = globalIndexer_->getFieldDOFManagers();
491 const int numBlocks =
static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
492 blockOffsets_ = Kokkos::View<LO*,PHX::Device>(
"GatherSolution_BlockedTpetra(Jacobian):blockOffsets_",
494 const auto hostBlockOffsets = Kokkos::create_mirror_view(blockOffsets_);
495 for (
int blk=0;blk<numBlocks;++blk) {
496 int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk);
497 hostBlockOffsets(blk) = blockOffset;
499 blockOffsets_(numBlocks) = blockOffsets_(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
500 Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
502 indexerNames_.clear();
503 PHX::Device::fence();
506 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
511 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
515 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
520 using Teuchos::rcp_dynamic_cast;
524 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
528 if (useTimeDerivativeSolutionVector_) {
529 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
530 seedValue = workset.alpha;
533 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
534 seedValue = workset.beta;
540 if(disableSensitivities_)
543 const int numFieldBlocks = globalIndexer_->getNumFieldBlocks();
546 int currentWorksetLIDSubBlock = -1;
547 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
549 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
550 const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
551 blockIndexer->getElementLIDs(localCellIds,worksetLIDs_);
552 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
555 const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
556 const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
557 const auto kokkosSolution = subblockSolution.template getLocalView<PHX::mem_space>();
560 const Kokkos::View<const int*,PHX::Device> fieldOffsets = fieldOffsets_[fieldIndex];
561 const Kokkos::View<const LO**,PHX::Device> worksetLIDs = worksetLIDs_;
562 const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
563 const Kokkos::View<const LO*,PHX::Device> blockOffsets = blockOffsets_;
564 const int blockStart = blockOffsets(blockRowIndex);
565 const int numDerivatives = blockOffsets(numFieldBlocks);
567 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
568 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
569 const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
570 fieldValues(cell,basis) =
ScalarT(numDerivatives,kokkosSolution(rowLID,0));
571 fieldValues(cell,basis).fastAccessDx(blockStart+fieldOffsets(basis)) = seedValue;
GatherSolution_BlockedTpetra(const Teuchos::RCP< const BlockedDOFManager< LO, GO > > &indexer)
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)
Gathers solution values from the Newton solution vector into the nodal fields of the field manager...
panzer::Traits::Jacobian::ScalarT ScalarT
TRAITS::RealType RealType
void evaluateFields(typename TRAITS::EvalData d)
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we'll contribute, or in which we'll store, the result of computing this integral...
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< PHX::DataLayout > functional
<Cell,Basis> or <Cell,Basis>
Kokkos::View< const int *, PHX::Device > offsets