Merge branch 'update-matrix-streaming' into 'develop'

Improve streaming matrix and internal memory management

See merge request Development/openfoam!671
This commit is contained in:
Kutalmış Berçin
2024-03-07 10:18:27 +00:00
19 changed files with 1012 additions and 894 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -42,17 +42,16 @@ namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::LUscalarMatrix::LUscalarMatrix() Foam::LUscalarMatrix::LUscalarMatrix() noexcept
: :
comm_(UPstream::worldComm) comm_(UPstream::worldComm)
{} {}
Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& matrix) Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& mat)
: :
scalarSquareMatrix(matrix), scalarSquareMatrix(mat),
comm_(UPstream::worldComm), comm_(UPstream::worldComm)
pivotIndices_(m())
{ {
LUDecompose(*this, pivotIndices_); LUDecompose(*this, pivotIndices_);
} }
@ -69,13 +68,14 @@ Foam::LUscalarMatrix::LUscalarMatrix
{ {
if (UPstream::parRun()) if (UPstream::parRun())
{ {
PtrList<procLduMatrix> lduMatrices(UPstream::nProcs(comm_)); PtrList<procLduMatrix> lduMatrices
(
label lduMatrixi = 0; UPstream::master(comm_) ? UPstream::nProcs(comm_) : 1
);
lduMatrices.set lduMatrices.set
( (
lduMatrixi++, 0, // rank-local matrix (and/or master)
new procLduMatrix new procLduMatrix
( (
ldum, ldum,
@ -88,101 +88,66 @@ Foam::LUscalarMatrix::LUscalarMatrix
{ {
for (const int proci : UPstream::subProcs(comm_)) for (const int proci : UPstream::subProcs(comm_))
{ {
lduMatrices.set auto& mat = lduMatrices.emplace_set(proci);
(
lduMatrixi++, IPstream::recv(mat, proci, UPstream::msgType(), comm_);
new procLduMatrix
(
IPstream
(
UPstream::commsTypes::scheduled,
proci,
0, // bufSize
UPstream::msgType(),
comm_
)()
)
);
} }
convert(lduMatrices);
} }
else else
{ {
OPstream toMaster OPstream::send
( (
UPstream::commsTypes::scheduled, lduMatrices[0], // rank-local matrix
UPstream::masterNo(), UPstream::masterNo(),
0, // bufSize
UPstream::msgType(), UPstream::msgType(),
comm_ comm_
); );
procLduMatrix cldum
(
ldum,
interfaceCoeffs,
interfaces
);
toMaster<< cldum;
}
if (UPstream::master(comm_))
{
label nCells = 0;
forAll(lduMatrices, i)
{
nCells += lduMatrices[i].size();
}
scalarSquareMatrix m(nCells, 0.0);
transfer(m);
convert(lduMatrices);
} }
} }
else else
{ {
label nCells = ldum.lduAddr().size();
scalarSquareMatrix m(nCells, Zero);
transfer(m);
convert(ldum, interfaceCoeffs, interfaces); convert(ldum, interfaceCoeffs, interfaces);
} }
if (debug && UPstream::master(comm_))
{
const label numRows = nRows();
const label numCols = nCols();
Pout<< "LUscalarMatrix : size:" << numRows << endl;
for (label rowi = 0; rowi < numRows; ++rowi)
{
const scalar* row = operator[](rowi);
Pout<< "cell:" << rowi << " diagCoeff:" << row[rowi] << nl;
Pout<< " connects to upper cells :";
for (label coli = rowi+1; coli < numCols; ++coli)
{
if (mag(row[coli]) > SMALL)
{
Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
}
}
Pout<< nl;
Pout<< " connects to lower cells :";
for (label coli = 0; coli < rowi; ++coli)
{
if (mag(row[coli]) > SMALL)
{
Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
}
}
Pout<< nl;
}
Pout<< endl;
}
if (UPstream::master(comm_)) if (UPstream::master(comm_))
{ {
if (debug)
{
const label numRows = m();
const label numCols = n();
Pout<< "LUscalarMatrix : size:" << numRows << endl;
for (label rowi = 0; rowi < numRows; ++rowi)
{
const scalar* row = operator[](rowi);
Pout<< "cell:" << rowi << " diagCoeff:" << row[rowi] << endl;
Pout<< " connects to upper cells :";
for (label coli = rowi+1; coli < numCols; ++coli)
{
if (mag(row[coli]) > SMALL)
{
Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
}
}
Pout<< endl;
Pout<< " connects to lower cells :";
for (label coli = 0; coli < rowi; ++coli)
{
if (mag(row[coli]) > SMALL)
{
Pout<< ' ' << coli << " (coeff:" << row[coli] << ')';
}
}
Pout<< nl;
}
Pout<< nl;
}
pivotIndices_.setSize(m());
LUDecompose(*this, pivotIndices_); LUDecompose(*this, pivotIndices_);
} }
} }
@ -197,6 +162,10 @@ void Foam::LUscalarMatrix::convert
const lduInterfaceFieldPtrsList& interfaces const lduInterfaceFieldPtrsList& interfaces
) )
{ {
// Resize and fill with zero
scalarSquareMatrix::resize_nocopy(ldum.lduAddr().size());
scalarSquareMatrix::operator=(Foam::zero{});
const label* __restrict__ uPtr = ldum.lduAddr().upperAddr().begin(); const label* __restrict__ uPtr = ldum.lduAddr().upperAddr().begin();
const label* __restrict__ lPtr = ldum.lduAddr().lowerAddr().begin(); const label* __restrict__ lPtr = ldum.lduAddr().lowerAddr().begin();
@ -259,14 +228,26 @@ void Foam::LUscalarMatrix::convert
const PtrList<procLduMatrix>& lduMatrices const PtrList<procLduMatrix>& lduMatrices
) )
{ {
procOffsets_.setSize(lduMatrices.size() + 1); procOffsets_.resize_nocopy(lduMatrices.size() + 1);
procOffsets_[0] = 0;
forAll(lduMatrices, ldumi)
{ {
procOffsets_[ldumi+1] = procOffsets_[ldumi] + lduMatrices[ldumi].size(); auto iter = procOffsets_.begin();
label nCellsTotal = 0;
*iter++ = nCellsTotal;
for (const auto& mat : lduMatrices)
{
nCellsTotal += mat.size();
*iter++ = nCellsTotal;
}
// Resize and fill with zero
scalarSquareMatrix::resize_nocopy(nCellsTotal);
scalarSquareMatrix::operator=(Foam::zero{});
} }
forAll(lduMatrices, ldumi) forAll(lduMatrices, ldumi)
{ {
const procLduMatrix& lduMatrixi = lduMatrices[ldumi]; const procLduMatrix& lduMatrixi = lduMatrices[ldumi];
@ -400,10 +381,9 @@ void Foam::LUscalarMatrix::printDiagonalDominance() const
} }
void Foam::LUscalarMatrix::decompose(const scalarSquareMatrix& M) void Foam::LUscalarMatrix::decompose(const scalarSquareMatrix& mat)
{ {
scalarSquareMatrix::operator=(M); scalarSquareMatrix::operator=(mat);
pivotIndices_.setSize(m());
LUDecompose(*this, pivotIndices_); LUDecompose(*this, pivotIndices_);
} }

View File

@ -34,8 +34,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef LUscalarMatrix_H #ifndef Foam_LUscalarMatrix_H
#define LUscalarMatrix_H #define Foam_LUscalarMatrix_H
#include "scalarMatrices.H" #include "scalarMatrices.H"
#include "labelList.H" #include "labelList.H"
@ -47,6 +47,7 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward Declarations
class lduMatrix; class lduMatrix;
class procLduMatrix; class procLduMatrix;
@ -58,7 +59,7 @@ class LUscalarMatrix
: :
public scalarSquareMatrix public scalarSquareMatrix
{ {
// Private data // Private Data
//- Communicator to use //- Communicator to use
const label comm_; const label comm_;
@ -70,7 +71,7 @@ class LUscalarMatrix
labelList pivotIndices_; labelList pivotIndices_;
// Private member functions // Private Member Functions
//- Convert the given lduMatrix into this LUscalarMatrix //- Convert the given lduMatrix into this LUscalarMatrix
void convert void convert
@ -81,12 +82,12 @@ class LUscalarMatrix
); );
//- Convert the given list of procLduMatrix into this LUscalarMatrix //- Convert the given list of procLduMatrix into this LUscalarMatrix
// on the master processor //- on the master processor
void convert(const PtrList<procLduMatrix>& lduMatrices); void convert(const PtrList<procLduMatrix>& lduMatrices);
//- Print the ratio of the mag-sum of the off-diagonal coefficients //- Print the ratio of the mag-sum of the off-diagonal coefficients
// to the mag-diagonal //- to the mag-diagonal
void printDiagonalDominance() const; void printDiagonalDominance() const;
@ -98,13 +99,14 @@ public:
// Constructors // Constructors
//- Construct null //- Default construct
LUscalarMatrix(); LUscalarMatrix() noexcept;
//- Construct from and perform LU decomposition of the matrix M //- Construct from and perform LU decomposition of the given matrix
LUscalarMatrix(const scalarSquareMatrix& M); explicit LUscalarMatrix(const scalarSquareMatrix& mat);
//- Construct from lduMatrix and perform LU decomposition //- Construct from lduMatrix and perform LU decomposition.
//- In parallel it assembles the matrix on the master.
LUscalarMatrix LUscalarMatrix
( (
const lduMatrix& ldum, const lduMatrix& ldum,
@ -115,8 +117,8 @@ public:
// Member Functions // Member Functions
//- Perform the LU decomposition of the matrix M //- Perform the LU decomposition of the matrix
void decompose(const scalarSquareMatrix& M); void decompose(const scalarSquareMatrix& mat);
//- Solve the linear system with the given source //- Solve the linear system with the given source
// and returning the solution in the Field argument x. // and returning the solution in the Field argument x.

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -44,79 +44,141 @@ void Foam::LUscalarMatrix::solve
x = source; x = source;
} }
if (Pstream::parRun()) const auto tag = UPstream::msgType();
if (UPstream::parRun())
{ {
List<Type> X; // scratch space (on master) List<Type> allx; // scratch space (on master)
if (Pstream::master(comm_)) const label startOfRequests = UPstream::nRequests();
// Like globalIndex::gather()
if (UPstream::master(comm_))
{ {
X.resize(m()); allx.resize(m());
SubList<Type>(X, x.size()) = x; SubList<Type>(allx, x.size()) = x;
for (const int proci : Pstream::subProcs(comm_)) for (const int proci : UPstream::subProcs(comm_))
{ {
UIPstream::read SubList<Type> procSlot
( (
Pstream::commsTypes::scheduled, allx,
proci, procOffsets_[proci+1]-procOffsets_[proci],
reinterpret_cast<char*> procOffsets_[proci]
(
&(X[procOffsets_[proci]])
),
(procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
Pstream::msgType(),
comm_
); );
if (procSlot.empty())
{
// Nothing to do
}
else if (is_contiguous<Type>::value)
{
UIPstream::read
(
UPstream::commsTypes::nonBlocking,
proci,
procSlot.data_bytes(),
procSlot.size_bytes(),
tag,
comm_
);
}
else
{
IPstream::recv(procSlot, proci, tag, comm_);
}
} }
} }
else else
{ {
UOPstream::write if (x.empty())
( {
Pstream::commsTypes::scheduled, // Nothing to do
Pstream::masterNo(), }
x.cdata_bytes(), else if (is_contiguous<Type>::value)
x.byteSize(),
Pstream::msgType(),
comm_
);
}
if (Pstream::master(comm_))
{
LUBacksubstitute(*this, pivotIndices_, X);
x = SubList<Type>(X, x.size());
for (const int proci : Pstream::subProcs(comm_))
{ {
UOPstream::write UOPstream::write
( (
Pstream::commsTypes::scheduled, UPstream::commsTypes::nonBlocking,
proci, UPstream::masterNo(),
reinterpret_cast<const char*> x.cdata_bytes(),
( x.size_bytes(),
&(X[procOffsets_[proci]]) tag,
),
(procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
Pstream::msgType(),
comm_ comm_
); );
} }
else
{
OPstream::send(x, UPstream::masterNo(), tag, comm_);
}
}
UPstream::waitRequests(startOfRequests);
// LUBacksubstitute and then like globalIndex::scatter()
if (UPstream::master(comm_))
{
LUBacksubstitute(*this, pivotIndices_, allx);
x = SubList<Type>(allx, x.size());
for (const int proci : UPstream::subProcs(comm_))
{
SubList<Type> procSlot
(
allx,
procOffsets_[proci+1]-procOffsets_[proci],
procOffsets_[proci]
);
if (procSlot.empty())
{
// Nothing to do
}
else if (is_contiguous<Type>::value)
{
UOPstream::write
(
UPstream::commsTypes::nonBlocking,
proci,
procSlot.cdata_bytes(),
procSlot.size_bytes(),
tag,
comm_
);
}
else
{
OPstream::send(procSlot, proci, tag, comm_);
}
}
} }
else else
{ {
UIPstream::read if (x.empty())
( {
Pstream::commsTypes::scheduled, // Nothing to do
Pstream::masterNo(), }
x.data_bytes(), else if (is_contiguous<Type>::value)
x.byteSize(), {
Pstream::msgType(), UIPstream::read
comm_ (
); UPstream::commsTypes::nonBlocking,
UPstream::masterNo(),
x.data_bytes(),
x.size_bytes(),
tag,
comm_
);
}
else
{
IPstream::recv(x, UPstream::masterNo(), tag, comm_);
}
} }
UPstream::waitRequests(startOfRequests);
} }
else else
{ {
@ -131,7 +193,7 @@ Foam::tmp<Foam::Field<Type>> Foam::LUscalarMatrix::solve
const UList<Type>& source const UList<Type>& source
) const ) const
{ {
auto tx(tmp<Field<Type>>::New(m())); auto tx = tmp<Field<Type>>::New(m());
solve(tx.ref(), source); solve(tx.ref(), source);

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -69,27 +70,47 @@ Foam::procLduInterface::procLduInterface
Foam::procLduInterface::procLduInterface(Istream& is) Foam::procLduInterface::procLduInterface(Istream& is)
: {
faceCells_(is), read(is);
coeffs_(is), }
myProcNo_(readLabel(is)),
neighbProcNo_(readLabel(is)),
tag_(readLabel(is)), // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
comm_(readLabel(is))
{} void Foam::procLduInterface::read(Istream& is)
{
is >> faceCells_
>> coeffs_
>> myProcNo_
>> neighbProcNo_
>> tag_
>> comm_;
}
void Foam::procLduInterface::write(Ostream& os) const
{
os << faceCells_
<< coeffs_
<< myProcNo_
<< neighbProcNo_
<< tag_
<< comm_;
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const procLduInterface& cldui) Foam::Istream& Foam::operator>>(Istream& is, procLduInterface& intf)
{ {
os << cldui.faceCells_ intf.read(is);
<< cldui.coeffs_ return is;
<< cldui.myProcNo_ }
<< cldui.neighbProcNo_
<< cldui.tag_
<< cldui.comm_;
Foam::Ostream& Foam::operator<<(Ostream& os, const procLduInterface& intf)
{
intf.write(os);
return os; return os;
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -49,10 +50,11 @@ namespace Foam
class lduInterfaceField; class lduInterfaceField;
class procLduInterface; class procLduInterface;
Istream& operator>>(Istream&, procLduInterface&);
Ostream& operator<<(Ostream&, const procLduInterface&); Ostream& operator<<(Ostream&, const procLduInterface&);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class procLduInterface Declaration Class procLduInterface Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class procLduInterface class procLduInterface
@ -68,6 +70,7 @@ class procLduInterface
public: public:
//- Friendship
friend class LUscalarMatrix; friend class LUscalarMatrix;
@ -85,7 +88,8 @@ public:
const scalarField& coeffs const scalarField& coeffs
); );
procLduInterface(Istream& is); //- Read construct from Istream
explicit procLduInterface(Istream& is);
autoPtr<procLduInterface> clone() autoPtr<procLduInterface> clone()
{ {
@ -99,8 +103,12 @@ public:
} }
// Ostream Operator // IO Operations
void read(Istream& is);
void write(Ostream& os) const;
friend Istream& operator>>(Istream&, procLduInterface&);
friend Ostream& operator<<(Ostream&, const procLduInterface&); friend Ostream& operator<<(Ostream&, const procLduInterface&);
}; };

View File

@ -50,7 +50,7 @@ Foam::procLduMatrix::procLduMatrix
forAll(interfaces, i) forAll(interfaces, i)
{ {
if (interfaces.set(i)) if (interfaces.test(i))
{ {
interfaces_.set interfaces_.set
( (
@ -67,27 +67,48 @@ Foam::procLduMatrix::procLduMatrix
Foam::procLduMatrix::procLduMatrix(Istream& is) Foam::procLduMatrix::procLduMatrix(Istream& is)
: {
upperAddr_(is), read(is);
lowerAddr_(is), }
diag_(is),
upper_(is),
lower_(is), // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
interfaces_(is)
{} // void Foam::procLduMatrix::clear()
// {
// upperAddr_.clear();
// lowerAddr_.clear();
// diag_.clear();
// upper_.clear();
// lower_.clear();
// interfaces_.clear();
// }
void Foam::procLduMatrix::read(Istream& is)
{
is >> upperAddr_ >> lowerAddr_ >> diag_ >> upper_ >> lower_ >> interfaces_;
}
void Foam::procLduMatrix::write(Ostream& os) const
{
os << upperAddr_ << lowerAddr_ << diag_ << upper_ << lower_ << interfaces_;
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const procLduMatrix& cldum) Foam::Istream& Foam::operator>>(Istream& is, procLduMatrix& mat)
{ {
os << cldum.upperAddr_ mat.read(is);
<< cldum.lowerAddr_ return is;
<< cldum.diag_ }
<< cldum.upper_
<< cldum.lower_
<< cldum.interfaces_;
Foam::Ostream& Foam::operator<<(Ostream& os, const procLduMatrix& mat)
{
mat.write(os);
return os; return os;
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef procLduMatrix_H #ifndef Foam_procLduMatrix_H
#define procLduMatrix_H #define Foam_procLduMatrix_H
#include "labelList.H" #include "labelList.H"
#include "scalarField.H" #include "scalarField.H"
@ -47,23 +48,21 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward Declarations
class procLduMatrix;
class procLduInterface; class procLduInterface;
class lduMatrix; class lduMatrix;
// Forward declaration of friend functions and operators Istream& operator>>(Istream&, procLduMatrix&);
class procLduMatrix;
Ostream& operator<<(Ostream&, const procLduMatrix&); Ostream& operator<<(Ostream&, const procLduMatrix&);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class procLduMatrix Declaration Class procLduMatrix Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class procLduMatrix class procLduMatrix
{ {
// Private data // Private Data
labelList upperAddr_; labelList upperAddr_;
labelList lowerAddr_; labelList lowerAddr_;
@ -72,20 +71,24 @@ class procLduMatrix
scalarField lower_; scalarField lower_;
PtrList<procLduInterface> interfaces_; PtrList<procLduInterface> interfaces_;
public:
// Private Member Functions //- Friendship
friend class LUscalarMatrix;
// Generated Methods
//- Default construct
procLduMatrix() = default;
//- No copy construct //- No copy construct
procLduMatrix(const procLduMatrix&) = delete; procLduMatrix(const procLduMatrix&) = delete;
public:
friend class LUscalarMatrix;
// Constructors // Constructors
//- Construct from components. Extracts active interfaces
procLduMatrix procLduMatrix
( (
const lduMatrix& ldum, const lduMatrix& ldum,
@ -93,19 +96,26 @@ public:
const lduInterfaceFieldPtrsList& interfaces const lduInterfaceFieldPtrsList& interfaces
); );
procLduMatrix(Istream& is); //- Read construct from Istream
explicit procLduMatrix(Istream& is);
// Member functions // Member Functions
label size() const label size() const noexcept
{ {
return diag_.size(); return diag_.size();
} }
// void clear();
// Ostream operator
// IO Operations
void read(Istream& is);
void write(Ostream& os) const;
friend Istream& operator>>(Istream&, procLduMatrix&);
friend Ostream& operator<<(Ostream&, const procLduMatrix&); friend Ostream& operator<<(Ostream&, const procLduMatrix&);
}; };

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -33,109 +34,86 @@ License
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const lduMesh& mesh) Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const lduMesh& mesh)
: :
lduMesh_(mesh), lduMesh_(mesh)
diagPtr_(nullptr),
upperPtr_(nullptr),
lowerPtr_(nullptr),
sourcePtr_(nullptr),
interfaces_(0),
interfacesUpper_(0),
interfacesLower_(0)
{} {}
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const LduMatrix& A) Foam::LduMatrix<Type, DType, LUType>::LduMatrix(const LduMatrix& A)
: :
lduMesh_(A.lduMesh_), lduMesh_(A.lduMesh_)
diagPtr_(nullptr),
upperPtr_(nullptr),
lowerPtr_(nullptr),
sourcePtr_(nullptr),
interfaces_(0),
interfacesUpper_(0),
interfacesLower_(0)
{ {
if (A.diagPtr_) if (A.diagPtr_)
{ {
diagPtr_ = new Field<DType>(*(A.diagPtr_)); diagPtr_ = std::make_unique<Field<DType>>(*(A.diagPtr_));
} }
if (A.upperPtr_) if (A.upperPtr_)
{ {
upperPtr_ = new Field<LUType>(*(A.upperPtr_)); upperPtr_ = std::make_unique<Field<LUType>>(*(A.upperPtr_));
} }
if (A.lowerPtr_) if (A.lowerPtr_)
{ {
lowerPtr_ = new Field<LUType>(*(A.lowerPtr_)); lowerPtr_ = std::make_unique<Field<LUType>>(*(A.lowerPtr_));
} }
if (A.sourcePtr_) if (A.sourcePtr_)
{ {
sourcePtr_ = new Field<Type>(*(A.sourcePtr_)); sourcePtr_ = std::make_unique<Field<Type>>(*(A.sourcePtr_));
} }
} }
template<class Type, class DType, class LUType>
Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix&& A)
:
lduMesh_(A.lduMesh_),
diagPtr_(std::move(A.diagPtr_)),
lowerPtr_(std::move(A.lowerPtr_)),
upperPtr_(std::move(A.upperPtr_)),
sourcePtr_(std::move(A.sourcePtr_))
{
// Clear the old interfaces?
}
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix& A, bool reuse) Foam::LduMatrix<Type, DType, LUType>::LduMatrix(LduMatrix& A, bool reuse)
: :
lduMesh_(A.lduMesh_), lduMesh_(A.lduMesh_)
diagPtr_(nullptr),
upperPtr_(nullptr),
lowerPtr_(nullptr),
sourcePtr_(nullptr),
interfaces_(0),
interfacesUpper_(0),
interfacesLower_(0)
{ {
if (reuse) if (reuse)
{ {
if (A.diagPtr_) // Move assignment
{ diagPtr_ = std::move(A.diagPtr_);
diagPtr_ = A.diagPtr_; upperPtr_ = std::move(A.upperPtr_);
A.diagPtr_ = nullptr; lowerPtr_ = std::move(A.lowerPtr_);
} sourcePtr_ = std::move(A.sourcePtr_);
if (A.upperPtr_) // Clear the old interfaces?
{
upperPtr_ = A.upperPtr_;
A.upperPtr_ = nullptr;
}
if (A.lowerPtr_)
{
lowerPtr_ = A.lowerPtr_;
A.lowerPtr_ = nullptr;
}
if (A.sourcePtr_)
{
sourcePtr_ = A.sourcePtr_;
A.sourcePtr_ = nullptr;
}
} }
else else
{ {
// Copy assignment
if (A.diagPtr_) if (A.diagPtr_)
{ {
diagPtr_ = new Field<DType>(*(A.diagPtr_)); diagPtr_ = std::make_unique<Field<DType>>(*(A.diagPtr_));
} }
if (A.upperPtr_) if (A.upperPtr_)
{ {
upperPtr_ = new Field<LUType>(*(A.upperPtr_)); upperPtr_ = std::make_unique<Field<LUType>>(*(A.upperPtr_));
} }
if (A.lowerPtr_) if (A.lowerPtr_)
{ {
lowerPtr_ = new Field<LUType>(*(A.lowerPtr_)); lowerPtr_ = std::make_unique<Field<LUType>>(*(A.lowerPtr_));
} }
if (A.sourcePtr_) if (A.sourcePtr_)
{ {
sourcePtr_ = new Field<Type>(*(A.sourcePtr_)); sourcePtr_ = std::make_unique<Field<Type>>(*(A.sourcePtr_));
} }
} }
} }
@ -152,109 +130,27 @@ Foam::LduMatrix<Type, DType, LUType>::LduMatrix
diagPtr_(new Field<DType>(is)), diagPtr_(new Field<DType>(is)),
upperPtr_(new Field<LUType>(is)), upperPtr_(new Field<LUType>(is)),
lowerPtr_(new Field<LUType>(is)), lowerPtr_(new Field<LUType>(is)),
sourcePtr_(new Field<Type>(is)), sourcePtr_(new Field<Type>(is))
interfaces_(0),
interfacesUpper_(0),
interfacesLower_(0)
{} {}
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
template<class Type, class DType, class LUType>
Foam::LduMatrix<Type, DType, LUType>::~LduMatrix()
{
if (diagPtr_)
{
delete diagPtr_;
}
if (upperPtr_)
{
delete upperPtr_;
}
if (lowerPtr_)
{
delete lowerPtr_;
}
if (sourcePtr_)
{
delete sourcePtr_;
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag() Foam::word Foam::LduMatrix<Type, DType, LUType>::matrixTypeName() const
{ {
if (!diagPtr_) if (diagPtr_)
{ {
diagPtr_ = new Field<DType>(lduAddr().size(), Zero); return
(
(!upperPtr_)
? (!lowerPtr_ ? "diagonal" : "diagonal-lower")
: (!lowerPtr_ ? "symmetric" : "asymmetric")
);
} }
return *diagPtr_; // is empty (or just wrong)
} return (!upperPtr_ && !lowerPtr_ ? "empty" : "ill-defined");
template<class Type, class DType, class LUType>
Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper()
{
if (!upperPtr_)
{
if (lowerPtr_)
{
upperPtr_ = new Field<LUType>(*lowerPtr_);
}
else
{
upperPtr_ = new Field<LUType>
(
lduAddr().lowerAddr().size(),
Zero
);
}
}
return *upperPtr_;
}
template<class Type, class DType, class LUType>
Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower()
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = new Field<LUType>(*upperPtr_);
}
else
{
lowerPtr_ = new Field<LUType>
(
lduAddr().lowerAddr().size(),
Zero
);
}
}
return *lowerPtr_;
}
template<class Type, class DType, class LUType>
Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source()
{
if (!sourcePtr_)
{
sourcePtr_ = new Field<Type>(lduAddr().size(), Zero);
}
return *sourcePtr_;
} }
@ -273,47 +169,107 @@ const Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag() const
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper() const Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag()
{ {
if (!lowerPtr_ && !upperPtr_) if (!diagPtr_)
{ {
FatalErrorInFunction diagPtr_ =
<< "lowerPtr_ or upperPtr_ unallocated" std::make_unique<Field<DType>>(lduAddr().size(), Foam::zero{});
<< abort(FatalError);
} }
return *diagPtr_;
}
template<class Type, class DType, class LUType>
const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper() const
{
if (upperPtr_) if (upperPtr_)
{ {
return *upperPtr_; return *upperPtr_;
} }
else else
{ {
if (!lowerPtr_)
{
FatalErrorInFunction
<< "lowerPtr_ and upperPtr_ unallocated"
<< abort(FatalError);
}
return *lowerPtr_; return *lowerPtr_;
} }
} }
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower() const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::upper()
{ {
if (!lowerPtr_ && !upperPtr_) if (!upperPtr_)
{ {
FatalErrorInFunction if (lowerPtr_)
<< "lowerPtr_ or upperPtr_ unallocated" {
<< abort(FatalError); upperPtr_ = std::make_unique<Field<LUType>>(*lowerPtr_);
}
else
{
upperPtr_ =
std::make_unique<Field<LUType>>
(
lduAddr().lowerAddr().size(),
Foam::zero{}
);
}
} }
return *upperPtr_;
}
template<class Type, class DType, class LUType>
const Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower() const
{
if (lowerPtr_) if (lowerPtr_)
{ {
return *lowerPtr_; return *lowerPtr_;
} }
else else
{ {
if (!upperPtr_)
{
FatalErrorInFunction
<< "lowerPtr_ and upperPtr_ unallocated"
<< abort(FatalError);
}
return *upperPtr_; return *upperPtr_;
} }
} }
template<class Type, class DType, class LUType>
Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower()
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = std::make_unique<Field<LUType>>(*upperPtr_);
}
else
{
lowerPtr_ = std::make_unique<Field<LUType>>
(
lduAddr().lowerAddr().size(),
Foam::zero{}
);
}
}
return *lowerPtr_;
}
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const
{ {
@ -328,45 +284,65 @@ const Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() const
} }
template<class Type, class DType, class LUType>
Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source()
{
if (!sourcePtr_)
{
sourcePtr_ =
std::make_unique<Field<Type>>(lduAddr().size(), Foam::zero{});
}
return *sourcePtr_;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// template<class Type, class DType, class LUType>
// Foam::Ostream& Foam::operator<<
// (
// Ostream& os,
// const InfoProxy<Type, DType, LUType>& iproxy
// )
// {
// const auto& mat = *iproxy;
//
// ...
//
// os.check(FUNCTION_NAME);
// return os;
// }
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
Foam::Ostream& Foam::operator<< Foam::Ostream& Foam::operator<<
( (
Ostream& os, Ostream& os,
const LduMatrix<Type, DType, LUType>& ldum const LduMatrix<Type, DType, LUType>& mat
) )
{ {
if (ldum.diagPtr_) if (mat.hasDiag())
{ {
os << "Diagonal = " os << "Diagonal = " << mat.diag() << nl << nl;
<< *ldum.diagPtr_
<< endl << endl;
} }
if (ldum.upperPtr_) if (mat.hasUpper())
{ {
os << "Upper triangle = " os << "Upper triangle = " << mat.upper() << nl << nl;
<< *ldum.upperPtr_
<< endl << endl;
} }
if (ldum.lowerPtr_) if (mat.hasLower())
{ {
os << "Lower triangle = " os << "Lower triangle = " << mat.lower() << nl << nl;
<< *ldum.lowerPtr_
<< endl << endl;
} }
if (ldum.sourcePtr_) if (mat.hasSource())
{ {
os << "Source = " os << "Source = " << mat.source() << nl << nl;
<< *ldum.sourcePtr_
<< endl << endl;
} }
os.check(FUNCTION_NAME); os.check(FUNCTION_NAME);
return os; return os;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -93,25 +93,32 @@ class LduMatrix
const lduMesh& lduMesh_; const lduMesh& lduMesh_;
//- Diagonal coefficients //- Diagonal coefficients
Field<DType> *diagPtr_; std::unique_ptr<Field<DType>> diagPtr_;
//- Off-diagonal coefficients //- Off-diagonal coefficients
Field<LUType> *upperPtr_, *lowerPtr_; std::unique_ptr<Field<LUType>> upperPtr_;
//- Off-diagonal coefficients
std::unique_ptr<Field<LUType>> lowerPtr_;
//- Source //- Source
Field<Type> *sourcePtr_; std::unique_ptr<Field<Type>> sourcePtr_;
//- Field interfaces (processor patches etc.) //- Field interfaces (processor patches etc.)
LduInterfaceFieldPtrsList<Type> interfaces_; LduInterfaceFieldPtrsList<Type> interfaces_;
//- Off-diagonal coefficients for interfaces //- Off-diagonal coefficients for interfaces
FieldField<Field, LUType> interfacesUpper_, interfacesLower_; FieldField<Field, LUType> interfacesUpper_;
//- Off-diagonal coefficients for interfaces
FieldField<Field, LUType> interfacesLower_;
public: public:
friend class SolverPerformance<Type>; friend class SolverPerformance<Type>;
// -----------------------------------------------------------------------
//- Abstract base-class for LduMatrix solvers //- Abstract base-class for LduMatrix solvers
class solver class solver
{ {
@ -274,6 +281,7 @@ public:
}; };
// -----------------------------------------------------------------------
//- Abstract base-class for LduMatrix smoothers //- Abstract base-class for LduMatrix smoothers
class smoother class smoother
{ {
@ -371,6 +379,7 @@ public:
}; };
// -----------------------------------------------------------------------
//- Abstract base-class for LduMatrix preconditioners //- Abstract base-class for LduMatrix preconditioners
class preconditioner class preconditioner
{ {
@ -466,6 +475,8 @@ public:
}; };
// -----------------------------------------------------------------------
// Static Data // Static Data
// Declare name of the class and its debug switch // Declare name of the class and its debug switch
@ -476,126 +487,125 @@ public:
//- Construct given an LDU addressed mesh. //- Construct given an LDU addressed mesh.
// The coefficients are initially empty for subsequent setting. // The coefficients are initially empty for subsequent setting.
LduMatrix(const lduMesh&); // Not yet 'explicit' (legacy code may rely on implicit construct)
LduMatrix(const lduMesh& mesh);
//- Construct as copy //- Copy construct
LduMatrix(const LduMatrix<Type, DType, LUType>&); LduMatrix(const LduMatrix<Type, DType, LUType>&);
//- Move construct
LduMatrix(LduMatrix<Type, DType, LUType>&&);
//- Construct as copy or re-use as specified. //- Construct as copy or re-use as specified.
LduMatrix(LduMatrix<Type, DType, LUType>&, bool reuse); LduMatrix(LduMatrix<Type, DType, LUType>&, bool reuse);
//- Construct given an LDU addressed mesh and an Istream //- Construct given an LDU addressed mesh and an Istream
// from which the coefficients are read //- from which the coefficients are read
LduMatrix(const lduMesh&, Istream&); LduMatrix(const lduMesh& mesh, Istream& is);
//- Destructor //- Destructor
~LduMatrix(); ~LduMatrix() = default;
// Member Functions // Member Functions
// Access to addressing // Addressing
//- Return the LDU mesh from which the addressing is obtained //- Return the LDU mesh from which the addressing is obtained
const lduMesh& mesh() const noexcept const lduMesh& mesh() const noexcept
{ {
return lduMesh_; return lduMesh_;
} }
//- Return the LDU addressing //- Return the LDU addressing
const lduAddressing& lduAddr() const const lduAddressing& lduAddr() const
{ {
return lduMesh_.lduAddr(); return lduMesh_.lduAddr();
} }
//- Return the patch evaluation schedule //- Return the patch evaluation schedule
const lduSchedule& patchSchedule() const const lduSchedule& patchSchedule() const
{ {
return lduAddr().patchSchedule(); return lduMesh_.lduAddr().patchSchedule();
} }
//- Return interfaces //- Const access to the interfaces
const LduInterfaceFieldPtrsList<Type>& interfaces() const const LduInterfaceFieldPtrsList<Type>& interfaces() const noexcept
{ {
return interfaces_; return interfaces_;
} }
//- Return interfaces //- Non-const access to the interfaces
LduInterfaceFieldPtrsList<Type>& interfaces() LduInterfaceFieldPtrsList<Type>& interfaces() noexcept
{ {
return interfaces_; return interfaces_;
} }
// Access to coefficients // Coefficients
Field<DType>& diag(); const Field<DType>& diag() const;
Field<LUType>& upper(); const Field<LUType>& upper() const;
Field<LUType>& lower(); const Field<LUType>& lower() const;
Field<Type>& source(); const Field<Type>& source() const;
FieldField<Field, LUType>& interfacesUpper() Field<DType>& diag();
{ Field<LUType>& upper();
return interfacesUpper_; Field<LUType>& lower();
} Field<Type>& source();
FieldField<Field, LUType>& interfacesLower()
{
return interfacesLower_;
}
const Field<DType>& diag() const; // Interfaces
const Field<LUType>& upper() const;
const Field<LUType>& lower() const;
const Field<Type>& source() const;
const FieldField<Field, LUType>& interfacesUpper() const const FieldField<Field, LUType>& interfacesUpper() const noexcept
{ {
return interfacesUpper_; return interfacesUpper_;
} }
const FieldField<Field, LUType>& interfacesLower() const const FieldField<Field, LUType>& interfacesLower() const noexcept
{ {
return interfacesLower_; return interfacesLower_;
} }
FieldField<Field, LUType>& interfacesUpper() noexcept
{
return interfacesUpper_;
}
FieldField<Field, LUType>& interfacesLower() noexcept
{
return interfacesLower_;
}
bool hasDiag() const noexcept // Characteristics
{
return (diagPtr_);
}
bool hasUpper() const noexcept //- The matrix type (empty, diagonal, symmetric, ...)
{ word matrixTypeName() const;
return (upperPtr_);
}
bool hasLower() const noexcept bool hasDiag() const noexcept { return bool(diagPtr_); }
{ bool hasUpper() const noexcept { return bool(upperPtr_); }
return (lowerPtr_); bool hasLower() const noexcept { return bool(lowerPtr_); }
} bool hasSource() const noexcept { return bool(sourcePtr_); }
bool hasSource() const noexcept //- Matrix has diagonal only
{ bool diagonal() const noexcept
return (sourcePtr_); {
} return (diagPtr_ && !lowerPtr_ && !upperPtr_);
}
bool diagonal() const noexcept //- Matrix is symmetric
{ bool symmetric() const noexcept
return (diagPtr_ && !lowerPtr_ && !upperPtr_); {
} return (diagPtr_ && !lowerPtr_ && upperPtr_);
}
bool symmetric() const noexcept //- Matrix is asymmetric (ie, full)
{ bool asymmetric() const noexcept
return (diagPtr_ && (!lowerPtr_ && upperPtr_)); {
} return (diagPtr_ && lowerPtr_ && upperPtr_);
}
bool asymmetric() const noexcept
{
return (diagPtr_ && lowerPtr_ && upperPtr_);
}
// Operations // Operations
@ -651,8 +661,12 @@ public:
// Member Operators // Member Operators
//- Copy assignment
void operator=(const LduMatrix<Type, DType, LUType>&); void operator=(const LduMatrix<Type, DType, LUType>&);
//- Move assignment
void operator=(LduMatrix<Type, DType, LUType>&&);
void negate(); void negate();
void operator+=(const LduMatrix<Type, DType, LUType>&); void operator+=(const LduMatrix<Type, DType, LUType>&);

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -92,7 +92,7 @@ Foam::LduMatrix<Type, DType, LUType>::H(const Field<Type>& psi) const
{ {
auto tHpsi = tmp<Field<Type>>::New(lduAddr().size(), Foam::zero{}); auto tHpsi = tmp<Field<Type>>::New(lduAddr().size(), Foam::zero{});
if (lowerPtr_ || upperPtr_) if (hasLower() || hasUpper())
{ {
Type* __restrict__ HpsiPtr = tHpsi.ref().begin(); Type* __restrict__ HpsiPtr = tHpsi.ref().begin();
@ -169,32 +169,30 @@ void Foam::LduMatrix<Type, DType, LUType>::operator=(const LduMatrix& A)
return; // Self-assignment is a no-op return; // Self-assignment is a no-op
} }
if (A.diagPtr_) if (A.hasDiag())
{ {
diag() = A.diag(); diag() = A.diag();
} }
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = A.upper(); upper() = A.upper();
} }
else if (upperPtr_) else
{ {
delete upperPtr_; upperPtr_.reset(nullptr);
upperPtr_ = nullptr;
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = A.lower(); lower() = A.lower();
} }
else if (lowerPtr_) else
{ {
delete lowerPtr_; lowerPtr_.reset(nullptr);
lowerPtr_ = nullptr;
} }
if (A.sourcePtr_) if (A.hasSource())
{ {
source() = A.source(); source() = A.source();
} }
@ -204,6 +202,24 @@ void Foam::LduMatrix<Type, DType, LUType>::operator=(const LduMatrix& A)
} }
template<class Type, class DType, class LUType>
void Foam::LduMatrix<Type, DType, LUType>::operator=(LduMatrix&& A)
{
if (this == &A)
{
return; // Self-assignment is a no-op
}
diagPtr_ = std::move(A.diagPtr_);
upperPtr_ = std::move(A.upperPtr_);
lowerPtr_ = std::move(A.lowerPtr_);
sourcePtr_ = std::move(A.sourcePtr_);
interfacesUpper_ = std::move(A.interfacesUpper_);
interfacesLower_ = std::move(A.interfacesLower_);
}
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
void Foam::LduMatrix<Type, DType, LUType>::negate() void Foam::LduMatrix<Type, DType, LUType>::negate()
{ {
@ -235,12 +251,12 @@ void Foam::LduMatrix<Type, DType, LUType>::negate()
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A) void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
{ {
if (A.diagPtr_) if (A.hasDiag())
{ {
diag() += A.diag(); diag() += A.diag();
} }
if (A.sourcePtr_) if (A.hasSource())
{ {
source() += A.source(); source() += A.source();
} }
@ -265,7 +281,7 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
} }
else if (asymmetric() && A.symmetric()) else if (asymmetric() && A.symmetric())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
lower() += A.upper(); lower() += A.upper();
upper() += A.upper(); upper() += A.upper();
@ -284,12 +300,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
} }
else if (diagonal()) else if (diagonal())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = A.upper(); upper() = A.upper();
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = A.lower(); lower() = A.lower();
} }
@ -312,12 +328,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)
template<class Type, class DType, class LUType> template<class Type, class DType, class LUType>
void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A) void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
{ {
if (A.diagPtr_) if (A.hasDiag())
{ {
diag() -= A.diag(); diag() -= A.diag();
} }
if (A.sourcePtr_) if (A.hasSource())
{ {
source() -= A.source(); source() -= A.source();
} }
@ -342,7 +358,7 @@ void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
} }
else if (asymmetric() && A.symmetric()) else if (asymmetric() && A.symmetric())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
lower() -= A.upper(); lower() -= A.upper();
upper() -= A.upper(); upper() -= A.upper();
@ -361,12 +377,12 @@ void Foam::LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)
} }
else if (diagonal()) else if (diagonal())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = -A.upper(); upper() = -A.upper();
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = -A.lower(); lower() = -A.lower();
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -124,7 +124,7 @@ scalar det(const SquareMatrix<Type>& matrix)
{ {
SquareMatrix<Type> matrixTmp = matrix; SquareMatrix<Type> matrixTmp = matrix;
labelList pivotIndices(matrix.m()); labelList pivotIndices;
label sign; label sign;
LUDecompose(matrixTmp, pivotIndices, sign); LUDecompose(matrixTmp, pivotIndices, sign);
@ -136,7 +136,7 @@ scalar det(const SquareMatrix<Type>& matrix)
template<class Type> template<class Type>
scalar det(SquareMatrix<Type>& matrix) scalar det(SquareMatrix<Type>& matrix)
{ {
labelList pivotIndices(matrix.m()); labelList pivotIndices;
label sign; label sign;
LUDecompose(matrix, pivotIndices, sign); LUDecompose(matrix, pivotIndices, sign);

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016 OpenCFD Ltd. Copyright (C) 2016-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "lduAddressing.H" #include "lduAddressing.H"
#include "demandDrivenData.H"
#include "scalarField.H" #include "scalarField.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -44,7 +43,7 @@ void Foam::lduAddressing::calcLosort() const
// Scan the neighbour list to find out how many times the cell // Scan the neighbour list to find out how many times the cell
// appears as a neighbour of the face. Done this way to avoid guessing // appears as a neighbour of the face. Done this way to avoid guessing
// and resizing list // and resizing list
labelList nNbrOfFace(size(), Zero); labelList nNbrOfFace(size(), Foam::zero{});
const labelUList& nbr = upperAddr(); const labelUList& nbr = upperAddr();
@ -73,9 +72,8 @@ void Foam::lduAddressing::calcLosort() const
} }
// Gather the neighbours into the losort array // Gather the neighbours into the losort array
losortPtr_ = new labelList(nbr.size(), -1); losortPtr_ = std::make_unique<labelList>(nbr.size(), -1);
auto& lst = *losortPtr_;
labelList& lst = *losortPtr_;
// Set counter for losort // Set counter for losort
label lstI = 0; label lstI = 0;
@ -104,9 +102,8 @@ void Foam::lduAddressing::calcOwnerStart() const
const labelList& own = lowerAddr(); const labelList& own = lowerAddr();
ownerStartPtr_ = new labelList(size() + 1, own.size()); ownerStartPtr_ = std::make_unique<labelList>(size() + 1, own.size());
auto& ownStart = *ownerStartPtr_;
labelList& ownStart = *ownerStartPtr_;
// Set up first lookup by hand // Set up first lookup by hand
ownStart[0] = 0; ownStart[0] = 0;
@ -139,9 +136,8 @@ void Foam::lduAddressing::calcLosortStart() const
<< abort(FatalError); << abort(FatalError);
} }
losortStartPtr_ = new labelList(size() + 1, Zero); losortStartPtr_ = std::make_unique<labelList>(size() + 1, Foam::zero{});
auto& lsrtStart = *losortStartPtr_;
labelList& lsrtStart = *losortStartPtr_;
const labelList& nbr = upperAddr(); const labelList& nbr = upperAddr();
@ -173,16 +169,6 @@ void Foam::lduAddressing::calcLosortStart() const
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::lduAddressing::~lduAddressing()
{
deleteDemandDrivenData(losortPtr_);
deleteDemandDrivenData(ownerStartPtr_);
deleteDemandDrivenData(losortStartPtr_);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::labelUList& Foam::lduAddressing::losortAddr() const const Foam::labelUList& Foam::lduAddressing::losortAddr() const
@ -220,9 +206,9 @@ const Foam::labelUList& Foam::lduAddressing::losortStartAddr() const
void Foam::lduAddressing::clearOut() void Foam::lduAddressing::clearOut()
{ {
deleteDemandDrivenData(losortPtr_); losortPtr_.reset(nullptr);
deleteDemandDrivenData(ownerStartPtr_); ownerStartPtr_.reset(nullptr);
deleteDemandDrivenData(losortStartPtr_); losortStartPtr_.reset(nullptr);
} }
@ -262,7 +248,7 @@ Foam::Tuple2<Foam::label, Foam::scalar> Foam::lduAddressing::band() const
const labelUList& owner = lowerAddr(); const labelUList& owner = lowerAddr();
const labelUList& neighbour = upperAddr(); const labelUList& neighbour = upperAddr();
labelList cellBandwidth(size(), Zero); labelList cellBandwidth(size(), Foam::zero{});
forAll(neighbour, facei) forAll(neighbour, facei)
{ {

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd. Copyright (C) 2016-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -123,23 +123,17 @@ class lduAddressing
//- Demand-driven data //- Demand-driven data
//- Losort addressing //- Losort addressing
mutable labelList* losortPtr_; mutable std::unique_ptr<labelList> losortPtr_;
//- Owner start addressing //- Owner start addressing
mutable labelList* ownerStartPtr_; mutable std::unique_ptr<labelList> ownerStartPtr_;
//- Losort start addressing //- Losort start addressing
mutable labelList* losortStartPtr_; mutable std::unique_ptr<labelList> losortStartPtr_;
// Private Member Functions // Private Member Functions
//- No copy construct
lduAddressing(const lduAddressing&) = delete;
//- No copy assignment
void operator=(const lduAddressing&) = delete;
//- Calculate losort //- Calculate losort
void calcLosort() const; void calcLosort() const;
@ -152,24 +146,32 @@ class lduAddressing
public: public:
//- Construct with size (number of equations) // Generated Methods
explicit lduAddressing(const label nEqns)
: //- No copy construct
size_(nEqns), lduAddressing(const lduAddressing&) = delete;
losortPtr_(nullptr),
ownerStartPtr_(nullptr), //- No copy assignment
losortStartPtr_(nullptr) void operator=(const lduAddressing&) = delete;
{}
// Constructors
//- Construct with size (number of equations)
explicit lduAddressing(const label nEqns) noexcept
:
size_(nEqns)
{}
//- Destructor //- Destructor
virtual ~lduAddressing(); virtual ~lduAddressing() = default;
// Member Functions // Member Functions
//- Return number of equations //- Return number of equations
label size() const label size() const noexcept
{ {
return size_; return size_;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-2021 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -60,79 +60,66 @@ Foam::lduMatrix::normTypesNames_
Foam::lduMatrix::lduMatrix(const lduMesh& mesh) Foam::lduMatrix::lduMatrix(const lduMesh& mesh)
: :
lduMesh_(mesh), lduMesh_(mesh)
lowerPtr_(nullptr),
diagPtr_(nullptr),
upperPtr_(nullptr)
{} {}
Foam::lduMatrix::lduMatrix(const lduMatrix& A) Foam::lduMatrix::lduMatrix(const lduMatrix& A)
: :
lduMesh_(A.lduMesh_), lduMesh_(A.lduMesh_)
lowerPtr_(nullptr),
diagPtr_(nullptr),
upperPtr_(nullptr)
{ {
if (A.lowerPtr_)
{
lowerPtr_ = new scalarField(*(A.lowerPtr_));
}
if (A.diagPtr_) if (A.diagPtr_)
{ {
diagPtr_ = new scalarField(*(A.diagPtr_)); diagPtr_ = std::make_unique<scalarField>(*(A.diagPtr_));
} }
if (A.upperPtr_) if (A.upperPtr_)
{ {
upperPtr_ = new scalarField(*(A.upperPtr_)); upperPtr_ = std::make_unique<scalarField>(*(A.upperPtr_));
}
if (A.lowerPtr_)
{
lowerPtr_ = std::make_unique<scalarField>(*(A.lowerPtr_));
} }
} }
Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse) Foam::lduMatrix::lduMatrix(lduMatrix&& A)
: :
lduMesh_(A.lduMesh_), lduMesh_(A.lduMesh_),
lowerPtr_(nullptr), diagPtr_(std::move(A.diagPtr_)),
diagPtr_(nullptr), lowerPtr_(std::move(A.lowerPtr_)),
upperPtr_(nullptr) upperPtr_(std::move(A.upperPtr_))
{}
Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse)
:
lduMesh_(A.lduMesh_)
{ {
if (reuse) if (reuse)
{ {
if (A.lowerPtr_) diagPtr_ = std::move(A.diagPtr_);
{ upperPtr_ = std::move(A.upperPtr_);
lowerPtr_ = A.lowerPtr_; lowerPtr_ = std::move(A.lowerPtr_);
A.lowerPtr_ = nullptr;
}
if (A.diagPtr_)
{
diagPtr_ = A.diagPtr_;
A.diagPtr_ = nullptr;
}
if (A.upperPtr_)
{
upperPtr_ = A.upperPtr_;
A.upperPtr_ = nullptr;
}
} }
else else
{ {
if (A.lowerPtr_) // Copy assignment
{
lowerPtr_ = new scalarField(*(A.lowerPtr_));
}
if (A.diagPtr_) if (A.diagPtr_)
{ {
diagPtr_ = new scalarField(*(A.diagPtr_)); diagPtr_ = std::make_unique<scalarField>(*(A.diagPtr_));
} }
if (A.upperPtr_) if (A.upperPtr_)
{ {
upperPtr_ = new scalarField(*(A.upperPtr_)); upperPtr_ = std::make_unique<scalarField>(*(A.upperPtr_));
}
if (A.lowerPtr_)
{
lowerPtr_ = std::make_unique<scalarField>(*(A.lowerPtr_));
} }
} }
} }
@ -140,160 +127,43 @@ Foam::lduMatrix::lduMatrix(lduMatrix& A, bool reuse)
Foam::lduMatrix::lduMatrix(const lduMesh& mesh, Istream& is) Foam::lduMatrix::lduMatrix(const lduMesh& mesh, Istream& is)
: :
lduMesh_(mesh), lduMesh_(mesh)
lowerPtr_(nullptr),
diagPtr_(nullptr),
upperPtr_(nullptr)
{ {
Switch hasLow(is); bool withLower, withDiag, withUpper;
Switch hasDiag(is);
Switch hasUp(is);
if (hasLow) is >> withLower >> withDiag >> withUpper;
if (withLower)
{ {
lowerPtr_ = new scalarField(is); lowerPtr_ = std::make_unique<scalarField>(is);
} }
if (hasDiag) if (withDiag)
{ {
diagPtr_ = new scalarField(is); diagPtr_ = std::make_unique<scalarField>(is);
} }
if (hasUp) if (withUpper)
{ {
upperPtr_ = new scalarField(is); upperPtr_ = std::make_unique<scalarField>(is);
} }
} }
Foam::lduMatrix::~lduMatrix() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
{
if (lowerPtr_)
{
delete lowerPtr_;
}
Foam::word Foam::lduMatrix::matrixTypeName() const
{
if (diagPtr_) if (diagPtr_)
{ {
delete diagPtr_; return
(
(!upperPtr_)
? (!lowerPtr_ ? "diagonal" : "diagonal-lower")
: (!lowerPtr_ ? "symmetric" : "asymmetric")
);
} }
if (upperPtr_) // is empty (or just wrong)
{ return (!upperPtr_ && !lowerPtr_ ? "empty" : "ill-defined");
delete upperPtr_;
}
}
Foam::scalarField& Foam::lduMatrix::lower()
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = new scalarField(*upperPtr_);
}
else
{
lowerPtr_ = new scalarField(lduAddr().lowerAddr().size(), Zero);
}
}
return *lowerPtr_;
}
Foam::scalarField& Foam::lduMatrix::diag()
{
if (!diagPtr_)
{
diagPtr_ = new scalarField(lduAddr().size(), Zero);
}
return *diagPtr_;
}
Foam::scalarField& Foam::lduMatrix::upper()
{
if (!upperPtr_)
{
if (lowerPtr_)
{
upperPtr_ = new scalarField(*lowerPtr_);
}
else
{
upperPtr_ = new scalarField(lduAddr().lowerAddr().size(), Zero);
}
}
return *upperPtr_;
}
Foam::scalarField& Foam::lduMatrix::lower(const label nCoeffs)
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = new scalarField(*upperPtr_);
}
else
{
lowerPtr_ = new scalarField(nCoeffs, Zero);
}
}
return *lowerPtr_;
}
Foam::scalarField& Foam::lduMatrix::diag(const label size)
{
if (!diagPtr_)
{
diagPtr_ = new scalarField(size, Zero);
}
return *diagPtr_;
}
Foam::scalarField& Foam::lduMatrix::upper(const label nCoeffs)
{
if (!upperPtr_)
{
if (lowerPtr_)
{
upperPtr_ = new scalarField(*lowerPtr_);
}
else
{
upperPtr_ = new scalarField(nCoeffs, Zero);
}
}
return *upperPtr_;
}
const Foam::scalarField& Foam::lduMatrix::lower() const
{
if (!lowerPtr_ && !upperPtr_)
{
FatalErrorInFunction
<< "lowerPtr_ or upperPtr_ unallocated"
<< abort(FatalError);
}
if (lowerPtr_)
{
return *lowerPtr_;
}
else
{
return *upperPtr_;
}
} }
@ -310,26 +180,164 @@ const Foam::scalarField& Foam::lduMatrix::diag() const
} }
const Foam::scalarField& Foam::lduMatrix::upper() const Foam::scalarField& Foam::lduMatrix::diag()
{ {
if (!lowerPtr_ && !upperPtr_) if (!diagPtr_)
{ {
FatalErrorInFunction diagPtr_ =
<< "lowerPtr_ or upperPtr_ unallocated" std::make_unique<scalarField>(lduAddr().size(), Foam::zero{});
<< abort(FatalError);
} }
return *diagPtr_;
}
Foam::scalarField& Foam::lduMatrix::diag(label size)
{
if (!diagPtr_)
{
// if (size < 0)
// {
// size = lduAddr().size();
// }
diagPtr_ = std::make_unique<scalarField>(size, Foam::zero{});
}
return *diagPtr_;
}
const Foam::scalarField& Foam::lduMatrix::upper() const
{
if (upperPtr_) if (upperPtr_)
{ {
return *upperPtr_; return *upperPtr_;
} }
else else
{ {
if (!lowerPtr_)
{
FatalErrorInFunction
<< "lowerPtr_ and upperPtr_ unallocated"
<< abort(FatalError);
}
return *lowerPtr_; return *lowerPtr_;
} }
} }
Foam::scalarField& Foam::lduMatrix::upper()
{
if (!upperPtr_)
{
if (lowerPtr_)
{
upperPtr_ = std::make_unique<scalarField>(*lowerPtr_);
}
else
{
upperPtr_ =
std::make_unique<scalarField>
(
lduAddr().lowerAddr().size(),
Foam::zero{}
);
}
}
return *upperPtr_;
}
Foam::scalarField& Foam::lduMatrix::upper(label nCoeffs)
{
if (!upperPtr_)
{
if (lowerPtr_)
{
upperPtr_ = std::make_unique<scalarField>(*lowerPtr_);
}
else
{
// if (nCoeffs < 0)
// {
// nCoeffs = lduAddr().lowerAddr().size();
// }
upperPtr_ = std::make_unique<scalarField>(nCoeffs, Foam::zero{});
}
}
return *upperPtr_;
}
const Foam::scalarField& Foam::lduMatrix::lower() const
{
if (lowerPtr_)
{
return *lowerPtr_;
}
else
{
if (!upperPtr_)
{
FatalErrorInFunction
<< "lowerPtr_ and upperPtr_ unallocated"
<< abort(FatalError);
}
return *upperPtr_;
}
}
Foam::scalarField& Foam::lduMatrix::lower()
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = std::make_unique<scalarField>(*upperPtr_);
}
else
{
lowerPtr_ =
std::make_unique<scalarField>
(
lduAddr().lowerAddr().size(),
Foam::zero{}
);
}
}
return *lowerPtr_;
}
Foam::scalarField& Foam::lduMatrix::lower(label nCoeffs)
{
if (!lowerPtr_)
{
if (upperPtr_)
{
lowerPtr_ = std::make_unique<scalarField>(*upperPtr_);
}
else
{
// if (nCoeffs < 0)
// {
// nCoeffs = lduAddr().lowerAddr().size();
// }
lowerPtr_ =
std::make_unique<scalarField>(nCoeffs, Foam::zero{});
}
}
return *lowerPtr_;
}
void Foam::lduMatrix::setResidualField void Foam::lduMatrix::setResidualField
( (
const scalarField& residual, const scalarField& residual,
@ -377,28 +385,25 @@ void Foam::lduMatrix::setResidualField
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const lduMatrix& ldum) Foam::Ostream& Foam::operator<<(Ostream& os, const lduMatrix& mat)
{ {
Switch hasLow = ldum.hasLower(); os << mat.hasLower() << token::SPACE
Switch hasDiag = ldum.hasDiag(); << mat.hasDiag() << token::SPACE
Switch hasUp = ldum.hasUpper(); << mat.hasUpper() << token::SPACE;
os << hasLow << token::SPACE << hasDiag << token::SPACE if (mat.hasLower())
<< hasUp << token::SPACE;
if (hasLow)
{ {
os << ldum.lower(); os << mat.lower();
} }
if (hasDiag) if (mat.hasDiag())
{ {
os << ldum.diag(); os << mat.diag();
} }
if (hasUp) if (mat.hasUpper())
{ {
os << ldum.upper(); os << mat.upper();
} }
os.check(FUNCTION_NAME); os.check(FUNCTION_NAME);
@ -413,54 +418,50 @@ Foam::Ostream& Foam::operator<<
const InfoProxy<lduMatrix>& iproxy const InfoProxy<lduMatrix>& iproxy
) )
{ {
const auto& ldum = *iproxy; const auto& mat = *iproxy;
Switch hasLow = ldum.hasLower(); os << "Lower:" << Switch::name(mat.hasLower())
Switch hasDiag = ldum.hasDiag(); << " Diag:" << Switch::name(mat.hasDiag())
Switch hasUp = ldum.hasUpper(); << " Upper:" << Switch::name(mat.hasUpper()) << endl;
os << "Lower:" << hasLow if (mat.hasLower())
<< " Diag:" << hasDiag
<< " Upper:" << hasUp << endl;
if (hasLow)
{ {
os << "lower:" << ldum.lower().size() << endl; os << "lower:" << mat.lower().size() << endl;
} }
if (hasDiag) if (mat.hasDiag())
{ {
os << "diag :" << ldum.diag().size() << endl; os << "diag :" << mat.diag().size() << endl;
} }
if (hasUp) if (mat.hasUpper())
{ {
os << "upper:" << ldum.upper().size() << endl; os << "upper:" << mat.upper().size() << endl;
} }
//if (hasLow) //if (hasLower)
//{ //{
// os << "lower contents:" << endl; // os << "lower contents:" << endl;
// forAll(ldum.lower(), i) // forAll(mat.lower(), i)
// { // {
// os << "i:" << i << "\t" << ldum.lower()[i] << endl; // os << "i:" << i << "\t" << mat.lower()[i] << endl;
// } // }
// os << endl; // os << endl;
//} //}
//if (hasDiag) //if (hasDiag)
//{ //{
// os << "diag contents:" << endl; // os << "diag contents:" << endl;
// forAll(ldum.diag(), i) // forAll(mat.diag(), i)
// { // {
// os << "i:" << i << "\t" << ldum.diag()[i] << endl; // os << "i:" << i << "\t" << mat.diag()[i] << endl;
// } // }
// os << endl; // os << endl;
//} //}
//if (hasUp) //if (hasUpper)
//{ //{
// os << "upper contents:" << endl; // os << "upper contents:" << endl;
// forAll(ldum.upper(), i) // forAll(mat.upper(), i)
// { // {
// os << "i:" << i << "\t" << ldum.upper()[i] << endl; // os << "i:" << i << "\t" << mat.upper()[i] << endl;
// } // }
// os << endl; // os << endl;
//} //}

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd. Copyright (C) 2016-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -57,13 +57,14 @@ SourceFiles
#include "primitiveFieldsFwd.H" #include "primitiveFieldsFwd.H"
#include "FieldField.H" #include "FieldField.H"
#include "lduInterfaceFieldPtrsList.H" #include "lduInterfaceFieldPtrsList.H"
#include "solverPerformance.H"
#include "typeInfo.H" #include "typeInfo.H"
#include "autoPtr.H" #include "autoPtr.H"
#include "runTimeSelectionTables.H" #include "runTimeSelectionTables.H"
#include "solverPerformance.H"
#include "InfoProxy.H" #include "InfoProxy.H"
#include "Enum.H" #include "Enum.H"
#include "profilingTrigger.H" #include "profilingTrigger.H"
#include <functional> // For reference_wrapper
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -89,8 +90,14 @@ class lduMatrix
//const lduMesh& lduMesh_; //const lduMesh& lduMesh_;
std::reference_wrapper<const lduMesh> lduMesh_; std::reference_wrapper<const lduMesh> lduMesh_;
//- Coefficients (not including interfaces) //- Diagonal coefficients
scalarField *lowerPtr_, *diagPtr_, *upperPtr_; std::unique_ptr<scalarField> diagPtr_;
//- Off-diagonal coefficients (not including interfaces)
std::unique_ptr<scalarField> lowerPtr_;
//- Off-diagonal coefficients (not including interfaces)
std::unique_ptr<scalarField> upperPtr_;
public: public:
@ -115,6 +122,7 @@ public:
static const scalar defaultTolerance; static const scalar defaultTolerance;
// -----------------------------------------------------------------------
//- Abstract base-class for lduMatrix solvers //- Abstract base-class for lduMatrix solvers
class solver class solver
{ {
@ -331,6 +339,7 @@ public:
}; };
// -----------------------------------------------------------------------
//- Abstract base-class for lduMatrix smoothers //- Abstract base-class for lduMatrix smoothers
class smoother class smoother
{ {
@ -478,6 +487,7 @@ public:
}; };
// -----------------------------------------------------------------------
//- Abstract base-class for lduMatrix preconditioners //- Abstract base-class for lduMatrix preconditioners
class preconditioner class preconditioner
{ {
@ -582,6 +592,8 @@ public:
}; };
// -----------------------------------------------------------------------
// Static Data // Static Data
// Declare name of the class and its debug switch // Declare name of the class and its debug switch
@ -590,101 +602,101 @@ public:
// Constructors // Constructors
//- Construct given an LDU addressed mesh. //- Construct (without coefficients) for an LDU addressed mesh.
// The coefficients are initially empty for subsequent setting. // Not yet 'explicit' (legacy code may rely on implicit construct)
lduMatrix(const lduMesh&); lduMatrix(const lduMesh& mesh);
//- Construct as copy //- Copy construct
lduMatrix(const lduMatrix&); lduMatrix(const lduMatrix&);
//- Move construct
lduMatrix(lduMatrix&&);
//- Construct as copy or re-use as specified. //- Construct as copy or re-use as specified.
lduMatrix(lduMatrix&, bool reuse); lduMatrix(lduMatrix&, bool reuse);
//- Construct given an LDU addressed mesh and an Istream //- Construct given an LDU addressed mesh and an Istream
//- from which the coefficients are read //- from which the coefficients are read
lduMatrix(const lduMesh&, Istream&); lduMatrix(const lduMesh& mesh, Istream& is);
//- Destructor //- Destructor
~lduMatrix(); ~lduMatrix() = default;
// Member Functions // Member Functions
// Access to addressing // Addressing
//- Return the LDU mesh from which the addressing is obtained //- Return the LDU mesh from which the addressing is obtained
const lduMesh& mesh() const noexcept const lduMesh& mesh() const noexcept
{ {
return lduMesh_; return lduMesh_;
} }
//- Set the LDU mesh containing the addressing is obtained //- Set the LDU mesh containing the addressing
void setLduMesh(const lduMesh& m) void setLduMesh(const lduMesh& m)
{ {
lduMesh_ = m; lduMesh_ = m;
} }
//- Return the LDU addressing //- Return the LDU addressing
const lduAddressing& lduAddr() const const lduAddressing& lduAddr() const
{ {
return mesh().lduAddr(); return mesh().lduAddr();
} }
//- Return the patch evaluation schedule //- Return the patch evaluation schedule
const lduSchedule& patchSchedule() const const lduSchedule& patchSchedule() const
{ {
return lduAddr().patchSchedule(); return mesh().lduAddr().patchSchedule();
} }
// Access to coefficients // Coefficients
scalarField& lower(); const scalarField& diag() const;
scalarField& diag(); const scalarField& upper() const;
scalarField& upper(); const scalarField& lower() const;
// Size with externally provided sizes (for constructing with 'fake' scalarField& diag();
// mesh in GAMG) scalarField& upper();
scalarField& lower();
scalarField& lower(const label size); // Size with externally provided sizes
scalarField& diag(const label nCoeffs); // (for constructing with 'fake' mesh in GAMG)
scalarField& upper(const label nCoeffs);
scalarField& diag(label size);
scalarField& upper(label nCoeffs);
scalarField& lower(label nCoeffs);
const scalarField& lower() const; // Characteristics
const scalarField& diag() const;
const scalarField& upper() const;
bool hasDiag() const noexcept //- The matrix type (empty, diagonal, symmetric, ...)
{ word matrixTypeName() const;
return (diagPtr_);
}
bool hasUpper() const noexcept bool hasDiag() const noexcept { return bool(diagPtr_); }
{ bool hasUpper() const noexcept { return bool(upperPtr_); }
return (upperPtr_); bool hasLower() const noexcept { return bool(lowerPtr_); }
}
bool hasLower() const noexcept //- Matrix has diagonal only
{ bool diagonal() const noexcept
return (lowerPtr_); {
} return (diagPtr_ && !lowerPtr_ && !upperPtr_);
}
bool diagonal() const noexcept //- Matrix is symmetric
{ bool symmetric() const noexcept
return (diagPtr_ && !lowerPtr_ && !upperPtr_); {
} return (diagPtr_ && !lowerPtr_ && upperPtr_);
}
bool symmetric() const noexcept //- Matrix is asymmetric (ie, full)
{ bool asymmetric() const noexcept
return (diagPtr_ && (!lowerPtr_ && upperPtr_)); {
} return (diagPtr_ && lowerPtr_ && upperPtr_);
}
bool asymmetric() const noexcept
{
return (diagPtr_ && lowerPtr_ && upperPtr_);
}
// Operations // Operations
@ -801,8 +813,12 @@ public:
// Member Operators // Member Operators
//- Copy assignment
void operator=(const lduMatrix&); void operator=(const lduMatrix&);
//- Move assignment
void operator=(lduMatrix&&);
void negate(); void negate();
void operator+=(const lduMatrix&); void operator+=(const lduMatrix&);

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -86,7 +86,7 @@ void Foam::lduMatrix::sumMagOffDiag
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::lduMatrix::operator=(const lduMatrix& A) void Foam::lduMatrix::operator=(const lduMatrix& A)
{ {
@ -95,38 +95,49 @@ void Foam::lduMatrix::operator=(const lduMatrix& A)
return; // Self-assignment is a no-op return; // Self-assignment is a no-op
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = A.lower(); lower() = A.lower();
} }
else if (lowerPtr_) else
{ {
delete lowerPtr_; lowerPtr_.reset(nullptr);
lowerPtr_ = nullptr;
} }
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = A.upper(); upper() = A.upper();
} }
else if (upperPtr_) else
{ {
delete upperPtr_; upperPtr_.reset(nullptr);
upperPtr_ = nullptr;
} }
if (A.diagPtr_) if (A.hasDiag())
{ {
diag() = A.diag(); diag() = A.diag();
} }
} }
void Foam::lduMatrix::operator=(lduMatrix&& A)
{
if (this == &A)
{
return; // Self-assignment is a no-op
}
diagPtr_ = std::move(A.diagPtr_);
upperPtr_ = std::move(A.upperPtr_);
lowerPtr_ = std::move(A.lowerPtr_);
}
void Foam::lduMatrix::negate() void Foam::lduMatrix::negate()
{ {
if (lowerPtr_) if (diagPtr_)
{ {
lowerPtr_->negate(); diagPtr_->negate();
} }
if (upperPtr_) if (upperPtr_)
@ -134,16 +145,16 @@ void Foam::lduMatrix::negate()
upperPtr_->negate(); upperPtr_->negate();
} }
if (diagPtr_) if (lowerPtr_)
{ {
diagPtr_->negate(); lowerPtr_->negate();
} }
} }
void Foam::lduMatrix::operator+=(const lduMatrix& A) void Foam::lduMatrix::operator+=(const lduMatrix& A)
{ {
if (A.diagPtr_) if (A.hasDiag())
{ {
diag() += A.diag(); diag() += A.diag();
} }
@ -168,7 +179,7 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
} }
else if (asymmetric() && A.symmetric()) else if (asymmetric() && A.symmetric())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
lower() += A.upper(); lower() += A.upper();
upper() += A.upper(); upper() += A.upper();
@ -187,12 +198,12 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
} }
else if (diagonal()) else if (diagonal())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = A.upper(); upper() = A.upper();
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = A.lower(); lower() = A.lower();
} }
@ -206,15 +217,8 @@ void Foam::lduMatrix::operator+=(const lduMatrix& A)
{ {
WarningInFunction WarningInFunction
<< "Unknown matrix type combination" << nl << "Unknown matrix type combination" << nl
<< " this :" << " this : " << this->matrixTypeName()
<< " diagonal:" << diagonal() << " A : " << A.matrixTypeName() << endl;
<< " symmetric:" << symmetric()
<< " asymmetric:" << asymmetric() << nl
<< " A :"
<< " diagonal:" << A.diagonal()
<< " symmetric:" << A.symmetric()
<< " asymmetric:" << A.asymmetric()
<< endl;
} }
} }
} }
@ -247,7 +251,7 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
} }
else if (asymmetric() && A.symmetric()) else if (asymmetric() && A.symmetric())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
lower() -= A.upper(); lower() -= A.upper();
upper() -= A.upper(); upper() -= A.upper();
@ -266,12 +270,12 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
} }
else if (diagonal()) else if (diagonal())
{ {
if (A.upperPtr_) if (A.hasUpper())
{ {
upper() = -A.upper(); upper() = -A.upper();
} }
if (A.lowerPtr_) if (A.hasLower())
{ {
lower() = -A.lower(); lower() = -A.lower();
} }
@ -285,15 +289,8 @@ void Foam::lduMatrix::operator-=(const lduMatrix& A)
{ {
WarningInFunction WarningInFunction
<< "Unknown matrix type combination" << nl << "Unknown matrix type combination" << nl
<< " this :" << " this : " << this->matrixTypeName()
<< " diagonal:" << diagonal() << " A : " << A.matrixTypeName() << endl;
<< " symmetric:" << symmetric()
<< " asymmetric:" << asymmetric() << nl
<< " A :"
<< " diagonal:" << A.diagonal()
<< " symmetric:" << A.symmetric()
<< " asymmetric:" << A.asymmetric()
<< endl;
} }
} }
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -48,17 +49,20 @@ void Foam::LUDecompose
label& sign label& sign
) )
{ {
label m = matrix.m(); const label size = matrix.m();
scalar vv[m];
pivotIndices.resize_nocopy(size);
List<scalar> vv(size);
sign = 1; sign = 1;
for (label i = 0; i < m; ++i) for (label i = 0; i < size; ++i)
{ {
scalar largestCoeff = 0.0; scalar largestCoeff = 0.0;
scalar temp; scalar temp;
const scalar* __restrict__ matrixi = matrix[i]; const scalar* __restrict__ matrixi = matrix[i];
for (label j = 0; j < m; ++j) for (label j = 0; j < size; ++j)
{ {
if ((temp = mag(matrixi[j])) > largestCoeff) if ((temp = mag(matrixi[j])) > largestCoeff)
{ {
@ -75,7 +79,7 @@ void Foam::LUDecompose
vv[i] = 1.0/largestCoeff; vv[i] = 1.0/largestCoeff;
} }
for (label j = 0; j < m; ++j) for (label j = 0; j < size; ++j)
{ {
scalar* __restrict__ matrixj = matrix[j]; scalar* __restrict__ matrixj = matrix[j];
@ -94,7 +98,7 @@ void Foam::LUDecompose
label iMax = 0; label iMax = 0;
scalar largestCoeff = 0.0; scalar largestCoeff = 0.0;
for (label i = j; i < m; ++i) for (label i = j; i < size; ++i)
{ {
scalar* __restrict__ matrixi = matrix[i]; scalar* __restrict__ matrixi = matrix[i];
scalar sum = matrixi[j]; scalar sum = matrixi[j];
@ -120,7 +124,7 @@ void Foam::LUDecompose
{ {
scalar* __restrict__ matrixiMax = matrix[iMax]; scalar* __restrict__ matrixiMax = matrix[iMax];
for (label k = 0; k < m; ++k) for (label k = 0; k < size; ++k)
{ {
std::swap(matrixj[k], matrixiMax[k]); std::swap(matrixj[k], matrixiMax[k]);
} }
@ -134,11 +138,11 @@ void Foam::LUDecompose
matrixj[j] = SMALL; matrixj[j] = SMALL;
} }
if (j != m-1) if (j != size-1)
{ {
scalar rDiag = 1.0/matrixj[j]; scalar rDiag = 1.0/matrixj[j];
for (label i = j + 1; i < m; ++i) for (label i = j + 1; i < size; ++i)
{ {
matrix(i, j) *= rDiag; matrix(i, j) *= rDiag;
} }
@ -150,7 +154,7 @@ void Foam::LUDecompose
void Foam::LUDecompose(scalarSymmetricSquareMatrix& matrix) void Foam::LUDecompose(scalarSymmetricSquareMatrix& matrix)
{ {
// Store result in upper triangular part of matrix // Store result in upper triangular part of matrix
label size = matrix.m(); const label size = matrix.m();
// Set upper triangular parts to zero. // Set upper triangular parts to zero.
for (label j = 0; j < size; ++j) for (label j = 0; j < size; ++j)
@ -223,7 +227,7 @@ void Foam::multiply
<< abort(FatalError); << abort(FatalError);
} }
ans = scalarRectangularMatrix(A.m(), C.n(), Zero); ans = scalarRectangularMatrix(A.m(), C.n(), Foam::zero{});
for (label i = 0; i < A.m(); ++i) for (label i = 0; i < A.m(); ++i)
{ {

View File

@ -74,19 +74,21 @@ void solve
const List<Type>& source const List<Type>& source
); );
//- LU decompose the matrix with pivoting //- LU decompose the matrix with pivoting.
void LUDecompose void LUDecompose
( (
scalarSquareMatrix& matrix, scalarSquareMatrix& matrix,
//! [out] size is adjusted as required
labelList& pivotIndices labelList& pivotIndices
); );
//- LU decompose the matrix with pivoting. //- LU decompose the matrix with pivoting.
//- sign is -1 for odd number of row interchanges and 1 for even number.
void LUDecompose void LUDecompose
( (
scalarSquareMatrix& matrix, scalarSquareMatrix& matrix,
//! [out] size is adjusted as required
labelList& pivotIndices, labelList& pivotIndices,
//! [out] is -1 for odd number of row interchanges and 1 for even number
label& sign label& sign
); );

View File

@ -216,7 +216,7 @@ void Foam::LUsolve
List<Type>& sourceSol List<Type>& sourceSol
) )
{ {
labelList pivotIndices(matrix.m()); labelList pivotIndices;
LUDecompose(matrix, pivotIndices); LUDecompose(matrix, pivotIndices);
LUBacksubstitute(matrix, pivotIndices, sourceSol); LUBacksubstitute(matrix, pivotIndices, sourceSol);
} }