27 #ifndef OPM_TRIDIAGONAL_MATRIX_HH 28 #define OPM_TRIDIAGONAL_MATRIX_HH 49 template <
class Scalar>
59 {
return matrix_.at(rowIdx_, colIdx); }
62 {
return matrix_.at(rowIdx_, colIdx); }
67 TridiagRow_& operator++()
68 { ++ rowIdx_;
return *
this; }
73 TridiagRow_& operator--()
74 { -- rowIdx_;
return *
this; }
79 bool operator==(
const TridiagRow_& other)
const 80 {
return other.rowIdx_ == rowIdx_ && &other.matrix_ == &matrix_; }
85 bool operator!=(
const TridiagRow_& other)
const 86 {
return !operator==(other); }
91 TridiagRow_& operator*()
99 std::size_t index()
const 104 mutable std::size_t rowIdx_;
108 typedef Scalar FieldType;
109 typedef TridiagRow_ RowType;
110 typedef std::size_t SizeType;
111 typedef TridiagRow_ iterator;
112 typedef TridiagRow_ const_iterator;
135 {
return diag_[0].size(); }
157 for (
int diagIdx = 0; diagIdx < 3; ++ diagIdx)
164 Scalar&
at(std::size_t rowIdx, std::size_t colIdx)
166 std::size_t n =
size();
170 if (rowIdx == 0 && colIdx == n - 1)
172 if (rowIdx == n - 1 && colIdx == 0)
173 return diag_[0][n - 1];
176 std::size_t diagIdx = 1 + colIdx - rowIdx;
179 return diag_[diagIdx][colIdx];
185 Scalar
at(std::size_t rowIdx, std::size_t colIdx)
const 187 std::size_t n =
size();
190 if (rowIdx == 0 && colIdx == n - 1)
192 if (rowIdx == n - 1 && colIdx == 0)
193 return diag_[0][n - 1];
195 std::size_t diagIdx = 1 + colIdx - rowIdx;
198 return diag_[diagIdx][colIdx];
206 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx)
207 diag_[diagIdx] = source.diag_[diagIdx];
217 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx)
227 {
return TridiagRow_(*
this, 0); }
233 {
return TridiagRow_(const_cast<TridiagonalMatrix&>(*
this), 0); }
238 const_iterator
end()
const 239 {
return TridiagRow_(const_cast<TridiagonalMatrix&>(*
this),
size()); }
245 {
return TridiagRow_(*
this, rowIdx); }
251 {
return TridiagRow_(*
this, rowIdx); }
259 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx) {
260 for (
unsigned i = 0; i < n; ++i) {
261 diag_[diagIdx][i] *= alpha;
275 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx) {
276 for (
unsigned i = 0; i < n; ++i) {
277 diag_[diagIdx][i] *= alpha;
288 {
return axpy(-1.0, other); }
294 {
return axpy(1.0, other); }
315 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx)
316 for (
unsigned i = 0; i < n; ++ i)
317 diag_[diagIdx][i] += alpha * other[diagIdx][i];
334 template<
class Vector>
335 void mv(
const Vector& source, Vector& dest)
const 337 assert(source.size() ==
size());
338 assert(dest.size() ==
size());
343 for (
unsigned i = 1; i < n - 1; ++ i) {
345 diag_[0][i - 1]*source[i-1] +
346 diag_[1][i]*source[i] +
347 diag_[2][i + 1]*source[i + 1];
352 diag_[1][0]*source[0] +
353 diag_[2][1]*source[1] +
354 diag_[2][0]*source[n - 1];
357 diag_[0][n-1]*source[0] +
358 diag_[0][n-2]*source[n-2] +
359 diag_[1][n-1]*source[n-1];
374 template<
class Vector>
375 void umv(
const Vector& source, Vector& dest)
const 377 assert(source.size() ==
size());
378 assert(dest.size() ==
size());
383 for (
unsigned i = 1; i < n - 1; ++ i) {
385 diag_[0][i - 1]*source[i-1] +
386 diag_[1][i]*source[i] +
387 diag_[2][i + 1]*source[i + 1];
392 diag_[1][0]*source[0] +
393 diag_[2][1]*source[1] +
394 diag_[2][0]*source[n - 1];
397 diag_[0][n-1]*source[0] +
398 diag_[0][n-2]*source[n-2] +
399 diag_[1][n-1]*source[n-1];
414 template<
class Vector>
415 void mmv(
const Vector& source, Vector& dest)
const 417 assert(source.size() ==
size());
418 assert(dest.size() ==
size());
423 for (
unsigned i = 1; i < n - 1; ++ i) {
425 diag_[0][i - 1]*source[i-1] +
426 diag_[1][i]*source[i] +
427 diag_[2][i + 1]*source[i + 1];
432 diag_[1][0]*source[0] +
433 diag_[2][1]*source[1] +
434 diag_[2][0]*source[n - 1];
437 diag_[0][n-1]*source[0] +
438 diag_[0][n-2]*source[n-2] +
439 diag_[1][n-1]*source[n-1];
454 template<
class Vector>
455 void usmv(Scalar alpha,
const Vector& source, Vector& dest)
const 457 assert(source.size() ==
size());
458 assert(dest.size() ==
size());
463 for (
unsigned i = 1; i < n - 1; ++ i) {
466 diag_[0][i - 1]*source[i-1] +
467 diag_[1][i]*source[i] +
468 diag_[2][i + 1]*source[i + 1]);
474 diag_[1][0]*source[0] +
475 diag_[2][1]*source[1] +
476 diag_[2][0]*source[n - 1]);
480 diag_[0][n-1]*source[0] +
481 diag_[0][n-2]*source[n-2] +
482 diag_[1][n-1]*source[n-1]);
497 template<
class Vector>
498 void mtv(
const Vector& source, Vector& dest)
const 500 assert(source.size() ==
size());
501 assert(dest.size() ==
size());
506 for (
unsigned i = 1; i < n - 1; ++ i) {
508 diag_[2][i + 1]*source[i-1] +
509 diag_[1][i]*source[i] +
510 diag_[0][i - 1]*source[i + 1];
515 diag_[1][0]*source[0] +
516 diag_[0][1]*source[1] +
517 diag_[0][n-1]*source[n - 1];
520 diag_[2][0]*source[0] +
521 diag_[2][n-1]*source[n-2] +
522 diag_[1][n-1]*source[n-1];
537 template<
class Vector>
538 void umtv(
const Vector& source, Vector& dest)
const 540 assert(source.size() ==
size());
541 assert(dest.size() ==
size());
546 for (
unsigned i = 1; i < n - 1; ++ i) {
548 diag_[2][i + 1]*source[i-1] +
549 diag_[1][i]*source[i] +
550 diag_[0][i - 1]*source[i + 1];
555 diag_[1][0]*source[0] +
556 diag_[0][1]*source[1] +
557 diag_[0][n-1]*source[n - 1];
560 diag_[2][0]*source[0] +
561 diag_[2][n-1]*source[n-2] +
562 diag_[1][n-1]*source[n-1];
577 template<
class Vector>
578 void mmtv (
const Vector& source, Vector& dest)
const 580 assert(source.size() ==
size());
581 assert(dest.size() ==
size());
586 for (
unsigned i = 1; i < n - 1; ++ i) {
588 diag_[2][i + 1]*source[i-1] +
589 diag_[1][i]*source[i] +
590 diag_[0][i - 1]*source[i + 1];
595 diag_[1][0]*source[0] +
596 diag_[0][1]*source[1] +
597 diag_[0][n-1]*source[n - 1];
600 diag_[2][0]*source[0] +
601 diag_[2][n-1]*source[n-2] +
602 diag_[1][n-1]*source[n-1];
617 template<
class Vector>
618 void usmtv(Scalar alpha,
const Vector& source, Vector& dest)
const 620 assert(source.size() ==
size());
621 assert(dest.size() ==
size());
626 for (
unsigned i = 1; i < n - 1; ++ i) {
629 diag_[2][i + 1]*source[i-1] +
630 diag_[1][i]*source[i] +
631 diag_[0][i - 1]*source[i + 1]);
637 diag_[1][0]*source[0] +
638 diag_[0][1]*source[1] +
639 diag_[0][n-1]*source[n - 1]);
643 diag_[2][0]*source[0] +
644 diag_[2][n-1]*source[n-2] +
645 diag_[1][n-1]*source[n-1]);
667 for (
unsigned i = 0; i < n; ++ i)
668 for (
unsigned diagIdx = 0; diagIdx < 3; ++ diagIdx)
669 result += diag_[diagIdx][i];
685 for (
unsigned i = 1; i < n - 1; ++ i) {
686 result = std::max(result,
687 std::abs(diag_[0][i - 1]) +
688 std::abs(diag_[1][i]) +
689 std::abs(diag_[2][i + 1]));
693 result = std::max(result,
694 std::abs(diag_[1][0]) +
695 std::abs(diag_[2][1]) +
696 std::abs(diag_[2][0]));
699 result = std::max(result,
700 std::abs(diag_[0][n-1]) +
701 std::abs(diag_[0][n-2]) +
702 std::abs(diag_[1][n-2]));
713 template <
class XVector,
class BVector>
714 void solve(XVector& x,
const BVector& b)
const 716 if (
size() > 2 && std::abs(diag_[2][0]) < 1e-30)
717 solveWithUpperRight_(x, b);
719 solveWithoutUpperRight_(x, b);
725 void print(std::ostream& os)
const;
728 template <
class XVector,
class BVector>
729 void solveWithUpperRight_(XVector& x,
const BVector& b)
const 731 std::size_t n =
size();
733 std::vector<Scalar> lowerDiag(diag_[0]), mainDiag(diag_[1]), upperDiag(diag_[2]), lastColumn(n);
734 std::vector<Scalar> bStar(n);
735 std::ranges::copy(b, bStar.begin());
737 lastColumn[0] = upperDiag[0];
740 for (std::size_t i = 1; i < n; ++i) {
741 Scalar alpha = lowerDiag[i - 1]/mainDiag[i - 1];
743 lowerDiag[i - 1] -= alpha * mainDiag[i - 1];
744 mainDiag[i] -= alpha * upperDiag[i];
746 bStar[i] -= alpha * bStar[i - 1];
750 if (lowerDiag[n - 1] != 0.0 &&
size() > 2) {
751 Scalar lastRow = lowerDiag[n - 1];
752 for (std::size_t i = 0; i < n - 1; ++i) {
753 Scalar alpha = lastRow/mainDiag[i];
754 lastRow = - alpha*upperDiag[i + 1];
755 bStar[n - 1] -= alpha * bStar[i];
758 mainDiag[n-1] += lastRow;
762 x[n - 1] = bStar[n - 1]/mainDiag[n-1];
763 for (
int i = static_cast<int>(n) - 2; i >= 0; --i) {
764 unsigned iu =
static_cast<unsigned>(i);
765 x[iu] = (bStar[iu] - x[iu + 1]*upperDiag[iu+1] - x[n-1]*lastColumn[iu])/mainDiag[iu];
769 template <
class XVector,
class BVector>
770 void solveWithoutUpperRight_(XVector& x,
const BVector& b)
const 772 std::size_t n =
size();
774 std::vector<Scalar> lowerDiag(diag_[0]), mainDiag(diag_[1]), upperDiag(diag_[2]);
775 std::vector<Scalar> bStar(n);
776 std::ranges::copy(b, bStar.begin());
779 for (std::size_t i = 1; i < n; ++i) {
780 Scalar alpha = lowerDiag[i - 1]/mainDiag[i - 1];
782 lowerDiag[i - 1] -= alpha * mainDiag[i - 1];
783 mainDiag[i] -= alpha * upperDiag[i];
785 bStar[i] -= alpha * bStar[i - 1];
789 if (lowerDiag[n - 1] != 0.0 &&
size() > 2) {
790 Scalar lastRow = lowerDiag[n - 1];
791 for (std::size_t i = 0; i < n - 1; ++i) {
792 Scalar alpha = lastRow/mainDiag[i];
793 lastRow = - alpha*upperDiag[i + 1];
794 bStar[n - 1] -= alpha * bStar[i];
797 mainDiag[n-1] += lastRow;
801 x[n - 1] = bStar[n - 1]/mainDiag[n-1];
802 for (
int i = static_cast<int>(n) - 2; i >= 0; --i) {
803 unsigned iu =
static_cast<unsigned>(i);
804 x[iu] = (bStar[iu] - x[iu + 1]*upperDiag[iu+1])/mainDiag[iu];
808 mutable std::vector<Scalar> diag_[3];
813 template <
class Scalar>
814 std::ostream& operator<<(std::ostream& os, const Opm::TridiagonalMatrix<Scalar>& mat)
void mv(const Vector &source, Vector &dest) const
Matrix-vector product.
Definition: TridiagonalMatrix.hpp:335
void print(std::ostream &os) const
Print the matrix to a given output stream.
Definition: TridiagonalMatrix.cpp:34
TridiagonalMatrix & axpy(Scalar alpha, const TridiagonalMatrix &other)
Multiply and add the matrix entries of another tridiagonal matrix.
Definition: TridiagonalMatrix.hpp:310
Scalar infinityNorm() const
Calculate the infinity norm.
Definition: TridiagonalMatrix.hpp:679
const_iterator end() const
Const iterator for the next-to-last row
Definition: TridiagonalMatrix.hpp:238
void solve(XVector &x, const BVector &b) const
Calculate the solution for a linear system of equations.
Definition: TridiagonalMatrix.hpp:714
Scalar frobeniusNormSquared() const
Calculate the squared frobenius norm.
Definition: TridiagonalMatrix.hpp:662
TridiagonalMatrix & operator=(const TridiagonalMatrix &source)
Assignment operator from another tridiagonal matrix.
Definition: TridiagonalMatrix.hpp:204
Scalar & at(std::size_t rowIdx, std::size_t colIdx)
Access an entry.
Definition: TridiagonalMatrix.hpp:164
void usmv(Scalar alpha, const Vector &source, Vector &dest) const
Scaled additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:455
TridiagonalMatrix & operator+=(const TridiagonalMatrix &other)
Addition operator.
Definition: TridiagonalMatrix.hpp:293
std::size_t rows() const
Return the number of rows of the matrix.
Definition: TridiagonalMatrix.hpp:140
TridiagonalMatrix & operator/=(Scalar alpha)
Division by a Scalar.
Definition: TridiagonalMatrix.hpp:271
TridiagonalMatrix(const TridiagonalMatrix &source)
Copy constructor.
Definition: TridiagonalMatrix.hpp:128
void mmv(const Vector &source, Vector &dest) const
Subtractive matrix-vector product.
Definition: TridiagonalMatrix.hpp:415
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
void usmtv(Scalar alpha, const Vector &source, Vector &dest) const
Transposed scaled additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:618
std::size_t cols() const
Return the number of columns of the matrix.
Definition: TridiagonalMatrix.hpp:146
iterator begin()
Iterator for the first row
Definition: TridiagonalMatrix.hpp:226
const_iterator begin() const
Const iterator for the first row
Definition: TridiagonalMatrix.hpp:232
std::size_t size() const
Return the number of rows/columns of the matrix.
Definition: TridiagonalMatrix.hpp:134
void mmtv(const Vector &source, Vector &dest) const
Transposed subtractive matrix-vector product.
Definition: TridiagonalMatrix.hpp:578
TridiagRow_ operator[](std::size_t rowIdx)
Row access operator.
Definition: TridiagonalMatrix.hpp:244
const TridiagRow_ operator[](std::size_t rowIdx) const
Row access operator.
Definition: TridiagonalMatrix.hpp:250
Scalar frobeniusNorm() const
Calculate the frobenius norm.
Definition: TridiagonalMatrix.hpp:654
void umv(const Vector &source, Vector &dest) const
Additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:375
Provides a tridiagonal matrix that also supports non-zero entries in the upper right and lower left...
Definition: TridiagonalMatrix.hpp:50
TridiagonalMatrix & operator=(Scalar value)
Assignment operator from a Scalar.
Definition: TridiagonalMatrix.hpp:215
Scalar at(std::size_t rowIdx, std::size_t colIdx) const
Access an entry.
Definition: TridiagonalMatrix.hpp:185
void resize(std::size_t n)
Change the number of rows of the matrix.
Definition: TridiagonalMatrix.hpp:152
TridiagonalMatrix & operator-=(const TridiagonalMatrix &other)
Subtraction operator.
Definition: TridiagonalMatrix.hpp:287
TridiagonalMatrix & operator*=(Scalar alpha)
Multiplication with a Scalar.
Definition: TridiagonalMatrix.hpp:256
void umtv(const Vector &source, Vector &dest) const
Transposed additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:538
void mtv(const Vector &source, Vector &dest) const
Transposed matrix-vector product.
Definition: TridiagonalMatrix.hpp:498
bool operator!=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Inequality operator for SummaryConfigNode objects.
Definition: SummaryConfig.hpp:278