251 using Teuchos::rcp_dynamic_cast;
255 const auto& localCellIds = this->
wda(workset).cell_local_ids_k;
257 RCP<ProductVectorBase<double> > thyraScatterTarget = (!
scatterIC_) ?
262 int currentWorksetLIDSubBlock = -1;
263 for (std::size_t fieldIndex = 0; fieldIndex <
scatterFields_.size(); fieldIndex++) {
271 auto& tpetraScatterTarget = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraScatterTarget->getNonconstVectorBlock(
productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
272 const auto& kokkosScatterTarget = tpetraScatterTarget.getLocalViewDevice(Tpetra::Access::ReadWrite);
275 auto& tpetraDirichletCounter = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(
dirichletCounter_->getNonconstVectorBlock(
productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
276 const auto& kokkosDirichletCounter = tpetraDirichletCounter.getLocalViewDevice(Tpetra::Access::ReadWrite);
282 const auto fieldValues =
scatterFields_[fieldIndex].get_static_view();
283 const auto applyBC =
applyBC_[fieldIndex].get_static_view();
288 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
289 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
290 const int lid = worksetLIDs(cell,fieldOffsets(basis));
293 const int basisIndex = basisIndices(basis);
297 if (!applyBC(cell,basisIndex))
300 kokkosScatterTarget(lid,0) = fieldValues(cell,basisIndex);
301 kokkosDirichletCounter(lid,0) = 1.0;
307 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
308 for (
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
309 const int lid = worksetLIDs(cell,fieldOffsets(basis));
312 kokkosScatterTarget(lid,0) = fieldValues(cell,basis);
313 kokkosDirichletCounter(lid,0) = 1.0;
383 const Workset & workset_0 = (*d.worksets_)[0];
384 const std::string blockId = this->
wda(workset_0).block_id;
393 const int globalFieldNum =
globalIndexer_->getFieldNum(fieldName);
396 fieldIds_[fd] = fieldGlobalIndexer->getFieldNum(fieldName);
400 const auto& offsets = offsetPair.first;
401 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
402 auto hostOffsets = Kokkos::create_mirror_view(
fieldOffsets_[fd]);
403 for (std::size_t i=0; i < offsets.size(); ++i)
404 hostOffsets(i) = offsets[i];
408 const auto& basisIndex = offsetPair.second;
409 basisIndexForMDFieldOffsets_[fd] = PHX::View<int*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):basisIndexForMDFieldOffsets",basisIndex.size());
411 for (std::size_t i=0; i < basisIndex.size(); ++i)
412 hostBasisIndex(i) = basisIndex[i];
420 int elementBlockGIDCount = 0;
421 for (
const auto& blockDOFMgr :
globalIndexer_->getFieldDOFManagers())
422 elementBlockGIDCount += blockDOFMgr->getElementBlockGIDCount(blockId);
424 worksetLIDs_ = PHX::View<LO**>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):worksetLIDs",
426 elementBlockGIDCount);
429 const auto& blockGlobalIndexers =
globalIndexer_->getFieldDOFManagers();
430 const int numBlocks =
static_cast<int>(
globalIndexer_->getFieldDOFManagers().size());
431 blockOffsets_ = PHX::View<LO*>(
"ScatterDirichletResidual_BlockedTpetra(Jacobian):blockOffsets_",
433 const auto hostBlockOffsets = Kokkos::create_mirror_view(
blockOffsets_);
434 for (
int blk=0;blk<numBlocks;blk++) {
436 hostBlockOffsets(blk) = blockOffset;
438 hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
444 for (
int blk=0;blk<numBlocks;blk++) {
445 const int blockDerivativeSize = hostBlockOffsets(blk+1) - hostBlockOffsets(blk);
447 "ERROR: the derivative dimension for sub block "
448 << blk <<
"with a value of " << blockDerivativeSize
449 <<
"is larger than the size allocated for cLIDs and vals "
450 <<
"in the evaluate call! You must manually increase the "
451 <<
"size and recompile!");
478 using Teuchos::rcp_dynamic_cast;
483 const auto& localCellIds = this->
wda(workset).cell_local_ids_k;
487 const RCP<ProductVectorBase<double>> thyraBlockResidual = rcp_dynamic_cast<ProductVectorBase<double>>(
blockedContainer_->get_f());
488 const bool haveResidual = Teuchos::nonnull(thyraBlockResidual);
489 const RCP<BlockedLinearOpBase<double>> Jac = rcp_dynamic_cast<BlockedLinearOpBase<double>>(
blockedContainer_->get_A(),
true);
495 using LocalMatrixType = KokkosSparse::CrsMatrix<double,LO,PHX::Device,Kokkos::MemoryTraits<Kokkos::Unmanaged>,
size_t>;
496 typename PHX::View<LocalMatrixType**>::HostMirror
497 hostJacTpetraBlocks(
"panzer::ScatterResidual_BlockTpetra<Jacobian>::hostJacTpetraBlocks", numFieldBlocks,numFieldBlocks);
499 PHX::View<int**> blockExistsInJac = PHX::View<int**>(
"blockExistsInJac_",numFieldBlocks,numFieldBlocks);
500 auto hostBlockExistsInJac = Kokkos::create_mirror_view(blockExistsInJac);
502 for (
int row=0; row < numFieldBlocks; ++row) {
503 for (
int col=0; col < numFieldBlocks; ++col) {
504 const auto thyraTpetraOperator = rcp_dynamic_cast<Thyra::TpetraLinearOp<double,LO,GO,NodeT>>(Jac->getNonconstBlock(row,col),
false);
505 if (nonnull(thyraTpetraOperator)) {
521 const auto tpetraCrsMatrix = rcp_dynamic_cast<Tpetra::CrsMatrix<double,LO,GO,NodeT>>(thyraTpetraOperator->getTpetraOperator(),
true);
522 const auto managedMatrix = tpetraCrsMatrix->getLocalMatrixDevice();
523 const auto managedGraph = managedMatrix.graph;
526 using StaticCrsGraphType =
typename LocalMatrixType::StaticCrsGraphType;
527 StaticCrsGraphType unmanagedGraph;
528 unmanagedGraph.entries =
typename StaticCrsGraphType::entries_type(managedGraph.entries.data(),managedGraph.entries.extent(0));
529 unmanagedGraph.row_map =
typename StaticCrsGraphType::row_map_type(managedGraph.row_map.data(),managedGraph.row_map.extent(0));
530 unmanagedGraph.row_block_offsets =
typename StaticCrsGraphType::row_block_type(managedGraph.row_block_offsets.data(),managedGraph.row_block_offsets.extent(0));
532 typename LocalMatrixType::values_type unmanagedValues(managedMatrix.values.data(),managedMatrix.values.extent(0));
533 LocalMatrixType unmanagedMatrix(managedMatrix.values.label(), managedMatrix.numCols(), unmanagedValues, unmanagedGraph);
534 new (&hostJacTpetraBlocks(row,col)) LocalMatrixType(unmanagedMatrix);
537 hostBlockExistsInJac(row,col) = 1;
540 hostBlockExistsInJac(row,col) = 0;
544 typename PHX::View<LocalMatrixType**>
545 jacTpetraBlocks(
"panzer::ScatterResidual_BlockedTpetra<Jacobian>::jacTpetraBlocks",numFieldBlocks,numFieldBlocks);
546 Kokkos::deep_copy(jacTpetraBlocks,hostJacTpetraBlocks);
547 Kokkos::deep_copy(blockExistsInJac,hostBlockExistsInJac);
554 const auto& globalIndexers =
globalIndexer_->getFieldDOFManagers();
555 auto blockOffsets_h = Kokkos::create_mirror_view(
blockOffsets_);
557 for (
size_t block=0; block < globalIndexers.size(); ++block) {
558 const auto subviewOfBlockLIDs = Kokkos::subview(
worksetLIDs_,Kokkos::ALL(), std::make_pair(blockOffsets_h(block),blockOffsets_h(block+1)));
559 globalIndexers[block]->getElementLIDs(localCellIds,subviewOfBlockLIDs);
563 for (std::size_t fieldIndex = 0; fieldIndex <
scatterFields_.size(); fieldIndex++) {
566 typename Tpetra::Vector<double,LO,GO,PHX::Device>::dual_view_type::t_dev kokkosResidual;
568 auto& tpetraResidual = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraBlockResidual->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
569 kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::OverwriteAll);
573 auto& tpetraDirichletCounter = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(
dirichletCounter_->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
574 const auto& kokkosDirichletCounter = tpetraDirichletCounter.getLocalViewDevice(Tpetra::Access::ReadWrite);
577 const PHX::View<const int*> fieldOffsets =
fieldOffsets_[fieldIndex];
580 const PHX::View<const ScalarT**> fieldValues =
scatterFields_[fieldIndex].get_static_view();
582 const auto& applyBC =
applyBC_[fieldIndex].get_static_view();
585 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
589 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
590 const int block_row_offset = blockOffsets(blockRowIndex);
591 const int rowLID = worksetLIDs(cell,block_row_offset+fieldOffsets(basis));
596 const int basisIndex = basisIndices(basis);
600 if (!applyBC(cell,basisIndex))
603 typedef PHX::MDField<const ScalarT,Cell,NODE>
FieldType;
604 typename FieldType::array_type::reference_type tmpFieldVal = fieldValues(cell,basisIndex);
607 kokkosResidual(rowLID,0) = tmpFieldVal.val();
609 kokkosDirichletCounter(rowLID,0) = 1.0;
612 for (
int blockColIndex=0; blockColIndex < numFieldBlocks; ++blockColIndex) {
613 if (blockExistsInJac(blockRowIndex,blockColIndex)) {
614 const auto& rowEntries = jacTpetraBlocks(blockRowIndex,blockColIndex).row(rowLID);
615 for (
int i=0; i < rowEntries.length; ++i)
621 for (
int blockColIndex=0; blockColIndex < numFieldBlocks; ++blockColIndex) {
622 if (blockExistsInJac(blockRowIndex,blockColIndex)) {
623 const int start = blockOffsets(blockColIndex);
624 const int stop = blockOffsets(blockColIndex+1);
625 const int sensSize = stop-start;
627 for (
int i=0; i < sensSize; ++i) {
628 cLIDs[i] = worksetLIDs(cell,start+i);
629 vals[i] = tmpFieldVal.fastAccessDx(start+i);
631 jacTpetraBlocks(blockRowIndex,blockColIndex).replaceValues(rowLID,cLIDs,sensSize,vals,
true,
true);
640 for (
int row=0; row < numFieldBlocks; ++row) {
641 for (
int col=0; col < numFieldBlocks; ++col) {
642 if (hostBlockExistsInJac(row,col)) {
643 hostJacTpetraBlocks(row,col).~CrsMatrix();