mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
- additional operators: + compound assignment + inner product: operator& + outer product: operator^ - additional functions: - MatrixBlock methods: subColumn, subRow, subMatrix - L2 norms for matrix or column - trace, diag, round, transpose - MatrixBlock methods: col(), block() are deprecated since their access patterns with (size, offset) are unnatural/unwieldy. - verifications by test/Matrix/Test-Matrix
655 lines
13 KiB
C++
655 lines
13 KiB
C++
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
|
\\/ M anipulation |
|
|
-------------------------------------------------------------------------------
|
|
| Copyright (C) 2011-2016 OpenFOAM Foundation
|
|
-------------------------------------------------------------------------------
|
|
License
|
|
This file is part of OpenFOAM.
|
|
|
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "MatrixBlock.H"
|
|
|
|
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
|
|
|
template<class Form, class Type>
|
|
inline void Foam::Matrix<Form, Type>::doAlloc()
|
|
{
|
|
const label len = size();
|
|
|
|
if (len)
|
|
{
|
|
v_ = new Type[len];
|
|
}
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::Matrix<Form, Type>::Matrix()
|
|
:
|
|
mRows_(0),
|
|
nCols_(0),
|
|
v_(nullptr)
|
|
{}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims)
|
|
:
|
|
Matrix<Form, Type>(dims.first(), dims.second())
|
|
{}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const zero)
|
|
:
|
|
Matrix<Form, Type>(dims.first(), dims.second(), Zero)
|
|
{}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::Matrix<Form, Type>::Matrix(const labelPair& dims, const Type& val)
|
|
:
|
|
Matrix<Form, Type>(dims.first(), dims.second(), val)
|
|
{}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::autoPtr<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::clone() const
|
|
{
|
|
return autoPtr<Matrix<Form, Type>>::New(*this);
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
|
|
template<class Form, class Type>
|
|
inline const Foam::Matrix<Form, Type>& Foam::Matrix<Form, Type>::null()
|
|
{
|
|
return NullObjectRef<Matrix<Form, Type>>();
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::label Foam::Matrix<Form, Type>::m() const noexcept
|
|
{
|
|
return mRows_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::label Foam::Matrix<Form, Type>::n() const noexcept
|
|
{
|
|
return nCols_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::label Foam::Matrix<Form, Type>::size() const
|
|
{
|
|
return mRows_ * nCols_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::labelPair Foam::Matrix<Form, Type>::sizes() const
|
|
{
|
|
return labelPair(mRows_, nCols_);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline bool Foam::Matrix<Form, Type>::empty() const noexcept
|
|
{
|
|
return !mRows_ || !nCols_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline void Foam::Matrix<Form, Type>::checki(const label i) const
|
|
{
|
|
if (!mRows_ || !nCols_)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "Attempt to access element from empty matrix"
|
|
<< abort(FatalError);
|
|
}
|
|
if (i < 0 || mRows_ <= i)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "Index " << i << " out of range 0 ... " << mRows_-1
|
|
<< abort(FatalError);
|
|
}
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline void Foam::Matrix<Form, Type>::checkj(const label j) const
|
|
{
|
|
if (!mRows_ || !nCols_)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "Attempt to access element from empty matrix"
|
|
<< abort(FatalError);
|
|
}
|
|
if (j < 0 || nCols_ <= j)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "index " << j << " out of range 0 ... " << nCols_-1
|
|
<< abort(FatalError);
|
|
}
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline void Foam::Matrix<Form, Type>::checkSize() const
|
|
{
|
|
if (mRows_ < 0 || nCols_ < 0)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "Incorrect size (" << mRows_ << ", " << nCols_ << ')' << nl
|
|
<< abort(FatalError);
|
|
}
|
|
// Could also check for odd sizes, like (0, N) and make (0,0)
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline bool Foam::Matrix<Form, Type>::uniform() const
|
|
{
|
|
const label len = size();
|
|
|
|
if (len == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (label idx = 1; idx < len; ++idx)
|
|
{
|
|
if (v_[0] != v_[idx])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline const Type* Foam::Matrix<Form, Type>::cdata() const noexcept
|
|
{
|
|
return v_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Type* Foam::Matrix<Form, Type>::data() noexcept
|
|
{
|
|
return v_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline const Type* Foam::Matrix<Form, Type>::rowData(const label irow) const
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
#endif
|
|
return (v_ + irow*nCols_);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Type* Foam::Matrix<Form, Type>::rowData(const label irow)
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
#endif
|
|
return (v_ + irow*nCols_);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline const Type& Foam::Matrix<Form, Type>::at(const label idx) const
|
|
{
|
|
#ifdef FULLDEBUG
|
|
if (idx < 0 || this->size() <= idx)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "index " << idx << " out of range 0 ... " << this->size()
|
|
<< abort(FatalError);
|
|
}
|
|
#endif
|
|
return (v_ + idx);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Type& Foam::Matrix<Form, Type>::at(const label idx)
|
|
{
|
|
#ifdef FULLDEBUG
|
|
if (idx < 0 || this->size() <= idx)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "index " << idx << " out of range 0 ... " << this->size()
|
|
<< abort(FatalError);
|
|
}
|
|
#endif
|
|
return (v_ + idx);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subColumn
|
|
(
|
|
const label colIndex,
|
|
const label rowIndex,
|
|
label len
|
|
) const
|
|
{
|
|
if (len < 0)
|
|
{
|
|
len = mRows_ - rowIndex;
|
|
}
|
|
|
|
return ConstMatrixBlock<mType>
|
|
(
|
|
*this,
|
|
len, // rows
|
|
1,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subRow
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex,
|
|
label len
|
|
) const
|
|
{
|
|
if (len < 0)
|
|
{
|
|
len = nCols_ - colIndex;
|
|
}
|
|
|
|
return ConstMatrixBlock<mType>
|
|
(
|
|
*this,
|
|
1,
|
|
len, // columns
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subMatrix
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex,
|
|
label szRows,
|
|
label szCols
|
|
) const
|
|
{
|
|
if (szRows < 0) szRows = mRows_ - rowIndex;
|
|
if (szCols < 0) szCols = nCols_ - colIndex;
|
|
|
|
return ConstMatrixBlock<mType>
|
|
(
|
|
*this,
|
|
szRows,
|
|
szCols,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
template<class VectorSpace>
|
|
inline Foam::ConstMatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::block
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex
|
|
) const
|
|
{
|
|
return ConstMatrixBlock<mType>
|
|
(
|
|
*this,
|
|
VectorSpace::mRows,
|
|
VectorSpace::nCols,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subColumn
|
|
(
|
|
const label colIndex,
|
|
const label rowIndex,
|
|
label len
|
|
)
|
|
{
|
|
if (len < 0)
|
|
{
|
|
len = mRows_ - rowIndex;
|
|
}
|
|
|
|
return MatrixBlock<mType>
|
|
(
|
|
*this,
|
|
len, // rows
|
|
1,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subRow
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex,
|
|
label len
|
|
)
|
|
{
|
|
if (len < 0)
|
|
{
|
|
len = nCols_ - colIndex;
|
|
}
|
|
|
|
return MatrixBlock<mType>
|
|
(
|
|
*this,
|
|
1,
|
|
len, // columns
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::subMatrix
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex,
|
|
label szRows,
|
|
label szCols
|
|
)
|
|
{
|
|
if (szRows < 0) szRows = mRows_ - rowIndex;
|
|
if (szCols < 0) szCols = nCols_ - colIndex;
|
|
|
|
return MatrixBlock<mType>
|
|
(
|
|
*this,
|
|
szRows,
|
|
szCols,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
template<class VectorSpace>
|
|
inline Foam::MatrixBlock<Foam::Matrix<Form, Type>>
|
|
Foam::Matrix<Form, Type>::block
|
|
(
|
|
const label rowIndex,
|
|
const label colIndex
|
|
)
|
|
{
|
|
return MatrixBlock<mType>
|
|
(
|
|
*this,
|
|
VectorSpace::mRows,
|
|
VectorSpace::nCols,
|
|
rowIndex,
|
|
colIndex
|
|
);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline void Foam::Matrix<Form, Type>::setSize(const label m, const label n)
|
|
{
|
|
resize(m, n);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
void Foam::Matrix<Form, Type>::shallowResize(const label m, const label n)
|
|
{
|
|
mRows_ = m;
|
|
nCols_ = n;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Amul
|
|
(
|
|
const UList<Type>& x
|
|
) const
|
|
{
|
|
return this->AmulImpl(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
template<class Addr>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Amul
|
|
(
|
|
const IndirectListBase<Type, Addr>& x
|
|
) const
|
|
{
|
|
return this->AmulImpl(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Tmul
|
|
(
|
|
const UList<Type>& x
|
|
) const
|
|
{
|
|
return this->TmulImpl(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
template<class Addr>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::Matrix<Form, Type>::Tmul
|
|
(
|
|
const IndirectListBase<Type, Addr>& x
|
|
) const
|
|
{
|
|
return this->TmulImpl(x);
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * //
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::iterator
|
|
Foam::Matrix<Form, Type>::begin()
|
|
{
|
|
return v_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::iterator
|
|
Foam::Matrix<Form, Type>::end()
|
|
{
|
|
return v_ + (mRows_ * nCols_);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::const_iterator
|
|
Foam::Matrix<Form, Type>::cbegin() const
|
|
{
|
|
return v_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::const_iterator
|
|
Foam::Matrix<Form, Type>::cend() const
|
|
{
|
|
return v_ + (mRows_ * nCols_);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::const_iterator
|
|
Foam::Matrix<Form, Type>::begin() const
|
|
{
|
|
return v_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline typename Foam::Matrix<Form, Type>::const_iterator
|
|
Foam::Matrix<Form, Type>::end() const
|
|
{
|
|
return v_ + (mRows_ * nCols_);
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
|
|
template<class Form, class Type>
|
|
inline const Type& Foam::Matrix<Form, Type>::operator()
|
|
(
|
|
const label irow,
|
|
const label jcol
|
|
) const
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
checkj(jcol);
|
|
#endif
|
|
return v_[irow*nCols_ + jcol];
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Type& Foam::Matrix<Form, Type>::operator()
|
|
(
|
|
const label irow,
|
|
const label jcol
|
|
)
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
checkj(jcol);
|
|
#endif
|
|
return v_[irow*nCols_ + jcol];
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline const Type* Foam::Matrix<Form, Type>::operator[](const label irow) const
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
#endif
|
|
return v_ + irow*nCols_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Type* Foam::Matrix<Form, Type>::operator[](const label irow)
|
|
{
|
|
#ifdef FULLDEBUG
|
|
checki(irow);
|
|
#endif
|
|
return v_ + irow*nCols_;
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::operator*
|
|
(
|
|
const Matrix<Form, Type>& mat,
|
|
const UList<Type>& x
|
|
)
|
|
{
|
|
return mat.Amul(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type, class Addr>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::operator*
|
|
(
|
|
const Matrix<Form, Type>& mat,
|
|
const IndirectListBase<Type, Addr>& x
|
|
)
|
|
{
|
|
return mat.Amul(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::operator*
|
|
(
|
|
const UList<Type>& x,
|
|
const Matrix<Form, Type>& mat
|
|
)
|
|
{
|
|
return mat.Tmul(x);
|
|
}
|
|
|
|
|
|
template<class Form, class Type, class Addr>
|
|
inline Foam::tmp<Foam::Field<Type>> Foam::operator*
|
|
(
|
|
const IndirectListBase<Type, Addr>& x,
|
|
const Matrix<Form, Type>& mat
|
|
)
|
|
{
|
|
return mat.Tmul(x);
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|