diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.C b/src/OpenFOAM/matrices/Matrix/Matrix.C index 6ccd1c79e5..808e00b86c 100644 --- a/src/OpenFOAM/matrices/Matrix/Matrix.C +++ b/src/OpenFOAM/matrices/Matrix/Matrix.C @@ -37,19 +37,7 @@ void Foam::Matrix::allocate() } -// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * // - -template -Foam::Matrix::~Matrix() -{ - if (v_) - { - delete[] v_; - } -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template Foam::Matrix::Matrix(const label m, const label n) @@ -69,6 +57,33 @@ Foam::Matrix::Matrix(const label m, const label n) } +template +Foam::Matrix::Matrix(const label m, const label n, const zero) +: + nRows_(m), + nCols_(n), + v_(NULL) +{ + if (nRows_ < 0 || nCols_ < 0) + { + FatalErrorInFunction + << "Bad m, n " << nRows_ << ", " << nCols_ + << abort(FatalError); + } + + allocate(); + + if (v_) + { + const label mn = size(); + for (label i=0; i Foam::Matrix::Matrix(const label m, const label n, const Type& a) : @@ -79,7 +94,7 @@ Foam::Matrix::Matrix(const label m, const label n, const Type& a) if (nRows_ < 0 || nCols_ < 0) { FatalErrorInFunction - << "bad m, n " << nRows_ << ", " << nCols_ + << "Bad m, n " << nRows_ << ", " << nCols_ << abort(FatalError); } @@ -96,6 +111,24 @@ Foam::Matrix::Matrix(const label m, const label n, const Type& a) } +template +inline Foam::Matrix::Matrix(const mType::Block& block) +: + nRows_(block.m()), + nCols_(block.n()) +{ + allocate(); + + for (label i=0; i Foam::Matrix::Matrix(const Matrix& a) : @@ -116,6 +149,20 @@ Foam::Matrix::Matrix(const Matrix& a) } +// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * // + +template +Foam::Matrix::~Matrix() +{ + if (v_) + { + delete[] v_; + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template void Foam::Matrix::clear() { @@ -146,6 +193,26 @@ void Foam::Matrix::transfer(Matrix& a) } +template +void Foam::Matrix::setSize(const label m, const label n) +{ + mType newMatrix(m, n, Zero); + + label minM = min(m, nRows_); + label minN = min(n, nCols_); + + for (label i=0; i Form Foam::Matrix::T() const { @@ -164,29 +231,57 @@ Form Foam::Matrix::T() const } -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - template -void Foam::Matrix::operator=(const Type& t) +Foam::Matrix::ConstBlock::operator Field() const { - if (v_) + if (nCols_ != 1) { - const label mn = size(); - for (label i=0; i f(nRows_); + + forAll(f, i) + { + f[i] = operator()(i, 0); + } + + return f; } +template +Foam::Matrix::Block::operator Field() const +{ + if (nCols_ != 1) + { + FatalErrorInFunction + << "Number of columns " << nCols_ << " != 1" + << abort(FatalError); + } + + Field f(nRows_); + + forAll(f, i) + { + f[i] = operator()(i, 0); + } + + return f; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + template void Foam::Matrix::operator=(const Matrix& a) { if (this == &a) { FatalErrorInFunction - << "attempted assignment to self" + << "Attempted assignment to self" << abort(FatalError); } @@ -209,6 +304,247 @@ void Foam::Matrix::operator=(const Matrix& a) } +template +void Foam::Matrix::operator=(const mType::Block& block) +{ + for (label i=0; i +void Foam::Matrix::Block::operator=(const Block& block) +{ + if (this != &block) + { + if (nRows_ != block.m() || nCols_ != block.n()) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << block.m() << "x" << block.n() + << abort(FatalError); + } + + for (label i=0; i +void Foam::Matrix::Block::operator=(const ConstBlock& block) +{ + if (this != &block) + { + if (nRows_ != block.m() || nCols_ != block.n()) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << block.m() << "x" << block.n() + << abort(FatalError); + } + + for (label i=0; i +void Foam::Matrix::Block::operator=(const mType& block) +{ + if (nRows_ != block.m() || nCols_ != block.n()) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << block.m() << "x" << block.n() + << abort(FatalError); + } + + for (label i=0; i +void Foam::Matrix::operator=(const Type& t) +{ + if (v_) + { + const label mn = size(); + for (label i=0; i +void Foam::Matrix::operator=(const zero) +{ + if (v_) + { + const label mn = size(); + for (label i=0; i +template +< + template class MSBlock, + class SubTensor, + Foam::direction BRowStart, + Foam::direction BColStart +> +void Foam::Matrix::Block::operator= +( + const MSBlock& block +) +{ + if (nRows_ != block.nRows || nCols_ != block.nCols) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << block.nRows << "x" << block.nCols + << abort(FatalError); + } + + for (direction i=0; i +template +< + template class VSBlock, + class SubVector, + Foam::direction BStart +> +void Foam::Matrix::Block::operator= +( + const VSBlock& block +) +{ + if (nRows_ != block.nComponents || nCols_ != 1) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << block.nComponents << "x" << 1 + << abort(FatalError); + } + + for (direction i=0; i +template +void Foam::Matrix::Block::operator= +( + const MatrixSpace& ms +) +{ + if (nRows_ != Nrows || nCols_ != Ncols) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << Nrows << "x" << Ncols + << abort(FatalError); + } + + for (label i=0; i +template +void Foam::Matrix::Block::operator= +( + const VectorSpace& ms +) +{ + if (nRows_ != Ncmpts || nCols_ != 1) + { + FatalErrorInFunction + << "Attempt to assign blocks of different sizes: " + << nRows_ << "x" << nCols_ << " != " + << Ncmpts << "x" << 1 + << abort(FatalError); + } + + for (direction i=0; i +void Foam::Matrix::Block::operator=(const Field& f) +{ + if (nRows_ != f.size() || nCols_ != 1) + { + FatalErrorInFunction + << "Error: cannot assign blocks of different size (left is " + << nRows_ << "x" << nCols_ << " != " + << f.size() << "x" << 1 + << abort(FatalError); + } + + forAll(f, i) + { + operator()(i, 0) = f[i]; + } +} + + // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // template @@ -234,7 +570,7 @@ const Type& Foam::max(const Matrix& a) else { FatalErrorInFunction - << "matrix is empty" + << "Matrix is empty" << abort(FatalError); // Return in error to keep compiler happy @@ -266,7 +602,7 @@ const Type& Foam::min(const Matrix& a) else { FatalErrorInFunction - << "matrix is empty" + << "Matrix is empty" << abort(FatalError); // Return in error to keep compiler happy @@ -304,7 +640,7 @@ Form Foam::operator+(const Matrix& a, const Matrix& b) if (a.m() != b.m()) { FatalErrorInFunction - << "attempted add matrices with different number of rows: " + << "Attempt to add matrices with different number of rows: " << a.m() << ", " << b.m() << abort(FatalError); } @@ -312,7 +648,7 @@ Form Foam::operator+(const Matrix& a, const Matrix& b) if (a.n() != b.n()) { FatalErrorInFunction - << "attempted add matrices with different number of columns: " + << "Attempt to add matrices with different number of columns: " << a.n() << ", " << b.n() << abort(FatalError); } @@ -339,7 +675,7 @@ Form Foam::operator-(const Matrix& a, const Matrix& b) if (a.m() != b.m()) { FatalErrorInFunction - << "attempted add matrices with different number of rows: " + << "Attempt to add matrices with different number of rows: " << a.m() << ", " << b.m() << abort(FatalError); } @@ -347,7 +683,7 @@ Form Foam::operator-(const Matrix& a, const Matrix& b) if (a.n() != b.n()) { FatalErrorInFunction - << "attempted add matrices with different number of columns: " + << "Attempt to add matrices with different number of columns: " << a.n() << ", " << b.n() << abort(FatalError); } @@ -389,13 +725,55 @@ Form Foam::operator*(const scalar s, const Matrix& a) } +template +Form Foam::operator*(const Matrix& a, const scalar s) +{ + Form sa(a.m(), a.n()); + + if (a.m() && a.n()) + { + Type* sav = sa.v(); + const Type* av = a.v(); + + const label mn = a.size(); + for (label i=0; i +Form Foam::operator/(const Matrix& a, const scalar s) +{ + Form sa(a.m(), a.n()); + + if (a.m() && a.n()) + { + Type* sav = sa.v(); + const Type* av = a.v(); + + const label mn = a.size(); + for (label i=0; i Form Foam::operator*(const Matrix& a, const Matrix& b) { if (a.n() != b.m()) { FatalErrorInFunction - << "attempted to multiply incompatible matrices:" << nl + << "Attempt to multiply incompatible matrices:" << nl << "Matrix A : " << a.m() << " rows, " << a.n() << " columns" << nl << "Matrix B : " << b.m() << " rows, " << b.n() << " columns" << nl << "In order to multiply matrices, columns of A must equal " @@ -405,13 +783,13 @@ Form Foam::operator*(const Matrix& a, const Matrix& b) Form ab(a.m(), b.n(), scalar(0)); - for (label i = 0; i < ab.m(); i++) + for (label i=0; i& a, const Matrix& b) } +template +inline Foam::tmp> Foam::operator* +( + const Matrix& M, + const Field& f +) +{ + if (M.n() != f.size()) + { + FatalErrorInFunction + << "Attempt to multiply incompatible matrix and field:" << nl + << "Matrix : " << M.m() << " rows, " << M.n() << " columns" << nl + << "Field : " << f.size() << " rows" << nl + << "In order to multiply a matrix M and field f, " + "columns of M must equal rows of f" + << abort(FatalError); + } + + tmp> tMf(new Field(f.size(), Zero)); + Field& Mf = tMf.ref(); + + for (label i=0; i mType; + + //- Component type + typedef Type cmptType; + + // Static Member Functions //- Return a null Matrix - inline static const Matrix& null(); + inline static const mType& null(); + + + // Sub-Block Classes + + class ConstBlock + { + // Private data + + //- Const reference to the parent matrix + const mType& matrix_; + + // Block size + const label nRows_; + const label nCols_; + + // Block location in parent matrix + const label rowStart_; + const label colStart_; + + public: + + typedef typename mType::cmptType cmptType; + + // Constructors + + //- Construct block for matrix, size and location + inline ConstBlock + ( + const mType& matrix, + const label m, + const label n, + const label mStart, + const label nStart + ); + + + // Member Functions + + //- Return the number of rows in the block + inline label m() const; + + //- Return the number of columns in the block + inline label n() const; + + //- (i, j) const element access operator + inline const Type& operator() + ( + const label i, + const label j + ) const; + + //- Convert a column of a matrix to a Field + operator Field() const; + }; + + + class Block + { + // Private data + + //- Reference to the parent matrix + mType& matrix_; + + // Block size + const label nRows_; + const label nCols_; + + // Block location in parent matrix + const label rowStart_; + const label colStart_; + + public: + + typedef typename mType::cmptType cmptType; + + // Constructors + + //- Construct block for matrix, size and location + inline Block + ( + mType& matrix, + const label m, + const label n, + const label mStart, + const label nStart + ); + + + // Member Functions + + //- Return the number of rows in the block + inline label m() const; + + //- Return the number of columns in the block + inline label n() const; + + //- (i, j) const element access operator + inline const Type& operator() + ( + const label i, + const label j + ) const; + + //- (i, j) element access operator + inline Type& operator()(const label i, const label j); + + //- Convert a column of a matrix to a Field + operator Field() const; + + + // Member operators + + //- Assignment to a compatible matrix + void operator=(const mType&); + + //- Assignment to a compatible block + void operator=(const Block&); + + //- Assignment to a compatible const block + void operator=(const ConstBlock&); + + //- Assignment to a compatible MatrixSpace + template + void operator=(const MatrixSpace&); + + //- Assignment to a compatible MatrixSpace block + template + < + template class Block, + class SubTensor, + direction BRowStart, + direction BColStart + > + void operator=(const Block&); + + //- Assignment to a compatible VectorSpace (column-vector) + template + void operator=(const VectorSpace&); + + //- Assignment to a compatible VectorSpace (column-vector) block + template + < + template class Block, + class SubVector, + direction BStart + > + void operator=(const Block&); + + //- Assignment to a Field (column-vector) + void operator=(const Field&); + }; // Constructors @@ -102,17 +262,24 @@ public: Matrix(const label m, const label n); //- Construct with given number of rows and columns - // and value for all elements. + // initializing all elements to zero + Matrix(const label m, const label n, const zero); + + //- Construct with given number of rows and columns + // initializing all elements to the given value Matrix(const label m, const label n, const Type&); //- Copy constructor. - Matrix(const Matrix&); + Matrix(const mType&); + + //- Construct from a block of another matrix + Matrix(const mType::Block&); //- Construct from Istream. Matrix(Istream&); //- Clone - inline autoPtr> clone() const; + inline autoPtr clone() const; //- Destructor @@ -132,6 +299,64 @@ public: //- Return the number of elements in matrix (m*n) inline label size() const; + //- Return element vector of the constant Matrix + inline const Type* v() const; + + //- Return element vector of the Matrix + inline Type* v(); + + + // Block access + + inline ConstBlock block + ( + const label m, + const label n, + const label mStart, + const label nStart + ) const; + + template + inline ConstBlock block + ( + const label mStart, + const label nStart + ) const; + + inline ConstBlock col + ( + const label m, + const label rowStart + ) const; + + inline ConstBlock col + ( + const label m, + const label mStart, + const label nStart + ) const; + + + inline Block block + ( + const label m, + const label n, + const label mStart, + const label nStart + ); + + template + inline Block block(const label mStart, const label nStart); + + inline Block col(const label m, const label rowStart); + + inline Block col + ( + const label m, + const label mStart, + const label nStart + ); + // Check @@ -149,7 +374,10 @@ public: //- Transfer the contents of the argument Matrix into this Matrix // and annul the argument Matrix. - void transfer(Matrix&); + void transfer(mType&); + + //- Resize the matrix preserving the elements + void setSize(const label m, const label nCols); //- Return the transpose of the matrix @@ -158,12 +386,6 @@ public: // Member operators - //- Return element vector of the constant Matrix - inline const Type* v() const; - - //- Return element vector of the Matrix - inline Type* v(); - //- Return subscript-checked row of Matrix. inline Type* operator[](const label); @@ -177,7 +399,13 @@ public: inline Type& operator()(const label i, const label j); //- Assignment operator. Takes linear time. - void operator=(const Matrix&); + void operator=(const mType&); + + //- Assignment to a block of another matrix + void operator=(const mType::Block&); + + //- Assignment of all entries to zero + void operator=(const zero); //- Assignment of all entries to the given value void operator=(const Type&); @@ -189,49 +417,78 @@ public: friend Istream& operator>> ( Istream&, - Matrix& + mType& ); // Write Matrix to Ostream. friend Ostream& operator<< ( Ostream&, - const Matrix& + const mType& ); }; // Global functions and operators -template const Type& max(const Matrix&); -template const Type& min(const Matrix&); +template +const Type& max(const Matrix&); -template Form operator-(const Matrix&); +template +const Type& min(const Matrix&); -template Form operator+ +template +Form operator-(const Matrix&); + +template +Form operator+ ( const Matrix&, const Matrix& ); -template Form operator- +template +Form operator- ( const Matrix&, const Matrix& ); -template Form operator* +template +Form operator* ( const scalar, const Matrix& ); -template Form operator* +template +Form operator* +( + const Matrix&, + const scalar +); + +template +Form operator/ +( + const Matrix&, + const scalar +); + +template +Form operator* ( const Matrix&, const Matrix& ); +template +tmp> operator* +( + const Matrix&, + const Field& +); + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/matrices/Matrix/MatrixI.H b/src/OpenFOAM/matrices/Matrix/MatrixI.H index 532e9df3f8..73992f3285 100644 --- a/src/OpenFOAM/matrices/Matrix/MatrixI.H +++ b/src/OpenFOAM/matrices/Matrix/MatrixI.H @@ -42,6 +42,68 @@ clone() const } +template +Foam::Matrix::ConstBlock::ConstBlock +( + const mType& matrix, + const label m, + const label n, + const label mStart, + const label nStart +) +: + matrix_(matrix), + nRows_(m), + nCols_(n), + rowStart_(mStart), + colStart_(nStart) +{ + #ifdef FULLDEBUG + if + ( + rowStart_ + nRows_ > matrix.m() + || colStart_ + nCols_ > matrix.n() + ) + { + FatalErrorInFunction + << "Block addresses outside matrix" + << abort(FatalError); + } + #endif +} + + +template +Foam::Matrix::Block::Block +( + mType& matrix, + const label m, + const label n, + const label mStart, + const label nStart +) +: + matrix_(matrix), + nRows_(m), + nCols_(n), + rowStart_(mStart), + colStart_(nStart) +{ + #ifdef FULLDEBUG + if + ( + rowStart_ + nRows_ > matrix.m() + || colStart_ + nCols_ > matrix.n() + ) + { + FatalErrorInFunction + << "Block addresses outside matrix" + << abort(FatalError); + } + #endif +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template @@ -76,16 +138,16 @@ template inline void Foam::Matrix::checki(const label i) const { #ifdef FULLDEBUG - if (!nRows_) + if (!nRows_ || !nCols_) { FatalErrorInFunction - << "attempt to access element from zero sized row" + << "Attempt to access element from empty matrix" << abort(FatalError); } else if (i<0 || i>=nRows_) { FatalErrorInFunction - << "index " << i << " out of range 0 ... " << nRows_-1 + << "Index " << i << " out of range 0 ... " << nRows_-1 << abort(FatalError); } #endif @@ -96,10 +158,10 @@ template inline void Foam::Matrix::checkj(const label j) const { #ifdef FULLDEBUG - if (!nCols_) + if (!nRows_ || !nCols_) { FatalErrorInFunction - << "attempt to access element from zero sized column" + << "Attempt to access element from empty matrix" << abort(FatalError); } else if (j<0 || j>=nCols_) @@ -112,7 +174,33 @@ inline void Foam::Matrix::checkj(const label j) const } -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // +template +inline Foam::label Foam::Matrix::ConstBlock::m() const +{ + return nRows_; +} + + +template +inline Foam::label Foam::Matrix::ConstBlock::n() const +{ + return nCols_; +} + + +template +inline Foam::label Foam::Matrix::Block::m() const +{ + return nRows_; +} + + +template +inline Foam::label Foam::Matrix::Block::n() const +{ + return nCols_; +} + template inline const Type* Foam::Matrix::v() const @@ -128,6 +216,238 @@ inline Type* Foam::Matrix::v() } +template +inline typename Foam::Matrix::ConstBlock +Foam::Matrix::block +( + const label m, + const label n, + const label mStart, + const label nStart +) const +{ + return ConstBlock + ( + *this, + m, + n, + mStart, + nStart + ); +} + + +template +template +inline typename Foam::Matrix::ConstBlock +Foam::Matrix::block +( + const label mStart, + const label nStart +) const +{ + return ConstBlock + ( + *this, + VectorSpace::nRows, + VectorSpace::nCols, + mStart, + nStart + ); +} + + +template +inline typename Foam::Matrix::ConstBlock +Foam::Matrix::col +( + const label m, + const label mStart +) const +{ + return ConstBlock + ( + *this, + m, + 1, + mStart, + 0 + ); +} + + +template +inline typename Foam::Matrix::ConstBlock +Foam::Matrix::col +( + const label m, + const label mStart, + const label nStart +) const +{ + return ConstBlock + ( + *this, + m, + 1, + mStart, + nStart + ); +} + + +template +inline typename Foam::Matrix::Block +Foam::Matrix::block +( + const label m, + const label n, + const label mStart, + const label nStart +) +{ + return Block + ( + *this, + m, + n, + mStart, + nStart + ); +} + + +template +template +inline typename Foam::Matrix::Block +Foam::Matrix::block(const label mStart, const label nStart) +{ + return Block + ( + *this, + VectorSpace::nRows, + VectorSpace::nCols, + mStart, + nStart + ); +} + + +template +inline typename Foam::Matrix::Block +Foam::Matrix::col(const label m, const label mStart) +{ + return Block + ( + *this, + m, + 1, + mStart, + 0 + ); +} + + +template +inline typename Foam::Matrix::Block +Foam::Matrix::col +( + const label m, + const label mStart, + const label nStart +) +{ + return Block + ( + *this, + m, + 1, + mStart, + nStart + ); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +template +inline const Type& Foam::Matrix::ConstBlock::operator() +( + const label i, + const label j +) const +{ + #ifdef FULLDEBUG + if (i<0 || i>=nRows_) + { + FatalErrorInFunction + << "Index " << i << " out of range 0 ... " << nRows_-1 + << abort(FatalError); + } + if (j<0 || j>=nCols_) + { + FatalErrorInFunction + << "Index " << j << " out of range 0 ... " << nCols_-1 + << abort(FatalError); + } + #endif + + return matrix_(i + rowStart_, j + colStart_); +} + + +template +inline const Type& Foam::Matrix::Block::operator() +( + const label i, + const label j +) const +{ + #ifdef FULLDEBUG + if (i<0 || i>=nRows_) + { + FatalErrorInFunction + << "Index " << i << " out of range 0 ... " << nRows_-1 + << abort(FatalError); + } + if (j<0 || j>=nCols_) + { + FatalErrorInFunction + << "Index " << j << " out of range 0 ... " << nCols_-1 + << abort(FatalError); + } + #endif + + return matrix_(i + rowStart_, j + colStart_); +} + + +template +inline Type& Foam::Matrix::Block::operator() +( + const label i, + const label j +) +{ + #ifdef FULLDEBUG + if (i<0 || i>=nRows_) + { + FatalErrorInFunction + << "Index " << i << " out of range 0 ... " << nRows_-1 + << abort(FatalError); + } + if (j<0 || j>=nCols_) + { + FatalErrorInFunction + << "Index " << j << " out of range 0 ... " << nCols_-1 + << abort(FatalError); + } + #endif + + return matrix_(i + rowStart_, j + colStart_); +} + + template inline const Type& Foam::Matrix::operator() (