11 #ifndef PANZER_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
12 #define PANZER_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
14 #include "Teuchos_Assert.hpp"
15 #include "Phalanx_DataLayout.hpp"
20 #include "Panzer_TpetraLinearObjFactory.hpp"
25 #include "Teuchos_FancyOStream.hpp"
27 #include "Thyra_SpmdVectorBase.hpp"
28 #include "Thyra_ProductVectorBase.hpp"
30 #include "Tpetra_Map.hpp"
32 template <
typename EvalT,
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
38 const std::vector<std::string>& names =
44 for (std::size_t fd = 0; fd < names.size(); ++fd) {
46 this->addEvaluatedField(field.fieldTag());
49 this->setName(
"Gather Solution");
56 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
61 : globalIndexer_(indexer)
62 , has_tangent_fields_(false)
64 typedef std::vector< std::vector<std::string> > vvstring;
69 const std::vector<std::string> & names = input.
getDofNames();
78 gatherFields_.resize(names.size());
79 for (std::size_t fd = 0; fd < names.size(); ++fd) {
82 this->addEvaluatedField(gatherFields_[fd]);
86 if (tangent_field_names.size()>0) {
87 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
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] =
96 this->addDependentField(tangentFields_[fd][i]);
102 std::string firstName =
"<none>";
104 firstName = names[0];
106 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" (Residual)";
111 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
118 const Workset & workset_0 = (*d.worksets_)[0];
119 const std::string blockId = this->wda(workset_0).
block_id;
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) {
128 const std::string& fieldName = indexerNames_[fd];
129 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
130 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
131 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
132 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName);
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);
141 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
147 worksetLIDs_ = PHX::View<LO**>(
"GatherSolution_BlockedTpetra(Residual):worksetLIDs",
148 gatherFields_[0].extent(0),
149 maxElementBlockGIDCount);
151 indexerNames_.clear();
155 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
160 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
164 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
169 using Teuchos::rcp_dynamic_cast;
173 const PHX::View<const int*>& localCellIds = this->wda(workset).cell_local_ids_k;
176 if (useTimeDerivativeSolutionVector_)
177 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),
true);
179 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),
true);
182 int currentWorksetLIDSubBlock = -1;
183 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
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];
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);
196 const auto& fieldOffsets = fieldOffsets_[fieldIndex];
197 const auto& worksetLIDs = worksetLIDs_;
198 const auto& fieldValues = gatherFields_[fieldIndex];
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);
214 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
219 : globalIndexer_(indexer)
220 , has_tangent_fields_(false)
222 typedef std::vector< std::vector<std::string> > vvstring;
227 const std::vector<std::string> & names = input.
getDofNames();
236 gatherFields_.resize(names.size());
237 for (std::size_t fd = 0; fd < names.size(); ++fd) {
240 this->addEvaluatedField(gatherFields_[fd]);
244 if (tangent_field_names.size()>0) {
245 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
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] =
254 this->addDependentField(tangentFields_[fd][i]);
260 std::string firstName =
"<none>";
262 firstName = names[0];
264 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" (Tangent)";
269 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
276 const Workset & workset_0 = (*d.worksets_)[0];
277 const std::string blockId = this->wda(workset_0).
block_id;
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) {
285 const std::string fieldName = indexerNames_[fd];
286 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
287 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
288 const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
289 fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName);
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);
303 worksetLIDs_ = PHX::View<LO**>(
"ScatterResidual_BlockedTpetra(Tangent):worksetLIDs",
304 gatherFields_[0].extent(0),
305 maxElementBlockGIDCount);
311 if (has_tangent_fields_) {
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);
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);
324 tangentFieldsVoV_.syncHostToDevice();
327 indexerNames_.clear();
331 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
336 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
340 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
346 using Teuchos::ptrFromRef;
347 using Teuchos::rcp_dynamic_cast;
350 using Thyra::SpmdVectorBase;
357 const PHX::View<const int*> & localCellIds = this->wda(workset).getLocalCellIDs();
360 if (useTimeDerivativeSolutionVector_)
361 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
363 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
366 int currentWorksetLIDSubBlock = -1;
367 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
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];
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);
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();
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);
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);
416 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
421 : globalIndexer_(indexer)
426 const std::vector<std::string> & names = input.
getDofNames();
435 gatherFields_.resize(names.size());
436 for (std::size_t fd = 0; fd < names.size(); ++fd) {
438 gatherFields_[fd] = f;
439 this->addEvaluatedField(gatherFields_[fd]);
443 std::string firstName =
"<none>";
445 firstName = names[0];
448 if(disableSensitivities_) {
449 std::string n =
"GatherSolution (BlockedTpetra, No Sensitivities): "+firstName+
" (Jacobian)";
453 std::string n =
"GatherSolution (BlockedTpetra): "+firstName+
" ("+PHX::print<EvalT>()+
") ";
459 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
466 const Workset & workset_0 = (*d.worksets_)[0];
467 const std::string blockId = this->wda(workset_0).
block_id;
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) {
475 const std::string fieldName = indexerNames_[fd];
476 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
477 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
478 const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
479 fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName);
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);
493 worksetLIDs_ = PHX::View<LO**>(
"ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
494 gatherFields_[0].extent(0),
495 maxElementBlockGIDCount);
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_",
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;
507 hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
508 Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
510 indexerNames_.clear();
513 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
518 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
522 template <
typename TRAITS,
typename S,
typename LO,
typename GO,
typename NodeT>
527 using Teuchos::rcp_dynamic_cast;
531 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
535 if (useTimeDerivativeSolutionVector_) {
536 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
537 seedValue = workset.alpha;
540 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
541 seedValue = workset.beta;
547 if(disableSensitivities_)
551 int currentWorksetLIDSubBlock = -1;
552 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
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];
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);
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);
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;
GatherSolution_BlockedTpetra(const Teuchos::RCP< const BlockedDOFManager > &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)
PHX::View< const int * > offsets
TRAITS::RealType RealType
void evaluateFields(typename TRAITS::EvalData d)
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'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>