void panzer::ScatterDirichletResidual_Tpetra<panzer::Traits::Jacobian, TRAITS,LO,GO,NodeT>:: evaluateFields(typename TRAITS::EvalData workset) { std::vector<GO> GIDs; // for convenience pull out some objects from workset std::string blockId = workset.block_id; const std::vector<std::size_t> & localCellIds = workset.cell_local_ids; Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->get_f(); Teuchos::RCP<typename LOC::CrsMatrixType> Jac = tpetraContainer_->get_A(); Teuchos::ArrayRCP<double> r_array = r->get1dViewNonConst(); Teuchos::ArrayRCP<double> dc_array = dirichletCounter_->get1dViewNonConst(); // NOTE: A reordering of these loops will likely improve performance // The "getGIDFieldOffsets may be expensive. However the // "getElementGIDs" can be cheaper. However the lookup for LIDs // may be more expensive! // scatter operation for each cell in workset for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) { std::size_t cellLocalId = localCellIds[worksetCellIndex]; globalIndexer_->getElementGIDs(cellLocalId,GIDs); const std::vector<LO> & LIDs = globalIndexer_->getElementLIDs(cellLocalId); // loop over each field to be scattered for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { int fieldNum = fieldIds_[fieldIndex]; // this call "should" get the right ordering according to the Intrepid basis const std::pair<std::vector<int>,std::vector<int> > & indicePair = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_); const std::vector<int> & elmtOffset = indicePair.first; const std::vector<int> & basisIdMap = indicePair.second; // loop over basis functions for(std::size_t basis=0;basis<elmtOffset.size();basis++) { int offset = elmtOffset[basis]; LO lid = LIDs[offset]; if(lid<0) // not on this processor continue; int basisId = basisIdMap[basis]; if (checkApplyBC_) if (!applyBC_[fieldIndex](worksetCellIndex,basisId)) continue; // zero out matrix row { std::size_t sz = Jac->getNumEntriesInLocalRow(lid); std::size_t numEntries = 0; Teuchos::Array<LO> rowIndices(sz); Teuchos::Array<double> rowValues(sz); // Jac->getLocalRowView(lid,numEntries,rowValues,rowIndices); Jac->getLocalRowCopy(lid,rowIndices,rowValues,numEntries); for(std::size_t i=0;i<numEntries;i++) rowValues[i] = 0.0; Jac->replaceLocalValues(lid,rowIndices,rowValues); } GO gid = GIDs[offset]; const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,basisId); r_array[lid] = scatterField.val(); dc_array[lid] = 1.0; // mark row as dirichlet // loop over the sensitivity indices: all DOFs on a cell std::vector<double> jacRow(scatterField.size(),0.0); for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex) jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex); TEUCHOS_ASSERT(jacRow.size()==GIDs.size()); Jac->replaceGlobalValues(gid, GIDs, jacRow); } } } }
void panzer::ScatterDirichletResidual_Epetra<panzer::Traits::Jacobian, Traits,LO,GO>:: evaluateFields(typename Traits::EvalData workset) { std::vector<GO> GIDs; std::vector<int> LIDs; // for convenience pull out some objects from workset std::string blockId = workset.block_id; const std::vector<std::size_t> & localCellIds = workset.cell_local_ids; Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_; TEUCHOS_ASSERT(epetraContainer!=Teuchos::null); Teuchos::RCP<Epetra_Vector> r = epetraContainer->get_f(); Teuchos::RCP<Epetra_CrsMatrix> Jac = epetraContainer->get_A(); // NOTE: A reordering of these loops will likely improve performance // The "getGIDFieldOffsets may be expensive. However the // "getElementGIDs" can be cheaper. However the lookup for LIDs // may be more expensive! // scatter operation for each cell in workset for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) { std::size_t cellLocalId = localCellIds[worksetCellIndex]; globalIndexer_->getElementGIDs(cellLocalId,GIDs); if(r!=Teuchos::null) { // caculate the local IDs for this element LIDs.resize(GIDs.size()); for(std::size_t i=0;i<GIDs.size();i++) LIDs[i] = r->Map().LID(GIDs[i]); } else { // caculate the local IDs for this element LIDs.resize(GIDs.size()); for(std::size_t i=0;i<GIDs.size();i++) LIDs[i] = Jac->RowMap().LID(GIDs[i]); } // loop over each field to be scattered for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { int fieldNum = fieldIds_[fieldIndex]; // this call "should" get the right ordering accordint to the Intrepid basis const std::pair<std::vector<int>,std::vector<int> > & indicePair = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_); const std::vector<int> & elmtOffset = indicePair.first; const std::vector<int> & basisIdMap = indicePair.second; // loop over basis functions for(std::size_t basis=0;basis<elmtOffset.size();basis++) { int offset = elmtOffset[basis]; int lid = LIDs[offset]; if(lid<0) // not on this processor continue; // zero out matrix row { int numEntries = 0; int * rowIndices = 0; double * rowValues = 0; Jac->ExtractMyRowView(lid,numEntries,rowValues,rowIndices); for(int i=0;i<numEntries;i++) { if(preserveDiagonal_) { if(lid!=rowIndices[i]) rowValues[i] = 0.0; } else rowValues[i] = 0.0; } } int basisId = basisIdMap[basis]; int gid = GIDs[offset]; const ScalarT & scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,basisId); if(r!=Teuchos::null) (*r)[lid] = scatterField.val(); if(dirichletCounter_!=Teuchos::null) (*dirichletCounter_)[lid] = 1.0; // mark row as dirichlet // loop over the sensitivity indices: all DOFs on a cell std::vector<double> jacRow(scatterField.size(),0.0); if(!preserveDiagonal_) { // this is the default case for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex) jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex); TEUCHOS_ASSERT(jacRow.size()==GIDs.size()); int err = Jac->ReplaceGlobalValues(gid, scatterField.size(), &jacRow[0],&GIDs[0]); TEUCHOS_ASSERT(err==0); } } } } }