11 #ifndef PANZER_SCATTER_DIRICHLET_RESIDUAL_BLOCEDTPETRA_IMPL_HPP
12 #define PANZER_SCATTER_DIRICHLET_RESIDUAL_BLOCEDTPETRA_IMPL_HPP
15 #include "Teuchos_Assert.hpp"
17 #include "Phalanx_DataLayout.hpp"
30 #include "Phalanx_DataLayout_MDALayout.hpp"
32 #include "Thyra_SpmdVectorBase.hpp"
33 #include "Thyra_ProductVectorBase.hpp"
34 #include "Thyra_BlockedLinearOpBase.hpp"
37 #include "Teuchos_FancyOStream.hpp"
39 #include <unordered_map>
41 template <
typename EvalT,
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
46 std::string scatterName = p.
get<std::string>(
"Scatter Name");
51 const std::vector<std::string>& names =
58 for (std::size_t eq = 0; eq < names.size(); ++eq) {
62 this->addDependentField(scatterField.fieldTag());
66 this->addEvaluatedField(*scatterHolder);
68 this->setName(scatterName+
" Scatter Residual");
76 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
80 : globalIndexer_(indexer)
81 , globalDataKey_(
"Residual Scatter Container")
83 std::string scatterName = p.
get<std::string>(
"Scatter Name");
88 const std::vector<std::string>& names =
95 scatterIC_ = p.
isParameter(
"Scatter Initial Condition") ? p.
get<
bool>(
"Scatter Initial Condition") :
false;
101 side_subcell_dim_ = p.
get<
int>(
"Side Subcell Dimension");
102 local_side_id_ = p.
get<
int>(
"Local Side ID");
106 scatterFields_.resize(names.size());
107 for (std::size_t eq = 0; eq < names.size(); ++eq) {
111 this->addDependentField(scatterFields_[eq]);
114 checkApplyBC_ = p.
isParameter(
"Check Apply BC") ? p.
get<
bool>(
"Check Apply BC") :
false;
115 applyBC_.resize(names.size());
117 for (std::size_t eq = 0; eq < names.size(); ++eq) {
119 this->addDependentField(applyBC_[eq]);
124 this->addEvaluatedField(*scatterHolder_);
126 if (p.
isType<std::string>(
"Global Data Key"))
127 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
129 this->setName(scatterName+
" Scatter Dirichlet Residual");
133 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
138 const Workset & workset_0 = (*d.worksets_)[0];
139 const std::string blockId = this->wda(workset_0).
block_id;
141 fieldIds_.resize(scatterFields_.size());
142 fieldOffsets_.resize(scatterFields_.size());
143 basisIndexForMDFieldOffsets_.resize(scatterFields_.size());
144 fieldGlobalIndexers_.resize(scatterFields_.size());
145 productVectorBlockIndex_.resize(scatterFields_.size());
146 int maxElementBlockGIDCount = -1;
147 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
149 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
151 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
152 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
153 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
154 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName);
158 const auto& offsetPair = fieldGlobalIndexers_[fd]->getGIDFieldOffsets_closure(blockId,fieldIds_[fd],side_subcell_dim_,local_side_id_);
160 const auto&
offsets = offsetPair.first;
161 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Residual):fieldOffsets",
offsets.size());
162 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
163 for (std::size_t i=0; i <
offsets.size(); ++i)
165 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
168 const auto& basisIndex = offsetPair.second;
169 basisIndexForMDFieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Residual):basisIndexForMDFieldOffsets",basisIndex.size());
170 auto hostBasisIndex = Kokkos::create_mirror_view(basisIndexForMDFieldOffsets_[fd]);
171 for (std::size_t i=0; i < basisIndex.size(); ++i)
172 hostBasisIndex(i) = basisIndex[i];
173 Kokkos::deep_copy(basisIndexForMDFieldOffsets_[fd], hostBasisIndex);
178 const std::vector<int>&
offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
179 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Residual):fieldOffsets",offsets.size());
180 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
181 for (std::size_t i=0; i < offsets.size(); ++i)
182 hostOffsets(i) = offsets[i];
183 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
186 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
192 worksetLIDs_ = PHX::View<LO**>(
"ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
193 scatterFields_[0].extent(0),
194 maxElementBlockGIDCount);
198 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
204 = Teuchos::rcp_dynamic_cast<
ContainerType>(d.gedc->getDataObject(
"Dirichlet Counter"),
true);
210 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
215 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
220 using Teuchos::rcp_dynamic_cast;
224 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
227 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_f(),
true) :
228 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x(),
true);
231 int currentWorksetLIDSubBlock = -1;
232 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
234 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
235 fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_);
236 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
240 auto& tpetraScatterTarget = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraScatterTarget->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
241 const auto& kokkosScatterTarget = tpetraScatterTarget.getLocalViewDevice(Tpetra::Access::ReadWrite);
244 auto& tpetraDirichletCounter = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(dirichletCounter_->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
245 const auto& kokkosDirichletCounter = tpetraDirichletCounter.getLocalViewDevice(Tpetra::Access::ReadWrite);
248 const auto fieldOffsets = fieldOffsets_[fieldIndex];
249 const auto basisIndices = basisIndexForMDFieldOffsets_[fieldIndex];
250 const auto worksetLIDs = worksetLIDs_;
251 const auto fieldValues = scatterFields_[fieldIndex].get_static_view();
252 const auto applyBC = applyBC_[fieldIndex].get_static_view();
257 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
258 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
259 const int lid = worksetLIDs(cell,fieldOffsets(basis));
262 const int basisIndex = basisIndices(basis);
269 kokkosScatterTarget(lid,0) = fieldValues(cell,basisIndex);
270 kokkosDirichletCounter(lid,0) = 1.0;
276 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
277 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
278 const int lid = worksetLIDs(cell,fieldOffsets(basis));
281 kokkosScatterTarget(lid,0) = fieldValues(cell,basis);
282 kokkosDirichletCounter(lid,0) = 1.0;
295 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
299 : globalIndexer_(indexer)
300 , globalDataKey_(
"Residual Scatter Container")
302 std::string scatterName = p.
get<std::string>(
"Scatter Name");
307 const std::vector<std::string>& names =
316 side_subcell_dim_ = p.
get<
int>(
"Side Subcell Dimension");
317 local_side_id_ = p.
get<
int>(
"Local Side ID");
320 scatterFields_.resize(names.size());
321 for (std::size_t eq = 0; eq < names.size(); ++eq) {
325 this->addDependentField(scatterFields_[eq]);
328 checkApplyBC_ = p.
get<
bool>(
"Check Apply BC");
329 applyBC_.resize(names.size());
331 for (std::size_t eq = 0; eq < names.size(); ++eq) {
333 this->addDependentField(applyBC_[eq]);
338 this->addEvaluatedField(*scatterHolder_);
340 if (p.
isType<std::string>(
"Global Data Key"))
341 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
343 this->setName(scatterName+
" Scatter Dirichlet Residual (Jacobian)");
347 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
352 const Workset & workset_0 = (*d.worksets_)[0];
353 const std::string blockId = this->wda(workset_0).
block_id;
355 fieldIds_.resize(scatterFields_.size());
356 fieldOffsets_.resize(scatterFields_.size());
357 basisIndexForMDFieldOffsets_.resize(scatterFields_.size());
358 productVectorBlockIndex_.resize(scatterFields_.size());
359 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
361 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
362 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
363 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
364 const auto& fieldGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
365 fieldIds_[fd] = fieldGlobalIndexer->getFieldNum(fieldName);
367 const auto& offsetPair = fieldGlobalIndexer->getGIDFieldOffsets_closure(blockId,fieldIds_[fd],side_subcell_dim_,local_side_id_);
369 const auto&
offsets = offsetPair.first;
370 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):fieldOffsets",
offsets.size());
371 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
372 for (std::size_t i=0; i <
offsets.size(); ++i)
374 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
377 const auto& basisIndex = offsetPair.second;
378 basisIndexForMDFieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):basisIndexForMDFieldOffsets",basisIndex.size());
379 auto hostBasisIndex = Kokkos::create_mirror_view(basisIndexForMDFieldOffsets_[fd]);
380 for (std::size_t i=0; i < basisIndex.size(); ++i)
381 hostBasisIndex(i) = basisIndex[i];
382 Kokkos::deep_copy(basisIndexForMDFieldOffsets_[fd], hostBasisIndex);
389 int elementBlockGIDCount = 0;
390 for (
const auto& blockDOFMgr : globalIndexer_->getFieldDOFManagers())
391 elementBlockGIDCount += blockDOFMgr->getElementBlockGIDCount(blockId);
393 worksetLIDs_ = PHX::View<LO**>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):worksetLIDs",
394 scatterFields_[0].extent(0),
395 elementBlockGIDCount);
398 const auto& blockGlobalIndexers = globalIndexer_->getFieldDOFManagers();
399 const int numBlocks =
static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
400 blockOffsets_ = PHX::View<LO*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):blockOffsets_",
402 const auto hostBlockOffsets = Kokkos::create_mirror_view(blockOffsets_);
403 for (
int blk=0;blk<numBlocks;blk++) {
404 int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk);
405 hostBlockOffsets(blk) = blockOffset;
407 hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
408 Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
413 for (
int blk=0;blk<numBlocks;blk++) {
414 const int blockDerivativeSize = hostBlockOffsets(blk+1) - hostBlockOffsets(blk);
416 "ERROR: the derivative dimension for sub block "
417 << blk <<
"with a value of " << blockDerivativeSize
418 <<
"is larger than the size allocated for cLIDs and vals "
419 <<
"in the evaluate call! You must manually increase the "
420 <<
"size and recompile!");
425 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
431 = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(
"Dirichlet Counter"),
true);
437 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
442 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
447 using Teuchos::rcp_dynamic_cast;
452 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
454 const int numFieldBlocks = globalIndexer_->getNumFieldBlocks();
464 using LocalMatrixType = KokkosSparse::CrsMatrix<double,LO,PHX::Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>,
size_t>;
465 typename PHX::View<LocalMatrixType**>::HostMirror
466 hostJacTpetraBlocks(
"panzer::ScatterResidual_BlockTpetra<Jacobian>::hostJacTpetraBlocks", numFieldBlocks,numFieldBlocks);
468 PHX::View<int**> blockExistsInJac = PHX::View<int**>(
"blockExistsInJac_",numFieldBlocks,numFieldBlocks);
469 auto hostBlockExistsInJac = Kokkos::create_mirror_view(blockExistsInJac);
471 for (
int row=0; row < numFieldBlocks; ++row) {
472 for (
int col=0; col < numFieldBlocks; ++col) {
473 const auto thyraTpetraOperator = rcp_dynamic_cast<Thyra::TpetraLinearOp<double,LO,GO,NodeT>>(Jac->getNonconstBlock(row,col),
false);
474 if (
nonnull(thyraTpetraOperator)) {
490 const auto tpetraCrsMatrix = rcp_dynamic_cast<Tpetra::CrsMatrix<double,LO,GO,NodeT>>(thyraTpetraOperator->getTpetraOperator(),
true);
491 const auto managedMatrix = tpetraCrsMatrix->getLocalMatrixDevice();
492 const auto managedGraph = managedMatrix.graph;
495 using StaticCrsGraphType =
typename LocalMatrixType::StaticCrsGraphType;
496 StaticCrsGraphType unmanagedGraph;
497 unmanagedGraph.entries =
typename StaticCrsGraphType::entries_type(managedGraph.entries.data(),managedGraph.entries.extent(0));
498 unmanagedGraph.row_map =
typename StaticCrsGraphType::row_map_type(managedGraph.row_map.data(),managedGraph.row_map.extent(0));
499 unmanagedGraph.row_block_offsets =
typename StaticCrsGraphType::row_block_type(managedGraph.row_block_offsets.data(),managedGraph.row_block_offsets.extent(0));
501 typename LocalMatrixType::values_type unmanagedValues(managedMatrix.values.data(),managedMatrix.values.extent(0));
502 LocalMatrixType unmanagedMatrix(managedMatrix.values.label(), managedMatrix.numCols(), unmanagedValues, unmanagedGraph);
503 new (&hostJacTpetraBlocks(row,col)) LocalMatrixType(unmanagedMatrix);
506 hostBlockExistsInJac(row,col) = 1;
509 hostBlockExistsInJac(row,col) = 0;
513 typename PHX::View<LocalMatrixType**>
514 jacTpetraBlocks(
"panzer::ScatterResidual_BlockedTpetra<Jacobian>::jacTpetraBlocks",numFieldBlocks,numFieldBlocks);
515 Kokkos::deep_copy(jacTpetraBlocks,hostJacTpetraBlocks);
516 Kokkos::deep_copy(blockExistsInJac,hostBlockExistsInJac);
523 const auto& globalIndexers = globalIndexer_->getFieldDOFManagers();
524 auto blockOffsets_h = Kokkos::create_mirror_view(blockOffsets_);
525 Kokkos::deep_copy(blockOffsets_h, blockOffsets_);
526 for (
size_t block=0; block < globalIndexers.size(); ++block) {
527 const auto subviewOfBlockLIDs = Kokkos::subview(worksetLIDs_,Kokkos::ALL(), std::make_pair(blockOffsets_h(block),blockOffsets_h(block+1)));
528 globalIndexers[block]->getElementLIDs(localCellIds,subviewOfBlockLIDs);
532 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
534 const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
535 typename Tpetra::Vector<double,LO,GO,PHX::Device>::dual_view_type::t_dev kokkosResidual;
537 auto& tpetraResidual = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraBlockResidual->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
538 kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::ReadWrite);
542 auto& tpetraDirichletCounter = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(dirichletCounter_->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
543 const auto& kokkosDirichletCounter = tpetraDirichletCounter.getLocalViewDevice(Tpetra::Access::ReadWrite);
546 const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
547 const auto& basisIndices = basisIndexForMDFieldOffsets_[fieldIndex];
548 const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
549 const PHX::View<const ScalarT**> fieldValues = scatterFields_[fieldIndex].get_static_view();
550 const PHX::View<const LO*> blockOffsets = blockOffsets_;
551 const auto&
applyBC = applyBC_[fieldIndex].get_static_view();
554 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
555 LO cLIDs[maxDerivativeArraySize_];
556 typename Sacado::ScalarType<ScalarT>::type
vals[maxDerivativeArraySize_];
558 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
559 const int block_row_offset = blockOffsets(blockRowIndex);
560 const int rowLID = worksetLIDs(cell,block_row_offset+fieldOffsets(basis));
565 const int basisIndex = basisIndices(basis);
573 typename FieldType::array_type::reference_type tmpFieldVal = fieldValues(cell,basisIndex);
576 kokkosResidual(rowLID,0) = tmpFieldVal.val();
578 kokkosDirichletCounter(rowLID,0) = 1.0;
581 for (
int blockColIndex=0; blockColIndex < numFieldBlocks; ++blockColIndex) {
582 if (blockExistsInJac(blockRowIndex,blockColIndex)) {
583 const auto& rowEntries = jacTpetraBlocks(blockRowIndex,blockColIndex).row(rowLID);
584 for (
int i=0; i < rowEntries.length; ++i)
590 for (
int blockColIndex=0; blockColIndex < numFieldBlocks; ++blockColIndex) {
591 if (blockExistsInJac(blockRowIndex,blockColIndex)) {
592 const int start = blockOffsets(blockColIndex);
593 const int stop = blockOffsets(blockColIndex+1);
594 const int sensSize = stop-start;
596 for (
int i=0; i < sensSize; ++i) {
597 cLIDs[i] = worksetLIDs(cell,start+i);
598 vals[i] = tmpFieldVal.fastAccessDx(start+i);
600 jacTpetraBlocks(blockRowIndex,blockColIndex).replaceValues(rowLID,cLIDs,sensSize,vals,
true,
true);
609 for (
int row=0; row < numFieldBlocks; ++row) {
610 for (
int col=0; col < numFieldBlocks; ++col) {
611 if (hostBlockExistsInJac(row,col)) {
612 hostJacTpetraBlocks(row,col).~CrsMatrix();
626 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
630 : globalIndexer_(indexer)
631 , globalDataKey_(
"Residual Scatter Container")
633 std::string scatterName = p.
get<std::string>(
"Scatter Name");
638 const std::vector<std::string>& names =
645 scatterIC_ = p.
isParameter(
"Scatter Initial Condition") ? p.
get<
bool>(
"Scatter Initial Condition") :
false;
651 side_subcell_dim_ = p.
get<
int>(
"Side Subcell Dimension");
652 local_side_id_ = p.
get<
int>(
"Local Side ID");
656 scatterFields_.resize(names.size());
657 for (std::size_t eq = 0; eq < names.size(); ++eq) {
661 this->addDependentField(scatterFields_[eq]);
664 checkApplyBC_ = p.
isParameter(
"Check Apply BC") ? p.
get<
bool>(
"Check Apply BC") :
false;
665 applyBC_.resize(names.size());
667 for (std::size_t eq = 0; eq < names.size(); ++eq) {
669 this->addDependentField(applyBC_[eq]);
674 this->addEvaluatedField(*scatterHolder_);
676 if (p.
isType<std::string>(
"Global Data Key"))
677 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
679 this->setName(scatterName+
" Scatter Dirichlet Residual");
683 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
688 const Workset & workset_0 = (*d.worksets_)[0];
689 const std::string blockId = this->wda(workset_0).
block_id;
691 fieldIds_.resize(scatterFields_.size());
692 fieldOffsets_.resize(scatterFields_.size());
693 basisIndexForMDFieldOffsets_.resize(scatterFields_.size());
694 fieldGlobalIndexers_.resize(scatterFields_.size());
695 productVectorBlockIndex_.resize(scatterFields_.size());
696 int maxElementBlockGIDCount = -1;
697 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
699 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
701 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName);
702 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
703 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
704 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName);
708 const auto& offsetPair = fieldGlobalIndexers_[fd]->getGIDFieldOffsets_closure(blockId,fieldIds_[fd],side_subcell_dim_,local_side_id_);
710 const auto&
offsets = offsetPair.first;
711 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Tangent):fieldOffsets",
offsets.size());
712 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
713 for (std::size_t i=0; i <
offsets.size(); ++i)
715 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
718 const auto& basisIndex = offsetPair.second;
719 basisIndexForMDFieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Tangent):basisIndexForMDFieldOffsets",basisIndex.size());
720 auto hostBasisIndex = Kokkos::create_mirror_view(basisIndexForMDFieldOffsets_[fd]);
721 for (std::size_t i=0; i < basisIndex.size(); ++i)
722 hostBasisIndex(i) = basisIndex[i];
723 Kokkos::deep_copy(basisIndexForMDFieldOffsets_[fd], hostBasisIndex);
728 const std::vector<int>&
offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
729 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Tangent):fieldOffsets",offsets.size());
730 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
731 for (std::size_t i=0; i < offsets.size(); ++i)
732 hostOffsets(i) = offsets[i];
733 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
736 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
742 worksetLIDs_ = PHX::View<LO**>(
"ScatterResidual_BlockedTpetra(Tangent):worksetLIDs",
743 scatterFields_[0].extent(0),
744 maxElementBlockGIDCount);
748 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
754 std::vector<std::string> activeParameters =
757 const int numBlocks =
static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
759 dfdpFieldsVoV_.initialize(
"ScatterResidual_Tpetra<Tangent>::dfdpFieldsVoV_",activeParameters.size(),numBlocks);
761 for(std::size_t i=0;i<activeParameters.size();i++) {
765 for(
int j=0;j<numBlocks;j++) {
766 auto& tpetraBlock = *((Teuchos::rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(productVector->getNonconstVectorBlock(j),
true))->getTpetraVector());
767 const auto& dfdp_view = tpetraBlock.getLocalViewDevice(Tpetra::Access::ReadWrite);
768 dfdpFieldsVoV_.addView(dfdp_view,i,j);
772 dfdpFieldsVoV_.syncHostToDevice();
776 = Teuchos::rcp_dynamic_cast<
ContainerType>(d.gedc->getDataObject(
"Dirichlet Counter"),
true);
782 blockedContainer_ = Teuchos::rcp_dynamic_cast<
const ContainerType>(d.gedc->getDataObject(globalDataKey_),
true);
787 template <
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
792 using Teuchos::rcp_dynamic_cast;
796 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
799 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_f(),
true) :
800 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x(),
true);
803 int currentWorksetLIDSubBlock = -1;
804 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
806 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
807 fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_);
808 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
812 auto& tpetraScatterTarget = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraScatterTarget->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
813 const auto& kokkosScatterTarget = tpetraScatterTarget.getLocalViewDevice(Tpetra::Access::ReadWrite);
816 auto& tpetraDirichletCounter = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(dirichletCounter_->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
817 const auto& kokkosDirichletCounter = tpetraDirichletCounter.getLocalViewDevice(Tpetra::Access::ReadWrite);
820 const auto fieldOffsets = fieldOffsets_[fieldIndex];
821 const auto basisIndices = basisIndexForMDFieldOffsets_[fieldIndex];
822 const auto worksetLIDs = worksetLIDs_;
823 const auto fieldValues = scatterFields_[fieldIndex].get_static_view();
824 const auto applyBC = applyBC_[fieldIndex].get_static_view();
826 const auto& tangentFieldsDevice = dfdpFieldsVoV_.getViewDevice();
827 const auto& kokkosTangents = Kokkos::subview(tangentFieldsDevice,Kokkos::ALL(),productVectorBlockIndex_[fieldIndex]);
828 const double num_params = Kokkos::dimension_scalar(fieldValues)-1;
832 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
833 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
834 const int lid = worksetLIDs(cell,fieldOffsets(basis));
837 const int basisIndex = basisIndices(basis);
844 kokkosScatterTarget(lid,0) = fieldValues(cell,basisIndex).val();
845 for(
int i_param=0; i_param<
num_params; i_param++)
846 kokkosTangents(i_param)(lid,0) = fieldValues(cell,basisIndex).fastAccessDx(i_param);
848 kokkosDirichletCounter(lid,0) = 1.0;
854 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
855 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
856 const int lid = worksetLIDs(cell,fieldOffsets(basis));
859 kokkosScatterTarget(lid,0) = fieldValues(cell,basis).val();
860 for(
int i_param=0; i_param<
num_params; i_param++)
861 kokkosTangents(i_param)(lid,0) = fieldValues(cell,basis).fastAccessDx(i_param);
862 kokkosDirichletCounter(lid,0) = 1.0;
T & get(const std::string &name, T def_value)
bool nonnull(const std::shared_ptr< T > &p)
bool is_null(const std::shared_ptr< T > &p)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
ScatterDirichletResidual_BlockedTpetra(const Teuchos::RCP< const BlockedDOFManager > &)
FieldType
The type of discretization to use for a field pattern.
PHX::View< const int * > offsets
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Kokkos::View< typename Sacado::ScalarType< ScalarT >::type **, Kokkos::LayoutRight, PHX::Device > vals
void evaluateFields(typename TRAITS::EvalData)
virtual void preEvaluate(typename Traits::PreEvalData d)=0
bool nonnull(const boost::shared_ptr< T > &p)
std::string block_id
DEPRECATED - use: getElementBlock()
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
void postRegistrationSetup(typename TRAITS::SetupData, PHX::FieldManager< TRAITS > &)