From 26f2c24d84d653169811d752b5ff3884c2c9c87a Mon Sep 17 00:00:00 2001 From: henry <Henry Weller h.weller@opencfd.co.uk> Date: Sat, 27 Sep 2008 09:25:30 +0100 Subject: [PATCH] Added support for quadraticFit interpolation scheme. Added the quadraticFit interpolation scheme. --- src/OpenFOAM/Make/files | 1 + .../matrices/DiagonalMatrix/DiagonalMatrix.C | 99 ++++ .../matrices/DiagonalMatrix/DiagonalMatrix.H | 102 ++++ .../LUscalarMatrix/LUscalarMatrixTemplates.C | 14 +- .../{containers => matrices}/Matrix/Matrix.C | 174 +++--- .../{containers => matrices}/Matrix/Matrix.H | 89 +-- .../{containers => matrices}/Matrix/MatrixI.H | 52 +- .../Matrix/MatrixIO.C | 44 +- src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.C | 400 +++++++++++++ src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.H | 128 +++++ src/OpenFOAM/matrices/scalarMatrix/SVD/SVDI.H | 75 +++ .../matrices/scalarMatrix/scalarMatrix.C | 159 +++++- .../matrices/scalarMatrix/scalarMatrix.H | 46 +- .../scalarMatrix/scalarMatrixTemplates.C | 26 +- .../matrices/simpleMatrix/simpleMatrix.C | 68 +-- .../matrices/simpleMatrix/simpleMatrix.H | 66 +-- src/finiteVolume/Make/files | 5 + .../fvMesh/extendedStencil/extendedStencil.C | 525 ++++++++++++++++++ .../fvMesh/extendedStencil/extendedStencil.H | 151 +++++ .../extendedStencilTemplates.C | 129 +++++ .../schemes/quadraticFit/quadraticFit.C | 36 ++ .../schemes/quadraticFit/quadraticFit.H | 138 +++++ .../schemes/quadraticFit/quadraticFitData.C | 310 +++++++++++ .../schemes/quadraticFit/quadraticFitData.H | 140 +++++ 24 files changed, 2725 insertions(+), 252 deletions(-) create mode 100644 src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C create mode 100644 src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H rename src/OpenFOAM/{containers => matrices}/Matrix/Matrix.C (62%) rename src/OpenFOAM/{containers => matrices}/Matrix/Matrix.H (70%) rename src/OpenFOAM/{containers => matrices}/Matrix/MatrixI.H (66%) rename src/OpenFOAM/{containers => matrices}/Matrix/MatrixIO.C (84%) create mode 100644 src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.C create mode 100644 src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.H create mode 100644 src/OpenFOAM/matrices/scalarMatrix/SVD/SVDI.H create mode 100644 src/finiteVolume/fvMesh/extendedStencil/extendedStencil.C create mode 100644 src/finiteVolume/fvMesh/extendedStencil/extendedStencil.H create mode 100644 src/finiteVolume/fvMesh/extendedStencil/extendedStencilTemplates.C create mode 100644 src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.C create mode 100644 src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.H create mode 100644 src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.C create mode 100644 src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.H diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 7b137dedc03..57dc7f8dc70 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -179,6 +179,7 @@ matrices/solution/solution.C scalarMatrix = matrices/scalarMatrix $(scalarMatrix)/scalarMatrix.C +$(scalarMatrix)/SVD/SVD.C LUscalarMatrix = matrices/LUscalarMatrix $(LUscalarMatrix)/LUscalarMatrix.C diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C new file mode 100644 index 00000000000..c023e59c5a2 --- /dev/null +++ b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.C @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "DiagonalMatrix.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> +Foam::DiagonalMatrix<Type>::DiagonalMatrix(const Matrix<Type>& a) +: + List<Type>(min(a.n(), a.m())) +{ + forAll(*this, i) + { + this->operator[](i) = a[i][i]; + } +} + + +template<class Type> +Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label size) +: + List<Type>(size) +{} + + +template<class Type> +Foam::DiagonalMatrix<Type>::DiagonalMatrix(const label size, const Type& val) +: + List<Type>(size, val) +{} + + +template<class Type> +Foam::DiagonalMatrix<Type>& Foam::DiagonalMatrix<Type>::invert() +{ + forAll(*this, i) + { + Type x = this->operator[](i); + if (mag(x) < VSMALL) + { + this->operator[](i) = Type(0); + } + else + { + this->operator[](i) = Type(1)/x; + } + } + + return this; +} + + +template<class Type> +Foam::DiagonalMatrix<Type> Foam::inv(const DiagonalMatrix<Type>& A) +{ + DiagonalMatrix<Type> Ainv = A; + + forAll(A, i) + { + Type x = A[i]; + if (mag(x) < VSMALL) + { + Ainv[i] = Type(0); + } + else + { + Ainv[i] = Type(1)/x; + } + } + + return Ainv; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H new file mode 100644 index 00000000000..36138fc25de --- /dev/null +++ b/src/OpenFOAM/matrices/DiagonalMatrix/DiagonalMatrix.H @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::DiagonalMatrix<Type> + +Description + DiagonalMatrix<Type> is a 2D diagonal matrix of objects + of type Type, size nxn + +SourceFiles + DiagonalMatrix.C + +\*---------------------------------------------------------------------------*/ + +#ifndef DiagonalMatrix_H +#define DiagonalMatrix_H + +#include "List.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * Class Forward declaration * * * * * * * * * * * // + +template<class Type> class Matrix; + +/*---------------------------------------------------------------------------*\ + Class DiagonalMatrix Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class DiagonalMatrix +: + public List<Type> +{ +public: + + // Constructors + + //- Construct from diagonal component of a Matrix + DiagonalMatrix<Type>(const Matrix<Type>&); + + //- Construct empty from size + DiagonalMatrix<Type>(const label size); + + //- Construct from size and a value + DiagonalMatrix<Type>(const label, const Type&); + + + // Member functions + + //- Invert the diaganol matrix and return itself + DiagonalMatrix<Type>& invert(); +}; + + +// Global functions + +//- Return the diagonal Matrix inverse +template<class Type> +DiagonalMatrix<Type> inv(const DiagonalMatrix<Type>&); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "DiagonalMatrix.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C index cbb59e2c864..ac0bc17207e 100644 --- a/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C +++ b/src/OpenFOAM/matrices/LUscalarMatrix/LUscalarMatrixTemplates.C @@ -28,16 +28,16 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -template<class T> -void Foam::LUscalarMatrix::solve(Field<T>& sourceSol) const +template<class Type> +void Foam::LUscalarMatrix::solve(Field<Type>& sourceSol) const { if (Pstream::parRun()) { - Field<T> completeSourceSol(n()); + Field<Type> completeSourceSol(n()); if (Pstream::master()) { - typename Field<T>::subField + typename Field<Type>::subField ( completeSourceSol, sourceSol.size() @@ -58,7 +58,7 @@ void Foam::LUscalarMatrix::solve(Field<T>& sourceSol) const ( &(completeSourceSol[procOffsets_[slave]]) ), - (procOffsets_[slave + 1] - procOffsets_[slave])*sizeof(T) + (procOffsets_[slave + 1] - procOffsets_[slave])*sizeof(Type) ); } } @@ -77,7 +77,7 @@ void Foam::LUscalarMatrix::solve(Field<T>& sourceSol) const { LUBacksubstitute(*this, pivotIndices_, completeSourceSol); - sourceSol = typename Field<T>::subField + sourceSol = typename Field<Type>::subField ( completeSourceSol, sourceSol.size() @@ -98,7 +98,7 @@ void Foam::LUscalarMatrix::solve(Field<T>& sourceSol) const ( &(completeSourceSol[procOffsets_[slave]]) ), - (procOffsets_[slave + 1] - procOffsets_[slave])*sizeof(T) + (procOffsets_[slave + 1] - procOffsets_[slave])*sizeof(Type) ); } } diff --git a/src/OpenFOAM/containers/Matrix/Matrix.C b/src/OpenFOAM/matrices/Matrix/Matrix.C similarity index 62% rename from src/OpenFOAM/containers/Matrix/Matrix.C rename to src/OpenFOAM/matrices/Matrix/Matrix.C index 733e04034ef..4fbef71c2b4 100644 --- a/src/OpenFOAM/containers/Matrix/Matrix.C +++ b/src/OpenFOAM/matrices/Matrix/Matrix.C @@ -28,13 +28,13 @@ License // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // -template<class T> -void Foam::Matrix<T>::allocate() +template<class Type> +void Foam::Matrix<Type>::allocate() { if (n_ && m_) { - v_ = new T*[n_]; - v_[0] = new T[n_*m_]; + v_ = new Type*[n_]; + v_[0] = new Type[n_*m_]; for (register label i=1; i<n_; i++) { @@ -46,12 +46,12 @@ void Foam::Matrix<T>::allocate() // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * // -template<class T> -Foam::Matrix<T>::~Matrix() +template<class Type> +Foam::Matrix<Type>::~Matrix() { if (v_) { - delete[] (v_[0]); + delete[] (v_[0]); delete[] v_; } } @@ -59,16 +59,16 @@ Foam::Matrix<T>::~Matrix() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -template<class T> -const Foam::Matrix<T>& Foam::Matrix<T>::null() +template<class Type> +const Foam::Matrix<Type>& Foam::Matrix<Type>::null() { - Matrix<T>* nullPtr = reinterpret_cast<Matrix<T>*>(NULL); + Matrix<Type>* nullPtr = reinterpret_cast<Matrix<Type>*>(NULL); return *nullPtr; } -template<class T> -Foam::Matrix<T>::Matrix(const label n, const label m) +template<class Type> +Foam::Matrix<Type>::Matrix(const label n, const label m) : n_(n), m_(m), @@ -76,7 +76,7 @@ Foam::Matrix<T>::Matrix(const label n, const label m) { if (n_ < 0 || m_ < 0) { - FatalErrorIn("Matrix<T>::Matrix(const label n, const label m)") + FatalErrorIn("Matrix<Type>::Matrix(const label n, const label m)") << "bad n, m " << n_ << ", " << m_ << abort(FatalError); } @@ -85,8 +85,8 @@ Foam::Matrix<T>::Matrix(const label n, const label m) } -template<class T> -Foam::Matrix<T>::Matrix(const label n, const label m, const T& a) +template<class Type> +Foam::Matrix<Type>::Matrix(const label n, const label m, const Type& a) : n_(n), m_(m), @@ -96,7 +96,7 @@ Foam::Matrix<T>::Matrix(const label n, const label m, const T& a) { FatalErrorIn ( - "Matrix<T>::Matrix(const label n, const label m, const T&)" + "Matrix<Type>::Matrix(const label n, const label m, const T&)" ) << "bad n, m " << n_ << ", " << m_ << abort(FatalError); } @@ -105,7 +105,7 @@ Foam::Matrix<T>::Matrix(const label n, const label m, const T& a) if (v_) { - T* v = v_[0]; + Type* v = v_[0]; label nm = n_*m_; @@ -117,8 +117,8 @@ Foam::Matrix<T>::Matrix(const label n, const label m, const T& a) } -template<class T> -Foam::Matrix<T>::Matrix(const Matrix<T>& a) +template<class Type> +Foam::Matrix<Type>::Matrix(const Matrix<Type>& a) : n_(a.n_), m_(a.m_), @@ -127,8 +127,8 @@ Foam::Matrix<T>::Matrix(const Matrix<T>& a) if (a.v_) { allocate(); - T* v = v_[0]; - const T* av = a.v_[0]; + Type* v = v_[0]; + const Type* av = a.v_[0]; label nm = n_*m_; for (register label i=0; i<nm; i++) @@ -138,13 +138,13 @@ Foam::Matrix<T>::Matrix(const Matrix<T>& a) } } - -template<class T> -void Foam::Matrix<T>::clear() + +template<class Type> +void Foam::Matrix<Type>::clear() { if (v_) { - delete[] (v_[0]); + delete[] (v_[0]); delete[] v_; } n_ = 0; @@ -153,8 +153,8 @@ void Foam::Matrix<T>::clear() } -template<class T> -void Foam::Matrix<T>::transfer(Matrix<T>& a) +template<class Type> +void Foam::Matrix<Type>::transfer(Matrix<Type>& a) { clear(); @@ -171,12 +171,30 @@ void Foam::Matrix<T>::transfer(Matrix<T>& a) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -template<class T> -void Foam::Matrix<T>::operator=(const T& t) +template<class Type> +Foam::Matrix<Type> Foam::Matrix<Type>::T() const +{ + const Matrix<Type>& A = *this; + Matrix<Type> At(m(), n()); + + for (register label i=0; i<n(); i++) + { + for (register label j=0; j<m(); j++) + { + At[j][i] = A[i][j]; + } + } + + return At; +} + + +template<class Type> +void Foam::Matrix<Type>::operator=(const Type& t) { if (v_) { - T* v = v_[0]; + Type* v = v_[0]; label nm = n_*m_; for (register label i=0; i<nm; i++) @@ -188,12 +206,12 @@ void Foam::Matrix<T>::operator=(const T& t) // Assignment operator. Takes linear time. -template<class T> -void Foam::Matrix<T>::operator=(const Matrix<T>& a) +template<class Type> +void Foam::Matrix<Type>::operator=(const Matrix<Type>& a) { if (this == &a) { - FatalErrorIn("Matrix<T>::operator=(const Matrix<T>&)") + FatalErrorIn("Matrix<Type>::operator=(const Matrix<Type>&)") << "attempted assignment to self" << abort(FatalError); } @@ -204,12 +222,12 @@ void Foam::Matrix<T>::operator=(const Matrix<T>& a) n_ = a.n_; m_ = a.m_; allocate(); - } + } if (v_) { - T* v = v_[0]; - const T* av = a.v_[0]; + Type* v = v_[0]; + const Type* av = a.v_[0]; label nm = n_*m_; for (register label i=0; i<nm; i++) @@ -222,15 +240,15 @@ void Foam::Matrix<T>::operator=(const Matrix<T>& a) // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // -template<class T> -const T& Foam::max(const Matrix<T>& a) +template<class Type> +const Type& Foam::max(const Matrix<Type>& a) { label nm = a.n_*a.m_; if (nm) { label curMaxI = 0; - const T* v = a.v_[0]; + const Type* v = a.v_[0]; for (register label i=1; i<nm; i++) { @@ -244,7 +262,7 @@ const T& Foam::max(const Matrix<T>& a) } else { - FatalErrorIn("max(const Matrix<T>&)") + FatalErrorIn("max(const Matrix<Type>&)") << "matrix is empty" << abort(FatalError); @@ -254,15 +272,15 @@ const T& Foam::max(const Matrix<T>& a) } -template<class T> -const T& Foam::min(const Matrix<T>& a) +template<class Type> +const Type& Foam::min(const Matrix<Type>& a) { label nm = a.n_*a.m_; if (nm) { label curMinI = 0; - const T* v = a.v_[0]; + const Type* v = a.v_[0]; for (register label i=1; i<nm; i++) { @@ -276,7 +294,7 @@ const T& Foam::min(const Matrix<T>& a) } else { - FatalErrorIn("min(const Matrix<T>&)") + FatalErrorIn("min(const Matrix<Type>&)") << "matrix is empty" << abort(FatalError); @@ -288,15 +306,15 @@ const T& Foam::min(const Matrix<T>& a) // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * // -template<class T> -Foam::Matrix<T> Foam::operator-(const Matrix<T>& a) +template<class Type> +Foam::Matrix<Type> Foam::operator-(const Matrix<Type>& a) { - Matrix<T> na(a.n_, a.m_); + Matrix<Type> na(a.n_, a.m_); if (a.n_ && a.m_) { - T* nav = na.v_[0]; - const T* av = a.v_[0]; + Type* nav = na.v_[0]; + const Type* av = a.v_[0]; label nm = a.n_*a.m_; for (register label i=0; i<nm; i++) @@ -309,30 +327,34 @@ Foam::Matrix<T> Foam::operator-(const Matrix<T>& a) } -template<class T> -Foam::Matrix<T> Foam::operator+(const Matrix<T>& a, const Matrix<T>& b) +template<class Type> +Foam::Matrix<Type> Foam::operator+(const Matrix<Type>& a, const Matrix<Type>& b) { if (a.n_ != b.n_) { - FatalErrorIn("Matrix<T>::operator+(const Matrix<T>&, const Matrix<T>&)") - << "attempted add matrices with different number of rows: " + FatalErrorIn + ( + "Matrix<Type>::operator+(const Matrix<Type>&, const Matrix<Type>&)" + ) << "attempted add matrices with different number of rows: " << a.n_ << ", " << b.n_ << abort(FatalError); } if (a.m_ != b.m_) { - FatalErrorIn("Matrix<T>::operator+(const Matrix<T>&, const Matrix<T>&)") - << "attempted add matrices with different number of columns: " + FatalErrorIn + ( + "Matrix<Type>::operator+(const Matrix<Type>&, const Matrix<Type>&)" + ) << "attempted add matrices with different number of columns: " << a.m_ << ", " << b.m_ << abort(FatalError); } - Matrix<T> ab(a.n_, a.m_); + Matrix<Type> ab(a.n_, a.m_); - T* abv = ab.v_[0]; - const T* av = a.v_[0]; - const T* bv = b.v_[0]; + Type* abv = ab.v_[0]; + const Type* av = a.v_[0]; + const Type* bv = b.v_[0]; label nm = a.n_*a.m_;; for (register label i=0; i<nm; i++) @@ -344,30 +366,34 @@ Foam::Matrix<T> Foam::operator+(const Matrix<T>& a, const Matrix<T>& b) } -template<class T> -Foam::Matrix<T> Foam::operator-(const Matrix<T>& a, const Matrix<T>& b) +template<class Type> +Foam::Matrix<Type> Foam::operator-(const Matrix<Type>& a, const Matrix<Type>& b) { if (a.n_ != b.n_) { - FatalErrorIn("Matrix<T>::operator-(const Matrix<T>&, const Matrix<T>&)") - << "attempted add matrices with different number of rows: " + FatalErrorIn + ( + "Matrix<Type>::operator-(const Matrix<Type>&, const Matrix<Type>&)" + ) << "attempted add matrices with different number of rows: " << a.n_ << ", " << b.n_ << abort(FatalError); } if (a.m_ != b.m_) { - FatalErrorIn("Matrix<T>::operator-(const Matrix<T>&, const Matrix<T>&)") - << "attempted add matrices with different number of columns: " + FatalErrorIn + ( + "Matrix<Type>::operator-(const Matrix<Type>&, const Matrix<Type>&)" + ) << "attempted add matrices with different number of columns: " << a.m_ << ", " << b.m_ << abort(FatalError); } - Matrix<T> ab(a.n_, a.m_); + Matrix<Type> ab(a.n_, a.m_); - T* abv = ab.v_[0]; - const T* av = a.v_[0]; - const T* bv = b.v_[0]; + Type* abv = ab.v_[0]; + const Type* av = a.v_[0]; + const Type* bv = b.v_[0]; label nm = a.n_*a.m_;; for (register label i=0; i<nm; i++) @@ -379,15 +405,15 @@ Foam::Matrix<T> Foam::operator-(const Matrix<T>& a, const Matrix<T>& b) } -template<class T> -Foam::Matrix<T> Foam::operator*(const scalar s, const Matrix<T>& a) +template<class Type> +Foam::Matrix<Type> Foam::operator*(const scalar s, const Matrix<Type>& a) { - Matrix<T> sa(a.n_, a.m_); + Matrix<Type> sa(a.n_, a.m_); if (a.n_ && a.m_) { - T* sav = sa.v_[0]; - const T* av = a.v_[0]; + Type* sav = sa.v_[0]; + const Type* av = a.v_[0]; label nm = a.n_*a.m_;; for (register label i=0; i<nm; i++) diff --git a/src/OpenFOAM/containers/Matrix/Matrix.H b/src/OpenFOAM/matrices/Matrix/Matrix.H similarity index 70% rename from src/OpenFOAM/containers/Matrix/Matrix.H rename to src/OpenFOAM/matrices/Matrix/Matrix.H index ab68ce5badb..6b4da39d4f2 100644 --- a/src/OpenFOAM/containers/Matrix/Matrix.H +++ b/src/OpenFOAM/matrices/Matrix/Matrix.H @@ -51,25 +51,37 @@ namespace Foam // Forward declaration of friend functions and operators -template<class T> class Matrix; - -template<class T> const T& max(const Matrix<T>&); -template<class T> const T& min(const Matrix<T>&); - -template<class T> Matrix<T> operator-(const Matrix<T>&); -template<class T> Matrix<T> operator+(const Matrix<T>&, const Matrix<T>&); -template<class T> Matrix<T> operator-(const Matrix<T>&, const Matrix<T>&); -template<class T> Matrix<T> operator*(const scalar, const Matrix<T>&); - -template<class T> Istream& operator>>(Istream&, Matrix<T>&); -template<class T> Ostream& operator<<(Ostream&, const Matrix<T>&); +template<class Type> class Matrix; + +template<class Type> const Type& max(const Matrix<Type>&); +template<class Type> const Type& min(const Matrix<Type>&); + +template<class Type> Matrix<Type> operator-(const Matrix<Type>&); +template<class Type> Matrix<Type> operator+ +( + const Matrix<Type>&, + const Matrix<Type>& +); +template<class Type> Matrix<Type> operator- +( + const Matrix<Type>&, + const Matrix<Type>& +); +template<class Type> Matrix<Type> operator* +( + const scalar, + const Matrix<Type>& +); + +template<class Type> Istream& operator>>(Istream&, Matrix<Type>&); +template<class Type> Ostream& operator<<(Ostream&, const Matrix<Type>&); /*---------------------------------------------------------------------------*\ Class Matrix Declaration \*---------------------------------------------------------------------------*/ -template<class T> +template<class Type> class Matrix { // Private data @@ -78,7 +90,7 @@ class Matrix label n_, m_; //- Row pointers - T** __restrict__ v_; + Type** __restrict__ v_; //- Allocate the storage for the row-pointers and the data // and set the row pointers @@ -97,16 +109,16 @@ public: //- Construct with given number of rows and columns // and value for all elements. - Matrix(const label n, const label m, const T&); + Matrix(const label n, const label m, const Type&); //- Copy constructor. - Matrix(const Matrix<T>&); + Matrix(const Matrix<Type>&); //- Construct from Istream. Matrix(Istream&); //- Clone - inline autoPtr<Matrix<T> > clone() const; + inline autoPtr<Matrix<Type> > clone() const; // Destructor @@ -117,7 +129,7 @@ public: // Member functions //- Return a null Matrix - static const Matrix<T>& null(); + static const Matrix<Type>& null(); // Access @@ -148,45 +160,60 @@ public: //- Transfer the contents of the argument Matrix into this Matrix // and annull the argument Matrix. - void transfer(Matrix<T>&); + void transfer(Matrix<Type>&); // Member operators //- Return subscript-checked element of Matrix. - inline T* operator[](const label); + inline Type* operator[](const label); //- Return subscript-checked element of constant Matrix. - inline const T* operator[](const label) const; + inline const Type* operator[](const label) const; + + //- Return the transpose of the matrix + Matrix<Type> T() const; //- Assignment operator. Takes linear time. - void operator=(const Matrix<T>&); + void operator=(const Matrix<Type>&); //- Assignment of all entries to the given value - void operator=(const T&); + void operator=(const Type&); // Friend functions - friend const T& max<T>(const Matrix<T>&); - friend const T& min<T>(const Matrix<T>&); + friend const Type& max<Type>(const Matrix<Type>&); + friend const Type& min<Type>(const Matrix<Type>&); // Friend operators - friend Matrix<T> operator-<T>(const Matrix<T>&); - friend Matrix<T> operator+<T>(const Matrix<T>&, const Matrix<T>&); - friend Matrix<T> operator-<T>(const Matrix<T>&, const Matrix<T>&); - friend Matrix<T> operator*<T>(const scalar, const Matrix<T>&); + friend Matrix<Type> operator-<Type>(const Matrix<Type>&); + friend Matrix<Type> operator+<Type> + ( + const Matrix<Type>&, + const Matrix<Type>& + ); + friend Matrix<Type> operator-<Type> + ( + const Matrix<Type>&, + const Matrix<Type>& + ); + friend Matrix<Type> operator*<Type> + ( + const scalar, + const Matrix<Type>& + ); // IOstream operators //- Read Matrix from Istream, discarding contents of existing Matrix. - friend Istream& operator>> <T>(Istream&, Matrix<T>&); + friend Istream& operator>> <Type>(Istream&, Matrix<Type>&); // Write Matrix to Ostream. - friend Ostream& operator<< <T>(Ostream&, const Matrix<T>&); + friend Ostream& operator<< <Type>(Ostream&, const Matrix<Type>&); }; diff --git a/src/OpenFOAM/containers/Matrix/MatrixI.H b/src/OpenFOAM/matrices/Matrix/MatrixI.H similarity index 66% rename from src/OpenFOAM/containers/Matrix/MatrixI.H rename to src/OpenFOAM/matrices/Matrix/MatrixI.H index d0e3fe8fdf3..8323174d4f9 100644 --- a/src/OpenFOAM/containers/Matrix/MatrixI.H +++ b/src/OpenFOAM/matrices/Matrix/MatrixI.H @@ -26,8 +26,8 @@ License // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -template<class T> -inline Foam::Matrix<T>::Matrix() +template<class Type> +inline Foam::Matrix<Type>::Matrix() : n_(0), m_(0), @@ -35,71 +35,67 @@ inline Foam::Matrix<T>::Matrix() {} -template<class T> -inline Foam::autoPtr<Foam::Matrix<T> > Foam::Matrix<T>::clone() const +template<class Type> +inline Foam::autoPtr<Foam::Matrix<Type> > Foam::Matrix<Type>::clone() const { - return autoPtr<Matrix<T> >(new Matrix<T>(*this)); + return autoPtr<Matrix<Type> >(new Matrix<Type>(*this)); } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // //- Return the number of rows -template<class T> -inline Foam::label Foam::Matrix<T>::n() const +template<class Type> +inline Foam::label Foam::Matrix<Type>::n() const { return n_; } -//- Return the number of columns -template<class T> -inline Foam::label Foam::Matrix<T>::m() const +template<class Type> +inline Foam::label Foam::Matrix<Type>::m() const { return m_; } -//- Return the number of columns -template<class T> -inline Foam::label Foam::Matrix<T>::size() const +template<class Type> +inline Foam::label Foam::Matrix<Type>::size() const { return n_*m_; } -// Check index i is within valid range (0 ... n-1). -template<class T> -inline void Foam::Matrix<T>::checki(const label i) const +template<class Type> +inline void Foam::Matrix<Type>::checki(const label i) const { if (!n_) { - FatalErrorIn("Matrix<T>::checki(const label)") + FatalErrorIn("Matrix<Type>::checki(const label)") << "attempt to access element from zero sized row" << abort(FatalError); } else if (i<0 || i>=n_) { - FatalErrorIn("Matrix<T>::checki(const label)") + FatalErrorIn("Matrix<Type>::checki(const label)") << "index " << i << " out of range 0 ... " << n_-1 << abort(FatalError); } } -// Check index j is within valid range (0 ... n-1). -template<class T> -inline void Foam::Matrix<T>::checkj(const label j) const +template<class Type> +inline void Foam::Matrix<Type>::checkj(const label j) const { if (!m_) { - FatalErrorIn("Matrix<T>::checkj(const label)") + FatalErrorIn("Matrix<Type>::checkj(const label)") << "attempt to access element from zero sized column" << abort(FatalError); } else if (j<0 || j>=m_) { - FatalErrorIn("Matrix<T>::checkj(const label)") + FatalErrorIn("Matrix<Type>::checkj(const label)") << "index " << j << " out of range 0 ... " << m_-1 << abort(FatalError); } @@ -108,9 +104,8 @@ inline void Foam::Matrix<T>::checkj(const label j) const // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -// Return subscript-checked element access -template<class T> -inline T* Foam::Matrix<T>::operator[](const label i) +template<class Type> +inline Type* Foam::Matrix<Type>::operator[](const label i) { # ifdef FULLDEBUG checki(i); @@ -119,9 +114,8 @@ inline T* Foam::Matrix<T>::operator[](const label i) } -// Return subscript-checked const element access -template<class T> -inline const T* Foam::Matrix<T>::operator[](const label i) const +template<class Type> +inline const Type* Foam::Matrix<Type>::operator[](const label i) const { # ifdef FULLDEBUG checki(i); diff --git a/src/OpenFOAM/containers/Matrix/MatrixIO.C b/src/OpenFOAM/matrices/Matrix/MatrixIO.C similarity index 84% rename from src/OpenFOAM/containers/Matrix/MatrixIO.C rename to src/OpenFOAM/matrices/Matrix/MatrixIO.C index 710e42876e6..9b5a922f0d5 100644 --- a/src/OpenFOAM/containers/Matrix/MatrixIO.C +++ b/src/OpenFOAM/matrices/Matrix/MatrixIO.C @@ -32,8 +32,8 @@ License // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // -template<class T> -Foam::Matrix<T>::Matrix(Istream& is) +template<class Type> +Foam::Matrix<Type>::Matrix(Istream& is) : n_(0), m_(0), @@ -43,17 +43,17 @@ Foam::Matrix<T>::Matrix(Istream& is) } -template<class T> -Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) +template<class Type> +Foam::Istream& Foam::operator>>(Istream& is, Matrix<Type>& M) { // Anull matrix M.clear(); - is.fatalCheck("operator>>(Istream&, Matrix<T>&)"); + is.fatalCheck("operator>>(Istream&, Matrix<Type>&)"); token firstToken(is); - is.fatalCheck("operator>>(Istream&, Matrix<T>&) : reading first token"); + is.fatalCheck("operator>>(Istream&, Matrix<Type>&) : reading first token"); if (firstToken.isLabel()) { @@ -63,7 +63,7 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) label nm = M.n_*M.m_; // Read list contents depending on data format - if (is.format() == IOstream::ASCII || !contiguous<T>()) + if (is.format() == IOstream::ASCII || !contiguous<Type>()) { // Read beginning of contents char listDelimiter = is.readBeginList("Matrix"); @@ -71,7 +71,7 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) if (nm) { M.allocate(); - T* v = M.v_[0]; + Type* v = M.v_[0]; if (listDelimiter == token::BEGIN_LIST) { @@ -88,7 +88,7 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) is.fatalCheck ( - "operator>>(Istream&, Matrix<T>&) : " + "operator>>(Istream&, Matrix<Type>&) : " "reading entry" ); } @@ -98,12 +98,12 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) } else { - T element; + Type element; is >> element; is.fatalCheck ( - "operator>>(Istream&, Matrix<T>&) : " + "operator>>(Istream&, Matrix<Type>&) : " "reading the single entry" ); @@ -122,13 +122,13 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) if (nm) { M.allocate(); - T* v = M.v_[0]; + Type* v = M.v_[0]; - is.read(reinterpret_cast<char*>(v), nm*sizeof(T)); + is.read(reinterpret_cast<char*>(v), nm*sizeof(Type)); is.fatalCheck ( - "operator>>(Istream&, Matrix<T>&) : " + "operator>>(Istream&, Matrix<Type>&) : " "reading the binary block" ); } @@ -136,7 +136,7 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) } else { - FatalIOErrorIn("operator>>(Istream&, Matrix<T>&)", is) + FatalIOErrorIn("operator>>(Istream&, Matrix<Type>&)", is) << "incorrect first token, expected <int>, found " << firstToken.info() << exit(FatalIOError); @@ -146,23 +146,23 @@ Foam::Istream& Foam::operator>>(Istream& is, Matrix<T>& M) } -template<class T> -Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<T>& M) +template<class Type> +Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Type>& M) { label nm = M.n_*M.m_; os << M.n() << token::SPACE << M.m(); // Write list contents depending on data format - if (os.format() == IOstream::ASCII || !contiguous<T>()) + if (os.format() == IOstream::ASCII || !contiguous<Type>()) { if (nm) { bool uniform = false; - const T* v = M.v_[0]; + const Type* v = M.v_[0]; - if (nm > 1 && contiguous<T>()) + if (nm > 1 && contiguous<Type>()) { uniform = true; @@ -187,7 +187,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<T>& M) // Write end of contents delimiter os << token::END_BLOCK; } - else if (nm < 10 && contiguous<T>()) + else if (nm < 10 && contiguous<Type>()) { // Write size of list and start contents delimiter os << token::BEGIN_LIST; @@ -246,7 +246,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<T>& M) { if (nm) { - os.write(reinterpret_cast<const char*>(M.v_[0]), nm*sizeof(T)); + os.write(reinterpret_cast<const char*>(M.v_[0]), nm*sizeof(Type)); } } diff --git a/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.C b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.C new file mode 100644 index 00000000000..a1355c393d1 --- /dev/null +++ b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.C @@ -0,0 +1,400 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2005 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "SVD.H" +#include "scalarList.H" +#include "scalarMatrix.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * * * Constructor * * * * * * * * * * * * * * // + +Foam::SVD::SVD(const Matrix<scalar>& A, const scalar minCondition) +: + U_(A), + V_(A.m(), A.m()), + S_(A.m()), + VSinvUt_(A.m(), A.n()), + nZeros_(0) +{ + // SVDcomp to find U_, V_ and S_ - the singular values + + const label Um = U_.m(); + const label Un = U_.n(); + + scalarList rv1(Um); + scalar g = 0; + scalar scale = 0; + scalar s = 0; + scalar anorm = 0; + label l = 0; + + for (label i = 0; i < Um; i++) + { + l = i+2; + rv1[i] = scale*g; + g = s = scale = 0; + + if (i < Un) + { + for (label k = i; k < Un; k++) + { + scale += mag(U_[k][i]); + } + + if (scale != 0) + { + for (label k = i; k < Un; k++) + { + U_[k][i] /= scale; + s += U_[k][i]*U_[k][i]; + } + + scalar f = U_[i][i]; + g = -sign(Foam::sqrt(s), f); + scalar h = f*g - s; + U_[i][i] = f - g; + + for (label j = l-1; j < Um; j++) + { + s = 0; + for (label k = i; k < Un; k++) + { + s += U_[k][i]*U_[k][j]; + } + + f = s/h; + for (label k = i; k < A.n(); k++) + { + U_[k][j] += f*U_[k][i]; + } + } + + for (label k = i; k < Un; k++) + { + U_[k][i] *= scale; + } + } + } + + S_[i] = scale*g; + + g = s = scale = 0; + + if (i+1 <= Un && i != Um) + { + for (label k = l-1; k < Um; k++) + { + scale += mag(U_[i][k]); + } + + if (scale != 0) + { + for (label k=l-1; k < Um; k++) + { + U_[i][k] /= scale; + s += U_[i][k]*U_[i][k]; + } + + scalar f = U_[i][l-1]; + g = -sign(Foam::sqrt(s),f); + scalar h = f*g - s; + U_[i][l-1] = f - g; + + for (label k = l-1; k < Um; k++) + { + rv1[k] = U_[i][k]/h; + } + + for (label j = l-1; j < Un; j++) + { + s = 0; + for (label k = l-1; k < Um; k++) + { + s += U_[j][k]*U_[i][k]; + } + + for (label k = l-1; k < Um; k++) + { + U_[j][k] += s*rv1[k]; + } + } + for (label k = l-1; k < Um; k++) + { + U_[i][k] *= scale; + } + } + } + + anorm = max(anorm, mag(S_[i]) + mag(rv1[i])); + } + + for (label i = Um-1; i >= 0; i--) + { + if (i < Um-1) + { + if (g != 0) + { + for (label j = l; j < Um; j++) + { + V_[j][i] = (U_[i][j]/U_[i][l])/g; + } + + for (label j=l; j < Um; j++) + { + s = 0; + for (label k = l; k < Um; k++) + { + s += U_[i][k]*V_[k][j]; + } + + for (label k = l; k < Um; k++) + { + V_[k][j] += s*V_[k][i]; + } + } + } + + for (label j = l; j < Um;j++) + { + V_[i][j] = V_[j][i] = 0.0; + } + } + + V_[i][i] = 1; + g = rv1[i]; + l = i; + } + + for (label i = min(Um, Un) - 1; i >= 0; i--) + { + l = i+1; + g = S_[i]; + + for (label j = l; j < Um; j++) + { + U_[i][j] = 0.0; + } + + if (g != 0) + { + g = 1.0/g; + + for (label j = l; j < Um; j++) + { + s = 0; + for (label k = l; k < Un; k++) + { + s += U_[k][i]*U_[k][j]; + } + + scalar f = (s/U_[i][i])*g; + + for (label k = i; k < Un; k++) + { + U_[k][j] += f*U_[k][i]; + } + } + + for (label j = i; j < Un; j++) + { + U_[j][i] *= g; + } + } + else + { + for (label j = i; j < Un; j++) + { + U_[j][i] = 0.0; + } + } + + ++U_[i][i]; + } + + for (label k = Um-1; k >= 0; k--) + { + for (label its = 0; its < 35; its++) + { + bool flag = true; + + label nm; + for (l = k; l >= 0; l--) + { + nm = l-1; + if (mag(rv1[l]) + anorm == anorm) + { + flag = false; + break; + } + if (mag(S_[nm]) + anorm == anorm) break; + } + + if (flag) + { + scalar c = 0.0; + s = 1.0; + for (label i = l-1; i < k+1; i++) + { + scalar f = s*rv1[i]; + rv1[i] = c*rv1[i]; + + if (mag(f) + anorm == anorm) break; + + g = S_[i]; + scalar h = sqrtSumSqr(f, g); + S_[i] = h; + h = 1.0/h; + c = g*h; + s = -f*h; + + for (label j = 0; j < Un; j++) + { + scalar y = U_[j][nm]; + scalar z = U_[j][i]; + U_[j][nm] = y*c + z*s; + U_[j][i] = z*c - y*s; + } + } + } + + scalar z = S_[k]; + + if (l == k) + { + if (z < 0.0) + { + S_[k] = -z; + + for (label j = 0; j < Um; j++) V_[j][k] = -V_[j][k]; + } + break; + } + if (its == 34) + { + WarningIn("SVD::SVD(Matrix<scalar>& A)") + << "no convergence in 35 SVD iterations" + << endl; + } + + scalar x = S_[l]; + nm = k-1; + scalar y = S_[nm]; + g = rv1[nm]; + scalar h = rv1[k]; + scalar f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y); + g = sqrtSumSqr(f, 1.0); + f = ((x - z)*(x + z) + h*((y/(f + sign(g, f))) - h))/x; + scalar c = 1.0; + s = 1.0; + + for (label j = l; j <= nm; j++) + { + label i = j + 1; + g = rv1[i]; + y = S_[i]; + h = s*g; + g = c*g; + scalar z = sqrtSumSqr(f, h); + rv1[j] = z; + c = f/z; + s = h/z; + f = x*c + g*s; + g = g*c - x*s; + h = y*s; + y *= c; + + for (label jj = 0; jj < Um; jj++) + { + x = V_[jj][j]; + z = V_[jj][i]; + V_[jj][j] = x*c + z*s; + V_[jj][i] = z*c - x*s; + } + + z = sqrtSumSqr(f, h); + S_[j] = z; + if (z) + { + z = 1.0/z; + c = f*z; + s = h*z; + } + f = c*g + s*y; + x = c*y - s*g; + + for (label jj=0; jj < Un; jj++) + { + y = U_[jj][j]; + z = U_[jj][i]; + U_[jj][j] = y*c + z*s; + U_[jj][i] = z*c - y*s; + } + } + rv1[l] = 0.0; + rv1[k] = f; + S_[k] = x; + } + } + + // zero singular values that are less than minCondition*maxS + const scalar minS = minCondition*S_[findMax(S_)]; + for (label i = 0; i < S_.size(); i++) + { + if (S_[i] <= minS) + { + //Info << "Removing " << S_[i] << " < " << minS << endl; + S_[i] = 0; + nZeros_++; + } + } + + // now multiply out to find the pseudo inverse of A, VSinvUt_ + multiply(VSinvUt_, V_, inv(S_), U_.T()); + + // test SVD + /*Matrix<scalar> SVDA(A.n(), A.m()); + multiply(SVDA, U_, S_, transpose(V_)); + scalar maxDiff = 0; + scalar diff = 0; + for(label i = 0; i < A.n(); i++) + { + for(label j = 0; j < A.m(); j++) + { + diff = mag(A[i][j] - SVDA[i][j]); + if (diff > maxDiff) maxDiff = diff; + } + } + Info << "Maximum discrepancy between A and svd(A) = " << maxDiff << endl; + + if (maxDiff > 4) + { + Info << "singular values " << S_ << endl; + } + */ +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.H b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.H new file mode 100644 index 00000000000..b597027732d --- /dev/null +++ b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVD.H @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2005 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + SVD + +Description + Singular value decomposition of a rectangular matrix. + +SourceFiles + SVD.C + +\*---------------------------------------------------------------------------*/ + +#ifndef SVD_H +#define SVD_H + +#include "DiagonalMatrix.H" +#include "Matrix.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +/*---------------------------------------------------------------------------*\ + Class SVD Declaration +\*---------------------------------------------------------------------------*/ + +class SVD +{ + // Private data + + //- Rectangular matrix with the same dimensions as the input + Matrix<scalar> U_; + + //- square matrix V + Matrix<scalar> V_; + + //- The singular values + DiagonalMatrix<scalar> S_; + + //- The matrix product V S^(-1) U^T + Matrix<scalar> VSinvUt_; + + //- The number of zero singular values + label nZeros_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + SVD(const SVD&); + + //- Disallow default bitwise assignment + void operator=(const SVD&); + + template<class T> + inline const T sign(const T& a, const T& b); + + +public: + + // Constructors + + //- Construct from a rectangular Matrix + SVD(const Matrix<scalar>& A, const scalar minCondition = 0); + + + // Access functions + + //- Return U + inline const Matrix<scalar>& U() const; + + //- Return the square matrix V + inline const Matrix<scalar>& V() const; + + //- Return the singular values + inline const DiagonalMatrix<scalar>& S() const; + + //- Return VSinvUt (the pseudo inverse) + inline const Matrix<scalar>& VSinvUt() const; + + //- Return the number of zero singular values + inline label nZeros() const; + + //- Return the minimum non-zero singular value + inline scalar minNonZeroS() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "SVDI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/scalarMatrix/SVD/SVDI.H b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVDI.H new file mode 100644 index 00000000000..337647edfb5 --- /dev/null +++ b/src/OpenFOAM/matrices/scalarMatrix/SVD/SVDI.H @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * // + +template<class T> +inline const T Foam::SVD::sign(const T& a, const T& b) +{ + return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline const Foam::Matrix<Foam::scalar>& Foam::SVD::U() const +{ + return U_; +} + +inline const Foam::Matrix<Foam::scalar>& Foam::SVD::V() const +{ + return V_; +} + +inline const Foam::DiagonalMatrix<Foam::scalar>& Foam::SVD::S() const +{ + return S_; +} + +inline const Foam::Matrix<Foam::scalar>& Foam::SVD::VSinvUt() const +{ + return VSinvUt_; +} + +inline Foam::label Foam::SVD::nZeros() const +{ + return nZeros_; +} + +inline Foam::scalar Foam::SVD::minNonZeroS() const +{ + scalar minS = S_[0]; + for(label i = 1; i < S_.size(); i++) + { + scalar s = S_[i]; + if (s > VSMALL && s < minS) minS = s; + } + return minS; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.C b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.C index 2ff9e39f18a..b88e167b6fb 100644 --- a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.C +++ b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.C @@ -25,6 +25,8 @@ License \*---------------------------------------------------------------------------*/ #include "scalarMatrix.H" +#include "SVD.H" + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -136,7 +138,7 @@ void Foam::scalarMatrix::LUDecompose { Swap(matrixj[k], matrixiMax[k]); } - + vv[iMax] = vv[j]; } @@ -158,4 +160,159 @@ void Foam::scalarMatrix::LUDecompose } +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +void Foam::multiply +( + Matrix<scalar>& ans, // value changed in return + const Matrix<scalar>& A, + const Matrix<scalar>& B +) +{ + if (A.m() != B.n()) + { + FatalErrorIn + ( + "multiply(" + "Matrix<scalar>& answer " + "const Matrix<scalar>& A, " + "const Matrix<scalar>& B)" + ) << "A and B must have identical inner dimensions but A.m = " + << A.m() << " and B.n = " << B.n() + << abort(FatalError); + } + + ans = Matrix<scalar>(A.n(), B.m(), scalar(0)); + + for(register label i = 0; i < A.n(); i++) + { + for(register label j = 0; j < B.m(); j++) + { + for(register label l = 0; l < B.n(); l++) + { + ans[i][j] += A[i][l]*B[l][j]; + } + } + } +} + + +void Foam::multiply +( + Matrix<scalar>& ans, // value changed in return + const Matrix<scalar>& A, + const Matrix<scalar>& B, + const Matrix<scalar>& C +) +{ + if (A.m() != B.n()) + { + FatalErrorIn + ( + "multiply(" + "const Matrix<scalar>& A, " + "const Matrix<scalar>& B, " + "const Matrix<scalar>& C, " + "Matrix<scalar>& answer)" + ) << "A and B must have identical inner dimensions but A.m = " + << A.m() << " and B.n = " << B.n() + << abort(FatalError); + } + + if (B.m() != C.n()) + { + FatalErrorIn + ( + "multiply(" + "const Matrix<scalar>& A, " + "const Matrix<scalar>& B, " + "const Matrix<scalar>& C, " + "Matrix<scalar>& answer)" + ) << "B and C must have identical inner dimensions but B.m = " + << B.m() << " and C.n = " << C.n() + << abort(FatalError); + } + + ans = Matrix<scalar>(A.n(), C.m(), scalar(0)); + + for(register label i = 0; i < A.n(); i++) + { + for(register label g = 0; g < C.m(); g++) + { + for(register label l = 0; l < C.n(); l++) + { + scalar ab = 0; + for(register label j = 0; j < A.m(); j++) + { + ab += A[i][j]*B[j][l]; + } + ans[i][g] += C[l][g] * ab; + } + } + } +} + + +void Foam::multiply +( + Matrix<scalar>& ans, // value changed in return + const Matrix<scalar>& A, + const DiagonalMatrix<scalar>& B, + const Matrix<scalar>& C +) +{ + if (A.m() != B.size()) + { + FatalErrorIn + ( + "multiply(" + "const Matrix<scalar>& A, " + "const DiagonalMatrix<scalar>& B, " + "const Matrix<scalar>& C, " + "Matrix<scalar>& answer)" + ) << "A and B must have identical inner dimensions but A.m = " + << A.m() << " and B.n = " << B.size() + << abort(FatalError); + } + + if (B.size() != C.n()) + { + FatalErrorIn + ( + "multiply(" + "const Matrix<scalar>& A, " + "const DiagonalMatrix<scalar>& B, " + "const Matrix<scalar>& C, " + "Matrix<scalar>& answer)" + ) << "B and C must have identical inner dimensions but B.m = " + << B.size() << " and C.n = " << C.n() + << abort(FatalError); + } + + ans = Matrix<scalar>(A.n(), C.m(), scalar(0)); + + for(register label i = 0; i < A.n(); i++) + { + for(register label g = 0; g < C.m(); g++) + { + for(register label l = 0; l < C.n(); l++) + { + ans[i][g] += C[l][g] * A[i][l]*B[l]; + } + } + } +} + + +Foam::Matrix<Foam::scalar> Foam::SVDinv +( + const Matrix<scalar>& A, + scalar minCondition +) +{ + SVD svd(A, minCondition); + return svd.VSinvUt(); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.H b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.H index f2b0764f1a5..2d22e71d4ea 100644 --- a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.H +++ b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrix.H @@ -37,6 +37,7 @@ SourceFiles #define scalarMatrix_H #include "Matrix.H" +#include "DiagonalMatrix.H" #include "scalarField.H" #include "labelList.H" @@ -75,13 +76,13 @@ public: //- Solve the matrix using Gaussian elimination with pivoting, // returning the solution in the source - template<class T> - static void solve(Matrix<scalar>& matrix, Field<T>& source); + template<class Type> + static void solve(Matrix<scalar>& matrix, Field<Type>& source); //- Solve the matrix using Gaussian elimination with pivoting // and return the solution - template<class T> - void solve(Field<T>& psi, const Field<T>& source) const; + template<class Type> + void solve(Field<Type>& psi, const Field<Type>& source) const; //- LU decompose the matrix with pivoting @@ -93,21 +94,50 @@ public: //- LU back-substitution with given source, returning the solution // in the source - template<class T> + template<class Type> static void LUBacksubstitute ( const Matrix<scalar>& luMmatrix, const labelList& pivotIndices, - Field<T>& source + Field<Type>& source ); //- Solve the matrix using LU decomposition with pivoting // returning the LU form of the matrix and the solution in the source - template<class T> - static void LUsolve(Matrix<scalar>& matrix, Field<T>& source); + template<class Type> + static void LUsolve(Matrix<scalar>& matrix, Field<Type>& source); }; +// Global functions + +void multiply +( + Matrix<scalar>& answer, // value changed in return + const Matrix<scalar>& A, + const Matrix<scalar>& B +); + +void multiply +( + Matrix<scalar>& answer, // value changed in return + const Matrix<scalar>& A, + const Matrix<scalar>& B, + const Matrix<scalar>& C +); + +void multiply +( + Matrix<scalar>& answer, // value changed in return + const Matrix<scalar>& A, + const DiagonalMatrix<scalar>& B, + const Matrix<scalar>& C +); + +//- Return the inverse of matrix A using SVD +Matrix<scalar> SVDinv(const Matrix<scalar>& A, scalar minCondition = 0); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrixTemplates.C b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrixTemplates.C index b729e32fcc7..fb48a9b26d5 100644 --- a/src/OpenFOAM/matrices/scalarMatrix/scalarMatrixTemplates.C +++ b/src/OpenFOAM/matrices/scalarMatrix/scalarMatrixTemplates.C @@ -29,11 +29,11 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -template<class T> +template<class Type> void Foam::scalarMatrix::solve ( Matrix<scalar>& tmpMatrix, - Field<T>& sourceSol + Field<Type>& sourceSol ) { label n = tmpMatrix.n(); @@ -89,7 +89,7 @@ void Foam::scalarMatrix::solve // Back-substitution for (register label j=n-1; j>=0; j--) { - T ntempvec = pTraits<T>::zero; + Type ntempvec = pTraits<Type>::zero; for (register label k=j+1; k<n; k++) { @@ -101,8 +101,8 @@ void Foam::scalarMatrix::solve } -template<class T> -void Foam::scalarMatrix::solve(Field<T>& psi, const Field<T>& source) const +template<class Type> +void Foam::scalarMatrix::solve(Field<Type>& psi, const Field<Type>& source) const { Matrix<scalar> tmpMatrix = *this; psi = source; @@ -110,12 +110,12 @@ void Foam::scalarMatrix::solve(Field<T>& psi, const Field<T>& source) const } -template<class T> +template<class Type> void Foam::scalarMatrix::LUBacksubstitute ( const Matrix<scalar>& luMatrix, const labelList& pivotIndices, - Field<T>& sourceSol + Field<Type>& sourceSol ) { label n = luMatrix.n(); @@ -125,7 +125,7 @@ void Foam::scalarMatrix::LUBacksubstitute for (register label i=0; i<n; i++) { label ip = pivotIndices[i]; - T sum = sourceSol[ip]; + Type sum = sourceSol[ip]; sourceSol[ip] = sourceSol[i]; const scalar* __restrict__ luMatrixi = luMatrix[i]; @@ -136,7 +136,7 @@ void Foam::scalarMatrix::LUBacksubstitute sum -= luMatrixi[j]*sourceSol[j]; } } - else if (sum != pTraits<T>::zero) + else if (sum != pTraits<Type>::zero) { ii = i+1; } @@ -146,11 +146,11 @@ void Foam::scalarMatrix::LUBacksubstitute for (register label i=n-1; i>=0; i--) { - T sum = sourceSol[i]; + Type sum = sourceSol[i]; const scalar* __restrict__ luMatrixi = luMatrix[i]; for (register label j=i+1; j<n; j++) - { + { sum -= luMatrixi[j]*sourceSol[j]; } @@ -159,11 +159,11 @@ void Foam::scalarMatrix::LUBacksubstitute } -template<class T> +template<class Type> void Foam::scalarMatrix::LUsolve ( Matrix<scalar>& matrix, - Field<T>& sourceSol + Field<Type>& sourceSol ) { labelList pivotIndices(matrix.n()); diff --git a/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.C b/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.C index 22de758f3ac..1265b87ee57 100644 --- a/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.C +++ b/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.C @@ -28,19 +28,19 @@ License // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -template<class T> -Foam::simpleMatrix<T>::simpleMatrix(const label mSize) +template<class Type> +Foam::simpleMatrix<Type>::simpleMatrix(const label mSize) : scalarMatrix(mSize), - source_(mSize, pTraits<T>::zero) + source_(mSize, pTraits<Type>::zero) {} -template<class T> -Foam::simpleMatrix<T>::simpleMatrix +template<class Type> +Foam::simpleMatrix<Type>::simpleMatrix ( const scalarMatrix& matrix, - const Field<T>& source + const Field<Type>& source ) : scalarMatrix(matrix), @@ -48,8 +48,8 @@ Foam::simpleMatrix<T>::simpleMatrix {} -template<class T> -Foam::simpleMatrix<T>::simpleMatrix(Istream& is) +template<class Type> +Foam::simpleMatrix<Type>::simpleMatrix(Istream& is) : scalarMatrix(is), source_(is) @@ -58,11 +58,11 @@ Foam::simpleMatrix<T>::simpleMatrix(Istream& is) // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -template<class T> -Foam::Field<T> Foam::simpleMatrix<T>::solve() const +template<class Type> +Foam::Field<Type> Foam::simpleMatrix<Type>::solve() const { scalarMatrix tmpMatrix = *this; - Field<T> sourceSol = source_; + Field<Type> sourceSol = source_; scalarMatrix::solve(tmpMatrix, sourceSol); @@ -70,11 +70,11 @@ Foam::Field<T> Foam::simpleMatrix<T>::solve() const } -template<class T> -Foam::Field<T> Foam::simpleMatrix<T>::LUsolve() const +template<class Type> +Foam::Field<Type> Foam::simpleMatrix<Type>::LUsolve() const { scalarMatrix luMatrix = *this; - Field<T> sourceSol = source_; + Field<Type> sourceSol = source_; scalarMatrix::LUsolve(luMatrix, sourceSol); @@ -84,26 +84,26 @@ Foam::Field<T> Foam::simpleMatrix<T>::LUsolve() const // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -template<class T> -void Foam::simpleMatrix<T>::operator=(const simpleMatrix<T>& m) +template<class Type> +void Foam::simpleMatrix<Type>::operator=(const simpleMatrix<Type>& m) { if (this == &m) { - FatalErrorIn("simpleMatrix<T>::operator=(const simpleMatrix<T>&)") + FatalErrorIn("simpleMatrix<Type>::operator=(const simpleMatrix<Type>&)") << "Attempted assignment to self" << abort(FatalError); } if (n() != m.n()) { - FatalErrorIn("simpleMatrix<T>::operator=(const simpleMatrix<T>&)") + FatalErrorIn("simpleMatrix<Type>::operator=(const simpleMatrix<Type>&)") << "Different size matrices" << abort(FatalError); } if (source_.size() != m.source_.size()) { - FatalErrorIn("simpleMatrix<T>::operator=(const simpleMatrix<T>&)") + FatalErrorIn("simpleMatrix<Type>::operator=(const simpleMatrix<Type>&)") << "Different size source vectors" << abort(FatalError); } @@ -115,14 +115,14 @@ void Foam::simpleMatrix<T>::operator=(const simpleMatrix<T>& m) // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // -template<class T> -Foam::simpleMatrix<T> Foam::operator+ +template<class Type> +Foam::simpleMatrix<Type> Foam::operator+ ( - const simpleMatrix<T>& m1, - const simpleMatrix<T>& m2 + const simpleMatrix<Type>& m1, + const simpleMatrix<Type>& m2 ) { - return simpleMatrix<T> + return simpleMatrix<Type> ( static_cast<const scalarMatrix&>(m1) + static_cast<const scalarMatrix&>(m2), @@ -131,14 +131,14 @@ Foam::simpleMatrix<T> Foam::operator+ } -template<class T> -Foam::simpleMatrix<T> Foam::operator- +template<class Type> +Foam::simpleMatrix<Type> Foam::operator- ( - const simpleMatrix<T>& m1, - const simpleMatrix<T>& m2 + const simpleMatrix<Type>& m1, + const simpleMatrix<Type>& m2 ) { - return simpleMatrix<T> + return simpleMatrix<Type> ( static_cast<const scalarMatrix&>(m1) - static_cast<const scalarMatrix&>(m2), @@ -147,17 +147,17 @@ Foam::simpleMatrix<T> Foam::operator- } -template<class T> -Foam::simpleMatrix<T> Foam::operator*(const scalar s, const simpleMatrix<T>& m) +template<class Type> +Foam::simpleMatrix<Type> Foam::operator*(const scalar s, const simpleMatrix<Type>& m) { - return simpleMatrix<T>(s*m.matrix_, s*m.source_); + return simpleMatrix<Type>(s*m.matrix_, s*m.source_); } // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // -template<class T> -Foam::Ostream& Foam::operator<<(Ostream& os, const simpleMatrix<T>& m) +template<class Type> +Foam::Ostream& Foam::operator<<(Ostream& os, const simpleMatrix<Type>& m) { os << static_cast<const scalarMatrix&>(m) << nl << m.source_; return os; diff --git a/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.H b/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.H index d1c411452b8..d7b1a027bec 100644 --- a/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.H +++ b/src/OpenFOAM/matrices/simpleMatrix/simpleMatrix.H @@ -45,35 +45,35 @@ namespace Foam // Forward declaration of friend functions and operators -template<class T> +template<class Type> class simpleMatrix; -template<class T> -simpleMatrix<T> operator+ +template<class Type> +simpleMatrix<Type> operator+ ( - const simpleMatrix<T>&, - const simpleMatrix<T>& + const simpleMatrix<Type>&, + const simpleMatrix<Type>& ); -template<class T> -simpleMatrix<T> operator- +template<class Type> +simpleMatrix<Type> operator- ( - const simpleMatrix<T>&, - const simpleMatrix<T>& + const simpleMatrix<Type>&, + const simpleMatrix<Type>& ); -template<class T> -simpleMatrix<T> operator* +template<class Type> +simpleMatrix<Type> operator* ( const scalar, - const simpleMatrix<T>& + const simpleMatrix<Type>& ); -template<class T> +template<class Type> Ostream& operator<< ( Ostream&, - const simpleMatrix<T>& + const simpleMatrix<Type>& ); @@ -81,14 +81,14 @@ Ostream& operator<< Class simpleMatrix Declaration \*---------------------------------------------------------------------------*/ -template<class T> +template<class Type> class simpleMatrix : public scalarMatrix { // Private data - Field<T> source_; + Field<Type> source_; public: @@ -99,25 +99,25 @@ public: simpleMatrix(const label); //- Construct from components - simpleMatrix(const scalarMatrix&, const Field<T>&); + simpleMatrix(const scalarMatrix&, const Field<Type>&); //- Construct from Istream simpleMatrix(Istream&); //- Construct as copy - simpleMatrix(const simpleMatrix<T>&); + simpleMatrix(const simpleMatrix<Type>&); // Member Functions // Access - Field<T>& source() + Field<Type>& source() { return source_; } - const Field<T>& source() const + const Field<Type>& source() const { return source_; } @@ -125,45 +125,45 @@ public: //- Solve the matrix using Gaussian elimination with pivoting // and return the solution - Field<T> solve() const; + Field<Type> solve() const; //- Solve the matrix using LU decomposition with pivoting // and return the solution - Field<T> LUsolve() const; + Field<Type> LUsolve() const; // Member Operators - void operator=(const simpleMatrix<T>&); + void operator=(const simpleMatrix<Type>&); // Friend Operators - friend simpleMatrix<T> operator+ <T> + friend simpleMatrix<Type> operator+ <Type> ( - const simpleMatrix<T>&, - const simpleMatrix<T>& + const simpleMatrix<Type>&, + const simpleMatrix<Type>& ); - friend simpleMatrix<T> operator- <T> + friend simpleMatrix<Type> operator- <Type> ( - const simpleMatrix<T>&, - const simpleMatrix<T>& + const simpleMatrix<Type>&, + const simpleMatrix<Type>& ); - friend simpleMatrix<T> operator* <T> + friend simpleMatrix<Type> operator* <Type> ( const scalar, - const simpleMatrix<T>& + const simpleMatrix<Type>& ); // Ostream Operator - friend Ostream& operator<< <T> + friend Ostream& operator<< <Type> ( Ostream&, - const simpleMatrix<T>& + const simpleMatrix<Type>& ); }; diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 0c3fae18872..25137c58c7d 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -38,6 +38,9 @@ fvMeshMapper = fvMesh/fvMeshMapper $(fvMeshMapper)/fvPatchMapper.C $(fvMeshMapper)/fvSurfaceMapper.C +extendedStencil = fvMesh/extendedStencil +$(extendedStencil)/extendedStencil.C + fvPatchFields = fields/fvPatchFields $(fvPatchFields)/fvPatchField/fvPatchFields.C @@ -165,6 +168,8 @@ $(schemes)/harmonic/harmonic.C $(schemes)/localBlended/localBlended.C $(schemes)/localMax/localMax.C $(schemes)/localMin/localMin.C +$(schemes)/quadraticFit/quadraticFit.C +$(schemes)/quadraticFit/quadraticFitData.C limitedSchemes = $(surfaceInterpolation)/limitedSchemes $(limitedSchemes)/limitedSurfaceInterpolationScheme/limitedSurfaceInterpolationSchemes.C diff --git a/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.C b/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.C new file mode 100644 index 00000000000..bb4c6c1534c --- /dev/null +++ b/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.C @@ -0,0 +1,525 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "extendedStencil.H" +#include "globalIndex.H" +#include "syncTools.H" +#include "SortableList.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// Calculates per face a list of global cell/face indices. +void Foam::extendedStencil::calcFaceStencils +( + const polyMesh& mesh, + const globalIndex& globalNumbering +) +{ + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + const label nBnd = mesh.nFaces()-mesh.nInternalFaces(); + const labelList& own = mesh.faceOwner(); + const labelList& nei = mesh.faceNeighbour(); + + + // Determine neighbouring global cell or boundary face + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + labelList neiGlobal(nBnd); + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + label faceI = pp.start(); + + if (pp.coupled()) + { + // For coupled faces get the cell on the other side + forAll(pp, i) + { + label bFaceI = faceI-mesh.nInternalFaces(); + neiGlobal[bFaceI] = globalNumbering.toGlobal(own[faceI]); + faceI++; + } + } + else if (isA<emptyPolyPatch>(pp)) + { + forAll(pp, i) + { + label bFaceI = faceI-mesh.nInternalFaces(); + neiGlobal[bFaceI] = -1; + faceI++; + } + } + else + { + // For noncoupled faces get the boundary face. + forAll(pp, i) + { + label bFaceI = faceI-mesh.nInternalFaces(); + neiGlobal[bFaceI] = + globalNumbering.toGlobal(mesh.nCells()+bFaceI); + faceI++; + } + } + } + syncTools::swapBoundaryFaceList(mesh, neiGlobal, false); + + + // Determine cellCells in global numbering + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + labelListList globalCellCells(mesh.nCells()); + forAll(globalCellCells, cellI) + { + const cell& cFaces = mesh.cells()[cellI]; + + labelList& cCells = globalCellCells[cellI]; + + cCells.setSize(cFaces.size()); + + // Collect neighbouring cells/faces + label nNbr = 0; + forAll(cFaces, i) + { + label faceI = cFaces[i]; + + if (mesh.isInternalFace(faceI)) + { + label nbrCellI = own[faceI]; + if (nbrCellI == cellI) + { + nbrCellI = nei[faceI]; + } + cCells[nNbr++] = globalNumbering.toGlobal(nbrCellI); + } + else + { + label nbrCellI = neiGlobal[faceI-mesh.nInternalFaces()]; + if (nbrCellI != -1) + { + cCells[nNbr++] = nbrCellI; + } + } + } + cCells.setSize(nNbr); + } + + + // Determine neighbouring global cell Cells + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + labelListList neiGlobalCellCells(nBnd); + for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++) + { + neiGlobalCellCells[faceI-mesh.nInternalFaces()] = + globalCellCells[own[faceI]]; + } + syncTools::swapBoundaryFaceList(mesh, neiGlobalCellCells, false); + + + + // Construct stencil in global numbering + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + stencil_.setSize(mesh.nFaces()); + + labelHashSet faceStencil; + + for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++) + { + faceStencil.clear(); + label globalOwn = globalNumbering.toGlobal(own[faceI]); + faceStencil.insert(globalOwn); + const labelList& ownCCells = globalCellCells[own[faceI]]; + forAll(ownCCells, i) + { + faceStencil.insert(ownCCells[i]); + } + + label globalNei = globalNumbering.toGlobal(nei[faceI]); + faceStencil.insert(globalNei); + const labelList& neiCCells = globalCellCells[nei[faceI]]; + forAll(neiCCells, i) + { + faceStencil.insert(neiCCells[i]); + } + + // Guarantee owner first, neighbour second. + stencil_[faceI].setSize(faceStencil.size()); + label n = 0; + stencil_[faceI][n++] = globalOwn; + stencil_[faceI][n++] = globalNei; + forAllConstIter(labelHashSet, faceStencil, iter) + { + if (iter.key() != globalOwn && iter.key() != globalNei) + { + stencil_[faceI][n++] = iter.key(); + } + } + //Pout<< "internalface:" << faceI << " toc:" << faceStencil.toc() + // << " stencil:" << stencil_[faceI] << endl; + } + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + label faceI = pp.start(); + + if (pp.coupled()) + { + forAll(pp, i) + { + faceStencil.clear(); + label globalOwn = globalNumbering.toGlobal(own[faceI]); + faceStencil.insert(globalOwn); + const labelList& ownCCells = globalCellCells[own[faceI]]; + forAll(ownCCells, i) + { + faceStencil.insert(ownCCells[i]); + } + // Get the coupled cell + label globalNei = neiGlobal[faceI-mesh.nInternalFaces()]; + faceStencil.insert(globalNei); + // And the neighbours of the coupled cell + const labelList& neiCCells = + neiGlobalCellCells[faceI-mesh.nInternalFaces()]; + forAll(neiCCells, i) + { + faceStencil.insert(neiCCells[i]); + } + + // Guarantee owner first, neighbour second. + stencil_[faceI].setSize(faceStencil.size()); + label n = 0; + stencil_[faceI][n++] = globalOwn; + stencil_[faceI][n++] = globalNei; + forAllConstIter(labelHashSet, faceStencil, iter) + { + if (iter.key() != globalOwn && iter.key() != globalNei) + { + stencil_[faceI][n++] = iter.key(); + } + } + + //Pout<< "coupledface:" << faceI + // << " toc:" << faceStencil.toc() + // << " stencil:" << stencil_[faceI] << endl; + + faceI++; + } + } + else if (!isA<emptyPolyPatch>(pp)) + { + forAll(pp, i) + { + faceStencil.clear(); + label globalOwn = globalNumbering.toGlobal(own[faceI]); + faceStencil.insert(globalOwn); + const labelList& ownCCells = globalCellCells[own[faceI]]; + forAll(ownCCells, i) + { + faceStencil.insert(ownCCells[i]); + } + + + // Guarantee owner first, neighbour second. + stencil_[faceI].setSize(faceStencil.size()); + label n = 0; + stencil_[faceI][n++] = globalOwn; + forAllConstIter(labelHashSet, faceStencil, iter) + { + if (iter.key() != globalOwn) + { + stencil_[faceI][n++] = iter.key(); + } + } + + //Pout<< "boundaryface:" << faceI + // << " toc:" << faceStencil.toc() + // << " stencil:" << stencil_[faceI] << endl; + + faceI++; + } + } + } +} + + +// Calculates extended stencil. This is per face +// - owner +// - cellCells of owner +// - neighbour +// - cellCells of neighbour +// It comes in two parts: +// - a map which collects/distributes all necessary data in a compact array +// - the stencil (a labelList per face) which is a set of indices into this +// compact array. +// The compact array is laid out as follows: +// - first data for current processor (Pstream::myProcNo()) +// - all cells +// - all boundary faces +// - then per processor +// - all used cells and boundary faces +void Foam::extendedStencil::calcExtendedFaceStencil(const polyMesh& mesh) +{ + const label nBnd = mesh.nFaces()-mesh.nInternalFaces(); + + // Global numbering for cells and boundary faces + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + globalIndex globalNumbering(mesh.nCells()+nBnd); + + + // Calculate stencil in global cell indices + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + calcFaceStencils(mesh, globalNumbering); + + + // Convert stencil to schedule + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // We now know what information we need from other processors. This needs + // to be converted into what information I need to send as well + // (mapDistribute) + + + // 1. Construct per processor compact addressing of the global cells + // needed. The ones from the local processor are not included since + // these are always all needed. + List<Map<label> > globalToProc(Pstream::nProcs()); + { + const labelList& procPatchMap = mesh.globalData().procPatchMap(); + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + // Presize with (as estimate) size of patch to neighbour. + forAll(procPatchMap, procI) + { + if (procPatchMap[procI] != -1) + { + globalToProc[procI].resize + ( + patches[procPatchMap[procI]].size() + ); + } + } + + // Collect all (non-local) globalcells/faces needed. + forAll(stencil_, faceI) + { + const labelList& stencilCells = stencil_[faceI]; + + forAll(stencilCells, i) + { + label globalCellI = stencilCells[i]; + label procI = globalNumbering.whichProcID(stencilCells[i]); + + if (procI != Pstream::myProcNo()) + { + label nCompact = globalToProc[procI].size(); + globalToProc[procI].insert(globalCellI, nCompact); + } + } + } + // Sort global cells needed (not really necessary) + forAll(globalToProc, procI) + { + if (procI != Pstream::myProcNo()) + { + Map<label>& globalMap = globalToProc[procI]; + + SortableList<label> sorted(globalMap.toc()); + + forAll(sorted, i) + { + Map<label>::iterator iter = globalMap.find(sorted[i]); + iter() = i; + } + } + } + + + // forAll(globalToProc, procI) + // { + // Pout<< "From processor:" << procI << " want cells/faces:" << endl; + // forAllConstIter(Map<label>, globalToProc[procI], iter) + // { + // Pout<< " global:" << iter.key() + // << " local:" << globalNumbering.toLocal(procI, iter.key()) + // << endl; + // } + // Pout<< endl; + // } + } + + + // 2. The overall compact addressing is + // - myProcNo first + // - all other processors consecutively + + labelList compactStart(Pstream::nProcs()); + compactStart[Pstream::myProcNo()] = 0; + label nCompact = mesh.nCells()+nBnd; + forAll(compactStart, procI) + { + if (procI != Pstream::myProcNo()) + { + compactStart[procI] = nCompact; + nCompact += globalToProc[procI].size(); + + // Pout<< "Data wanted from " << procI << " starts at " + // << compactStart[procI] << endl; + } + } + // Pout<< "Overall cells needed:" << nCompact << endl; + + + // 3. Find out what to receive/send in compact addressing. + labelListList recvCompact(Pstream::nProcs()); + for (label procI = 0; procI < Pstream::nProcs(); procI++) + { + if (procI != Pstream::myProcNo()) + { + labelList wantedGlobals(globalToProc[procI].size()); + recvCompact[procI].setSize(globalToProc[procI].size()); + + label i = 0; + forAllConstIter(Map<label>, globalToProc[procI], iter) + { + wantedGlobals[i] = iter.key(); + recvCompact[procI][i] = compactStart[procI]+iter(); + i++; + } + + // Pout<< "From proc:" << procI + // << " I need (globalcells):" << wantedGlobals + // << " which are my compact:" << recvCompact[procI] + // << endl; + + // Send the global cell numbers I need from procI + OPstream str(Pstream::blocking, procI); + str << wantedGlobals; + } + else + { + recvCompact[procI] = + compactStart[procI] + + identity(mesh.nCells()+nBnd); + } + } + labelListList sendCompact(Pstream::nProcs()); + for (label procI = 0; procI < Pstream::nProcs(); procI++) + { + if (procI != Pstream::myProcNo()) + { + // See what neighbour wants to receive (= what I need to send) + + IPstream str(Pstream::blocking, procI); + labelList globalCells(str); + + labelList& procCompact = sendCompact[procI]; + procCompact.setSize(globalCells.size()); + + // Convert from globalCells (all on my processor!) into compact + // addressing + forAll(globalCells, i) + { + label cellI = globalNumbering.toLocal(globalCells[i]); + procCompact[i] = compactStart[Pstream::myProcNo()]+cellI; + } + } + else + { + sendCompact[procI] = recvCompact[procI]; + } + } + + // Convert stencil to compact numbering + forAll(stencil_, faceI) + { + labelList& stencilCells = stencil_[faceI]; + + forAll(stencilCells, i) + { + label globalCellI = stencilCells[i]; + label procI = globalNumbering.whichProcID(globalCellI); + if (procI != Pstream::myProcNo()) + { + label localCompact = globalToProc[procI][globalCellI]; + stencilCells[i] = compactStart[procI]+localCompact; + } + else + { + label localCompact = globalNumbering.toLocal(globalCellI); + stencilCells[i] = compactStart[procI]+localCompact; + } + + } + } + // Pout<< "***stencil_:" << stencil_ << endl; + + // Constuct map for distribution of compact data. + mapPtr_.reset + ( + new mapDistribute + ( + nCompact, + sendCompact, + recvCompact, + true // reuse send/recv maps. + ) + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::extendedStencil::extendedStencil +( + const mapDistribute& map, + const labelListList& stencil +) +: + mapPtr_ + ( + autoPtr<mapDistribute> + ( + new mapDistribute + ( + map.constructSize(), + map.subMap(), + map.constructMap() + ) + ) + ), + stencil_(stencil) +{} + + +Foam::extendedStencil::extendedStencil(const polyMesh& mesh) +{ + calcExtendedFaceStencil(mesh); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.H b/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.H new file mode 100644 index 00000000000..1d00972403b --- /dev/null +++ b/src/finiteVolume/fvMesh/extendedStencil/extendedStencil.H @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::extendedStencil + +Description + Calculates/constains the extended face stencil. + + The stencil is a list of indices into either cells or boundary faces + in a compact way. (element 0 is owner, 1 is neighbour). The index numbering + is + - cells first + - then all (non-empty patch) boundary faces + + When used in evaluation is a two stage process: + - collect the data (cell data and non-empty boundaries) into a + single field + - (parallel) distribute the field + - sum the weights*field. + +SourceFiles + extendedStencil.C + +\*---------------------------------------------------------------------------*/ + +#ifndef extendedStencil_H +#define extendedStencil_H + +#include "mapDistribute.H" +#include "volFields.H" +#include "surfaceFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class globalIndex; + +/*---------------------------------------------------------------------------*\ + Class extendedStencil Declaration +\*---------------------------------------------------------------------------*/ + +class extendedStencil +{ + // Private data + + //- Swap map for getting neigbouring data + autoPtr<mapDistribute> mapPtr_; + + //- Per face the stencil. + labelListList stencil_; + + + // Private Member Functions + + void calcFaceStencils(const polyMesh&, const globalIndex&); + + //- Calculate the stencil (but not weights) + void calcExtendedFaceStencil(const polyMesh&); + + + //- Disallow default bitwise copy construct + extendedStencil(const extendedStencil&); + + //- Disallow default bitwise assignment + void operator=(const extendedStencil&); + + +public: + + // Constructors + + //- Construct from components + extendedStencil(const mapDistribute& map, const labelListList&); + + //- Construct from all cells and boundary faces + extendedStencil(const polyMesh&); + + + + // Member Functions + + //- Return reference to the parallel distribution map + const mapDistribute& map() const + { + return mapPtr_(); + } + + //- Return reference to the stencil + const labelListList& stencil() const + { + return stencil_; + } + + //- Use map to get the data into stencil order + template<class T> + void collectData + ( + const GeometricField<T, fvPatchField, volMesh>& fld, + List<List<T> >& stencilFld + ) const; + + //- Given weights interpolate vol field + template<class Type> + tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > interpolate + ( + const GeometricField<Type, fvPatchField, volMesh>& fld, + const List<List<scalar> >& stencilWeights + ) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "extendedStencilTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/fvMesh/extendedStencil/extendedStencilTemplates.C b/src/finiteVolume/fvMesh/extendedStencil/extendedStencilTemplates.C new file mode 100644 index 00000000000..a408621dc4c --- /dev/null +++ b/src/finiteVolume/fvMesh/extendedStencil/extendedStencilTemplates.C @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "extendedStencil.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::extendedStencil::collectData +( + const GeometricField<Type, fvPatchField, volMesh>& fld, + List<List<Type> >& stencilFld +) const +{ + // 1. Construct cell data in compact addressing + List<Type> compactFld(map().constructSize(), pTraits<Type>::zero); + + // Insert my internal values + forAll(fld, cellI) + { + compactFld[cellI] = fld[cellI]; + } + // Insert my boundary values + label nCompact = fld.size(); + forAll(fld.boundaryField(), patchI) + { + const fvPatchField<Type>& pfld = fld.boundaryField()[patchI]; + + forAll(pfld, i) + { + compactFld[nCompact++] = pfld[i]; + } + } + + // Do all swapping + map().distribute(compactFld); + + // 2. Pull to stencil + stencilFld.setSize(stencil_.size()); + + forAll(stencil_, faceI) + { + const labelList& compactCells = stencil_[faceI]; + + stencilFld[faceI].setSize(compactCells.size()); + + forAll(compactCells, i) + { + stencilFld[faceI][i] = compactFld[compactCells[i]]; + } + } +} + + +template<class Type> +Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> > +Foam::extendedStencil::interpolate +( + const GeometricField<Type, fvPatchField, volMesh>& fld, + const List<List<scalar> >& stencilWeights +) const +{ + const fvMesh& mesh = fld.mesh(); + + // Collect internal and boundary values + List<List<Type> > stencilFld; + collectData(fld, stencilFld); + + tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tsfCorr + ( + new GeometricField<Type, fvsPatchField, surfaceMesh> + ( + IOobject + ( + fld.name(), + mesh.time().timeName(), + mesh + ), + mesh, + dimensioned<Type> + ( + fld.name(), + fld.dimensions(), + pTraits<Type>::zero + ) + ) + ); + GeometricField<Type, fvsPatchField, surfaceMesh>& sf = tsfCorr(); + + for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++) + { + const List<Type>& stField = stencilFld[faceI]; + const List<scalar>& stWeight = stencilWeights[faceI]; + + forAll(stField, i) + { + sf[faceI] += stField[i]*stWeight[i]; + } + } + // And what for boundaries? + + return tsfCorr; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.C b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.C new file mode 100644 index 00000000000..a215576330b --- /dev/null +++ b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.C @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "quadraticFit.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + makeSurfaceInterpolationScheme(quadraticFit); +} + +// ************************************************************************* // diff --git a/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.H b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.H new file mode 100644 index 00000000000..412b454015d --- /dev/null +++ b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFit.H @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + quadraticFit + +Description + Quadratic fit interpolation scheme which applies an explicit correction to + linear. + +SourceFiles + quadraticFit.C + +\*---------------------------------------------------------------------------*/ + +#ifndef quadraticFit_H +#define quadraticFit_H + +#include "linear.H" +#include "quadraticFitData.H" +#include "extendedStencil.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class quadraticFit Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class quadraticFit +: + public linear<Type> +{ + // Private Data + const scalar centralWeight_; + + // Private Member Functions + + //- Disallow default bitwise copy construct + quadraticFit(const quadraticFit&); + + //- Disallow default bitwise assignment + void operator=(const quadraticFit&); + + +public: + + //- Runtime type information + TypeName("quadraticFit"); + + + // Constructors + + //- Construct from mesh and Istream + quadraticFit(const fvMesh& mesh, Istream& is) + : + linear<Type>(mesh), + centralWeight_(readScalar(is)) + {} + + + //- Construct from mesh, faceFlux and Istream + quadraticFit + ( + const fvMesh& mesh, + const surfaceScalarField& faceFlux, + Istream& is + ) + : + linear<Type>(mesh), + centralWeight_(readScalar(is)) + {} + + + // Member Functions + + //- Return true if this scheme uses an explicit correction + virtual bool corrected() const + { + return true; + } + + //- Return the explicit correction to the face-interpolate + virtual tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > + correction + ( + const GeometricField<Type, fvPatchField, volMesh>& vf + ) const + { + const fvMesh& mesh = this->mesh(); + + const quadraticFitData& cfd = quadraticFitData::New + ( + mesh, + centralWeight_ + ); + + const extendedStencil& stencil = cfd.stencil(); + const List<scalarList>& f = cfd.fit(); + + return stencil.interpolate(vf, f); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.C b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.C new file mode 100644 index 00000000000..fd0e55fcdd6 --- /dev/null +++ b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.C @@ -0,0 +1,310 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "quadraticFitData.H" +#include "surfaceFields.H" +#include "volFields.H" +#include "SVD.H" +#include "syncTools.H" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(quadraticFitData, 0); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::quadraticFitData::quadraticFitData +( + const fvMesh& mesh, + const scalar cWeight +) +: + MeshObject<fvMesh, quadraticFitData>(mesh), + centralWeight_(cWeight), +#ifdef SPHERICAL_GEOMETRY + dim_(2), +#else + dim_(mesh.nGeometricD()), +#endif + minSize_ + ( + dim_ == 1 ? 3 : + dim_ == 2 ? 6 : + dim_ == 3 ? 9 : 0 + ), + stencil_(mesh), + fit_(mesh.nInternalFaces()) +{ + if (debug) + { + Info << "Contructing quadraticFitData" << endl; + } + + // check input + if (centralWeight_ < 1 - SMALL) + { + FatalErrorIn("quadraticFitData::quadraticFitData") + << "centralWeight requested = " << centralWeight_ + << " should not be less than one" + << exit(FatalError); + } + + if (minSize_ == 0) + { + FatalErrorIn("quadraticFitSnGradData") + << " dimension must be 1,2 or 3, not" << dim_ << exit(FatalError); + } + + // store the polynomial size for each cell to write out + surfaceScalarField interpPolySize + ( + IOobject + ( + "quadraticFitInterpPolySize", + "constant", + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("quadraticFitInterpPolySize", dimless, scalar(0)) + ); + + // Get the cell/face centres in stencil order. + // Centred face stencils no good for triangles of tets. Need bigger stencils + List<List<point> > stencilPoints(stencil_.stencil().size()); + stencil_.collectData + ( + mesh.C(), + stencilPoints + ); + + // find the fit coefficients for every face in the mesh + + for(label faci = 0; faci < mesh.nInternalFaces(); faci++) + { + interpPolySize[faci] = calcFit(stencilPoints[faci], faci); + } + interpPolySize.write(); + if (debug) + { + Info<< "quadraticFitData::quadraticFitData() :" + << "Finished constructing polynomialFit data" + << endl; + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::quadraticFitData::findFaceDirs +( + vector& idir, // value changed in return + vector& jdir, // value changed in return + vector& kdir, // value changed in return + const fvMesh& mesh, + const label faci +) +{ + idir = mesh.Sf()[faci]; + idir /= mag(idir); + +# ifndef SPHERICAL_GEOMETRY + if (mesh.nGeometricD() <= 2) // find the normal direcion + { + if (mesh.directions()[0] == -1) + { + kdir = vector(1, 0, 0); + } + else if (mesh.directions()[1] == -1) + { + kdir = vector(0, 1, 0); + } + else + { + kdir = vector(0, 0, 1); + } + } + else // 3D so find a direction in the place of the face + { + const face& f = mesh.faces()[faci]; + kdir = mesh.points()[f[0]] - mesh.points()[f[1]]; + } +# else + // Spherical geometry so kdir is the radial direction + kdir = mesh.Cf()[faci]; +# endif + + if (mesh.nGeometricD() == 3) + { + // Remove the idir component from kdir and normalise + kdir -= (idir & kdir)*idir; + + scalar magk = mag(kdir); + + if (magk < SMALL) + { + FatalErrorIn("findFaceDirs") << " calculated kdir = zero" + << exit(FatalError); + } + else + { + kdir /= magk; + } + } + + jdir = kdir ^ idir; +} + + +Foam::label Foam::quadraticFitData::calcFit +( + const List<point>& C, + const label faci +) +{ + vector idir(1,0,0); + vector jdir(0,1,0); + vector kdir(0,0,1); + findFaceDirs(idir, jdir, kdir, mesh(), faci); + + scalarList wts(C.size(), scalar(1)); + wts[0] = centralWeight_; + wts[1] = centralWeight_; + + point p0 = mesh().faceCentres()[faci]; + scalar scale = 0; + + // calculate the matrix of the polynomial components + Matrix<scalar> B(C.size(), minSize_, scalar(0)); + + for(label ip = 0; ip < C.size(); ip++) + { + const point& p = C[ip]; + + scalar px = (p - p0)&idir; + scalar py = (p - p0)&jdir; +#ifndef SPHERICAL_GEOMETRY + scalar pz = (p - p0)&kdir; +#else + scalar pz = mag(p) - mag(p0); +#endif + + if (ip == 0) + { + scale = max(max(mag(px), mag(py)), mag(pz)); + } + + px /= scale; + py /= scale; + pz /= scale; + + label is = 0; + B[ip][is++] = wts[ip]; + + B[ip][is++] = wts[ip]*px; + B[ip][is++] = wts[ip]*sqr(px); + + if (dim_ >= 2) + { + B[ip][is++] = wts[ip]*py; + B[ip][is++] = wts[ip]*px*py; + B[ip][is++] = wts[ip]*sqr(py); + } + if (dim_ == 3) + { + B[ip][is++] = wts[ip]*pz; + B[ip][is++] = wts[ip]*px*pz; + //B[ip][is++] = wts[ip]*py*pz; + B[ip][is++] = wts[ip]*sqr(pz); + } + } + + // Set the fit + label stencilSize = C.size(); + fit_[faci].setSize(stencilSize); + scalarList singVals(minSize_); + label nSVDzeros = 0; + + bool goodFit = false; + for(scalar tol = SMALL; tol < 0.1 && !goodFit; tol *= 10) + { + SVD svd(B, tol); + + scalar fit0 = wts[0]*svd.VSinvUt()[0][0]; + scalar fit1 = wts[1]*svd.VSinvUt()[0][1]; + + goodFit = sign(fit0) == sign(fit1); + + if (goodFit) + { + fit_[faci][0] = fit0; + fit_[faci][1] = fit1; + for(label i = 2; i < stencilSize; i++) + { + fit_[faci][i] = wts[i]*svd.VSinvUt()[0][i]; + } + + singVals = svd.S(); + nSVDzeros = svd.nZeros(); + } + } + if (!goodFit) + { + FatalErrorIn + ( + "quadraticFitData::calcFit(const pointField&, const label)" + ) << "For face " << faci << endl + << "Fit not good even once tol >= 0.1" + << exit(FatalError); + } + + const GeometricField<scalar, fvsPatchField, surfaceMesh>& w = + mesh().surfaceInterpolation::weights(); + + // remove the uncorrected linear coefficients + + fit_[faci][0] -= w[faci]; + fit_[faci][1] -= 1 - w[faci]; + + return minSize_ - nSVDzeros; +} + + +bool Foam::quadraticFitData::movePoints() +{ + notImplemented("quadraticFitData::movePoints()"); + + return true; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.H b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.H new file mode 100644 index 00000000000..19859ea621c --- /dev/null +++ b/src/finiteVolume/interpolation/surfaceInterpolation/schemes/quadraticFit/quadraticFitData.H @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + quadraticFitData + +Description + Data for the quadratic fit correction interpolation scheme + +SourceFiles + quadraticFitData.C + +\*---------------------------------------------------------------------------*/ + +#ifndef quadraticFitData_H +#define quadraticFitData_H + +#include "MeshObject.H" +#include "fvMesh.H" +#include "extendedStencil.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class globalIndex; + +/*---------------------------------------------------------------------------*\ + Class quadraticFitData Declaration +\*---------------------------------------------------------------------------*/ + +class quadraticFitData +: + public MeshObject<fvMesh, quadraticFitData> +{ + // Private data + + //- weights for central stencil + const scalar centralWeight_; + + //- dimensionality of the geometry + const label dim_; + + //- minimum stencil size + const label minSize_; + + //- Extended stencil addressing + extendedStencil stencil_; + + //- For each cell in the mesh store the values which multiply the + // values of the stencil to obtain the gradient for each direction + List<scalarList> fit_; + + + // Private member functions + + //- Find the normal direction and i, j and k directions for face faci + static void findFaceDirs + ( + vector& idir, // value changed in return + vector& jdir, // value changed in return + vector& kdir, // value changed in return + const fvMesh& mesh, + const label faci + ); + + label calcFit(const List<point>&, const label faci); + + +public: + + TypeName("quadraticFitData"); + + + // Constructors + + explicit quadraticFitData + ( + const fvMesh& mesh, + scalar cWeightDim + ); + + + // Destructor + + virtual ~quadraticFitData() + {} + + + // Member functions + + + //- Return reference to the stencil + const extendedStencil& stencil() const + { + return stencil_; + } + + //- Return reference to fit coefficients + const List<scalarList>& fit() const + { + return fit_; + } + + //- Delete the data when the mesh moves not implemented + virtual bool movePoints(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // -- GitLab