00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "faceLimitedGrad.H"
00027 #include <finiteVolume/gaussGrad.H>
00028 #include <finiteVolume/fvMesh.H>
00029 #include <finiteVolume/volMesh.H>
00030 #include <finiteVolume/surfaceMesh.H>
00031 #include <finiteVolume/volFields.H>
00032 #include <finiteVolume/fixedValueFvPatchFields.H>
00033
00034
00035
00036 namespace Foam
00037 {
00038
00039
00040
00041 namespace fv
00042 {
00043
00044
00045
00046 makeFvGradScheme(faceLimitedGrad)
00047
00048
00049
00050 template<class Type>
00051 inline void faceLimitedGrad<Type>::limitFace
00052 (
00053 scalar& limiter,
00054 const scalar maxDelta,
00055 const scalar minDelta,
00056 const scalar extrapolate
00057 ) const
00058 {
00059 if (extrapolate > maxDelta + VSMALL)
00060 {
00061 limiter = min(limiter, maxDelta/extrapolate);
00062 }
00063 else if (extrapolate < minDelta - VSMALL)
00064 {
00065 limiter = min(limiter, minDelta/extrapolate);
00066 }
00067 }
00068
00069
00070
00071
00072 template<>
00073 tmp<volVectorField> faceLimitedGrad<scalar>::grad
00074 (
00075 const volScalarField& vsf
00076 ) const
00077 {
00078 const fvMesh& mesh = vsf.mesh();
00079
00080 tmp<volVectorField> tGrad = basicGradScheme_().grad(vsf);
00081
00082 if (k_ < SMALL)
00083 {
00084 return tGrad;
00085 }
00086
00087 volVectorField& g = tGrad();
00088
00089 const unallocLabelList& owner = mesh.owner();
00090 const unallocLabelList& neighbour = mesh.neighbour();
00091
00092 const volVectorField& C = mesh.C();
00093 const surfaceVectorField& Cf = mesh.Cf();
00094
00095
00096 scalarField limiter(vsf.internalField().size(), 1.0);
00097
00098 scalar rk = (1.0/k_ - 1.0);
00099
00100 forAll(owner, facei)
00101 {
00102 label own = owner[facei];
00103 label nei = neighbour[facei];
00104
00105 scalar vsfOwn = vsf[own];
00106 scalar vsfNei = vsf[nei];
00107
00108 scalar maxFace = max(vsfOwn, vsfNei);
00109 scalar minFace = min(vsfOwn, vsfNei);
00110 scalar maxMinFace = rk*(maxFace - minFace);
00111 maxFace += maxMinFace;
00112 minFace -= maxMinFace;
00113
00114
00115 limitFace
00116 (
00117 limiter[own],
00118 maxFace - vsfOwn, minFace - vsfOwn,
00119 (Cf[facei] - C[own]) & g[own]
00120 );
00121
00122
00123 limitFace
00124 (
00125 limiter[nei],
00126 maxFace - vsfNei, minFace - vsfNei,
00127 (Cf[facei] - C[nei]) & g[nei]
00128 );
00129 }
00130
00131 const volScalarField::GeometricBoundaryField& bsf = vsf.boundaryField();
00132
00133 forAll(bsf, patchi)
00134 {
00135 const fvPatchScalarField& psf = bsf[patchi];
00136
00137 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
00138 const vectorField& pCf = Cf.boundaryField()[patchi];
00139
00140 if (psf.coupled())
00141 {
00142 scalarField psfNei = psf.patchNeighbourField();
00143
00144 forAll(pOwner, pFacei)
00145 {
00146 label own = pOwner[pFacei];
00147
00148 scalar vsfOwn = vsf[own];
00149 scalar vsfNei = psfNei[pFacei];
00150
00151 scalar maxFace = max(vsfOwn, vsfNei);
00152 scalar minFace = min(vsfOwn, vsfNei);
00153 scalar maxMinFace = rk*(maxFace - minFace);
00154 maxFace += maxMinFace;
00155 minFace -= maxMinFace;
00156
00157 limitFace
00158 (
00159 limiter[own],
00160 maxFace - vsfOwn, minFace - vsfOwn,
00161 (pCf[pFacei] - C[own]) & g[own]
00162 );
00163 }
00164 }
00165 else if (psf.fixesValue())
00166 {
00167 forAll(pOwner, pFacei)
00168 {
00169 label own = pOwner[pFacei];
00170
00171 scalar vsfOwn = vsf[own];
00172 scalar vsfNei = psf[pFacei];
00173
00174 scalar maxFace = max(vsfOwn, vsfNei);
00175 scalar minFace = min(vsfOwn, vsfNei);
00176 scalar maxMinFace = rk*(maxFace - minFace);
00177 maxFace += maxMinFace;
00178 minFace -= maxMinFace;
00179
00180 limitFace
00181 (
00182 limiter[own],
00183 maxFace - vsfOwn, minFace - vsfOwn,
00184 (pCf[pFacei] - C[own]) & g[own]
00185 );
00186 }
00187 }
00188 }
00189
00190 if (fv::debug)
00191 {
00192 Info<< "gradient limiter for: " << vsf.name()
00193 << " max = " << gMax(limiter)
00194 << " min = " << gMin(limiter)
00195 << " average: " << gAverage(limiter) << endl;
00196 }
00197
00198 g.internalField() *= limiter;
00199 g.correctBoundaryConditions();
00200 gaussGrad<scalar>::correctBoundaryConditions(vsf, g);
00201
00202 return tGrad;
00203 }
00204
00205
00206 template<>
00207 tmp<volTensorField> faceLimitedGrad<vector>::grad
00208 (
00209 const volVectorField& vvf
00210 ) const
00211 {
00212 const fvMesh& mesh = vvf.mesh();
00213
00214 tmp<volTensorField> tGrad = basicGradScheme_().grad(vvf);
00215
00216 if (k_ < SMALL)
00217 {
00218 return tGrad;
00219 }
00220
00221 volTensorField& g = tGrad();
00222
00223 const unallocLabelList& owner = mesh.owner();
00224 const unallocLabelList& neighbour = mesh.neighbour();
00225
00226 const volVectorField& C = mesh.C();
00227 const surfaceVectorField& Cf = mesh.Cf();
00228
00229
00230 scalarField limiter(vvf.internalField().size(), 1.0);
00231
00232 scalar rk = (1.0/k_ - 1.0);
00233
00234 forAll(owner, facei)
00235 {
00236 label own = owner[facei];
00237 label nei = neighbour[facei];
00238
00239 vector vvfOwn = vvf[own];
00240 vector vvfNei = vvf[nei];
00241
00242
00243 vector gradf = (Cf[facei] - C[own]) & g[own];
00244
00245 scalar vsfOwn = gradf & vvfOwn;
00246 scalar vsfNei = gradf & vvfNei;
00247
00248 scalar maxFace = max(vsfOwn, vsfNei);
00249 scalar minFace = min(vsfOwn, vsfNei);
00250 scalar maxMinFace = rk*(maxFace - minFace);
00251 maxFace += maxMinFace;
00252 minFace -= maxMinFace;
00253
00254 limitFace
00255 (
00256 limiter[own],
00257 maxFace - vsfOwn, minFace - vsfOwn,
00258 magSqr(gradf)
00259 );
00260
00261
00262
00263 gradf = (Cf[facei] - C[nei]) & g[nei];
00264
00265 vsfOwn = gradf & vvfOwn;
00266 vsfNei = gradf & vvfNei;
00267
00268 maxFace = max(vsfOwn, vsfNei);
00269 minFace = min(vsfOwn, vsfNei);
00270
00271 limitFace
00272 (
00273 limiter[nei],
00274 maxFace - vsfNei, minFace - vsfNei,
00275 magSqr(gradf)
00276 );
00277 }
00278
00279
00280 const volVectorField::GeometricBoundaryField& bvf = vvf.boundaryField();
00281
00282 forAll(bvf, patchi)
00283 {
00284 const fvPatchVectorField& psf = bvf[patchi];
00285
00286 const unallocLabelList& pOwner = mesh.boundary()[patchi].faceCells();
00287 const vectorField& pCf = Cf.boundaryField()[patchi];
00288
00289 if (psf.coupled())
00290 {
00291 vectorField psfNei = psf.patchNeighbourField();
00292
00293 forAll(pOwner, pFacei)
00294 {
00295 label own = pOwner[pFacei];
00296
00297 vector vvfOwn = vvf[own];
00298 vector vvfNei = psfNei[pFacei];
00299
00300 vector gradf = (pCf[pFacei] - C[own]) & g[own];
00301
00302 scalar vsfOwn = gradf & vvfOwn;
00303 scalar vsfNei = gradf & vvfNei;
00304
00305 scalar maxFace = max(vsfOwn, vsfNei);
00306 scalar minFace = min(vsfOwn, vsfNei);
00307 scalar maxMinFace = rk*(maxFace - minFace);
00308 maxFace += maxMinFace;
00309 minFace -= maxMinFace;
00310
00311 limitFace
00312 (
00313 limiter[own],
00314 maxFace - vsfOwn, minFace - vsfOwn,
00315 magSqr(gradf)
00316 );
00317 }
00318 }
00319 else if (psf.fixesValue())
00320 {
00321 forAll(pOwner, pFacei)
00322 {
00323 label own = pOwner[pFacei];
00324
00325 vector vvfOwn = vvf[own];
00326 vector vvfNei = psf[pFacei];
00327
00328 vector gradf = (pCf[pFacei] - C[own]) & g[own];
00329
00330 scalar vsfOwn = gradf & vvfOwn;
00331 scalar vsfNei = gradf & vvfNei;
00332
00333 scalar maxFace = max(vsfOwn, vsfNei);
00334 scalar minFace = min(vsfOwn, vsfNei);
00335 scalar maxMinFace = rk*(maxFace - minFace);
00336 maxFace += maxMinFace;
00337 minFace -= maxMinFace;
00338
00339 limitFace
00340 (
00341 limiter[own],
00342 maxFace - vsfOwn, minFace - vsfOwn,
00343 magSqr(gradf)
00344 );
00345 }
00346 }
00347 }
00348
00349 if (fv::debug)
00350 {
00351 Info<< "gradient limiter for: " << vvf.name()
00352 << " max = " << gMax(limiter)
00353 << " min = " << gMin(limiter)
00354 << " average: " << gAverage(limiter) << endl;
00355 }
00356
00357 g.internalField() *= limiter;
00358 g.correctBoundaryConditions();
00359 gaussGrad<vector>::correctBoundaryConditions(vvf, g);
00360
00361 return tGrad;
00362 }
00363
00364
00365
00366
00367 }
00368
00369
00370
00371 }
00372
00373