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 -------------------------------------------------------------------------------
10 License
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"
31 #include "cellCellStencilObject.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 
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 
57  surfaceScalarField::Boundary& bphi =
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 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::fvPatchField< vector >
nZones
label nZones
Definition: interpolatedFaces.H:24
volFields.H
Foam::fvc::flux
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
fv.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::fvPatch::start
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:173
Foam::fvsPatchField
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:68
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
surfaceFields.H
Foam::surfaceFields.
syncTools.H
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::Field< scalar >
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
phi
surfaceScalarField & phi
Definition: setRegionFluidFields.H:8
reduce
reduce(hasMovingMesh, orOp< bool >())
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
U
U
Definition: pEqn.H:72
Foam::oversetAdjustPhi
bool oversetAdjustPhi(surfaceScalarField &phi, const volVectorField &U)
Adjust the balance of fluxes to obey continuity.
Definition: oversetAdjustPhi.C:38
cellTypes
const labelList & cellTypes
Definition: setCellMask.H:33
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::List< label >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::UList< label >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::fvPatch::faceCells
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:113
overlap
const cellCellStencilObject & overlap
Definition: correctPhi.H:57
Foam::fvPatchField::patch
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:357
Foam::flux
Definition: vector.H:56
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
cellCellStencilObject.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
oversetAdjustPhi.H
Adjust the balance of fluxes on the faces between interpolated and calculated to obey continuity.
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::cellCellStencilObject
Definition: cellCellStencilObject.H:57