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
26 Cell to face interpolation scheme. Included in fvMesh.
28 \*---------------------------------------------------------------------------*/
31 #include "volFields.H"
32 #include "surfaceFields.H"
33 #include "demandDrivenData.H"
34 #include "coupledFvPatch.H"
35 #include "mathematicalConstants.H"
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(surfaceInterpolation, 0);
47 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
49 void surfaceInterpolation::clearOut()
51 deleteDemandDrivenData(weightingFactors_);
52 deleteDemandDrivenData(differenceFactors_);
53 deleteDemandDrivenData(correctionVectors_);
57 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
59 surfaceInterpolation::surfaceInterpolation(const fvMesh& fvm)
61 fvSchemes(static_cast<const objectRegistry&>(fvm)),
62 fvSolution(static_cast<const objectRegistry&>(fvm)),
64 weightingFactors_(NULL),
65 differenceFactors_(NULL),
67 correctionVectors_(NULL)
71 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
73 surfaceInterpolation::~surfaceInterpolation()
79 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
81 const surfaceScalarField& surfaceInterpolation::weights() const
83 if (!weightingFactors_)
88 return (*weightingFactors_);
92 const surfaceScalarField& surfaceInterpolation::deltaCoeffs() const
94 if (!differenceFactors_)
99 return (*differenceFactors_);
103 bool surfaceInterpolation::orthogonal() const
105 if (orthogonal_ == false && !correctionVectors_)
107 makeCorrectionVectors();
114 const surfaceVectorField& surfaceInterpolation::correctionVectors() const
118 FatalErrorIn("surfaceInterpolation::correctionVectors()")
119 << "cannot return correctionVectors; mesh is orthogonal"
120 << abort(FatalError);
123 return (*correctionVectors_);
127 // Do what is neccessary if the mesh has moved
128 bool surfaceInterpolation::movePoints()
130 deleteDemandDrivenData(weightingFactors_);
131 deleteDemandDrivenData(differenceFactors_);
134 deleteDemandDrivenData(correctionVectors_);
140 void surfaceInterpolation::makeWeights() const
144 Info<< "surfaceInterpolation::makeWeights() : "
145 << "Constructing weighting factors for face interpolation"
150 weightingFactors_ = new surfaceScalarField
155 mesh_.pointsInstance(),
161 surfaceScalarField& weightingFactors = *weightingFactors_;
164 // Set local references to mesh data
165 // (note that we should not use fvMesh sliced fields at this point yet
166 // since this causes a loop when generating weighting factors in
167 // coupledFvPatchField evaluation phase)
168 const unallocLabelList& owner = mesh_.owner();
169 const unallocLabelList& neighbour = mesh_.neighbour();
171 const vectorField& Cf = mesh_.faceCentres();
172 const vectorField& C = mesh_.cellCentres();
173 const vectorField& Sf = mesh_.faceAreas();
175 // ... and reference to the internal field of the weighting factors
176 scalarField& w = weightingFactors.internalField();
180 // Note: mag in the dot-product.
181 // For all valid meshes, the non-orthogonality will be less that
182 // 90 deg and the dot-product will be positive. For invalid
183 // meshes (d & s <= 0), this will stabilise the calculation
184 // but the result will be poor.
185 scalar SfdOwn = mag(Sf[facei] & (Cf[facei] - C[owner[facei]]));
186 scalar SfdNei = mag(Sf[facei] & (C[neighbour[facei]] - Cf[facei]));
187 w[facei] = SfdNei/(SfdOwn + SfdNei);
190 forAll(mesh_.boundary(), patchi)
192 mesh_.boundary()[patchi].makeWeights
194 weightingFactors.boundaryField()[patchi]
201 Info<< "surfaceInterpolation::makeWeights() : "
202 << "Finished constructing weighting factors for face interpolation"
208 void surfaceInterpolation::makeDeltaCoeffs() const
212 Info<< "surfaceInterpolation::makeDeltaCoeffs() : "
213 << "Constructing differencing factors array for face gradient"
217 // Force the construction of the weighting factors
218 // needed to make sure deltaCoeffs are calculated for parallel runs.
221 differenceFactors_ = new surfaceScalarField
225 "differenceFactors_",
226 mesh_.pointsInstance(),
232 surfaceScalarField& DeltaCoeffs = *differenceFactors_;
235 // Set local references to mesh data
236 const volVectorField& C = mesh_.C();
237 const unallocLabelList& owner = mesh_.owner();
238 const unallocLabelList& neighbour = mesh_.neighbour();
239 const surfaceVectorField& Sf = mesh_.Sf();
240 const surfaceScalarField& magSf = mesh_.magSf();
244 vector delta = C[neighbour[facei]] - C[owner[facei]];
245 vector unitArea = Sf[facei]/magSf[facei];
247 // Standard cell-centre distance form
248 //DeltaCoeffs[facei] = (unitArea & delta)/magSqr(delta);
250 // Slightly under-relaxed form
251 //DeltaCoeffs[facei] = 1.0/mag(delta);
253 // More under-relaxed form
254 //DeltaCoeffs[facei] = 1.0/(mag(unitArea & delta) + VSMALL);
256 // Stabilised form for bad meshes
257 DeltaCoeffs[facei] = 1.0/max(unitArea & delta, 0.05*mag(delta));
260 forAll(DeltaCoeffs.boundaryField(), patchi)
262 mesh_.boundary()[patchi].makeDeltaCoeffs
264 DeltaCoeffs.boundaryField()[patchi]
270 void surfaceInterpolation::makeCorrectionVectors() const
274 Info<< "surfaceInterpolation::makeCorrectionVectors() : "
275 << "Constructing non-orthogonal correction vectors"
279 correctionVectors_ = new surfaceVectorField
284 mesh_.pointsInstance(),
290 surfaceVectorField& corrVecs = *correctionVectors_;
292 // Set local references to mesh data
293 const volVectorField& C = mesh_.C();
294 const unallocLabelList& owner = mesh_.owner();
295 const unallocLabelList& neighbour = mesh_.neighbour();
296 const surfaceVectorField& Sf = mesh_.Sf();
297 const surfaceScalarField& magSf = mesh_.magSf();
298 const surfaceScalarField& DeltaCoeffs = deltaCoeffs();
302 vector unitArea = Sf[facei]/magSf[facei];
303 vector delta = C[neighbour[facei]] - C[owner[facei]];
305 corrVecs[facei] = unitArea - delta*DeltaCoeffs[facei];
308 // Boundary correction vectors set to zero for boundary patches
309 // and calculated consistently with internal corrections for
312 forAll(corrVecs.boundaryField(), patchi)
314 fvsPatchVectorField& patchcorrVecs = corrVecs.boundaryField()[patchi];
316 if (!patchcorrVecs.coupled())
318 patchcorrVecs = vector::zero;
322 const fvsPatchScalarField& patchDeltaCoeffs
323 = DeltaCoeffs.boundaryField()[patchi];
325 const fvPatch& p = patchcorrVecs.patch();
327 vectorField patchDeltas = mesh_.boundary()[patchi].delta();
329 forAll(p, patchFacei)
332 Sf.boundaryField()[patchi][patchFacei]
333 /magSf.boundaryField()[patchi][patchFacei];
335 const vector& delta = patchDeltas[patchFacei];
337 patchcorrVecs[patchFacei] =
338 unitArea - delta*patchDeltaCoeffs[patchFacei];
343 scalar NonOrthogCoeff = 0.0;
345 // Calculate the non-orthogonality for meshes with 1 face or more
346 if (returnReduce(magSf.size(), sumOp<label>()) > 0)
353 (sum(magSf*mag(corrVecs))/sum(magSf)).value(),
356 )*180.0/mathematicalConstant::pi;
361 Info<< "surfaceInterpolation::makeCorrectionVectors() : "
362 << "non-orthogonality coefficient = " << NonOrthogCoeff << " deg."
366 //NonOrthogCoeff = 0.0;
368 if (NonOrthogCoeff < 0.1)
371 deleteDemandDrivenData(correctionVectors_);
380 Info<< "surfaceInterpolation::makeCorrectionVectors() : "
381 << "Finished constructing non-orthogonal correction vectors"
387 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
389 } // End namespace Foam
391 // ************************************************************************* //