ENH: improve procLduMatrix streaming and assembly of LUscalarMatrix

- reduce local overhead prior to sending for master assembly
- non-blocking mode when assembling solution vector
- automatic resizing of pivots
This commit is contained in:
Mark Olesen
2024-02-08 11:20:08 +01:00
parent 43c0c3989b
commit 27aa7e4e91
11 changed files with 340 additions and 230 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,17 +42,16 @@ namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::LUscalarMatrix::LUscalarMatrix()
Foam::LUscalarMatrix::LUscalarMatrix() noexcept
:
comm_(UPstream::worldComm)
{}
Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& matrix)
Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& mat)
:
scalarSquareMatrix(matrix),
comm_(UPstream::worldComm),
pivotIndices_(m())
scalarSquareMatrix(mat),
comm_(UPstream::worldComm)
{
LUDecompose(*this, pivotIndices_);
}
@ -69,13 +68,14 @@ Foam::LUscalarMatrix::LUscalarMatrix
{
if (UPstream::parRun())
{
PtrList<procLduMatrix> lduMatrices(UPstream::nProcs(comm_));
label lduMatrixi = 0;
PtrList<procLduMatrix> lduMatrices
(
UPstream::master(comm_) ? UPstream::nProcs(comm_) : 1
);
lduMatrices.set
(
lduMatrixi++,
0, // rank-local matrix (and/or master)
new procLduMatrix
(
ldum,
@ -88,101 +88,66 @@ Foam::LUscalarMatrix::LUscalarMatrix
{
for (const int proci : UPstream::subProcs(comm_))
{
lduMatrices.set
(
lduMatrixi++,
new procLduMatrix
(
IPstream
(
UPstream::commsTypes::scheduled,
proci,
0, // bufSize
UPstream::msgType(),
comm_
)()
)
);
auto& mat = lduMatrices.emplace_set(proci);
IPstream::recv(mat, proci, UPstream::msgType(), comm_);
}
convert(lduMatrices);
}
else
{
OPstream toMaster
OPstream::send
(
UPstream::commsTypes::scheduled,
lduMatrices[0], // rank-local matrix
UPstream::masterNo(),
0, // bufSize
UPstream::msgType(),
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
{
label nCells = ldum.lduAddr().size();
scalarSquareMatrix m(nCells, Zero);
transfer(m);
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 (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_);
}
}
@ -197,6 +162,10 @@ void Foam::LUscalarMatrix::convert
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__ lPtr = ldum.lduAddr().lowerAddr().begin();
@ -259,14 +228,26 @@ void Foam::LUscalarMatrix::convert
const PtrList<procLduMatrix>& lduMatrices
)
{
procOffsets_.setSize(lduMatrices.size() + 1);
procOffsets_[0] = 0;
procOffsets_.resize_nocopy(lduMatrices.size() + 1);
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)
{
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);
pivotIndices_.setSize(m());
scalarSquareMatrix::operator=(mat);
LUDecompose(*this, pivotIndices_);
}

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -44,79 +44,141 @@ void Foam::LUscalarMatrix::solve
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,
proci,
reinterpret_cast<char*>
(
&(X[procOffsets_[proci]])
),
(procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
Pstream::msgType(),
comm_
allx,
procOffsets_[proci+1]-procOffsets_[proci],
procOffsets_[proci]
);
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
{
UOPstream::write
(
Pstream::commsTypes::scheduled,
Pstream::masterNo(),
x.cdata_bytes(),
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_))
if (x.empty())
{
// Nothing to do
}
else if (is_contiguous<Type>::value)
{
UOPstream::write
(
Pstream::commsTypes::scheduled,
proci,
reinterpret_cast<const char*>
(
&(X[procOffsets_[proci]])
),
(procOffsets_[proci+1]-procOffsets_[proci])*sizeof(Type),
Pstream::msgType(),
UPstream::commsTypes::nonBlocking,
UPstream::masterNo(),
x.cdata_bytes(),
x.size_bytes(),
tag,
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
{
UIPstream::read
(
Pstream::commsTypes::scheduled,
Pstream::masterNo(),
x.data_bytes(),
x.byteSize(),
Pstream::msgType(),
comm_
);
if (x.empty())
{
// Nothing to do
}
else if (is_contiguous<Type>::value)
{
UIPstream::read
(
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
{
@ -131,7 +193,7 @@ Foam::tmp<Foam::Field<Type>> Foam::LUscalarMatrix::solve
const UList<Type>& source
) const
{
auto tx(tmp<Field<Type>>::New(m()));
auto tx = tmp<Field<Type>>::New(m());
solve(tx.ref(), source);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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