11 #ifndef PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
12 #define PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
15 #include "Teuchos_Assert.hpp"
17 #include "Phalanx_DataLayout.hpp"
19 #include "Epetra_Map.h"
20 #include "Epetra_Vector.h"
21 #include "Epetra_CrsMatrix.h"
31 #include "Thyra_SpmdVectorBase.hpp"
32 #include "Thyra_ProductVectorBase.hpp"
33 #include "Thyra_DefaultProductVector.hpp"
34 #include "Thyra_BlockedLinearOpBase.hpp"
35 #include "Thyra_DefaultBlockedLinearOp.hpp"
36 #include "Thyra_get_Epetra_Operator.hpp"
38 #include "Phalanx_DataLayout_MDALayout.hpp"
40 #include "Teuchos_FancyOStream.hpp"
46 template<
typename TRAITS,
typename LO,
typename GO>
52 : rowIndexers_(rIndexers)
53 , colIndexers_(cIndexers)
54 , globalDataKey_(
"Residual Scatter Container")
56 std::string scatterName = p.
get<std::string>(
"Scatter Name");
61 const std::vector<std::string>& names =
71 scatterFields_.resize(names.size());
72 for (std::size_t eq = 0; eq < names.size(); ++eq) {
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");
89 template<
typename TRAITS,
typename LO,
typename GO>
94 indexerIds_.resize(scatterFields_.size());
95 subFieldIds_.resize(scatterFields_.size());
98 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
100 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
103 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
108 template<
typename TRAITS,
typename LO,
typename GO>
116 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<
const BLOC>(d.gedc->getDataObject(globalDataKey_));
117 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<
const ELOC>(d.gedc->getDataObject(globalDataKey_));
120 if(blockedContainer!=Teuchos::null)
122 else if(epetraContainer!=Teuchos::null)
123 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
129 template<
typename TRAITS,
typename LO,
typename GO>
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;
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);
188 template<
typename TRAITS,
typename LO,
typename GO>
194 : rowIndexers_(rIndexers)
195 , colIndexers_(cIndexers)
196 , globalDataKey_(
"Residual Scatter Container")
198 std::string scatterName = p.
get<std::string>(
"Scatter Name");
203 const std::vector<std::string>& names =
213 scatterFields_.resize(names.size());
214 for (std::size_t eq = 0; eq < names.size(); ++eq) {
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");
231 template<
typename TRAITS,
typename LO,
typename GO>
236 indexerIds_.resize(scatterFields_.size());
237 subFieldIds_.resize(scatterFields_.size());
240 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
242 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
245 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
250 template<
typename TRAITS,
typename LO,
typename GO>
258 Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<
const BLOC>(d.gedc->getDataObject(globalDataKey_));
259 Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<
const ELOC>(d.gedc->getDataObject(globalDataKey_));
262 if(blockedContainer!=Teuchos::null)
264 else if(epetraContainer!=Teuchos::null)
265 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
271 template<
typename TRAITS,
typename LO,
typename GO>
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;
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();
326 template<
typename TRAITS,
typename LO,
typename GO>
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");
342 const std::vector<std::string>& names =
352 scatterFields_.resize(names.size());
353 for (std::size_t eq = 0; eq < names.size(); ++eq) {
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)
372 if(colIndexers_.size()==0)
373 colIndexers_ = rowIndexers_;
375 this->setName(scatterName+
" Scatter Residual BlockedEpetra (Jacobian)");
379 template<
typename TRAITS,
typename LO,
typename GO>
384 indexerIds_.resize(scatterFields_.size());
385 subFieldIds_.resize(scatterFields_.size());
388 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
390 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
393 subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
398 template<
typename TRAITS,
typename LO,
typename GO>
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) {
417 else if(epetraContainer!=Teuchos::null) {
419 if(epetraContainer->get_f_th()!=Teuchos::null)
420 r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
431 template<
typename TRAITS,
typename LO,
typename GO>
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;
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);
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) {
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);
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);
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)
virtual void preEvaluate(typename Traits::PreEvalData d)=0
panzer::Traits::Jacobian::ScalarT ScalarT
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we'll contribute, or in which we'll store, the result of computing this integral...
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)