void EquilibriumConcentrationBC<PHAL::AlbanyTraits::Tangent, Traits>:: evaluateFields(typename Traits::EvalData dirichletWorkset) { Teuchos::RCP<Tpetra_Vector> fT = dirichletWorkset.fT; Teuchos::RCP<Tpetra_MultiVector> fpT = dirichletWorkset.fpT; Teuchos::RCP<Tpetra_MultiVector> JVT = dirichletWorkset.JVT; Teuchos::RCP<const Tpetra_Vector> xT = dirichletWorkset.xT; Teuchos::RCP<const Tpetra_MultiVector> VxT = dirichletWorkset.VxT; Teuchos::ArrayRCP<const ST> VxT_constView; Teuchos::ArrayRCP<ST> fT_nonconstView; if (fT != Teuchos::null) fT_nonconstView = fT->get1dViewNonConst(); Teuchos::ArrayRCP<const ST> xT_constView = xT->get1dView(); const RealType j_coeff = dirichletWorkset.j_coeff; const std::vector<std::vector<int>>& nsNodes = dirichletWorkset.nodeSets->find(this->nodeSetID)->second; int cunk, punk; ScalarT Cval; ScalarT pressure; for (unsigned int inode = 0; inode < nsNodes.size(); inode++) { cunk = nsNodes[inode][this->coffset_]; punk = nsNodes[inode][this->poffset_]; pressure = xT_constView[punk]; this->computeBCs(pressure, Cval); if (fT != Teuchos::null) { fT_nonconstView[cunk] = xT_constView[cunk] - Cval.val(); } if (JVT != Teuchos::null) { Teuchos::ArrayRCP<ST> JVT_nonconstView; for (int i=0; i<dirichletWorkset.num_cols_x; i++) { JVT_nonconstView = JVT->getDataNonConst(i); VxT_constView = VxT->getData(i); JVT_nonconstView[cunk] = j_coeff*VxT_constView[cunk]; } } if (fpT != Teuchos::null) { Teuchos::ArrayRCP<ST> fpT_nonconstView; for (int i=0; i<dirichletWorkset.num_cols_p; i++) { fpT_nonconstView = fpT->getDataNonConst(i); fpT_nonconstView[cunk] = -Cval.dx(dirichletWorkset.param_offset+i); } } } }
void EquilibriumConcentrationBC<PHAL::AlbanyTraits::Jacobian, Traits>:: evaluateFields(typename Traits::EvalData dirichletWorkset) { Teuchos::RCP<Tpetra_Vector> fT = dirichletWorkset.fT; Teuchos::RCP<const Tpetra_Vector> xT = dirichletWorkset.xT; Teuchos::ArrayRCP<const ST> xT_constView = xT->get1dView(); Teuchos::RCP<Tpetra_CrsMatrix> jacT = dirichletWorkset.JacT; const RealType j_coeff = dirichletWorkset.j_coeff; const std::vector<std::vector<int>>& nsNodes = dirichletWorkset.nodeSets->find(this->nodeSetID)->second; bool fillResid = (fT != Teuchos::null); Teuchos::ArrayRCP<ST> fT_nonconstView; if (fillResid) fT_nonconstView = fT->get1dViewNonConst(); int cunk, punk; ScalarT Cval; ScalarT pressure; Teuchos::Array<LO> index(1); Teuchos::Array<ST> value(1); size_t numEntriesT; value[0] = j_coeff; Teuchos::Array<ST> matrixEntriesT; Teuchos::Array<LO> matrixIndicesT; for (unsigned int inode = 0; inode < nsNodes.size(); inode++) { cunk = nsNodes[inode][this->coffset_]; punk = nsNodes[inode][this->poffset_]; pressure = xT_constView[punk]; this->computeBCs(pressure, Cval); // replace jac values for the C dof numEntriesT = jacT->getNumEntriesInLocalRow(cunk); matrixEntriesT.resize(numEntriesT); matrixIndicesT.resize(numEntriesT); jacT->getLocalRowCopy(cunk, matrixIndicesT(), matrixEntriesT(), numEntriesT); for (int i=0; i<numEntriesT; i++) matrixEntriesT[i]=0; jacT->replaceLocalValues(cunk, matrixIndicesT(), matrixEntriesT()); index[0] = cunk; jacT->replaceLocalValues(cunk, index(), value()); if (fillResid) { fT_nonconstView[cunk] = xT_constView[cunk] - Cval.val(); } } }
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_BlockedTpetra<panzer::Traits::Jacobian, TRAITS,LO,GO,NodeT>:: evaluateFields(typename TRAITS::EvalData workset) { using Teuchos::RCP; using Teuchos::ArrayRCP; using Teuchos::ptrFromRef; using Teuchos::rcp_dynamic_cast; using Thyra::VectorBase; using Thyra::SpmdVectorBase; using Thyra::ProductVectorBase; using Thyra::BlockedLinearOpBase; std::vector<std::pair<int,GO> > GIDs; std::vector<LO> LIDs; // for convenience pull out some objects from workset std::string blockId = this->wda(workset).block_id; const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids; RCP<ProductVectorBase<double> > r = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_f()); Teuchos::RCP<BlockedLinearOpBase<double> > Jac = rcp_dynamic_cast<BlockedLinearOpBase<double> >(blockedContainer_->get_A()); int numFieldBlocks = globalIndexer_->getNumFieldBlocks(); std::vector<int> blockOffsets(numFieldBlocks+1); // number of fields, plus a sentinnel for(int blk=0; blk<numFieldBlocks; blk++) { int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk); blockOffsets[blk] = blockOffset; } std::unordered_map<std::pair<int,int>,Teuchos::RCP<CrsMatrixType>,panzer::pair_hash> jacTpetraBlocks; // 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); blockOffsets[numFieldBlocks] = GIDs.size(); // caculate the local IDs for this element LIDs.resize(GIDs.size()); for(std::size_t i=0; i<GIDs.size(); i++) { // used for doing local ID lookups RCP<const MapType> r_map = blockedContainer_->getMapForBlock(GIDs[i].first); LIDs[i] = r_map->getLocalElement(GIDs[i].second); } // loop over each field to be scattered Teuchos::ArrayRCP<double> local_r, local_dc; for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { int fieldNum = fieldIds_[fieldIndex]; int blockRowIndex = globalIndexer_->getFieldBlock(fieldNum); RCP<SpmdVectorBase<double> > dc = rcp_dynamic_cast<SpmdVectorBase<double> >(dirichletCounter_->getNonconstVectorBlock(blockRowIndex)); dc->getNonconstLocalData(ptrFromRef(local_dc)); // grab local data for inputing RCP<SpmdVectorBase<double> > block_r = rcp_dynamic_cast<SpmdVectorBase<double> >(r->getNonconstVectorBlock(blockRowIndex)); block_r->getNonconstLocalData(ptrFromRef(local_r)); // 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]; int 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 for(int blockColIndex=0; blockColIndex<numFieldBlocks; blockColIndex++) { int start = blockOffsets[blockColIndex]; int end = blockOffsets[blockColIndex+1]; if(end-start<=0) continue; // check hash table for jacobian sub block std::pair<int,int> blockIndex = std::make_pair(blockRowIndex,blockColIndex); Teuchos::RCP<CrsMatrixType> subJac = jacTpetraBlocks[blockIndex]; // if you didn't find one before, add it to the hash table if(subJac==Teuchos::null) { Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac->getNonconstBlock(blockIndex.first,blockIndex.second); // block operator is null, don't do anything (it is excluded) if(Teuchos::is_null(tOp)) continue; Teuchos::RCP<OperatorType> tpetra_Op = rcp_dynamic_cast<ThyraLinearOp>(tOp)->getTpetraOperator(); subJac = rcp_dynamic_cast<CrsMatrixType>(tpetra_Op,true); jacTpetraBlocks[blockIndex] = subJac; } std::size_t sz = subJac->getNumEntriesInLocalRow(lid); std::size_t numEntries = 0; Teuchos::Array<LO> rowIndices(sz); Teuchos::Array<double> rowValues(sz); subJac->getLocalRowCopy(lid,rowIndices,rowValues,numEntries); for(std::size_t i=0; i<numEntries; i++) rowValues[i] = 0.0; subJac->replaceLocalValues(lid,rowIndices,rowValues); } const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,basisId); local_r[lid] = scatterField.val(); local_dc[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()); for(int blockColIndex=0; blockColIndex<numFieldBlocks; blockColIndex++) { int start = blockOffsets[blockColIndex]; int end = blockOffsets[blockColIndex+1]; if(end-start<=0) continue; // check hash table for jacobian sub block std::pair<int,int> blockIndex = std::make_pair(blockRowIndex,blockColIndex); Teuchos::RCP<CrsMatrixType> subJac = jacTpetraBlocks[blockIndex]; // if you didn't find one before, add it to the hash table if(subJac==Teuchos::null) { Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac->getNonconstBlock(blockIndex.first,blockIndex.second); // block operator is null, don't do anything (it is excluded) if(Teuchos::is_null(tOp)) continue; Teuchos::RCP<OperatorType> tpetra_Op = rcp_dynamic_cast<ThyraLinearOp>(tOp)->getTpetraOperator(); subJac = rcp_dynamic_cast<CrsMatrixType>(tpetra_Op,true); jacTpetraBlocks[blockIndex] = subJac; } // Sum Jacobian subJac->replaceLocalValues(lid, Teuchos::arrayViewFromVector(LIDs).view(start,end-start), Teuchos::arrayViewFromVector(jacRow).view(start,end-start)); } } } } }
void panzer::ScatterResidual_BlockedEpetra<panzer::Traits::Jacobian, TRAITS,LO,GO>:: evaluateFields(typename TRAITS::EvalData workset) { using Teuchos::RCP; using Teuchos::ArrayRCP; using Teuchos::ptrFromRef; using Teuchos::rcp_dynamic_cast; using Thyra::VectorBase; using Thyra::SpmdVectorBase; using Thyra::ProductVectorBase; using Thyra::BlockedLinearOpBase; typedef BlockedEpetraLinearObjContainer BLOC; std::vector<std::pair<int,GO> > GIDs; std::vector<LO> LIDs; std::vector<double> jacRow; // for convenience pull out some objects from workset std::string blockId = this->wda(workset).block_id; const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids; RCP<const BLOC> blockedContainer = blockedContainer_; RCP<ProductVectorBase<double> > r = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer->get_f()); Teuchos::RCP<BlockedLinearOpBase<double> > Jac = rcp_dynamic_cast<BlockedLinearOpBase<double> >(blockedContainer->get_A()); int numFieldBlocks = globalIndexer_->getNumFieldBlocks(); std::vector<int> blockOffsets(numFieldBlocks+1); // number of fields, plus a sentinnel for(int blk=0;blk<numFieldBlocks;blk++) { int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk); blockOffsets[blk] = blockOffset; } std::unordered_map<std::pair<int,int>,Teuchos::RCP<Epetra_CrsMatrix>,panzer::pair_hash> jacEpetraBlocks; // 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,blockId); // caculate the local IDs for this element LIDs.resize(GIDs.size()); for(std::size_t i=0;i<GIDs.size();i++) { // used for doing local ID lookups RCP<const Epetra_Map> r_map = blockedContainer->getMapForBlock(GIDs[i].first); LIDs[i] = r_map->LID(GIDs[i].second); } // loop over each field to be scattered Teuchos::ArrayRCP<double> local_r; for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { int fieldNum = fieldIds_[fieldIndex]; int blockRowIndex = globalIndexer_->getFieldBlock(fieldNum); // grab local data for inputing if(r!=Teuchos::null) { RCP<SpmdVectorBase<double> > block_r = rcp_dynamic_cast<SpmdVectorBase<double> >(r->getNonconstVectorBlock(blockRowIndex)); block_r->getNonconstLocalData(ptrFromRef(local_r)); } const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum); // loop over the basis functions (currently they are nodes) for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) { const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,rowBasisNum); int rowOffset = elmtOffset[rowBasisNum]; int r_lid = LIDs[rowOffset]; // Sum residual if(local_r!=Teuchos::null) local_r[r_lid] += (scatterField.val()); blockOffsets[numFieldBlocks] = scatterField.size(); // add the sentinel // loop over the sensitivity indices: all DOFs on a cell jacRow.resize(scatterField.size()); // For Neumann conditions with no dependence on degrees of freedom, there should be no Jacobian contribution if(scatterField.size() == 0) continue; for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex) { jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex); } for(int blockColIndex=0;blockColIndex<numFieldBlocks;blockColIndex++) { int start = blockOffsets[blockColIndex]; int end = blockOffsets[blockColIndex+1]; if(end-start<=0) continue; // check hash table for jacobian sub block std::pair<int,int> blockIndex = std::make_pair(blockRowIndex,blockColIndex); Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex]; // if you didn't find one before, add it to the hash table if(subJac==Teuchos::null) { Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac->getNonconstBlock(blockIndex.first,blockIndex.second); // block operator is null, don't do anything (it is excluded) if(Teuchos::is_null(tOp)) continue; Teuchos::RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*tOp); subJac = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,true); jacEpetraBlocks[blockIndex] = subJac; } // Sum Jacobian int err = subJac->SumIntoMyValues(r_lid, end-start, &jacRow[start],&LIDs[start]); if(err!=0) { RCP<const Epetra_Map> rr = blockedContainer->getMapForBlock(GIDs[start].first); bool sameColMap = subJac->ColMap().SameAs(*rr); std::stringstream ss; ss << "Failed inserting row: " << GIDs[rowOffset].second << " (" << r_lid << "): "; for(int i=start;i<end;i++) ss << GIDs[i].second << " (" << LIDs[i] << ") "; ss << std::endl; ss << "Into block " << blockRowIndex << ", " << blockColIndex << std::endl; ss << "scatter field = "; scatterFields_[fieldIndex].print(ss); ss << std::endl; ss << "Same map = " << (sameColMap ? "true" : "false") << std::endl; TEUCHOS_TEST_FOR_EXCEPTION(err!=0,std::runtime_error,ss.str()); } } } // end rowBasisNum } // end fieldIndex } }
double QCAD::EvaluatorTools<PHAL::AlbanyTraits::Tangent, Traits>:: getDoubleValue(const ScalarT& t) const { return t.val(); }
void Response_Functional<panzer::Traits::Tangent>:: scatterResponse() { const int n = value.size(); const int num_deriv = this->numDeriv(); TEUCHOS_ASSERT(n == 0 || n == num_deriv); ScalarT glbValue = ScalarT(num_deriv, 0.0); // do global summation -- it is possible to do the reduceAll() on the Fad's directly, but it is somewhat // complicated for DFad (due to temporaries that might get created). Since this is just a sum, it is // easier to do the reduction for each value and derivative component. Teuchos::reduceAll(*this->getComm(), Teuchos::REDUCE_SUM, Thyra::Ordinal(1), &value.val(), &glbValue.val()); if (num_deriv > 0) Teuchos::reduceAll(*this->getComm(), Teuchos::REDUCE_SUM, Thyra::Ordinal(n), value.dx(), &glbValue.fastAccessDx(0)); value = glbValue; // copy data in vectors if(this->useEpetra()) { // use epetra Epetra_MultiVector& deriv = this->getEpetraMultiVector(); for (int i=0; i<num_deriv; ++i) deriv[i][0] = glbValue.dx(i); } else { // use thyra TEUCHOS_ASSERT(this->useThyra()); Thyra::ArrayRCP< Thyra::ArrayRCP<double> > deriv = this->getThyraMultiVector(); for (int i=0; i<num_deriv; ++i) deriv[i][0] = glbValue.dx(i); } }