diff --git a/opm/simulators/wells/MultisegmentWell.hpp b/opm/simulators/wells/MultisegmentWell.hpp index e7138ff87..34f9ad54e 100644 --- a/opm/simulators/wells/MultisegmentWell.hpp +++ b/opm/simulators/wells/MultisegmentWell.hpp @@ -137,7 +137,7 @@ namespace Opm WellState& well_state, DeferredLogger& deferred_logger) const override; - virtual void addWellContributions(SparseMatrixAdapter& jacobian) const override; + void addWellContributions(SparseMatrixAdapter& jacobian) const override; virtual void addWellPressureEquations(PressureMatrix& mat, const BVector& x, diff --git a/opm/simulators/wells/MultisegmentWellEquations.cpp b/opm/simulators/wells/MultisegmentWellEquations.cpp index e5fde70b2..219a8a853 100644 --- a/opm/simulators/wells/MultisegmentWellEquations.cpp +++ b/opm/simulators/wells/MultisegmentWellEquations.cpp @@ -27,6 +27,9 @@ #include #include +#include +#include +#include #include #include @@ -248,8 +251,47 @@ extract(WellContributions& wellContribs) const Cvals); } + +template +template +void MultisegmentWellEquations:: +extract(SparseMatrixAdapter& jacobian) const +{ + const auto invDuneD = mswellhelpers::invertWithUMFPack(numWellEq, + numEq, + *duneDSolver_); + + // We need to change matrix A as follows + // A -= C^T D^-1 B + // D is a (nseg x nseg) block matrix with (4 x 4) blocks. + // B and C are (nseg x ncells) block matrices with (4 x 4 blocks). + // They have nonzeros at (i, j) only if this well has a + // perforation at cell j connected to segment i. The code + // assumes that no cell is connected to more than one segment, + // i.e. the columns of B/C have no more than one nonzero. + for (size_t rowC = 0; rowC < duneC_.N(); ++rowC) { + for (auto colC = duneC_[rowC].begin(), + endC = duneC_[rowC].end(); colC != endC; ++colC) { + const auto row_index = colC.index(); + for (size_t rowB = 0; rowB < duneB_.N(); ++rowB) { + for (auto colB = duneB_[rowB].begin(), + endB = duneB_[rowB].end(); colB != endB; ++colB) { + const auto col_index = colB.index(); + OffDiagMatrixBlockWellType tmp1; + detail::multMatrixImpl(invDuneD[rowC][rowB], (*colB), tmp1, std::true_type()); + typename SparseMatrixAdapter::MatrixBlock tmp2; + detail::multMatrixTransposedImpl((*colC), tmp1, tmp2, std::false_type()); + jacobian.addToBlock(row_index, col_index, tmp2); + } + } + } + } +} + #define INSTANCE(numWellEq, numEq) \ -template class MultisegmentWellEquations; +template class MultisegmentWellEquations; \ +template void MultisegmentWellEquations:: \ + extract(Linear::IstlSparseMatrixAdapter>&) const; INSTANCE(2,1) INSTANCE(2,2) diff --git a/opm/simulators/wells/MultisegmentWellEquations.hpp b/opm/simulators/wells/MultisegmentWellEquations.hpp index 059cc9541..42a04a59f 100644 --- a/opm/simulators/wells/MultisegmentWellEquations.hpp +++ b/opm/simulators/wells/MultisegmentWellEquations.hpp @@ -94,6 +94,10 @@ public: //! \brief Add the matrices of this well to the WellContributions object. void extract(WellContributions& wellContribs) const; + //! \brief Add the matrices of this well to the sparse matrix adapter. + template + void extract(SparseMatrixAdapter& jacobian) const; + // two off-diagonal matrices OffDiagMatWell duneB_; OffDiagMatWell duneC_; diff --git a/opm/simulators/wells/MultisegmentWell_impl.hpp b/opm/simulators/wells/MultisegmentWell_impl.hpp index efd798a95..158005862 100644 --- a/opm/simulators/wells/MultisegmentWell_impl.hpp +++ b/opm/simulators/wells/MultisegmentWell_impl.hpp @@ -19,8 +19,6 @@ */ -#include -#include #include #include #include @@ -722,35 +720,7 @@ namespace Opm MultisegmentWell:: addWellContributions(SparseMatrixAdapter& jacobian) const { - const auto invDuneD = mswellhelpers::invertWithUMFPack(numWellEq, - Indices::numEq, - *this->linSys_.duneDSolver_); - - // We need to change matrix A as follows - // A -= C^T D^-1 B - // D is a (nseg x nseg) block matrix with (4 x 4) blocks. - // B and C are (nseg x ncells) block matrices with (4 x 4 blocks). - // They have nonzeros at (i, j) only if this well has a - // perforation at cell j connected to segment i. The code - // assumes that no cell is connected to more than one segment, - // i.e. the columns of B/C have no more than one nonzero. - for (size_t rowC = 0; rowC < this->linSys_.duneC_.N(); ++rowC) { - for (auto colC = this->linSys_.duneC_[rowC].begin(), - endC = this->linSys_.duneC_[rowC].end(); colC != endC; ++colC) { - const auto row_index = colC.index(); - for (size_t rowB = 0; rowB < this->linSys_.duneB_.N(); ++rowB) { - for (auto colB = this->linSys_.duneB_[rowB].begin(), - endB = this->linSys_.duneB_[rowB].end(); colB != endB; ++colB) { - const auto col_index = colB.index(); - typename Equations::OffDiagMatrixBlockWellType tmp1; - detail::multMatrixImpl(invDuneD[rowC][rowB], (*colB), tmp1, std::true_type()); - typename SparseMatrixAdapter::MatrixBlock tmp2; - detail::multMatrixTransposedImpl((*colC), tmp1, tmp2, std::false_type()); - jacobian.addToBlock(row_index, col_index, tmp2); - } - } - } - } + this->linSys_.extract(jacobian); }