43 #ifndef PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
44 #define PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
47 #include "Teuchos_Assert.hpp"
49 #include "Phalanx_DataLayout.hpp"
51 #include "Epetra_Map.h"
52 #include "Epetra_Vector.h"
53 #include "Epetra_CrsMatrix.h"
63 #include "Thyra_SpmdVectorBase.hpp"
64 #include "Thyra_ProductVectorBase.hpp"
65 #include "Thyra_DefaultProductVector.hpp"
66 #include "Thyra_BlockedLinearOpBase.hpp"
67 #include "Thyra_DefaultBlockedLinearOp.hpp"
68 #include "Thyra_get_Epetra_Operator.hpp"
70 #include "Phalanx_DataLayout_MDALayout.hpp"
72 #include "Teuchos_FancyOStream.hpp"
78 template<
typename TRAITS,
typename LO,
typename GO>
84 : rowIndexers_(rIndexers)
85 , colIndexers_(cIndexers)
86 , globalDataKey_(
"Residual Scatter Container")
88 std::string scatterName = p.
get<std::string>(
"Scatter Name");
93 const std::vector<std::string>& names =
103 scatterFields_.resize(names.size());
104 for (std::size_t eq = 0; eq < names.size(); ++eq) {
105 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
108 this->addDependentField(scatterFields_[eq]);
112 this->addEvaluatedField(*scatterHolder_);
114 if (p.
isType<std::string>(
"Global Data Key"))
115 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
117 this->setName(scatterName+
" Scatter Residual");
121 template<
typename TRAITS,
typename LO,
typename GO>
126 indexerIds_.resize(scatterFields_.size());
127 subFieldIds_.resize(scatterFields_.size());
130 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
132 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
135 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
140 template<
typename TRAITS,
typename LO,
typename GO>
148 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<
const BLOC>(d.gedc->getDataObject(globalDataKey_));
149 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<
const ELOC>(d.gedc->getDataObject(globalDataKey_));
152 if(blockedContainer!=Teuchos::null)
154 else if(epetraContainer!=Teuchos::null)
155 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
161 template<
typename TRAITS,
typename LO,
typename GO>
166 using Teuchos::ptrFromRef;
167 using Teuchos::rcp_dynamic_cast;
170 using Thyra::SpmdVectorBase;
174 std::string blockId = this->wda(workset).block_id;
175 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
184 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
185 int indexerId = indexerIds_[fieldIndex];
186 int subFieldNum = subFieldIds_[fieldIndex];
189 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
191 auto subRowIndexer = rowIndexers_[indexerId];
192 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
195 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
196 std::size_t cellLocalId = localCellIds[worksetCellIndex];
198 auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
201 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
202 int offset = elmtOffset[basis];
203 int lid = LIDs[offset];
204 local_r[lid] += (scatterFields_[fieldIndex])(worksetCellIndex,basis);
214 template<
typename TRAITS,
typename LO,
typename GO>
220 : rowIndexers_(rIndexers)
221 , colIndexers_(cIndexers)
222 , globalDataKey_(
"Residual Scatter Container")
224 std::string scatterName = p.
get<std::string>(
"Scatter Name");
229 const std::vector<std::string>& names =
239 scatterFields_.resize(names.size());
240 for (std::size_t eq = 0; eq < names.size(); ++eq) {
241 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
244 this->addDependentField(scatterFields_[eq]);
248 this->addEvaluatedField(*scatterHolder_);
250 if (p.
isType<std::string>(
"Global Data Key"))
251 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
253 this->setName(scatterName+
" Scatter Tangent");
257 template<
typename TRAITS,
typename LO,
typename GO>
262 indexerIds_.resize(scatterFields_.size());
263 subFieldIds_.resize(scatterFields_.size());
266 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
268 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
271 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
276 template<
typename TRAITS,
typename LO,
typename GO>
284 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<
const BLOC>(d.gedc->getDataObject(globalDataKey_));
285 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<
const ELOC>(d.gedc->getDataObject(globalDataKey_));
288 if(blockedContainer!=Teuchos::null)
290 else if(epetraContainer!=Teuchos::null)
291 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
297 template<
typename TRAITS,
typename LO,
typename GO>
304 using Teuchos::ptrFromRef;
305 using Teuchos::rcp_dynamic_cast;
308 using Thyra::SpmdVectorBase;
312 std::string blockId = this->wda(workset).block_id;
313 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
322 for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
323 int indexerId = indexerIds_[fieldIndex];
324 int subFieldNum = subFieldIds_[fieldIndex];
327 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
329 auto subRowIndexer = rowIndexers_[indexerId];
330 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
333 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
334 std::size_t cellLocalId = localCellIds[worksetCellIndex];
336 auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
339 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
340 int offset = elmtOffset[basis];
341 int lid = LIDs[offset];
342 local_r[lid] += (scatterFields_[fieldIndex])(worksetCellIndex,basis).val();
352 template<
typename TRAITS,
typename LO,
typename GO>
357 bool useDiscreteAdjoint)
358 : rowIndexers_(rIndexers)
359 , colIndexers_(cIndexers)
360 , globalDataKey_(
"Residual Scatter Container")
361 , useDiscreteAdjoint_(useDiscreteAdjoint)
363 std::string scatterName = p.
get<std::string>(
"Scatter Name");
368 const std::vector<std::string>& names =
378 scatterFields_.resize(names.size());
379 for (std::size_t eq = 0; eq < names.size(); ++eq) {
380 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
383 this->addDependentField(scatterFields_[eq]);
387 this->addEvaluatedField(*scatterHolder_);
389 if (p.
isType<std::string>(
"Global Data Key"))
390 globalDataKey_ = p.
get<std::string>(
"Global Data Key");
391 if (p.
isType<
bool>(
"Use Discrete Adjoint"))
392 useDiscreteAdjoint = p.
get<
bool>(
"Use Discrete Adjoint");
395 if(useDiscreteAdjoint)
398 if(colIndexers_.size()==0)
399 colIndexers_ = rowIndexers_;
401 this->setName(scatterName+
" Scatter Residual BlockedEpetra (Jacobian)");
405 template<
typename TRAITS,
typename LO,
typename GO>
410 indexerIds_.resize(scatterFields_.size());
411 subFieldIds_.resize(scatterFields_.size());
414 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
416 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
419 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
424 template<
typename TRAITS,
typename LO,
typename GO>
429 using Teuchos::rcp_dynamic_cast;
435 RCP<const BLOC> blockedContainer = rcp_dynamic_cast<
const BLOC>(d.gedc->getDataObject(globalDataKey_));
436 RCP<const ELOC> epetraContainer = rcp_dynamic_cast<
const ELOC>(d.gedc->getDataObject(globalDataKey_));
439 if(blockedContainer!=Teuchos::null) {
443 else if(epetraContainer!=Teuchos::null) {
445 if(epetraContainer->get_f_th()!=Teuchos::null)
446 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
457 template<
typename TRAITS,
typename LO,
typename GO>
463 using Teuchos::ptrFromRef;
464 using Teuchos::rcp_dynamic_cast;
467 using Thyra::SpmdVectorBase;
471 std::vector<double> jacRow;
474 std::string blockId = this->wda(workset).block_id;
475 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
477 int numFieldBlocks = Teuchos::as<int>(colIndexers_.size());
479 std::vector<int> blockOffsets;
486 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
487 int rowIndexer = indexerIds_[fieldIndex];
488 int subFieldNum = subFieldIds_[fieldIndex];
491 if(r_!=Teuchos::null)
492 rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))->getNonconstLocalData(ptrFromRef(local_r));
494 auto subRowIndexer = rowIndexers_[rowIndexer];
495 const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
498 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
499 std::size_t cellLocalId = localCellIds[worksetCellIndex];
501 auto rLIDs = subRowIndexer->getElementLIDs(cellLocalId);
504 for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) {
505 const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,rowBasisNum);
506 int rowOffset = elmtOffset[rowBasisNum];
507 int r_lid = rLIDs[rowOffset];
510 if(local_r!=Teuchos::null)
511 local_r[r_lid] += (scatterField.val());
514 jacRow.
resize(scatterField.size());
517 if(scatterField.size() == 0)
520 for(
int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
521 jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex);
524 for(
int colIndexer=0;colIndexer<numFieldBlocks;colIndexer++) {
525 int start = blockOffsets[colIndexer];
526 int end = blockOffsets[colIndexer+1];
531 auto subColIndexer = colIndexers_[colIndexer];
532 auto cLIDs = subColIndexer->getElementLIDs(cellLocalId);
537 std::pair<int,int> blockIndex = useDiscreteAdjoint_ ? std::make_pair(colIndexer,rowIndexer)
538 : std::make_pair(rowIndexer,colIndexer);
539 Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex];
542 if(subJac==Teuchos::null) {
551 jacEpetraBlocks[blockIndex] = subJac;
555 if(!useDiscreteAdjoint_) {
556 int err = subJac->
SumIntoMyValues(r_lid, end-start, &jacRow[start],&cLIDs[0]);
559 std::stringstream ss;
560 ss <<
"Failed inserting row: " <<
"LID = " << r_lid <<
"): ";
561 for(
int i=start;i<end;i++)
562 ss << cLIDs[i] <<
" ";
564 ss <<
"Into block " << rowIndexer <<
", " << colIndexer << std::endl;
566 ss <<
"scatter field = ";
567 scatterFields_[fieldIndex].print(ss);
574 for(std::size_t c=0;c<cLIDs.size();c++) {
575 int err = subJac->
SumIntoMyValues(cLIDs[c], 1, &jacRow[start+c],&r_lid);
ScatterResidual_BlockedEpetra(const Teuchos::ParameterList &p)
T & get(const std::string &name, T def_value)
bool is_null(const std::shared_ptr< T > &p)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void computeBlockOffsets(const std::string &blockId, const std::vector< Teuchos::RCP< GlobalIndexer >> &ugis, std::vector< int > &blockOffsets)
void evaluateFields(typename TRAITS::EvalData d)
void resize(const size_type n, const T &val=T())
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
int getFieldBlock(const std::string &fieldName, const std::vector< Teuchos::RCP< const GlobalIndexer >> &ugis)
int SumIntoMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
Pushes residual values into the residual vector for a Newton-based solve.
panzer::Traits::Jacobian::ScalarT ScalarT
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)