1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "cellLimitedGrad.H"
28 #include "gaussGrad.H"
31 #include "surfaceMesh.H"
32 #include "volFields.H"
33 #include "fixedValueFvPatchFields.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 makeFvGradScheme(cellLimitedGrad)
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 inline void cellLimitedGrad<scalar>::limitFace
55 const scalar& maxDelta,
56 const scalar& minDelta,
57 const scalar& extrapolate
60 if (extrapolate > maxDelta + VSMALL)
62 limiter = min(limiter, maxDelta/extrapolate);
64 else if (extrapolate < minDelta - VSMALL)
66 limiter = min(limiter, minDelta/extrapolate);
71 inline void cellLimitedGrad<Type>::limitFace
76 const Type& extrapolate
79 for(direction cmpt=0; cmpt<Type::nComponents; cmpt++)
81 cellLimitedGrad<scalar>::limitFace
83 limiter.component(cmpt),
84 maxDelta.component(cmpt),
85 minDelta.component(cmpt),
86 extrapolate.component(cmpt)
92 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
95 tmp<volVectorField> cellLimitedGrad<scalar>::grad
97 const volScalarField& vsf
100 const fvMesh& mesh = vsf.mesh();
102 tmp<volVectorField> tGrad = basicGradScheme_().grad(vsf);
109 volVectorField& g = tGrad();
111 const unallocLabelList& owner = mesh.owner();
112 const unallocLabelList& neighbour = mesh.neighbour();
114 const volVectorField& C = mesh.C();
115 const surfaceVectorField& Cf = mesh.Cf();
117 scalarField maxVsf(vsf.internalField());
118 scalarField minVsf(vsf.internalField());
122 label own = owner[facei];
123 label nei = neighbour[facei];
125 scalar vsfOwn = vsf[own];
126 scalar vsfNei = vsf[nei];
128 maxVsf[own] = max(maxVsf[own], vsfNei);
129 minVsf[own] = min(minVsf[own], vsfNei);
131 maxVsf[nei] = max(maxVsf[nei], vsfOwn);
132 minVsf[nei] = min(minVsf[nei], vsfOwn);
136 const volScalarField::GeometricBoundaryField& bsf = vsf.boundaryField();
140 const fvPatchScalarField& psf = bsf[patchi];
142 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
146 scalarField psfNei = psf.patchNeighbourField();
148 forAll(pOwner, pFacei)
150 label own = pOwner[pFacei];
151 scalar vsfNei = psfNei[pFacei];
153 maxVsf[own] = max(maxVsf[own], vsfNei);
154 minVsf[own] = min(minVsf[own], vsfNei);
159 forAll(pOwner, pFacei)
161 label own = pOwner[pFacei];
162 scalar vsfNei = psf[pFacei];
164 maxVsf[own] = max(maxVsf[own], vsfNei);
165 minVsf[own] = min(minVsf[own], vsfNei);
175 scalarField maxMinVsf = (1.0/k_ - 1.0)*(maxVsf - minVsf);
185 scalarField limiter(vsf.internalField().size(), 1.0);
189 label own = owner[facei];
190 label nei = neighbour[facei];
198 (Cf[facei] - C[own]) & g[own]
207 (Cf[facei] - C[nei]) & g[nei]
213 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
214 const vectorField& pCf = Cf.boundaryField()[patchi];
216 forAll(pOwner, pFacei)
218 label own = pOwner[pFacei];
225 (pCf[pFacei] - C[own]) & g[own]
232 Info<< "gradient limiter for: " << vsf.name()
233 << " max = " << gMax(limiter)
234 << " min = " << gMin(limiter)
235 << " average: " << gAverage(limiter) << endl;
238 g.internalField() *= limiter;
239 g.correctBoundaryConditions();
240 gaussGrad<scalar>::correctBoundaryConditions(vsf, g);
247 tmp<volTensorField> cellLimitedGrad<vector>::grad
249 const volVectorField& vsf
252 const fvMesh& mesh = vsf.mesh();
254 tmp<volTensorField> tGrad = basicGradScheme_().grad(vsf);
261 volTensorField& g = tGrad();
263 const unallocLabelList& owner = mesh.owner();
264 const unallocLabelList& neighbour = mesh.neighbour();
266 const volVectorField& C = mesh.C();
267 const surfaceVectorField& Cf = mesh.Cf();
269 vectorField maxVsf(vsf.internalField());
270 vectorField minVsf(vsf.internalField());
274 label own = owner[facei];
275 label nei = neighbour[facei];
277 const vector& vsfOwn = vsf[own];
278 const vector& vsfNei = vsf[nei];
280 maxVsf[own] = max(maxVsf[own], vsfNei);
281 minVsf[own] = min(minVsf[own], vsfNei);
283 maxVsf[nei] = max(maxVsf[nei], vsfOwn);
284 minVsf[nei] = min(minVsf[nei], vsfOwn);
288 const volVectorField::GeometricBoundaryField& bsf = vsf.boundaryField();
292 const fvPatchVectorField& psf = bsf[patchi];
293 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
297 vectorField psfNei = psf.patchNeighbourField();
299 forAll(pOwner, pFacei)
301 label own = pOwner[pFacei];
302 const vector& vsfNei = psfNei[pFacei];
304 maxVsf[own] = max(maxVsf[own], vsfNei);
305 minVsf[own] = min(minVsf[own], vsfNei);
310 forAll(pOwner, pFacei)
312 label own = pOwner[pFacei];
313 const vector& vsfNei = psf[pFacei];
315 maxVsf[own] = max(maxVsf[own], vsfNei);
316 minVsf[own] = min(minVsf[own], vsfNei);
326 vectorField maxMinVsf = (1.0/k_ - 1.0)*(maxVsf - minVsf);
336 vectorField limiter(vsf.internalField().size(), vector::one);
340 label own = owner[facei];
341 label nei = neighbour[facei];
349 (Cf[facei] - C[own]) & g[own]
358 (Cf[facei] - C[nei]) & g[nei]
364 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
365 const vectorField& pCf = Cf.boundaryField()[patchi];
367 forAll(pOwner, pFacei)
369 label own = pOwner[pFacei];
376 ((pCf[pFacei] - C[own]) & g[own])
383 Info<< "gradient limiter for: " << vsf.name()
384 << " max = " << gMax(limiter)
385 << " min = " << gMin(limiter)
386 << " average: " << gAverage(limiter) << endl;
389 tensorField& gIf = g.internalField();
393 gIf[celli].x() = cmptMultiply(limiter[celli], gIf[celli].x());
394 gIf[celli].y() = cmptMultiply(limiter[celli], gIf[celli].y());
395 gIf[celli].z() = cmptMultiply(limiter[celli], gIf[celli].z());
398 g.correctBoundaryConditions();
399 gaussGrad<vector>::correctBoundaryConditions(vsf, g);
405 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
407 } // End namespace fv
409 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
411 } // End namespace Foam
413 // ************************************************************************* //