49 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
50 const Teuchos::ParameterList& p,
52 : rowIndexers_(rIndexers)
53 , colIndexers_(cIndexers)
54 , globalDataKey_(
"Residual Scatter Container")
56 std::string scatterName = p.get<std::string>(
"Scatter Name");
58 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
61 const std::vector<std::string>& names =
62 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
65 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
67 Teuchos::RCP<PHX::DataLayout> dl =
68 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
71 scatterFields_.resize(names.size());
72 for (std::size_t eq = 0; eq < names.size(); ++eq) {
73 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
76 this->addDependentField(scatterFields_[eq]);
80 this->addEvaluatedField(*scatterHolder_);
82 if (p.isType<std::string>(
"Global Data Key"))
83 globalDataKey_ = p.get<std::string>(
"Global Data Key");
85 this->setName(scatterName+
" Scatter Residual");
134 using Teuchos::ptrFromRef;
135 using Teuchos::rcp_dynamic_cast;
138 using Thyra::SpmdVectorBase;
142 std::string blockId = this->wda(workset).block_id;
143 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
151 Teuchos::ArrayRCP<double> local_r;
152 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
153 int indexerId = indexerIds_[fieldIndex];
154 int subFieldNum = subFieldIds_[fieldIndex];
157 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
159 auto subRowIndexer = rowIndexers_[indexerId];
160 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
162 auto field = PHX::as_view(scatterFields_[fieldIndex]);
163 auto field_h = Kokkos::create_mirror_view(
field);
164 Kokkos::deep_copy(field_h,
field);
167 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
168 std::size_t cellLocalId = localCellIds[worksetCellIndex];
170 auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
171 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
172 Kokkos::deep_copy(LIDs_h, LIDs);
175 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
176 int offset = elmtOffset[basis];
177 int lid = LIDs_h[offset];
178 local_r[lid] += field_h(worksetCellIndex,basis);
191 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
192 const Teuchos::ParameterList& p,
194 : rowIndexers_(rIndexers)
195 , colIndexers_(cIndexers)
196 , globalDataKey_(
"Residual Scatter Container")
198 std::string scatterName = p.get<std::string>(
"Scatter Name");
200 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
203 const std::vector<std::string>& names =
204 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
207 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
209 Teuchos::RCP<PHX::DataLayout> dl =
210 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
213 scatterFields_.resize(names.size());
214 for (std::size_t eq = 0; eq < names.size(); ++eq) {
215 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
218 this->addDependentField(scatterFields_[eq]);
222 this->addEvaluatedField(*scatterHolder_);
224 if (p.isType<std::string>(
"Global Data Key"))
225 globalDataKey_ = p.get<std::string>(
"Global Data Key");
227 this->setName(scatterName+
" Scatter Tangent");
275 TEUCHOS_ASSERT(
false);
278 using Teuchos::ptrFromRef;
279 using Teuchos::rcp_dynamic_cast;
282 using Thyra::SpmdVectorBase;
286 std::string blockId = this->wda(workset).block_id;
287 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
295 Teuchos::ArrayRCP<double> local_r;
296 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
297 int indexerId = indexerIds_[fieldIndex];
298 int subFieldNum = subFieldIds_[fieldIndex];
301 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
303 auto subRowIndexer = rowIndexers_[indexerId];
304 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
307 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
308 std::size_t cellLocalId = localCellIds[worksetCellIndex];
310 auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
313 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
314 int offset = elmtOffset[basis];
315 int lid = LIDs[offset];
316 local_r[lid] += (scatterFields_[fieldIndex])(worksetCellIndex,basis).val();
329 const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
330 const Teuchos::ParameterList& p,
331 bool useDiscreteAdjoint)
332 : rowIndexers_(rIndexers)
333 , colIndexers_(cIndexers)
334 , globalDataKey_(
"Residual Scatter Container")
335 , useDiscreteAdjoint_(useDiscreteAdjoint)
337 std::string scatterName = p.get<std::string>(
"Scatter Name");
339 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
342 const std::vector<std::string>& names =
343 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
346 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
348 Teuchos::RCP<PHX::DataLayout> dl =
349 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
352 scatterFields_.resize(names.size());
353 for (std::size_t eq = 0; eq < names.size(); ++eq) {
354 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
357 this->addDependentField(scatterFields_[eq]);
361 this->addEvaluatedField(*scatterHolder_);
363 if (p.isType<std::string>(
"Global Data Key"))
364 globalDataKey_ = p.get<std::string>(
"Global Data Key");
365 if (p.isType<
bool>(
"Use Discrete Adjoint"))
366 useDiscreteAdjoint = p.get<
bool>(
"Use Discrete Adjoint");
369 if(useDiscreteAdjoint)
370 { TEUCHOS_ASSERT(colIndexers_.size()==0); }
372 if(colIndexers_.size()==0)
373 colIndexers_ = rowIndexers_;
375 this->setName(scatterName+
" Scatter Residual BlockedEpetra (Jacobian)");
403 using Teuchos::rcp_dynamic_cast;
409 RCP<const BLOC> blockedContainer = rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
410 RCP<const ELOC> epetraContainer = rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
413 if(blockedContainer!=Teuchos::null) {
414 r_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockedContainer->get_f());
415 Jac_ = rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(blockedContainer->get_A());
417 else if(epetraContainer!=Teuchos::null) {
419 if(epetraContainer->get_f_th()!=Teuchos::null)
420 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
423 RCP<Thyra::LinearOpBase<double> > J = blockedContainer->get_A_th();
424 Jac_ = rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(Thyra::nonconstBlock1x1(J));
427 TEUCHOS_ASSERT(Jac_!=Teuchos::null);
436 using Teuchos::ArrayRCP;
437 using Teuchos::ptrFromRef;
438 using Teuchos::rcp_dynamic_cast;
441 using Thyra::SpmdVectorBase;
445 std::vector<double> jacRow;
448 std::string blockId = this->wda(workset).block_id;
449 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
451 int numFieldBlocks = Teuchos::as<int>(colIndexers_.size());
453 std::vector<int> blockOffsets;
456 std::unordered_map<std::pair<int,int>,Teuchos::RCP<Epetra_CrsMatrix>,
panzer::pair_hash> jacEpetraBlocks;
459 Teuchos::ArrayRCP<double> local_r;
460 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
461 int rowIndexer = indexerIds_[fieldIndex];
462 int subFieldNum = subFieldIds_[fieldIndex];
465 if(r_!=Teuchos::null)
466 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))->getNonconstLocalData(ptrFromRef(local_r));
468 auto subRowIndexer = rowIndexers_[rowIndexer];
469 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
471 auto field = scatterFields_[fieldIndex].get_view();
472 auto field_h = Kokkos::create_mirror_view(
field);
473 Kokkos::deep_copy(field_h,
field);
475 auto rLIDs = subRowIndexer->getLIDs();
476 auto rLIDs_h = Kokkos::create_mirror_view(rLIDs);
477 Kokkos::deep_copy(rLIDs_h, rLIDs);
480 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
481 std::size_t cellLocalId = localCellIds[worksetCellIndex];
484 for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) {
485 const ScalarT scatterField = field_h(worksetCellIndex,rowBasisNum);
486 int rowOffset = elmtOffset[rowBasisNum];
487 int r_lid = rLIDs_h(cellLocalId, rowOffset);
490 if(local_r!=Teuchos::null)
491 local_r[r_lid] += (scatterField.val());
494 jacRow.resize(scatterField.size());
497 if(scatterField.size() == 0)
500 for(
int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
501 jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex);
504 for(
int colIndexer=0;colIndexer<numFieldBlocks;colIndexer++) {
505 int start = blockOffsets[colIndexer];
506 int end = blockOffsets[colIndexer+1];
511 auto subColIndexer = colIndexers_[colIndexer];
512 auto cLIDs = subColIndexer->getElementLIDs(cellLocalId);
513 auto cLIDs_h = Kokkos::create_mirror_view(cLIDs);
514 Kokkos::deep_copy(cLIDs_h, cLIDs);
516 TEUCHOS_ASSERT(end-start==Teuchos::as<int>(cLIDs.size()));
519 std::pair<int,int> blockIndex = useDiscreteAdjoint_ ? std::make_pair(colIndexer,rowIndexer)
520 : std::make_pair(rowIndexer,colIndexer);
521 Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex];
524 if(subJac==Teuchos::null) {
525 Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac_->getNonconstBlock(blockIndex.first,blockIndex.second);
528 if(Teuchos::is_null(tOp))
531 Teuchos::RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*tOp);
532 subJac = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
533 jacEpetraBlocks[blockIndex] = subJac;
537 if(!useDiscreteAdjoint_) {
538 int err = subJac->SumIntoMyValues(r_lid, end-start, &jacRow[start],&cLIDs_h[0]);
541 std::stringstream ss;
542 ss <<
"Failed inserting row: " <<
"LID = " << r_lid <<
"): ";
543 for(
int i=start;i<end;i++)
544 ss << cLIDs_h[i] <<
" ";
546 ss <<
"Into block " << rowIndexer <<
", " << colIndexer << std::endl;
548 ss <<
"scatter field = ";
549 scatterFields_[fieldIndex].print(ss);
552 TEUCHOS_TEST_FOR_EXCEPTION(err!=0,std::runtime_error,ss.str());
556 for(std::size_t c=0;c<cLIDs.size();c++) {
557 int err = subJac->SumIntoMyValues(cLIDs_h[c], 1, &jacRow[start+c],&r_lid);
558 TEUCHOS_ASSERT_EQUALITY(err,0);