From af221634929a89e7da7fa26e3f3d570e2971a4a4 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin Date: Mon, 2 Mar 2020 14:24:44 +0000 Subject: [PATCH 1/4] ENH: improve Matrix classes and tests --- applications/test/TestTools/TestTools.H | 305 +++++ .../test/matrices/DiagonalMatrix/Make/files | 3 + .../test/matrices/DiagonalMatrix/Make/options | 2 + .../DiagonalMatrix/Test-DiagonalMatrix.C | 231 ++++ .../test/{ => matrices}/Matrix/Make/files | 0 .../test/{ => matrices}/Matrix/Make/options | 0 .../test/{ => matrices}/Matrix/Test-Matrix.C | 2 +- .../test/{ => matrices}/QRMatrix/Make/files | 0 .../test/{ => matrices}/QRMatrix/Make/options | 0 .../{ => matrices}/QRMatrix/Test-QRMatrix.C | 3 +- .../matrices/RectangularMatrix/Make/files | 3 + .../matrices/RectangularMatrix/Make/options | 2 + .../Test-RectangularMatrix.C | 878 +++++++++++++++ .../test/matrices/SquareMatrix/Make/files | 3 + .../test/matrices/SquareMatrix/Make/options | 2 + .../matrices/SquareMatrix/Test-SquareMatrix.C | 1000 +++++++++++++++++ .../matrices/SymmetricSquareMatrix/Make/files | 3 + .../SymmetricSquareMatrix/Make/options | 2 + .../Test-SymmetricSquareMatrix.C | 207 ++++ .../matrices/DiagonalMatrix/DiagonalMatrix.C | 120 +- .../matrices/DiagonalMatrix/DiagonalMatrix.H | 48 +- src/OpenFOAM/matrices/Matrix/Matrix.C | 90 +- src/OpenFOAM/matrices/Matrix/Matrix.H | 161 +-- src/OpenFOAM/matrices/Matrix/MatrixI.H | 26 +- .../matrices/MatrixBlock/MatrixBlock.C | 4 +- .../RectangularMatrix/RectangularMatrix.H | 71 +- .../RectangularMatrix/RectangularMatrixI.H | 40 +- .../matrices/SquareMatrix/SquareMatrix.C | 131 ++- .../matrices/SquareMatrix/SquareMatrix.H | 75 +- .../matrices/SquareMatrix/SquareMatrixI.H | 12 +- .../SymmetricSquareMatrix.C | 4 +- .../SymmetricSquareMatrix.H | 26 +- .../SymmetricSquareMatrixI.H | 9 +- 33 files changed, 3100 insertions(+), 363 deletions(-) create mode 100644 applications/test/TestTools/TestTools.H create mode 100644 applications/test/matrices/DiagonalMatrix/Make/files create mode 100644 applications/test/matrices/DiagonalMatrix/Make/options create mode 100644 applications/test/matrices/DiagonalMatrix/Test-DiagonalMatrix.C rename applications/test/{ => matrices}/Matrix/Make/files (100%) rename applications/test/{ => matrices}/Matrix/Make/options (100%) rename applications/test/{ => matrices}/Matrix/Test-Matrix.C (99%) rename applications/test/{ => matrices}/QRMatrix/Make/files (100%) rename applications/test/{ => matrices}/QRMatrix/Make/options (100%) rename applications/test/{ => matrices}/QRMatrix/Test-QRMatrix.C (99%) create mode 100644 applications/test/matrices/RectangularMatrix/Make/files create mode 100644 applications/test/matrices/RectangularMatrix/Make/options create mode 100644 applications/test/matrices/RectangularMatrix/Test-RectangularMatrix.C create mode 100644 applications/test/matrices/SquareMatrix/Make/files create mode 100644 applications/test/matrices/SquareMatrix/Make/options create mode 100644 applications/test/matrices/SquareMatrix/Test-SquareMatrix.C create mode 100644 applications/test/matrices/SymmetricSquareMatrix/Make/files create mode 100644 applications/test/matrices/SymmetricSquareMatrix/Make/options create mode 100644 applications/test/matrices/SymmetricSquareMatrix/Test-SymmetricSquareMatrix.C diff --git a/applications/test/TestTools/TestTools.H b/applications/test/TestTools/TestTools.H new file mode 100644 index 0000000000..c24cb9fa05 --- /dev/null +++ b/applications/test/TestTools/TestTools.H @@ -0,0 +1,305 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 . + +Description + Various tools for test applications. + +\*---------------------------------------------------------------------------*/ + +using namespace Foam; + +#include "Random.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Total number of unit tests +unsigned nTest_ = 0; + + +// Total number of failed unit tests +unsigned nFail_ = 0; + + +// Create a non-complex random Matrix. +template +typename std::enable_if +< + !std::is_same:: value, + MatrixType +>::type makeRandomMatrix +( + const labelPair& dims, + Random& rndGen +) +{ + MatrixType mat(dims); + + std::generate + ( + mat.begin(), + mat.end(), + [&]{return rndGen.GaussNormal();} + ); + + return mat; +} + + +// Create a complex random Matrix. +template +typename std::enable_if +< + std::is_same:: value, + MatrixType +>::type makeRandomMatrix +( + const labelPair& dims, + Random& rndGen +) +{ + MatrixType mat(dims); + + for (auto& x : mat) + { + x = complex(rndGen.GaussNormal(), rndGen.GaussNormal()); + } + + return mat; +} + + +// Copy an initializer list into a DiagonalMatrix +template +void assignMatrix +( + UList& A, + std::initializer_list list +) +{ + std::copy(list.begin(), list.end(), A.begin()); +} + + +// Copy an initializer list into a SymmetricSquareMatrix. +template +void assignMatrix +( + Matrix& A, + std::initializer_list::cmptType> list +) +{ + const label nargs = list.size(); + + if (nargs != A.size()) + { + FatalErrorInFunction + << "Mismatch in matrix dimension (" + << A.m() << ", " + << A.n() << ") and number of args (" << nargs << ')' << nl + << exit(FatalError); + } + + std::copy(list.begin(), list.end(), A.begin()); +} + + +// Return a copy of the Matrix collapsed into one dimension. +template +List flt +( + const Matrix& A, + const bool rowMajorOrder = true +) +{ + List flatMatrix(A.size()); + + if (rowMajorOrder) + { + std::copy(A.cbegin(), A.cend(), flatMatrix.begin()); + } + else + { + for (label j = 0; j < A.n(); ++j) + { + for (label i = 0; i < A.m(); ++i) + { + flatMatrix[i + j*A.m()] = A(i, j); + } + } + } + + return flatMatrix; +} + + +// Compare two floating point types, and print output. +// Do ++nFail_ if values of two objects are not equal within a given tolerance. +// The function is converted from PEP-485. +template +typename std::enable_if +< + std::is_same::value || + std::is_same::value || + std::is_same::value, + void +>::type cmp +( + const word& msg, + const Type& x, + const Type& y, + const scalar absTol = 0, // +typename std::enable_if +< + !std::is_same::value && + !std::is_same::value && + !std::is_same::value, + void +>::type cmp +( + const word& msg, + const Type& x, + const Type& y, + const scalar absTol = 0, + const scalar relTol = 1e-8 +) +{ + Info<< msg << x << "?=" << y << endl; + + unsigned nFail = 0; + + for (label i = 0; i < x.size(); ++i) + { + if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i])) + { + ++nFail; + } + } + + if (nFail) + { + Info<< nl + << " #### Fail in " << nFail << " comps ####" << nl << endl; + ++nFail_; + } + ++nTest_; +} + + +// Compare two containers elementwise, and print output. +// Do ++nFail_ if two components are not equal within a given tolerance. +// The function is converted from PEP-485 +template +typename std::enable_if +< + !std::is_same::value && + !std::is_same::value && + !std::is_same::value, + void +>::type cmp +( + const word& msg, + const Type1& x, + const Type2& y, + const scalar absTol = 0, + const scalar relTol = 1e-8 +) +{ + Info<< msg << x << "?=" << y << endl; + + unsigned nFail = 0; + + for (label i = 0; i < x.size(); ++i) + { + if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i])) + { + ++nFail; + } + } + + if (nFail) + { + Info<< nl + << " #### Fail in " << nFail << " comps ####" << nl << endl; + ++nFail_; + } + ++nTest_; +} + + +// Compare two Booleans, and print output. +// Do ++nFail_ if two Booleans are not equal. +void cmp +( + const word& msg, + const bool x, + const bool y +) +{ + Info<< msg << x << "?=" << y << endl; + + unsigned nFail = 0; + + if (x != y) + { + ++nFail; + } + + if (nFail) + { + Info<< nl + << " #### Fail in " << nFail << " comps ####" << nl << endl; + ++nFail_; + } + ++nTest_; +} + + +// ************************************************************************* // diff --git a/applications/test/matrices/DiagonalMatrix/Make/files b/applications/test/matrices/DiagonalMatrix/Make/files new file mode 100644 index 0000000000..0f5877472a --- /dev/null +++ b/applications/test/matrices/DiagonalMatrix/Make/files @@ -0,0 +1,3 @@ +Test-DiagonalMatrix.C + +EXE = $(FOAM_USER_APPBIN)/Test-DiagonalMatrix diff --git a/applications/test/matrices/DiagonalMatrix/Make/options b/applications/test/matrices/DiagonalMatrix/Make/options new file mode 100644 index 0000000000..b23590707c --- /dev/null +++ b/applications/test/matrices/DiagonalMatrix/Make/options @@ -0,0 +1,2 @@ +EXE_INC = -I../../TestTools +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/matrices/DiagonalMatrix/Test-DiagonalMatrix.C b/applications/test/matrices/DiagonalMatrix/Test-DiagonalMatrix.C new file mode 100644 index 0000000000..3d8ae06979 --- /dev/null +++ b/applications/test/matrices/DiagonalMatrix/Test-DiagonalMatrix.C @@ -0,0 +1,231 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 . + +Application + Test-DiagonalMatrix + +Description + Tests for \c DiagonalMatrix constructors, member functions and global + functions using \c floatScalar, \c doubleScalar, and \c complex base types. + + Cross-checks were obtained from 'NumPy 1.15.1' if no theoretical + cross-check exists (like eigendecomposition relations), and + were hard-coded for elementwise comparisons. + +\*---------------------------------------------------------------------------*/ + +#include "DiagonalMatrix.H" +#include "RectangularMatrix.H" +#include "floatScalar.H" +#include "doubleScalar.H" +#include "complex.H" +#include "TestTools.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Create each constructor of DiagonalMatrix, and print output +template +void test_constructors(Type) +{ + { + Info<< "# Construct empty from size:" << nl; + const DiagonalMatrix A(5); + Info<< A << endl; + } + { + Info<< "# Construct from size and initialise all elems to zero:" << nl; + const DiagonalMatrix A(5, Zero); + Info<< A << endl; + } + { + Info<< "# Construct from size and initialise all elems to value" << nl; + const DiagonalMatrix A(5, Type(8)); + Info<< A << endl; + } + { + Info<< "# Construct from the diagonal of a Matrix" << nl; + const RectangularMatrix M(3, 5, Zero); + const DiagonalMatrix A(M); + Info<< A << endl; + } +} + + +// Execute each member function of DiagonalMatrix, and print output +template +void test_member_funcs(Type) +{ + DiagonalMatrix A(3, Zero); + assignMatrix(A, {Type(1), Type(2), Type(-3)}); + + Info<< "# Operand: " << nl + << " DiagonalMatrix = " << A << endl; + + + { + Info<< "# Return the matrix inverse into itself:" << nl; + A.invert(); + cmp + ( + " DiagonalMatrix.invert() = ", + A, + List({Type(1), Type(0.5), Type(-0.333333)}), + 1e-6 + ); + } + { + Info<< "# Sort:" << nl; + + DiagonalMatrix B(5, Zero); + assignMatrix(B, {Type(1), Type(2), Type(-3), Type(5), Type(1.01)}); + + auto descend = [&](Type a, Type b){ return mag(a) > mag(b); }; + const List