BUGFIX: Seg-fault in multiphaseInterFoam. Author: Henrik Rusche. Merge: Hrvoje Jasak
[foam-extend-3.2.git] / src / lduSolvers / amg / amgCycle.C
blob1c0fe90cd471ca934bb1499463b619b2bf6dc9b4
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Class
25     amgCycle
27 Description
28     Algebraic multigrid cycle class
30 Author
31     Hrvoje Jasak, Wikki Ltd.  All rights reserved
33 \*---------------------------------------------------------------------------*/
35 #include "amgCycle.H"
36 #include "demandDrivenData.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 template<>
41 const char* Foam::NamedEnum<Foam::amgCycle::cycleType, 3>::names[] =
43     "V-cycle",
44     "W-cycle",
45     "F-cycle"
49 const Foam::NamedEnum<Foam::amgCycle::cycleType, 3>
50 Foam::amgCycle::cycleNames_;
53 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
55 // Construct from AMG level
56 Foam::amgCycle::amgCycle(autoPtr<amgLevel> levelPtr)
58     levelPtr_(levelPtr),
59     coarseLevelPtr_(NULL),
60     nLevels_(0)
64 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
66 Foam::amgCycle::~amgCycle()
68     deleteDemandDrivenData(coarseLevelPtr_);
72 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
74 void Foam::amgCycle::makeCoarseLevels(const label nMaxLevels)
76     // Make coarse levels
77     if (nLevels_ == 0)
78     {
79         bool addCoarse = true;
80         amgCycle* curCyclePtr = this;
82         // Do forever
83         for (;;)
84         {
85             nLevels_++;
87             autoPtr<amgLevel> coarsePtr =
88                 curCyclePtr->levelPtr_->makeNextLevel();
90             // Check if a coarse level is valid and allowed
91             if (nLevels_ >= nMaxLevels || !coarsePtr.valid())
92             {
93                 addCoarse = false;
94             }
96             reduce(addCoarse, andOp<bool>());
98             if (addCoarse)
99             {
100                 curCyclePtr->coarseLevelPtr_ = new amgCycle(coarsePtr);
102                 // Point to the next coarse level
103                 curCyclePtr = curCyclePtr->coarseLevelPtr_;
104             }
105             else
106             {
107                 break;
108             }
109         }
111         if (lduMatrix::debug >= 2)
112         {
113             Info<< "Created " << nLevels_ << " AMG levels" << endl;
114         }
115     }
119 void Foam::amgCycle::fixedCycle
121     scalarField& x,
122     const scalarField& b,
123     const direction cmpt,
124     scalarField& xBuffer,
125     const cycleType cycle,
126     const label nPreSweeps,
127     const label nPostSweeps,
128     const bool scale
129 ) const
131     if (coarseLevelPtr_)
132     {
133         // Pre-smoothing
134         levelPtr_->smooth(x, b, cmpt, nPreSweeps);
136         // Get reference to coarse level
137         scalarField& xCoarse = coarseLevelPtr_->levelPtr_->x();
138         scalarField& bCoarse = coarseLevelPtr_->levelPtr_->b();
140         // Zero out coarse x
141         xCoarse = 0;
143         // Restrict residual: optimisation on number of pre-sweeps
144         levelPtr_->restrictResidual
145         (
146             x,
147             b,
148             cmpt,
149             xBuffer,
150             bCoarse,
151             nPreSweeps > 0 || cycle != V_CYCLE
152         );
154         coarseLevelPtr_->fixedCycle
155         (
156             xCoarse,
157             bCoarse,
158             cmpt,
159             xBuffer,
160             cycle,
161             nPreSweeps,
162             nPostSweeps,
163             scale
164         );
166         if (cycle == F_CYCLE)
167         {
168             coarseLevelPtr_->fixedCycle
169             (
170                 xCoarse,
171                 bCoarse,
172                 cmpt,
173                 xBuffer,
174                 V_CYCLE,
175                 nPreSweeps,
176                 nPostSweeps,
177                 scale
178             );
179         }
180         else if (cycle == W_CYCLE)
181         {
182             coarseLevelPtr_->fixedCycle
183             (
184                 xCoarse,
185                 bCoarse,
186                 cmpt,
187                 xBuffer,
188                 W_CYCLE,
189                 nPreSweeps,
190                 nPostSweeps,
191                 scale
192             );
193         }
195         if (scale)
196         {
197             // Calculate scaling factor using a buffer
199             coarseLevelPtr_->levelPtr_->scaleX
200             (
201                 xCoarse,
202                 bCoarse,
203                 cmpt,
204                 xBuffer
205             );
206         }
208         levelPtr_->prolongateCorrection(x, xCoarse);
210         // Post-smoothing
211         levelPtr_->smooth(x, b, cmpt, nPostSweeps);
212     }
213     else
214     {
215         // Call direct solver
216         // Changed tolerance because a better guess will be used on coarsest
217         // mesh level.  HJ, 27/Jun/2013
218         levelPtr_->solve(x, b, cmpt, 1e-6, 0);
219     }
223 // ************************************************************************* //