oversetAdjustPhi.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2017-2018 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "oversetAdjustPhi.H"
29#include "volFields.H"
30#include "surfaceFields.H"
32#include "syncTools.H"
33#include "fv.H"
34
35// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
36
38(
40 const volVectorField& U
41)
42{
43 const fvMesh& mesh = U.mesh();
44
45 const cellCellStencilObject& overlap = Stencil::New(mesh);
46 const labelList& cellTypes = overlap.cellTypes();
47 const labelList& zoneID = overlap.zoneID();
48 label nZones = gMax(zoneID)+1;
49
50
51
52 // Pass1: accumulate all fluxes, calculate correction factor
53
54 scalarField massIn(nZones, Zero);
55 scalarField adjustableMassOut(nZones, Zero);
56
58 phi.boundaryFieldRef();
59
60
61 // Check all faces on the outside of interpolated cells
62 const labelUList& own = mesh.owner();
63 const labelUList& nei = mesh.neighbour();
64 {
65 forAll(own, facei)
66 {
67 label zonei = zoneID[own[facei]]; // note:own and nei in same zone
68
69 label ownType = cellTypes[own[facei]];
70 label neiType = cellTypes[nei[facei]];
71
72 bool ownCalc =
73 (ownType == cellCellStencil::CALCULATED)
74 && (neiType == cellCellStencil::INTERPOLATED);
75
76 bool neiCalc =
77 (ownType == cellCellStencil::INTERPOLATED)
78 && (neiType == cellCellStencil::CALCULATED);
79
80
81 if (ownCalc || neiCalc)
82 {
83 // Calculate flux w.r.t. calculated cell
84 scalar flux = phi[facei];
85 if (neiCalc)
86 {
87 flux = -flux;
88 }
89
90 if (flux < 0.0)
91 {
92 massIn[zonei] -= flux;
93 }
94 else
95 {
96 adjustableMassOut[zonei] += flux;
97 }
98 }
99 }
100 }
101
102
103 // Check all coupled faces on the outside of interpolated cells
104 labelList neiCellTypes;
105 syncTools::swapBoundaryCellList(mesh, cellTypes, neiCellTypes);
106 {
107 forAll(bphi, patchi)
108 {
109 const fvPatchVectorField& Up = U.boundaryField()[patchi];
110 const fvsPatchScalarField& phip = bphi[patchi];
111 const labelUList& fc = Up.patch().faceCells();
112
113 label start = Up.patch().start();
114
115 forAll(fc, i)
116 {
117 label facei = start+i;
118 label celli = fc[i];
119 label ownType = cellTypes[celli];
120 label neiType = neiCellTypes[facei-mesh.nInternalFaces()];
121
122 bool ownCalc =
123 (ownType == cellCellStencil::CALCULATED)
124 && (neiType == cellCellStencil::INTERPOLATED);
125
126
127 if (ownCalc)
128 {
129 // Calculate flux w.r.t. calculated cell
130 scalar flux = phip[i];
131
132 if (flux < 0.0)
133 {
134 massIn[zoneID[celli]] -= flux;
135 }
136 else
137 {
138 adjustableMassOut[zoneID[celli]] += flux;
139 }
140 }
141 }
142 }
143 }
144
145 // Calculate the total flux in the domain, used for normalisation
146 scalar totalFlux = VSMALL + sum(mag(phi)).value();
147
148 forAll(massIn, zonei)
149 {
150 reduce(massIn[zonei], sumOp<scalar>());
151 reduce(adjustableMassOut[zonei], sumOp<scalar>());
152 }
153
154
155 scalarField massCorr(nZones, 1.0);
156
157 forAll(massIn, zonei)
158 {
159 scalar magAdjustableMassOut = mag(adjustableMassOut[zonei]);
160
161 if
162 (
163 magAdjustableMassOut > VSMALL
164 && magAdjustableMassOut/totalFlux > SMALL
165 )
166 {
167 massCorr[zonei] = massIn[zonei]/adjustableMassOut[zonei];
168 }
169 else if (mag(massIn[zonei])/totalFlux > 1e-8)
170 {
172 << "Continuity error cannot be removed by adjusting the"
173 " flow at fringe faces.\n Please check the cell types"
174 << " from the overset analysis."
175 << nl
176 << "Zone : " << zonei << nl
177 << "Total flux : " << totalFlux << nl
178 << "Specified mass inflow : " << massIn[zonei] << nl
179 << "Adjustable mass outflow : " << adjustableMassOut[zonei]
180 << nl << endl;
181 }
182
183
184 if (fv::debug)
185 {
186 Info<< "Zone : " << zonei << nl
187 << "Total flux : " << totalFlux << nl
188 << "Specified mass inflow : " << massIn[zonei] << nl
189 << "Adjustable mass outflow : " << adjustableMassOut[zonei]
190 << nl
191 << "Correction factor : " << massCorr[zonei] << nl
192 << endl;
193 }
194 }
195
196
197
198 // Pass2: adjust fluxes
199
200 forAll(own, facei)
201 {
202 label zonei = zoneID[own[facei]]; // note:own and nei in same zone
203
204 label ownType = cellTypes[own[facei]];
205 label neiType = cellTypes[nei[facei]];
206
207 bool ownCalc =
208 (ownType == cellCellStencil::CALCULATED)
209 && (neiType == cellCellStencil::INTERPOLATED);
210
211 bool neiCalc =
212 (ownType == cellCellStencil::INTERPOLATED)
213 && (neiType == cellCellStencil::CALCULATED);
214
215 if (ownCalc || neiCalc)
216 {
217 // Calculate flux w.r.t. calculated cell
218 scalar flux = phi[facei];
219 if (neiCalc)
220 {
221 flux = -flux;
222 }
223
224 if (flux < 0.0)
225 {
226 phi[facei] /= Foam::sqrt(massCorr[zonei]);
227 }
228 else
229 {
230 phi[facei] *= Foam::sqrt(massCorr[zonei]);
231 }
232 }
233 }
234
235 forAll(bphi, patchi)
236 {
237 const fvPatchVectorField& Up = U.boundaryField()[patchi];
238 fvsPatchScalarField& phip = bphi[patchi];
239 const labelUList& fc = Up.patch().faceCells();
240
241 label start = Up.patch().start();
242
243 forAll(fc, i)
244 {
245 label facei = start+i;
246 label celli = fc[i];
247 label zonei = zoneID[celli]; // note:own and nei in same zone
248 label ownType = cellTypes[celli];
249 label neiType = neiCellTypes[facei-mesh.nInternalFaces()];
250
251 bool ownCalc =
252 (ownType == cellCellStencil::CALCULATED)
253 && (neiType == cellCellStencil::INTERPOLATED);
254
255 bool neiCalc =
256 (ownType == cellCellStencil::INTERPOLATED)
257 && (neiType == cellCellStencil::CALCULATED);
258
259 if (ownCalc || neiCalc)
260 {
261 // Calculate flux w.r.t. calculated cell
262 scalar flux = phip[i];
263 if (neiCalc)
264 {
265 flux = -flux;
266 }
267
268 if (flux < 0.0)
269 {
270 phip[i] /= Foam::sqrt(massCorr[zonei]);
271 }
272 else
273 {
274 phip[i] *= Foam::sqrt(massCorr[zonei]);
275 }
276 }
277 }
278 }
279
280 return sum(mag(massIn))/totalFlux < SMALL
281 && sum(mag(adjustableMassOut))/totalFlux < SMALL;
282}
283
284
285// ************************************************************************* //
reduce(hasMovingMesh, orOp< bool >())
surfaceScalarField & phi
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:362
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:179
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:113
U
Definition: pEqn.H:72
dynamicFvMesh & mesh
const cellCellStencilObject & overlap
Definition: correctPhi.H:57
label nZones
const labelIOList & zoneID
#define WarningInFunction
Report a warning using Foam::Warning.
bool oversetAdjustPhi(surfaceScalarField &phi, const volVectorField &U)
Adjust the balance of fluxes to obey continuity.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Type gMax(const FieldField< Field, Type > &f)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
Adjust the balance of fluxes on the faces between interpolated and calculated to obey continuity.
const labelList & cellTypes
Definition: setCellMask.H:33
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Foam::surfaceFields.