Files
openfoam/src/OpenFOAM/matrices/Matrix/MatrixI.H
kuti 745624c024 ENH: partial overhaul of Matrix type (#1220)
- 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
2019-05-23 11:32:45 +01:00

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);
}
// ************************************************************************* //