50 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
51 const Teuchos::ParameterList& p,
53 : rowIndexers_(rIndexers)
54 , colIndexers_(cIndexers)
55 , globalDataKey_(
"Residual Scatter Container")
57 std::string scatterName = p.get<std::string>(
"Scatter Name");
59 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
62 const std::vector<std::string>& names =
63 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
66 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
69 scatterIC_ = p.isParameter(
"Scatter Initial Condition") ? p.get<
bool>(
"Scatter Initial Condition") :
false;
71 Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
72 p.get< Teuchos::RCP<panzer::PureBasis> >(
"Basis")->functional :
73 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
75 side_subcell_dim_ = p.get<
int>(
"Side Subcell Dimension");
76 local_side_id_ = p.get<
int>(
"Local Side ID");
80 scatterFields_.resize(names.size());
81 for (std::size_t eq = 0; eq < names.size(); ++eq) {
82 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
85 this->addDependentField(scatterFields_[eq]);
88 checkApplyBC_ = p.isParameter(
"Check Apply BC") ? p.get<
bool>(
"Check Apply BC") :
false;
90 applyBC_.resize(names.size());
91 for (std::size_t eq = 0; eq < names.size(); ++eq) {
92 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string(
"APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
93 this->addDependentField(applyBC_[eq]);
98 this->addEvaluatedField(*scatterHolder_);
100 if (p.isType<std::string>(
"Global Data Key"))
101 globalDataKey_ = p.get<std::string>(
"Global Data Key");
103 this->setName(scatterName+
" Scatter Residual");
136 using Teuchos::rcp_dynamic_cast;
140 Teuchos::RCP<BLOC> blockContainer
141 = Teuchos::rcp_dynamic_cast<BLOC>(d.gedc->getDataObject(
"Dirichlet Counter"),
true);
143 dirichletCounter_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockContainer->get_f(),
true);
144 TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
147 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
148 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
151 if(blockedContainer!=Teuchos::null)
153 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer->get_f(),
true) :
154 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer->get_x(),
true);
155 else if(epetraContainer!=Teuchos::null)
157 Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th()) :
158 Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_x_th());
160 TEUCHOS_ASSERT(r_!=Teuchos::null);
169 using Teuchos::ArrayRCP;
170 using Teuchos::ptrFromRef;
171 using Teuchos::rcp_dynamic_cast;
174 using Thyra::SpmdVectorBase;
178 std::string blockId = this->wda(workset).block_id;
179 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
187 Teuchos::ArrayRCP<double> local_r;
188 Teuchos::ArrayRCP<double> local_dc;
189 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
190 int rowIndexer = indexerIds_[fieldIndex];
191 int subFieldNum = subFieldIds_[fieldIndex];
193 rcp_dynamic_cast<SpmdVectorBase<double> >(dirichletCounter_->getNonconstVectorBlock(rowIndexer))
194 ->getNonconstLocalData(ptrFromRef(local_dc));
197 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))
198 ->getNonconstLocalData(ptrFromRef(local_r));
200 auto subRowIndexer = rowIndexers_[rowIndexer];
201 auto LIDs = subRowIndexer->getLIDs();
202 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
203 Kokkos::deep_copy(LIDs_h, LIDs);
205 auto field = scatterFields_[fieldIndex].get_view();
206 auto field_h = Kokkos::create_mirror_view(
field);
207 Kokkos::deep_copy(field_h,
field);
209 BCFieldType::array_type::host_mirror_type applyBC_h;
211 auto applyBC = applyBC_[fieldIndex].get_static_view();
212 applyBC_h = Kokkos::create_mirror_view(
applyBC);
213 Kokkos::deep_copy(applyBC_h,
applyBC);
217 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
218 std::size_t cellLocalId = localCellIds[worksetCellIndex];
222 const std::pair<std::vector<int>,std::vector<int> > & indicePair
223 = subRowIndexer->getGIDFieldOffsets_closure(blockId,subFieldNum, side_subcell_dim_, local_side_id_);
224 const std::vector<int> & elmtOffset = indicePair.first;
225 const std::vector<int> & basisIdMap = indicePair.second;
228 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
229 int offset = elmtOffset[basis];
230 int lid = LIDs_h(cellLocalId, offset);
234 int basisId = basisIdMap[basis];
236 if (checkApplyBC_ and !applyBC_h(worksetCellIndex,basisId))
239 local_r[lid] = field_h(worksetCellIndex,basisId);
246 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
249 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
250 int offset = elmtOffset[basis];
251 int lid = LIDs_h(cellLocalId, offset);
255 local_r[lid] = field_h(worksetCellIndex,basis);
273 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
274 const Teuchos::ParameterList& p,
276 : rowIndexers_(rIndexers)
277 , colIndexers_(cIndexers)
278 , globalDataKey_(
"Residual Scatter Container")
280 std::string scatterName = p.get<std::string>(
"Scatter Name");
282 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
285 const std::vector<std::string>& names =
286 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
289 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
292 scatterIC_ = p.isParameter(
"Scatter Initial Condition") ? p.get<
bool>(
"Scatter Initial Condition") :
false;
294 Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
295 p.get< Teuchos::RCP<panzer::PureBasis> >(
"Basis")->functional :
296 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
298 side_subcell_dim_ = p.get<
int>(
"Side Subcell Dimension");
299 local_side_id_ = p.get<
int>(
"Local Side ID");
303 scatterFields_.resize(names.size());
304 for (std::size_t eq = 0; eq < names.size(); ++eq) {
305 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
308 this->addDependentField(scatterFields_[eq]);
311 checkApplyBC_ = p.isParameter(
"Check Apply BC") ? p.get<
bool>(
"Check Apply BC") :
false;
313 applyBC_.resize(names.size());
314 for (std::size_t eq = 0; eq < names.size(); ++eq) {
315 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string(
"APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
316 this->addDependentField(applyBC_[eq]);
321 this->addEvaluatedField(*scatterHolder_);
323 if (p.isType<std::string>(
"Global Data Key"))
324 globalDataKey_ = p.get<std::string>(
"Global Data Key");
326 this->setName(scatterName+
" Scatter Tangent");
359 using Teuchos::rcp_dynamic_cast;
363 Teuchos::RCP<BLOC> blockContainer
364 = Teuchos::rcp_dynamic_cast<BLOC>(d.gedc->getDataObject(
"Dirichlet Counter"),
true);
366 dirichletCounter_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockContainer->get_f(),
true);
367 TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
370 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
371 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
374 if(blockedContainer!=Teuchos::null)
376 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer->get_f(),
true) :
377 rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer->get_x(),
true);
378 else if(epetraContainer!=Teuchos::null)
380 Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th()) :
381 Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_x_th());
383 TEUCHOS_ASSERT(r_!=Teuchos::null);
391 TEUCHOS_ASSERT(
false);
394 using Teuchos::ArrayRCP;
395 using Teuchos::ptrFromRef;
396 using Teuchos::rcp_dynamic_cast;
399 using Thyra::SpmdVectorBase;
403 std::string blockId = this->wda(workset).block_id;
404 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
412 Teuchos::ArrayRCP<double> local_r;
413 Teuchos::ArrayRCP<double> local_dc;
414 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
415 int rowIndexer = indexerIds_[fieldIndex];
416 int subFieldNum = subFieldIds_[fieldIndex];
418 rcp_dynamic_cast<SpmdVectorBase<double> >(dirichletCounter_->getNonconstVectorBlock(rowIndexer))
419 ->getNonconstLocalData(ptrFromRef(local_dc));
422 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))
423 ->getNonconstLocalData(ptrFromRef(local_r));
425 auto subRowIndexer = rowIndexers_[rowIndexer];
427 auto LIDs = subRowIndexer->getLIDs();
428 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
429 Kokkos::deep_copy(LIDs_h, LIDs);
431 auto field = scatterFields_[fieldIndex].get_view();
432 auto field_h = Kokkos::create_mirror_view(
field);
433 Kokkos::deep_copy(field_h,
field);
435 BCFieldType::array_type::host_mirror_type applyBC_h;
437 auto applyBC = applyBC_[fieldIndex].get_static_view();
438 applyBC_h = Kokkos::create_mirror_view(
applyBC);
439 Kokkos::deep_copy(applyBC_h,
applyBC);
443 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
444 std::size_t cellLocalId = localCellIds[worksetCellIndex];
448 const std::pair<std::vector<int>,std::vector<int> > & indicePair
449 = subRowIndexer->getGIDFieldOffsets_closure(blockId,subFieldNum, side_subcell_dim_, local_side_id_);
450 const std::vector<int> & elmtOffset = indicePair.first;
451 const std::vector<int> & basisIdMap = indicePair.second;
454 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
455 int offset = elmtOffset[basis];
456 int lid = LIDs_h(cellLocalId, offset);
460 int basisId = basisIdMap[basis];
462 if (checkApplyBC_ and !applyBC_h(worksetCellIndex,basisId))
465 local_r[lid] = field_h(worksetCellIndex,basisId).val();
472 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
475 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
476 int offset = elmtOffset[basis];
477 int lid = LIDs_h(cellLocalId, offset);
481 local_r[lid] = field_h(worksetCellIndex,basis).val();
498 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
499 const Teuchos::ParameterList& p,
501 : rowIndexers_(rIndexers)
502 , colIndexers_(cIndexers)
503 , globalDataKey_(
"Residual Scatter Container")
505 std::string scatterName = p.get<std::string>(
"Scatter Name");
507 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
510 const std::vector<std::string>& names =
511 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
514 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
516 Teuchos::RCP<PHX::DataLayout> dl =
517 p.get< Teuchos::RCP<panzer::PureBasis> >(
"Basis")->functional;
519 side_subcell_dim_ = p.get<
int>(
"Side Subcell Dimension");
520 local_side_id_ = p.get<
int>(
"Local Side ID");
523 scatterFields_.resize(names.size());
524 for (std::size_t eq = 0; eq < names.size(); ++eq) {
525 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
528 this->addDependentField(scatterFields_[eq]);
531 checkApplyBC_ = p.get<
bool>(
"Check Apply BC");
533 applyBC_.resize(names.size());
534 for (std::size_t eq = 0; eq < names.size(); ++eq) {
535 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string(
"APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
536 this->addDependentField(applyBC_[eq]);
541 this->addEvaluatedField(*scatterHolder_);
543 if (p.isType<std::string>(
"Global Data Key"))
544 globalDataKey_ = p.get<std::string>(
"Global Data Key");
546 if(colIndexers_.size()==0)
547 colIndexers_ = rowIndexers_;
549 this->setName(scatterName+
" Scatter Residual (Jacobian)");
605 using Teuchos::ArrayRCP;
606 using Teuchos::ptrFromRef;
607 using Teuchos::rcp_dynamic_cast;
609 using Thyra::SpmdVectorBase;
612 std::string blockId = this->wda(workset).block_id;
613 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
615 int numFieldBlocks = Teuchos::as<int>(colIndexers_.size());
617 std::vector<int> blockOffsets;
620 std::unordered_map<std::pair<int,int>,Teuchos::RCP<Epetra_CrsMatrix>,
panzer::pair_hash> jacEpetraBlocks;
627 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
628 int rowIndexer = indexerIds_[fieldIndex];
629 int subFieldNum = subFieldIds_[fieldIndex];
632 Teuchos::ArrayRCP<double> local_dc;
633 rcp_dynamic_cast<SpmdVectorBase<double> >(dirichletCounter_->getNonconstVectorBlock(rowIndexer))
634 ->getNonconstLocalData(ptrFromRef(local_dc));
637 Teuchos::ArrayRCP<double> local_r;
638 if(r_!=Teuchos::null)
639 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))
640 ->getNonconstLocalData(ptrFromRef(local_r));
642 auto subRowIndexer = rowIndexers_[rowIndexer];
643 auto subIndicePair = subRowIndexer->getGIDFieldOffsets_closure(blockId,subFieldNum, side_subcell_dim_, local_side_id_);
644 const std::vector<int> & subElmtOffset = subIndicePair.first;
645 const std::vector<int> & subBasisIdMap = subIndicePair.second;
647 auto rLIDs = subRowIndexer->getLIDs();
648 auto rLIDs_h = Kokkos::create_mirror_view(rLIDs);
649 Kokkos::deep_copy(rLIDs_h, rLIDs);
651 auto field = scatterFields_[fieldIndex].get_view();
652 auto field_h = Kokkos::create_mirror_view(
field);
653 Kokkos::deep_copy(field_h,
field);
655 BCFieldType::array_type::host_mirror_type applyBC_h;
657 auto applyBC = applyBC_[fieldIndex].get_static_view();
658 applyBC_h = Kokkos::create_mirror_view(
applyBC);
659 Kokkos::deep_copy(applyBC_h,
applyBC);
663 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
664 std::size_t cellLocalId = localCellIds[worksetCellIndex];
667 for(std::size_t basis=0;basis<subElmtOffset.size();basis++) {
668 int offset = subElmtOffset[basis];
669 int lid = rLIDs_h(cellLocalId, offset);
673 int basisId = subBasisIdMap[basis];
675 if (checkApplyBC_ and !applyBC_h(worksetCellIndex,basisId))
679 for(
int colIndexer=0;colIndexer<numFieldBlocks;colIndexer++) {
680 int start = blockOffsets[colIndexer];
681 int end = blockOffsets[colIndexer+1];
687 std::pair<int,int> blockIndex = std::make_pair(rowIndexer,colIndexer);
688 Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex];
690 if(subJac==Teuchos::null) {
691 Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac_->getNonconstBlock(blockIndex.first,blockIndex.second);
694 if(Teuchos::is_null(tOp))
697 Teuchos::RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*tOp);
698 subJac = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
699 jacEpetraBlocks[blockIndex] = subJac;
703 int * rowIndices = 0;
704 double * rowValues = 0;
706 subJac->ExtractMyRowView(lid,numEntries,rowValues,rowIndices);
708 for(
int i=0;i<numEntries;i++)
712 const ScalarT scatterField = field_h(worksetCellIndex,basisId);
714 if(r_!=Teuchos::null)
715 local_r[lid] = scatterField.val();
719 std::vector<double> jacRow(scatterField.size(),0.0);
721 for(
int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
722 jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex);
724 for(
int colIndexer=0;colIndexer<numFieldBlocks;colIndexer++) {
725 int start = blockOffsets[colIndexer];
726 int end = blockOffsets[colIndexer+1];
731 auto subColIndexer = colIndexers_[colIndexer];
733 auto cLIDs = subColIndexer->getElementLIDs(cellLocalId);
734 auto cLIDs_h = Kokkos::create_mirror_view(cLIDs);
735 Kokkos::deep_copy(cLIDs_h, cLIDs);
737 TEUCHOS_ASSERT(end-start==Teuchos::as<int>(cLIDs.size()));
740 std::pair<int,int> blockIndex = std::make_pair(rowIndexer,colIndexer);
741 Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex];
744 if(subJac==Teuchos::null) {
745 Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac_->getNonconstBlock(blockIndex.first,blockIndex.second);
748 if(Teuchos::is_null(tOp))
751 Teuchos::RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*tOp);
752 subJac = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
753 jacEpetraBlocks[blockIndex] = subJac;
757 int err = subJac->ReplaceMyValues(lid, end-start, &jacRow[start],&cLIDs_h[0]);
759 std::stringstream ss;
760 ss <<
"Failed inserting row: " <<
" (" << lid <<
"): ";
761 for(
int i=0;i<end-start;i++)
762 ss << cLIDs_h[i] <<
" ";
764 ss <<
"Into block " << rowIndexer <<
", " << colIndexer << std::endl;
766 ss <<
"scatter field = ";
767 scatterFields_[fieldIndex].print(ss);
770 TEUCHOS_TEST_FOR_EXCEPTION(err!=0,std::runtime_error,ss.str());