1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 \*---------------------------------------------------------------------------*/
29 #include "volFields.H"
30 #include "surfaceFields.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 Foam::scalar Foam::CICSAM::limiter
37 const scalar cdWeight,
38 const scalar faceFlux,
47 // Calculate CICSAM weight
61 // Calculate CICSAM face value
62 scalar phif = w*phiP + (1 - w)*phiN;
64 // Calculate UD and CD face value
65 scalar phiU = faceFlux >= 0 ? phiP : phiN;
66 scalar phiCD = cdWeight*phiP + (1 - cdWeight)*phiN;
68 // Calculate the effective limiter for the QUICK interpolation
69 scalar CLimiter = (phif - phiU)/stabilise(phiCD - phiU, SMALL);
71 // Limit the limiter between upwind and downwind
72 return max(min(CLimiter, 2), 0);
76 Foam::scalar Foam::CICSAM::weight
78 const scalar cdWeight,
79 const scalar faceFlux,
88 // Calculate upwind value, faceFlux C tilde and do a stabilisation
96 costheta = mag((gradcP & d)/(mag(gradcP)*mag(d) + SMALL));
98 phiupw = phiN - 2*(gradcP & d);
100 phiupw = max(min(phiupw, 1.0), 0.0);
102 if ((phiN - phiupw) > 0)
104 phict = (phiP - phiupw)/(phiN - phiupw + SMALL);
108 phict = (phiP - phiupw)/(phiN - phiupw - SMALL);
113 costheta = mag((gradcN & d)/(mag(gradcN)*mag(d) + SMALL));
115 phiupw = phiP + 2*(gradcN & d);
117 phiupw = max(min(phiupw, 1.0), 0.0);
119 if ((phiP - phiupw) > 0)
121 phict = (phiN - phiupw)/(phiP - phiupw + SMALL);
125 phict = (phiN - phiupw)/(phiP - phiupw - SMALL);
130 // Calculate the weighting factors for CICSAM
132 scalar cicsamFactor = (k_ + SMALL)/(1 - k_ + SMALL);
134 costheta = min(1.0, cicsamFactor*(costheta));
135 costheta = (cos(2*(acos(costheta))) + 1)/2;
137 scalar k1 = (3*Cof*Cof - 3*Cof)/(2*Cof*Cof + 6*Cof - 8);
139 scalar k3 = (3*Cof + 5)/(2*Cof + 6);
142 if (phict > 0 && phict <= k1) // use blended scheme 1
144 scalar phifCM = phict/(Cof + SMALL);
145 weight = (phifCM - phict)/(1 - phict);
147 else if (phict > k1 && phict <= k2) // use blended scheme 2
149 scalar phifHC = phict/(Cof + SMALL);
150 scalar phifUQ = (8*Cof*phict + (1 - Cof)*(6*phict + 3))/8;
151 scalar phifCM = costheta*phifHC + (1 - costheta)*phifUQ;
152 weight = (phifCM - phict)/(1 - phict);
154 else if (phict > k2 && phict < k3) // use blended scheme 3
156 scalar phifUQ = (8*Cof*phict + (1 - Cof)*(6*phict + 3))/8;
157 scalar phifCM = costheta + (1 - costheta)*phifUQ;
158 weight = (phifCM - phict)/(1 - phict);
160 else if (phict >= k3 && phict <= 1) // use downwind
180 Foam::tmp<Foam::surfaceScalarField> Foam::CICSAM::limiter
182 const volScalarField& phi
185 const fvMesh& mesh = this->mesh();
187 tmp<surfaceScalarField> tLimiter
189 new surfaceScalarField
193 type() + "Limiter(" + phi.name() + ')',
194 mesh.time().timeName(),
201 surfaceScalarField& lim = tLimiter();
203 volVectorField gradc = fvc::grad(phi);
205 surfaceScalarField Cof =
207 *upwind<scalar>(mesh, faceFlux_).interpolate
209 fvc::surfaceIntegrate(faceFlux_)
212 const surfaceScalarField& CDweights = mesh.surfaceInterpolation::weights();
214 const unallocLabelList& owner = mesh.owner();
215 const unallocLabelList& neighbour = mesh.neighbour();
217 const vectorField& C = mesh.C();
219 scalarField& pLim = lim.internalField();
223 label own = owner[faceI];
224 label nei = neighbour[faceI];
226 pLim[faceI] = limiter
229 this->faceFlux_[faceI],
239 surfaceScalarField::GeometricBoundaryField& bLim = lim.boundaryField();
240 surfaceScalarField::GeometricBoundaryField& bCof = Cof.boundaryField();
243 scalarField& pLim = bLim[patchi];
245 if (bLim[patchi].coupled())
247 const scalarField& pCDweights = CDweights.boundaryField()[patchi];
249 const scalarField& pFaceFlux =
250 this->faceFlux_.boundaryField()[patchi];
253 phi.boundaryField()[patchi].patchInternalField();
256 phi.boundaryField()[patchi].patchNeighbourField();
258 vectorField pGradcP =
259 gradc.boundaryField()[patchi].patchInternalField();
261 vectorField pGradcN =
262 gradc.boundaryField()[patchi].patchNeighbourField();
264 const scalarField& pCof = Cof.boundaryField()[patchi];
266 // Build the d-vectors
267 // Better version of d-vectors: Zeljko Tukovic, 25/Apr/2010
268 vectorField pd = bLim[patchi].patch().delta();
272 pLim[faceI] = limiter
296 Foam::tmp<Foam::surfaceScalarField> Foam::CICSAM::weights
298 const volScalarField& phi
301 const fvMesh& mesh = this->mesh();
303 tmp<surfaceScalarField> tWeightingFactors
305 new surfaceScalarField(mesh.surfaceInterpolation::weights())
307 surfaceScalarField& weightingFactors = tWeightingFactors();
309 scalarField& weights = weightingFactors.internalField();
312 volVectorField gradc = fvc::grad(phi);
314 surfaceScalarField Cof =
316 *upwind<scalar>(mesh, faceFlux_).interpolate
318 fvc::surfaceIntegrate(faceFlux_)
321 const surfaceScalarField& CDweights = mesh.surfaceInterpolation::weights();
323 const unallocLabelList& owner = mesh.owner();
324 const unallocLabelList& neighbour = mesh.neighbour();
326 const vectorField& C = mesh.C();
328 scalarField& w = weightingFactors.internalField();
332 label own = owner[faceI];
333 label nei = neighbour[faceI];
338 this->faceFlux_[faceI],
348 surfaceScalarField::GeometricBoundaryField& bWeights =
349 weightingFactors.boundaryField();
351 surfaceScalarField::GeometricBoundaryField& bCof = Cof.boundaryField();
353 forAll(bWeights, patchi)
355 scalarField& pWeights = bWeights[patchi];
357 if (bWeights[patchi].coupled())
359 const scalarField& pCDweights = CDweights.boundaryField()[patchi];
361 const scalarField& pFaceFlux =
362 this->faceFlux_.boundaryField()[patchi];
365 phi.boundaryField()[patchi].patchInternalField();
368 phi.boundaryField()[patchi].patchNeighbourField();
370 vectorField pGradcP =
371 gradc.boundaryField()[patchi].patchInternalField();
373 vectorField pGradcN =
374 gradc.boundaryField()[patchi].patchNeighbourField();
376 const scalarField& pCof = Cof.boundaryField()[patchi];
378 // Build the d-vectors
379 // Better version of d-vectors: Zeljko Tukovic, 25/Apr/2010
380 vectorField pd = bWeights[patchi].patch().delta();
382 forAll(pWeights, faceI)
384 pWeights[faceI] = weight
403 return tWeightingFactors;
409 defineNamedTemplateTypeNameAndDebug(CICSAM, 0);
411 surfaceInterpolationScheme<scalar>::addMeshConstructorToTable<CICSAM>
412 addCICSAMMeshConstructorToTable_;
414 surfaceInterpolationScheme<scalar>::addMeshFluxConstructorToTable<CICSAM>
415 addCICSAMMeshFluxConstructorToTable_;
417 limitedSurfaceInterpolationScheme<scalar>::addMeshConstructorToTable<CICSAM>
418 addCICSAMMeshConstructorToLimitedTable_;
420 limitedSurfaceInterpolationScheme<scalar>::
421 addMeshFluxConstructorToTable<CICSAM>
422 addCICSAMMeshFluxConstructorToLimitedTable_;
425 // ************************************************************************* //