1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "GaussSeidelSmoother.H"
28 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 defineTypeNameAndDebug(GaussSeidelSmoother, 0);
34 lduMatrix::smoother::addsymMatrixConstructorToTable<GaussSeidelSmoother>
35 addGaussSeidelSmootherSymMatrixConstructorToTable_;
37 lduMatrix::smoother::addasymMatrixConstructorToTable<GaussSeidelSmoother>
38 addGaussSeidelSmootherAsymMatrixConstructorToTable_;
42 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 Foam::GaussSeidelSmoother::GaussSeidelSmoother
46 const word& fieldName,
47 const lduMatrix& matrix,
48 const FieldField<Field, scalar>& interfaceBouCoeffs,
49 const FieldField<Field, scalar>& interfaceIntCoeffs,
50 const lduInterfaceFieldPtrsList& interfaces
64 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
66 void Foam::GaussSeidelSmoother::smooth
68 const word& fieldName_,
70 const lduMatrix& matrix_,
71 const scalarField& source,
72 const FieldField<Field, scalar>& interfaceBouCoeffs_,
73 const lduInterfaceFieldPtrsList& interfaces_,
78 register scalar* __restrict__ psiPtr = psi.begin();
80 register const label nCells = psi.size();
82 scalarField bPrime(nCells);
83 register scalar* __restrict__ bPrimePtr = bPrime.begin();
85 register const scalar* const __restrict__ diagPtr = matrix_.diag().begin();
86 register const scalar* const __restrict__ upperPtr =
87 matrix_.upper().begin();
88 register const scalar* const __restrict__ lowerPtr =
89 matrix_.lower().begin();
91 register const label* const __restrict__ uPtr =
92 matrix_.lduAddr().upperAddr().begin();
94 register const label* const __restrict__ ownStartPtr =
95 matrix_.lduAddr().ownerStartAddr().begin();
98 // Parallel boundary initialisation. The parallel boundary is treated
99 // as an effective jacobi interface in the boundary.
100 // Note: there is a change of sign in the coupled
101 // interface update. The reason for this is that the
102 // internal coefficients are all located at the l.h.s. of
103 // the matrix whereas the "implicit" coefficients on the
104 // coupled boundaries are all created as if the
105 // coefficient contribution is of a source-kind (i.e. they
106 // have a sign as if they are on the r.h.s. of the matrix.
107 // To compensate for this, it is necessary to turn the
108 // sign of the contribution.
110 FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs_.size());
112 forAll(mBouCoeffs, patchi)
114 if (interfaces_.set(patchi))
116 mBouCoeffs.set(patchi, -interfaceBouCoeffs_[patchi]);
120 for (label sweep=0; sweep<nSweeps; sweep++)
124 matrix_.initMatrixInterfaces
133 matrix_.updateMatrixInterfaces
142 register scalar curPsi;
143 register label fStart;
144 register label fEnd = ownStartPtr[0];
146 for (register label cellI=0; cellI<nCells; cellI++)
148 // Start and end of this row
150 fEnd = ownStartPtr[cellI + 1];
152 // Get the accumulated neighbour side
153 curPsi = bPrimePtr[cellI];
155 // Accumulate the owner product side
156 for (register label curFace=fStart; curFace<fEnd; curFace++)
158 curPsi -= upperPtr[curFace]*psiPtr[uPtr[curFace]];
161 // Finish current psi
162 curPsi /= diagPtr[cellI];
164 // Distribute the neighbour side using current psi
165 for (register label curFace=fStart; curFace<fEnd; curFace++)
167 bPrimePtr[uPtr[curFace]] -= lowerPtr[curFace]*curPsi;
170 psiPtr[cellI] = curPsi;
176 void Foam::GaussSeidelSmoother::smooth
179 const scalarField& source,
180 const direction cmpt,
198 // ************************************************************************* //