27#ifndef OPM_TRIDIAGONAL_MATRIX_HH
28#define OPM_TRIDIAGONAL_MATRIX_HH
49template <
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); }
104 mutable size_t rowIdx_;
135 {
return diag_[0].size(); }
157 for (
int diagIdx = 0; diagIdx < 3; ++ diagIdx)
164 Scalar&
at(
size_t rowIdx,
size_t colIdx)
170 if (rowIdx == 0 && colIdx == n - 1)
172 if (rowIdx == n - 1 && colIdx == 0)
173 return diag_[0][n - 1];
176 size_t diagIdx = 1 + colIdx - rowIdx;
179 return diag_[diagIdx][colIdx];
185 Scalar
at(
size_t rowIdx,
size_t colIdx)
const
190 if (rowIdx == 0 && colIdx == n - 1)
192 if (rowIdx == n - 1 && colIdx == 0)
193 return diag_[0][n - 1];
195 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)
218 diag_[diagIdx].assign(
size(), value);
227 {
return TridiagRow_(*
this, 0); }
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) {
713 template <
class XVector,
class BVector>
714 void solve(XVector& x,
const BVector& b)
const
717 solveWithUpperRight_(x, b);
719 solveWithoutUpperRight_(x, b);
725 void print(std::ostream& os = std::cout)
const
730 os <<
at(0, 0) <<
"\t"
740 for (
unsigned rowIdx = 1; rowIdx < n-1; ++rowIdx) {
746 os <<
at(rowIdx, rowIdx - 1) <<
"\t"
747 <<
at(rowIdx, rowIdx) <<
"\t"
748 <<
at(rowIdx, rowIdx + 1) <<
"\n";
753 os <<
at(n-1, 0) <<
"\t";
758 os <<
at(n-1, n-2) <<
"\t"
759 <<
at(n-1, n-1) <<
"\n";
763 template <
class XVector,
class BVector>
764 void solveWithUpperRight_(XVector& x,
const BVector& b)
const
768 std::vector<Scalar> lowerDiag(diag_[0]), mainDiag(diag_[1]), upperDiag(diag_[2]), lastColumn(n);
769 std::vector<Scalar> bStar(n);
770 std::copy(b.begin(), b.end(), bStar.begin());
772 lastColumn[0] = upperDiag[0];
775 for (
size_t i = 1; i < n; ++i) {
776 Scalar alpha = lowerDiag[i - 1]/mainDiag[i - 1];
778 lowerDiag[i - 1] -= alpha * mainDiag[i - 1];
779 mainDiag[i] -= alpha * upperDiag[i];
781 bStar[i] -= alpha * bStar[i - 1];
785 if (lowerDiag[n - 1] != 0.0 &&
size() > 2) {
786 Scalar lastRow = lowerDiag[n - 1];
787 for (
size_t i = 0; i < n - 1; ++i) {
788 Scalar alpha = lastRow/mainDiag[i];
789 lastRow = - alpha*upperDiag[i + 1];
790 bStar[n - 1] -= alpha * bStar[i];
793 mainDiag[n-1] += lastRow;
797 x[n - 1] = bStar[n - 1]/mainDiag[n-1];
798 for (
int i =
static_cast<int>(n) - 2; i >= 0; --i) {
799 unsigned iu =
static_cast<unsigned>(i);
800 x[iu] = (bStar[iu] - x[iu + 1]*upperDiag[iu+1] - x[n-1]*lastColumn[iu])/mainDiag[iu];
804 template <
class XVector,
class BVector>
805 void solveWithoutUpperRight_(XVector& x,
const BVector& b)
const
809 std::vector<Scalar> lowerDiag(diag_[0]), mainDiag(diag_[1]), upperDiag(diag_[2]);
810 std::vector<Scalar> bStar(n);
811 std::copy(b.begin(), b.end(), bStar.begin());
814 for (
size_t i = 1; i < n; ++i) {
815 Scalar alpha = lowerDiag[i - 1]/mainDiag[i - 1];
817 lowerDiag[i - 1] -= alpha * mainDiag[i - 1];
818 mainDiag[i] -= alpha * upperDiag[i];
820 bStar[i] -= alpha * bStar[i - 1];
824 if (lowerDiag[n - 1] != 0.0 &&
size() > 2) {
825 Scalar lastRow = lowerDiag[n - 1];
826 for (
size_t i = 0; i < n - 1; ++i) {
827 Scalar alpha = lastRow/mainDiag[i];
828 lastRow = - alpha*upperDiag[i + 1];
829 bStar[n - 1] -= alpha * bStar[i];
832 mainDiag[n-1] += lastRow;
836 x[n - 1] = bStar[n - 1]/mainDiag[n-1];
837 for (
int i =
static_cast<int>(n) - 2; i >= 0; --i) {
838 unsigned iu =
static_cast<unsigned>(i);
839 x[iu] = (bStar[iu] - x[iu + 1]*upperDiag[iu+1])/mainDiag[iu];
843 mutable std::vector<Scalar> diag_[3];
848template <
class Scalar>
std::ostream & operator<<(std::ostream &os, const Opm::TridiagonalMatrix< Scalar > &mat)
Definition: TridiagonalMatrix.hpp:849
Provides a tridiagonal matrix that also supports non-zero entries in the upper right and lower left.
Definition: TridiagonalMatrix.hpp:51
const_iterator end() const
Definition: TridiagonalMatrix.hpp:238
TridiagonalMatrix(size_t numRows, Scalar value)
Definition: TridiagonalMatrix.hpp:119
TridiagonalMatrix(const TridiagonalMatrix &source)
Copy constructor.
Definition: TridiagonalMatrix.hpp:128
TridiagRow_ operator[](size_t rowIdx)
Row access operator.
Definition: TridiagonalMatrix.hpp:244
size_t cols() const
Return the number of columns of the matrix.
Definition: TridiagonalMatrix.hpp:146
size_t rows() const
Return the number of rows of the matrix.
Definition: TridiagonalMatrix.hpp:140
Scalar frobeniusNormSquared() const
Calculate the squared frobenius norm.
Definition: TridiagonalMatrix.hpp:662
TridiagonalMatrix & operator/=(Scalar alpha)
Division by a Scalar.
Definition: TridiagonalMatrix.hpp:271
size_t SizeType
Definition: TridiagonalMatrix.hpp:110
TridiagonalMatrix & operator=(Scalar value)
Assignment operator from a Scalar.
Definition: TridiagonalMatrix.hpp:215
void umtv(const Vector &source, Vector &dest) const
Transposed additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:538
const_iterator begin() const
Definition: TridiagonalMatrix.hpp:232
TridiagRow_ iterator
Definition: TridiagonalMatrix.hpp:111
TridiagRow_ RowType
Definition: TridiagonalMatrix.hpp:109
iterator begin()
Definition: TridiagonalMatrix.hpp:226
void print(std::ostream &os=std::cout) const
Print the matrix to a given output stream.
Definition: TridiagonalMatrix.hpp:725
void usmtv(Scalar alpha, const Vector &source, Vector &dest) const
Transposed scaled additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:618
TridiagonalMatrix & operator+=(const TridiagonalMatrix &other)
Addition operator.
Definition: TridiagonalMatrix.hpp:293
TridiagRow_ const_iterator
Definition: TridiagonalMatrix.hpp:112
void mv(const Vector &source, Vector &dest) const
Matrix-vector product.
Definition: TridiagonalMatrix.hpp:335
Scalar infinityNorm() const
Calculate the infinity norm.
Definition: TridiagonalMatrix.hpp:679
Scalar at(size_t rowIdx, size_t colIdx) const
Access an entry.
Definition: TridiagonalMatrix.hpp:185
const TridiagRow_ operator[](size_t rowIdx) const
Row access operator.
Definition: TridiagonalMatrix.hpp:250
void mmv(const Vector &source, Vector &dest) const
Subtractive matrix-vector product.
Definition: TridiagonalMatrix.hpp:415
void usmv(Scalar alpha, const Vector &source, Vector &dest) const
Scaled additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:455
void mmtv(const Vector &source, Vector &dest) const
Transposed subtractive matrix-vector product.
Definition: TridiagonalMatrix.hpp:578
TridiagonalMatrix & operator-=(const TridiagonalMatrix &other)
Subtraction operator.
Definition: TridiagonalMatrix.hpp:287
size_t size() const
Return the number of rows/columns of the matrix.
Definition: TridiagonalMatrix.hpp:134
TridiagonalMatrix & axpy(Scalar alpha, const TridiagonalMatrix &other)
Multiply and add the matrix entries of another tridiagonal matrix.
Definition: TridiagonalMatrix.hpp:310
TridiagonalMatrix & operator=(const TridiagonalMatrix &source)
Assignment operator from another tridiagonal matrix.
Definition: TridiagonalMatrix.hpp:204
void solve(XVector &x, const BVector &b) const
Calculate the solution for a linear system of equations.
Definition: TridiagonalMatrix.hpp:714
void resize(size_t n)
Change the number of rows of the matrix.
Definition: TridiagonalMatrix.hpp:152
void mtv(const Vector &source, Vector &dest) const
Transposed matrix-vector product.
Definition: TridiagonalMatrix.hpp:498
Scalar frobeniusNorm() const
Calculate the frobenius norm.
Definition: TridiagonalMatrix.hpp:654
TridiagonalMatrix(size_t numRows=0)
Definition: TridiagonalMatrix.hpp:114
void umv(const Vector &source, Vector &dest) const
Additive matrix-vector product.
Definition: TridiagonalMatrix.hpp:375
Scalar FieldType
Definition: TridiagonalMatrix.hpp:108
Scalar & at(size_t rowIdx, size_t colIdx)
Access an entry.
Definition: TridiagonalMatrix.hpp:164
TridiagonalMatrix & operator*=(Scalar alpha)
Multiplication with a Scalar.
Definition: TridiagonalMatrix.hpp:256
bool operator!=(const RhsValueType &a, const Evaluation< ValueType, numVars, staticSize > &b)
Definition: Evaluation.hpp:574
Evaluation< ValueType, numVars, staticSize > operator*(const RhsValueType &a, const Evaluation< ValueType, numVars, staticSize > &b)
Definition: Evaluation.hpp:600
Definition: Air_Mesitylene.hpp:34
Evaluation sqrt(const Evaluation &value)
Definition: MathToolbox.hpp:399
ReturnEval_< Evaluation1, Evaluation2 >::type max(const Evaluation1 &arg1, const Evaluation2 &arg2)
Definition: MathToolbox.hpp:341
Evaluation abs(const Evaluation &value)
Definition: MathToolbox.hpp:350