diff --git a/applications/test/Matrix/Test-Matrix.C b/applications/test/Matrix/Test-Matrix.C index 600d0ad60f..40e79d15e9 100644 --- a/applications/test/Matrix/Test-Matrix.C +++ b/applications/test/Matrix/Test-Matrix.C @@ -23,7 +23,7 @@ License \*---------------------------------------------------------------------------*/ -#include "SquareMatrix.H" +#include "scalarMatrices.H" #include "vector.H" using namespace Foam; @@ -49,15 +49,15 @@ int main(int argc, char *argv[]) Info<< max(hmm) << endl; Info<< min(hmm) << endl; - SquareMatrix hmm2(3, 1.0); + SquareMatrix hmm2(3, 3, 1.0); hmm = hmm2; Info<< hmm << endl; - SquareMatrix hmm3(Sin); + //SquareMatrix hmm3(Sin); - Info<< hmm3 << endl; + //Info<< hmm3 << endl; SquareMatrix hmm4; @@ -70,7 +70,65 @@ int main(int argc, char *argv[]) hmm4 = hmm5; Info<< hmm5 << endl; - Info<< "End\n" << endl; + { + scalarSymmetricSquareMatrix symmMatrix(3, 3, 0); + + symmMatrix(0, 0) = 4; + symmMatrix(1, 0) = 12; + symmMatrix(1, 1) = 37; + symmMatrix(2, 0) = -16; + symmMatrix(2, 1) = -43; + symmMatrix(2, 2) = 98; + + Info<< "Symmetric Square Matrix = " << symmMatrix << endl; + + Info<< "Inverse = " << inv(symmMatrix) << endl; + Info<< "Determinant = " << det(symmMatrix) << endl; + + scalarSymmetricSquareMatrix symmMatrix2(symmMatrix); + LUDecompose(symmMatrix2); + + Info<< "Inverse = " << invDecomposed(symmMatrix2) << endl; + Info<< "Determinant = " << detDecomposed(symmMatrix2) << endl; + + scalarDiagonalMatrix rhs(3, 0); + rhs[0] = 1; + rhs[1] = 2; + rhs[2] = 3; + + LUsolve(symmMatrix, rhs); + + Info<< "Decomposition = " << symmMatrix << endl; + Info<< "Solution = " << rhs << endl; + } + + { + scalarSquareMatrix squareMatrix(3, 3, 0); + + squareMatrix[0][0] = 4; + squareMatrix[0][1] = 12; + squareMatrix[0][2] = -16; + squareMatrix[1][0] = 12; + squareMatrix[1][1] = 37; + squareMatrix[1][2] = -43; + squareMatrix[2][0] = -16; + squareMatrix[2][1] = -43; + squareMatrix[2][2] = 98; + + Info<< nl << "Square Matrix = " << squareMatrix << endl; + + scalarDiagonalMatrix rhs(3, 0); + rhs[0] = 1; + rhs[1] = 2; + rhs[2] = 3; + + LUsolve(squareMatrix, rhs); + + Info<< "Decomposition = " << squareMatrix << endl; + Info<< "Solution = " << rhs << endl; + } + + Info<< "\nEnd\n" << endl; return 0; } diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H index 031320a457..a065b3aec3 100644 --- a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H +++ b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -76,7 +76,7 @@ public: // Member functions - //- Invert the diaganol matrix and return itself + //- Invert the diagonal matrix and return itself DiagonalMatrix& invert(); }; diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.H b/src/OpenFOAM/matrices/Matrix/Matrix.H index dd55db770c..005982d9e0 100644 --- a/src/OpenFOAM/matrices/Matrix/Matrix.H +++ b/src/OpenFOAM/matrices/Matrix/Matrix.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -221,7 +221,6 @@ template Form operator* const Matrix& ); - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C new file mode 100644 index 0000000000..bb6bea65c7 --- /dev/null +++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.C @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "SymmetricSquareMatrix.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +Foam::SymmetricSquareMatrix Foam::invDecomposed +( + const SymmetricSquareMatrix& matrix +) +{ + SymmetricSquareMatrix inv(matrix.n(), matrix.n(), 0.0); + + for (label i = 0; i < matrix.n(); ++i) + { + inv[i][i] = 1.0/matrix[i][i]; + + for (label j = 0; j < i; ++j) + { + scalar sum = 0.0; + + for (label k = j; k < i; k++) + { + sum -= matrix[i][k]*inv[k][j]; + } + + inv[i][j] = sum/matrix[i][i]; + } + } + + return inv.T()*inv; +} + + +template +Foam::SymmetricSquareMatrix Foam::inv +( + const SymmetricSquareMatrix& matrix +) +{ + SymmetricSquareMatrix matrixTmp(matrix); + + LUDecompose(matrixTmp); + + return invDecomposed(matrixTmp); +} + + +template +Foam::scalar Foam::detDecomposed(const SymmetricSquareMatrix& matrix) +{ + scalar diagProduct = 1.0; + + for (label i = 0; i < matrix.n(); ++i) + { + diagProduct *= matrix[i][i]; + } + + return sqr(diagProduct); +} + + +template +Foam::scalar Foam::det(const SymmetricSquareMatrix& matrix) +{ + SymmetricSquareMatrix matrixTmp = matrix; + + LUDecompose(matrixTmp); + + return detDecomposed(matrixTmp); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H new file mode 100644 index 0000000000..6983250078 --- /dev/null +++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrix.H @@ -0,0 +1,126 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::SymmetricSquareMatrix + +Description + A templated 2D square symmetric matrix of objects of \, where the + n x n matrix dimension is known and used for subscript bounds checking, etc. + +SourceFiles + SymmetricSquareMatrixI.H + SymmetricSquareMatrix.C + +\*---------------------------------------------------------------------------*/ + +#ifndef SymmetricSquareMatrix_H +#define SymmetricSquareMatrix_H + +#include "SquareMatrix.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class SymmetricSquareMatrix Declaration +\*---------------------------------------------------------------------------*/ + +template +class SymmetricSquareMatrix +: + public Matrix, Type> +{ + +public: + + // Constructors + + //- Null constructor. + inline SymmetricSquareMatrix(); + + //- Construct given number of rows/columns. + inline SymmetricSquareMatrix(const label n); + + //- Construct with given number of rows/columns + inline SymmetricSquareMatrix(const label m, const label n); + + //- Construct with given number of rows/columns + // and value for all elements. + inline SymmetricSquareMatrix(const label m, const label n, const Type&); + + //- Construct from Istream. + inline SymmetricSquareMatrix(Istream&); + + //- Clone + inline autoPtr > clone() const; + + + //- Return subscript-checked row of Matrix. + inline Type& operator()(const label r, const label c); + + //- Return subscript-checked row of constant Matrix. + inline const Type& operator()(const label r, const label c) const; +}; + + +// Global functions + +//- Return the LU decomposed SymmetricSquareMatrix inverse +template +SymmetricSquareMatrix invDecomposed(const SymmetricSquareMatrix&); + +//- Return the SymmetricSquareMatrix inverse +template +SymmetricSquareMatrix inv(const SymmetricSquareMatrix&); + +//- Return the LU decomposed SymmetricSquareMatrix det +template +scalar detDecomposed(const SymmetricSquareMatrix&); + +//- Return the SymmetricSquareMatrix det +template +scalar det(const SymmetricSquareMatrix&); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +# include "SymmetricSquareMatrixI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "SymmetricSquareMatrix.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H new file mode 100644 index 0000000000..1dee0ab9d0 --- /dev/null +++ b/src/OpenFOAM/matrices/SymmetricSquareMatrix/SymmetricSquareMatrixI.H @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +inline Foam::SymmetricSquareMatrix::SymmetricSquareMatrix() +: + Matrix, Type>() +{} + + +template +inline Foam::SymmetricSquareMatrix::SymmetricSquareMatrix(const label n) +: + Matrix, Type>(n, n) +{} + + +template +inline Foam::SymmetricSquareMatrix::SymmetricSquareMatrix +( + const label m, + const label n +) +: + Matrix, Type>(m, n) +{ + if (m != n) + { + FatalErrorIn + ( + "SymmetricSquareMatrix::SymmetricSquareMatrix" + "(const label m, const label n)" + ) << "m != n for constructing a symmetric square matrix" + << exit(FatalError); + } +} + + +template +inline Foam::SymmetricSquareMatrix::SymmetricSquareMatrix +( + const label m, + const label n, + const Type& t +) +: + Matrix, Type>(m, n, t) +{ + if (m != n) + { + FatalErrorIn + ( + "SymmetricSquareMatrix::SymmetricSquareMatrix" + "(const label m, const label n, const Type&)" + ) << "m != n for constructing a symmetric square matrix" + << exit(FatalError); + } +} + + +template +inline Foam::SymmetricSquareMatrix::SymmetricSquareMatrix(Istream& is) +: + Matrix, Type>(is) +{} + + +template +inline Foam::autoPtr > +Foam::SymmetricSquareMatrix::clone() const +{ + return autoPtr > + ( + new SymmetricSquareMatrix(*this) + ); +} + + +template +inline Type& Foam::SymmetricSquareMatrix::operator() +( + const label r, + const label c +) +{ + if (r > c) + { + return this->operator[](r)[c]; + } + else + { + return this->operator[](c)[r]; + } +} + + +template +inline const Type& Foam::SymmetricSquareMatrix::operator() +( + const label r, + const label c +) const +{ + if (r > c) + { + return this->operator[](r)[c]; + } + else + { + return this->operator[](c)[r]; + } +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C index 58b196da09..68a6955d71 100644 --- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C +++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -134,6 +134,56 @@ void Foam::LUDecompose } +void Foam::LUDecompose(scalarSymmetricSquareMatrix& matrix) +{ + // Store result in upper triangular part of matrix + label size = matrix.n(); + + // Set upper triangular parts to zero. + for (label j = 0; j < size; j++) + { + for (label k = j + 1; k < size; k++) + { + matrix[j][k] = 0.0; + } + } + + for (label j = 0; j < size; j++) + { + scalar d = 0.0; + + for (label k = 0; k < j; k++) + { + scalar s = 0.0; + + for (label i = 0; i < k; i++) + { + s += matrix[i][k]*matrix[i][j]; + } + + s = (matrix[j][k] - s)/matrix[k][k]; + + matrix[k][j] = s; + matrix[j][k] = s; + + d += sqr(s); + } + + d = matrix[j][j] - d; + + if (d < 0.0) + { + FatalErrorIn("Foam::LUDecompose(scalarSymmetricSquareMatrix&)") + << "Matrix is not symmetric positive-definite. Unable to " + << "decompose." + << abort(FatalError); + } + + matrix[j][j] = sqrt(d); + } +} + + // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // void Foam::multiply diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H index 0830b33ae6..3eecda8ebf 100644 --- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H +++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatrices.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -27,6 +27,10 @@ Class Description Scalar matrices + LUDecompose for scalarSymmetricSquareMatrix implements the Cholesky + decomposition method from JAMA, a public-domain library developed at NIST, + available at http://math.nist.gov/tnt/index.html + SourceFiles scalarMatrices.C scalarMatricesTemplates.C @@ -38,6 +42,7 @@ SourceFiles #include "RectangularMatrix.H" #include "SquareMatrix.H" +#include "SymmetricSquareMatrix.H" #include "DiagonalMatrix.H" #include "scalarField.H" #include "labelList.H" @@ -49,21 +54,22 @@ namespace Foam typedef RectangularMatrix scalarRectangularMatrix; typedef SquareMatrix scalarSquareMatrix; +typedef SymmetricSquareMatrix scalarSymmetricSquareMatrix; typedef DiagonalMatrix scalarDiagonalMatrix; //- Solve the matrix using Gaussian elimination with pivoting, // returning the solution in the source template -void solve(scalarSquareMatrix& matrix, Field& source); +void solve(scalarSquareMatrix& matrix, List& source); //- Solve the matrix using Gaussian elimination with pivoting // and return the solution template void solve ( - Field& psi, + List& psi, const scalarSquareMatrix& matrix, - const Field& source + const List& source ); //- LU decompose the matrix with pivoting @@ -73,6 +79,9 @@ void LUDecompose labelList& pivotIndices ); +//- LU decompose the matrix into a lower (L) and upper (U) part. U = L.T() +void LUDecompose(scalarSymmetricSquareMatrix& matrix); + //- LU back-substitution with given source, returning the solution // in the source template @@ -80,13 +89,28 @@ void LUBacksubstitute ( const scalarSquareMatrix& luMmatrix, const labelList& pivotIndices, - Field& source + List& source +); + +//- LU back-substitution with given source, returning the solution +// in the source. Specialised for symmetric square matrices that have been +// decomposed into LU where U = L.T() as pivoting is not required +template +void LUBacksubstitute +( + const scalarSymmetricSquareMatrix& luMmatrix, + List& source ); //- Solve the matrix using LU decomposition with pivoting // returning the LU form of the matrix and the solution in the source template -void LUsolve(scalarSquareMatrix& matrix, Field& source); +void LUsolve(scalarSquareMatrix& matrix, List& source); + +//- Solve the matrix using LU decomposition returning the LU form of the matrix +// and the solution in the source, where U = L.T() +template +void LUsolve(scalarSymmetricSquareMatrix& matrix, List& source); template void multiply diff --git a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C index 0489ed012d..7aaaabb695 100644 --- a/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C +++ b/src/OpenFOAM/matrices/scalarMatrices/scalarMatricesTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,6 +25,7 @@ License #include "scalarMatrices.H" #include "Swap.H" +#include "ListOps.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // @@ -32,7 +33,7 @@ template void Foam::solve ( scalarSquareMatrix& tmpMatrix, - Field& sourceSol + List& sourceSol ) { label n = tmpMatrix.n(); @@ -103,9 +104,9 @@ void Foam::solve template void Foam::solve ( - Field& psi, + List& psi, const scalarSquareMatrix& matrix, - const Field& source + const List& source ) { scalarSquareMatrix tmpMatrix = matrix; @@ -119,7 +120,7 @@ void Foam::LUBacksubstitute ( const scalarSquareMatrix& luMatrix, const labelList& pivotIndices, - Field& sourceSol + List& sourceSol ) { label n = luMatrix.n(); @@ -163,11 +164,57 @@ void Foam::LUBacksubstitute } +template +void Foam::LUBacksubstitute +( + const scalarSymmetricSquareMatrix& luMatrix, + List& sourceSol +) +{ + label n = luMatrix.n(); + + label ii = 0; + + for (register label i=0; i::zero) + { + ii = i+1; + } + + sourceSol[i] = sum/luMatrixi[i]; + } + + for (register label i=n-1; i>=0; i--) + { + Type sum = sourceSol[i]; + const scalar* __restrict__ luMatrixi = luMatrix[i]; + + for (register label j=i+1; j void Foam::LUsolve ( scalarSquareMatrix& matrix, - Field& sourceSol + List& sourceSol ) { labelList pivotIndices(matrix.n()); @@ -176,6 +223,18 @@ void Foam::LUsolve } +template +void Foam::LUsolve +( + scalarSymmetricSquareMatrix& matrix, + List& sourceSol +) +{ + LUDecompose(matrix); + LUBacksubstitute(matrix, sourceSol); +} + + template void Foam::multiply (