From f8d14b0b289d653f5be64f2b7b99487e1b0e869c Mon Sep 17 00:00:00 2001 From: Henry <Henry> Date: Sun, 16 Dec 2012 22:29:33 +0000 Subject: [PATCH] symGaussSeidelSmoother: symmetric Gauss-Seidel smoother --- .../symGaussSeidel/symGaussSeidelSmoother.C | 241 ++++++++++++++++++ .../symGaussSeidel/symGaussSeidelSmoother.H | 108 ++++++++ 2 files changed, 349 insertions(+) create mode 100644 src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.C create mode 100644 src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.H diff --git a/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.C b/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.C new file mode 100644 index 00000000000..c8794ba5d6b --- /dev/null +++ b/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.C @@ -0,0 +1,241 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "symGaussSeidelSmoother.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(symGaussSeidelSmoother, 0); + + lduMatrix::smoother::addsymMatrixConstructorToTable<symGaussSeidelSmoother> + addsymGaussSeidelSmootherSymMatrixConstructorToTable_; + + lduMatrix::smoother::addasymMatrixConstructorToTable<symGaussSeidelSmoother> + addsymGaussSeidelSmootherAsymMatrixConstructorToTable_; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::symGaussSeidelSmoother::symGaussSeidelSmoother +( + const word& fieldName, + const lduMatrix& matrix, + const FieldField<Field, scalar>& interfaceBouCoeffs, + const FieldField<Field, scalar>& interfaceIntCoeffs, + const lduInterfaceFieldPtrsList& interfaces +) +: + lduMatrix::smoother + ( + fieldName, + matrix, + interfaceBouCoeffs, + interfaceIntCoeffs, + interfaces + ) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::symGaussSeidelSmoother::smooth +( + const word& fieldName_, + scalarField& psi, + const lduMatrix& matrix_, + const scalarField& source, + const FieldField<Field, scalar>& interfaceBouCoeffs_, + const lduInterfaceFieldPtrsList& interfaces_, + const direction cmpt, + const label nSweeps +) +{ + register scalar* __restrict__ psiPtr = psi.begin(); + + register const label nCells = psi.size(); + + scalarField bPrime(nCells); + register scalar* __restrict__ bPrimePtr = bPrime.begin(); + + register const scalar* const __restrict__ diagPtr = matrix_.diag().begin(); + register const scalar* const __restrict__ upperPtr = + matrix_.upper().begin(); + register const scalar* const __restrict__ lowerPtr = + matrix_.lower().begin(); + + register const label* const __restrict__ uPtr = + matrix_.lduAddr().upperAddr().begin(); + + register const label* const __restrict__ ownStartPtr = + matrix_.lduAddr().ownerStartAddr().begin(); + + + // Parallel boundary initialisation. The parallel boundary is treated + // as an effective jacobi interface in the boundary. + // Note: there is a change of sign in the coupled + // interface update. The reason for this is that the + // internal coefficients are all located at the l.h.s. of + // the matrix whereas the "implicit" coefficients on the + // coupled boundaries are all created as if the + // coefficient contribution is of a source-kind (i.e. they + // have a sign as if they are on the r.h.s. of the matrix. + // To compensate for this, it is necessary to turn the + // sign of the contribution. + + FieldField<Field, scalar>& mBouCoeffs = + const_cast<FieldField<Field, scalar>&> + ( + interfaceBouCoeffs_ + ); + + forAll(mBouCoeffs, patchi) + { + if (interfaces_.set(patchi)) + { + mBouCoeffs[patchi].negate(); + } + } + + + for (label sweep=0; sweep<nSweeps; sweep++) + { + bPrime = source; + + matrix_.initMatrixInterfaces + ( + mBouCoeffs, + interfaces_, + psi, + bPrime, + cmpt + ); + + matrix_.updateMatrixInterfaces + ( + mBouCoeffs, + interfaces_, + psi, + bPrime, + cmpt + ); + + register scalar psii; + register label fStart; + register label fEnd = ownStartPtr[0]; + + for (register label celli=0; celli<nCells; celli++) + { + // Start and end of this row + fStart = fEnd; + fEnd = ownStartPtr[celli + 1]; + + // Get the accumulated neighbour side + psii = bPrimePtr[celli]; + + // Accumulate the owner product side + for (register label facei=fStart; facei<fEnd; facei++) + { + psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; + } + + // Finish current psi + psii /= diagPtr[celli]; + + // Distribute the neighbour side using current psi + for (register label facei=fStart; facei<fEnd; facei++) + { + bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; + } + + psiPtr[celli] = psii; + } + + fStart = ownStartPtr[nCells]; + + for (register label celli=nCells-1; celli>=0; celli--) + { + // Start and end of this row + fEnd = fStart; + fStart = ownStartPtr[celli]; + + // Get the accumulated neighbour side + psii = bPrimePtr[celli]; + + // Accumulate the owner product side + for (register label facei=fStart; facei<fEnd; facei++) + { + psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; + } + + // Finish psi for this cell + psii /= diagPtr[celli]; + + // Distribute the neighbour side using psi for this cell + for (register label facei=fStart; facei<fEnd; facei++) + { + bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; + } + + psiPtr[celli] = psii; + } + } + + // Restore interfaceBouCoeffs_ + forAll(mBouCoeffs, patchi) + { + if (interfaces_.set(patchi)) + { + mBouCoeffs[patchi].negate(); + } + } +} + + +void Foam::symGaussSeidelSmoother::smooth +( + scalarField& psi, + const scalarField& source, + const direction cmpt, + const label nSweeps +) const +{ + smooth + ( + fieldName_, + psi, + matrix_, + source, + interfaceBouCoeffs_, + interfaces_, + cmpt, + nSweeps + ); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.H b/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.H new file mode 100644 index 00000000000..a9a25e651fb --- /dev/null +++ b/src/OpenFOAM/matrices/lduMatrix/smoothers/symGaussSeidel/symGaussSeidelSmoother.H @@ -0,0 +1,108 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::symGaussSeidelSmoother + +Description + A lduMatrix::smoother for symmetric Gauss-Seidel + +SourceFiles + symGaussSeidelSmoother.C + +\*---------------------------------------------------------------------------*/ + +#ifndef symGaussSeidelSmoother_H +#define symGaussSeidelSmoother_H + +#include "lduMatrix.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class symGaussSeidelSmoother Declaration +\*---------------------------------------------------------------------------*/ + +class symGaussSeidelSmoother +: + public lduMatrix::smoother +{ + +public: + + //- Runtime type information + TypeName("symGaussSeidel"); + + + // Constructors + + //- Construct from components + symGaussSeidelSmoother + ( + const word& fieldName, + const lduMatrix& matrix, + const FieldField<Field, scalar>& interfaceBouCoeffs, + const FieldField<Field, scalar>& interfaceIntCoeffs, + const lduInterfaceFieldPtrsList& interfaces + ); + + + // Member Functions + + //- Smooth for the given number of sweeps + static void smooth + ( + const word& fieldName, + scalarField& psi, + const lduMatrix& matrix, + const scalarField& source, + const FieldField<Field, scalar>& interfaceBouCoeffs, + const lduInterfaceFieldPtrsList& interfaces, + const direction cmpt, + const label nSweeps + ); + + + //- Smooth the solution for a given number of sweeps + virtual void smooth + ( + scalarField& psi, + const scalarField& Source, + const direction cmpt, + const label nSweeps + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // -- GitLab