43 const Teuchos::ParameterList& p)
45 std::string scatterName = p.get<std::string>(
"Scatter Name");
46 Teuchos::RCP<PHX::FieldTag> scatterHolder =
47 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
50 const std::vector<std::string>& names =
51 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
53 Teuchos::RCP<PHX::DataLayout> dl =
54 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
57 for (std::size_t eq = 0; eq < names.size(); ++eq) {
58 PHX::MDField<const ScalarT,Cell,NODE> field = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
61 this->addDependentField(field.fieldTag());
65 this->addEvaluatedField(*scatterHolder);
67 this->setName(scatterName+
" Scatter Residual");
175 using Teuchos::rcp_dynamic_cast;
179 const auto& localCellIds = this->
wda(workset).cell_local_ids_k;
180 const RCP<ProductVectorBase<double>> thyraBlockResidual = rcp_dynamic_cast<ProductVectorBase<double> >(
blockedContainer_->get_f(),
true);
183 int currentWorksetLIDSubBlock = -1;
184 for (std::size_t fieldIndex = 0; fieldIndex <
scatterFields_.size(); fieldIndex++) {
191 auto& tpetraResidual = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraBlockResidual->getNonconstVectorBlock(
productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
192 const auto& kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::ReadWrite);
197 const auto& fieldValues =
scatterFields_[fieldIndex].get_static_view();
199 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::ExecutionSpace>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
200 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
201 const int lid = worksetLIDs(cell,fieldOffsets(basis));
202 Kokkos::atomic_add(&kokkosResidual(lid,0), fieldValues(cell,basis));
222 const std::vector<Teuchos::RCP<const panzer::GlobalIndexer> > & colIndexers,
223 const Teuchos::ParameterList& p)
236 std::string scatterName = p.get<std::string>(
"Scatter Name");
238 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
241 const std::vector<std::string>& names =
242 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
245 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
247 Teuchos::RCP<PHX::DataLayout> dl =
248 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
252 for (std::size_t eq = 0; eq < names.size(); ++eq) {
253 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
262 if (p.isType<std::string>(
"Global Data Key"))
265 this->setName(scatterName+
" Scatter Residual (Jacobian)");
274 const Workset & workset_0 = (*d.worksets_)[0];
275 const std::string blockId = this->
wda(workset_0).block_id;
282 const int globalFieldNum =
globalIndexer_->getFieldNum(fieldName);
285 fieldIds_[fd] = fieldGlobalIndexer->getFieldNum(fieldName);
287 const std::vector<int>& offsets =
globalIndexer_->getGIDFieldOffsets(blockId,globalFieldNum);
288 fieldOffsets_[fd] = PHX::View<int*>(
"ScatterResidual_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
289 auto hostOffsets = Kokkos::create_mirror_view(
fieldOffsets_[fd]);
290 for (std::size_t i=0; i < offsets.size(); ++i)
291 hostOffsets(i) = offsets[i];
298 int elementBlockGIDCount = 0;
299 for (
const auto& blockDOFMgr :
globalIndexer_->getFieldDOFManagers())
300 elementBlockGIDCount += blockDOFMgr->getElementBlockGIDCount(blockId);
302 worksetLIDs_ = Kokkos::View<LO**, Kokkos::LayoutRight, PHX::Device>(
303 "ScatterResidual_BlockedTpetra(Jacobian):worksetLIDs_",
307 const auto& blockGlobalIndexers =
globalIndexer_->getFieldDOFManagers();
308 const int numBlocks =
static_cast<int>(
globalIndexer_->getFieldDOFManagers().size());
309 blockOffsets_ = PHX::View<LO*>(
"ScatterResidual_BlockedTpetra(Jacobian):blockOffsets_",
311 const auto hostBlockOffsets = Kokkos::create_mirror_view(
blockOffsets_);
312 for (
int blk=0;blk<numBlocks;blk++) {
314 hostBlockOffsets(blk) = blockOffset;
316 hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
322 auto hostColBlockOffsets = hostBlockOffsets;
329 colBlockOffsets_ = PHX::View<LO*>(
"ScatterResidual_BlockedTpetra(Jacobian):colBlockOffsets_",
332 hostColOffsets(0) = 0;
333 for (
int blk=0;blk<numColBlocks;blk++)
334 hostColOffsets(blk+1) = hostColOffsets(blk) +
colGlobalIndexers_[blk]->getElementBlockGIDCount(blockId);
337 colWorksetLIDs_ = Kokkos::View<LO**, Kokkos::LayoutRight, PHX::Device>(
338 "ScatterResidual_BlockedTpetra(Jacobian):colWorksetLIDs_",
340 hostColBlockOffsets = hostColOffsets;
357 "ScatterResidual_BlockedTpetra(Jacobian):hostJacTpetraBlocks", numRowBlocks, numColBlocks);
359 "ScatterResidual_BlockedTpetra(Jacobian):jacTpetraBlocks", numRowBlocks, numColBlocks);
360 blockExistsInJac_ = PHX::View<int**>(
"ScatterResidual_BlockedTpetra(Jacobian):blockExistsInJac", numRowBlocks, numColBlocks);
366 int max_blockDerivativeSize = 0;
368 const int blockDerivativeSize = hostColBlockOffsets(blk+1) - hostColBlockOffsets(blk);
369 if ( blockDerivativeSize > max_blockDerivativeSize )
370 max_blockDerivativeSize = blockDerivativeSize;
372 workset_vals_ = Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device>(
373 "ScatterResidual_BlockedTpetra(Jacobian):workset_vals_",
400 using Teuchos::rcp_dynamic_cast;
405 const auto& localCellIds = this->
wda(workset).cell_local_ids_k;
410 const RCP<ProductVectorBase<double>> thyraBlockResidual = rcp_dynamic_cast<ProductVectorBase<double> >(
blockedContainer_->get_f());
411 const bool haveResidual = Teuchos::nonnull(thyraBlockResidual);
412 const RCP<BlockedLinearOpBase<double>> Jac = rcp_dynamic_cast<BlockedLinearOpBase<double> >(
blockedContainer_->get_A(),
true);
419 TEUCHOS_ASSERT(
static_cast<int>(
jacTpetraBlocks_.extent(0))==numFieldBlocks &&
425 for (
int row=0; row < numFieldBlocks; ++row) {
426 for (
int col=0; col < numColFieldBlocks; ++col) {
427 const auto thyraTpetraOperator = rcp_dynamic_cast<Thyra::TpetraLinearOp<double,LO,GO,NodeT>>(Jac->getNonconstBlock(row,col),
false);
428 if (nonnull(thyraTpetraOperator)) {
444 const auto tpetraCrsMatrix = rcp_dynamic_cast<Tpetra::CrsMatrix<double,LO,GO,NodeT>>(thyraTpetraOperator->getTpetraOperator(),
true);
445 const auto managedMatrix = tpetraCrsMatrix->getLocalMatrixDevice();
446 const auto managedGraph = managedMatrix.graph;
449 using StaticCrsGraphType =
typename LocalMatrixType::StaticCrsGraphType;
450 StaticCrsGraphType unmanagedGraph;
451 unmanagedGraph.entries =
typename StaticCrsGraphType::entries_type(managedGraph.entries.data(),managedGraph.entries.extent(0));
452 unmanagedGraph.row_map =
typename StaticCrsGraphType::row_map_type(managedGraph.row_map.data(),managedGraph.row_map.extent(0));
453 unmanagedGraph.row_block_offsets =
typename StaticCrsGraphType::row_block_type(managedGraph.row_block_offsets.data(),managedGraph.row_block_offsets.extent(0));
455 typename LocalMatrixType::values_type unmanagedValues(managedMatrix.values.data(),managedMatrix.values.extent(0));
456 LocalMatrixType unmanagedMatrix(managedMatrix.values.label(), managedMatrix.numCols(), unmanagedValues, unmanagedGraph);
460 hostBlockExistsInJac(row,col) = 1;
463 hostBlockExistsInJac(row,col) = 0;
468 Kokkos::deep_copy(jacTpetraBlocks,hostJacTpetraBlocks);
469 Kokkos::deep_copy(blockExistsInJac,hostBlockExistsInJac);
476 const auto& globalIndexers =
globalIndexer_->getFieldDOFManagers();
478 for (
size_t block=0; block < globalIndexers.size(); ++block) {
479 const auto subviewOfBlockLIDs = Kokkos::subview(
worksetLIDs_,Kokkos::ALL(), std::make_pair(blockOffsets_h(block),blockOffsets_h(block+1)));
480 globalIndexers[block]->getElementLIDs(localCellIds,subviewOfBlockLIDs);
486 const auto subviewOfBlockLIDs = Kokkos::subview(
colWorksetLIDs_,Kokkos::ALL(), std::make_pair(colBlockOffsets_h(block),colBlockOffsets_h(block+1)));
492 for (std::size_t fieldIndex = 0; fieldIndex <
scatterFields_.size(); fieldIndex++) {
495 typename Tpetra::Vector<double,LO,GO,panzer::TpetraNodeType>::dual_view_type::t_dev kokkosResidual;
497 auto& tpetraResidual = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraBlockResidual->getNonconstVectorBlock(blockRowIndex),
true))->getTpetraVector());
498 kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::ReadWrite);
502 const PHX::View<const int*> fieldOffsets =
fieldOffsets_[fieldIndex];
503 const PHX::View<const ScalarT**> fieldValues =
scatterFields_[fieldIndex].get_static_view();
506 const Kokkos::View<const LO**, Kokkos::LayoutRight, PHX::Device> worksetLIDs =
worksetLIDs_;
507 const Kokkos::View<const LO**, Kokkos::LayoutRight, PHX::Device> colWorksetLIDs =
colWorksetLIDs_;
508 Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device> workset_vals =
workset_vals_;
510 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::ExecutionSpace>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
511 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
512 typedef PHX::MDField<const ScalarT,Cell,NODE>
FieldType;
513 typename FieldType::array_type::reference_type tmpFieldVal = fieldValues(cell,basis);
514 const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
517 Kokkos::atomic_add(&kokkosResidual(rowLID,0), tmpFieldVal.val());
519 for (
int blockColIndex=0; blockColIndex < numColFieldBlocks; ++blockColIndex) {
520 if (blockExistsInJac(blockRowIndex,blockColIndex)) {
521 const int start = colBlockOffsets(blockColIndex);
522 const int stop = colBlockOffsets(blockColIndex+1);
523 const int sensSize = stop-start;
525 for (
int i=0; i < sensSize; ++i)
526 workset_vals(cell,i) = tmpFieldVal.fastAccessDx(start+i);
528 jacTpetraBlocks(blockRowIndex,blockColIndex).sumIntoValues(rowLID, &colWorksetLIDs(cell,start), sensSize, &workset_vals(cell,0),
true,
true);
537 for (
int row=0; row < numFieldBlocks; ++row) {
538 for (
int col=0; col < numColFieldBlocks; ++col) {
539 if (hostBlockExistsInJac(row,col)) {
540 hostJacTpetraBlocks(row,col).~CrsMatrix();
635 using Teuchos::rcp_dynamic_cast;
639 std::vector<std::string> activeParameters =
640 rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject(
"PARAMETER_NAMES"))->getActiveParameters();
642 const int numBlocks =
static_cast<int>(
globalIndexer_->getFieldDOFManagers().size());
646 dfdpFieldsVoV_.initialize(
"ScatterResidual_Tpetra<Tangent>::dfdpFieldsVoV_",activeParameters.size(),numBlocks);
649 for(std::size_t i=0;i<activeParameters.size();i++) {
650 RCP<ContainerType> paramBlockedContainer = rcp_dynamic_cast<ContainerType>(d.gedc->getDataObject(activeParameters[i]),
true);
651 RCP<ProductVectorBase<double>> productVector =
652 rcp_dynamic_cast<ProductVectorBase<double>>(paramBlockedContainer->get_f(),
true);
654 for(
int j=0;j<numBlocks;j++)
655 dfdpVectors_[i][j] = rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(productVector->getNonconstVectorBlock(j),
true)->getTpetraVector();
662 RCP<const LOCPair_GlobalEvaluationData> gdata = rcp_dynamic_cast<const LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(
globalDataKey_),
true);
663 blockedContainer_ = rcp_dynamic_cast<const ContainerType>(gdata->getGhostedLOC());
673 using Teuchos::rcp_dynamic_cast;
677 const auto& localCellIds = this->
wda(workset).cell_local_ids_k;
678 const RCP<ProductVectorBase<double>> thyraBlockResidual = rcp_dynamic_cast<ProductVectorBase<double> >(
blockedContainer_->get_f(),
true);
688 int currentWorksetLIDSubBlock = -1;
689 for (std::size_t fieldIndex = 0; fieldIndex <
scatterFields_.size(); fieldIndex++) {
696 auto& tpetraResidual = *((rcp_dynamic_cast<Thyra::TpetraVector<RealType,LO,GO,NodeT>>(thyraBlockResidual->getNonconstVectorBlock(
productVectorBlockIndex_[fieldIndex]),
true))->getTpetraVector());
697 const auto& kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::ReadWrite);
702 const auto& fieldValues =
scatterFields_[fieldIndex].get_static_view();
704 const auto& kokkosTangents = Kokkos::subview(tangentFieldsDevice,Kokkos::ALL(),
productVectorBlockIndex_[fieldIndex]);
705 const std::size_t num_params = Sacado::dimension_scalar(fieldValues)-1;
707 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::ExecutionSpace>(0,workset.num_cells), KOKKOS_LAMBDA (
const int& cell) {
708 for(
int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
709 const int lid = worksetLIDs(cell,fieldOffsets(basis));
710 Kokkos::atomic_add(&kokkosResidual(lid,0), fieldValues(cell,basis).val());
711 for(std::size_t i_param=0; i_param<num_params; i_param++)
712 Kokkos::atomic_add(&kokkosTangents(i_param)(lid,0), fieldValues(cell,basis).fastAccessDx(i_param));
722 dfdpFieldsVoV_.addView(Kokkos::View<RealType**,Kokkos::LayoutLeft,PHX::Device>(),i,j);