MULES.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "MULES.H"
27 
28 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
29 
30 namespace Foam
31 {
33 }
34 
35 
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 
39 {
40  read(dict);
41 }
42 
43 
45 {
46  const dictionary& MULEScontrols = dict.optionalSubDict("MULES");
47 
48  globalBounds = MULEScontrols.lookupOrDefault<Switch>("globalBounds", false);
49 
50  smoothingCoeff = MULEScontrols.lookupOrDefault<scalar>("smoothingCoeff", 0);
51 
52  extremaCoeff = MULEScontrols.lookupOrDefault<scalar>("extremaCoeff", 0);
53 
54  boundaryExtremaCoeff =
55  MULEScontrols.lookupOrDefault<scalar>("boundaryExtremaCoeff", 0);
56 
57  if (dict.found("MULES"))
58  {
59  nIter = MULEScontrols.lookupOrDefault<label>("nIter", 3);
60 
61  tol =
62  nIter == 1
63  ? 0
64  : MULEScontrols.lookupOrDefault<scalar>("tolerance", 0);
65  }
66  else
67  {
68  nIter = MULEScontrols.lookupOrDefault<label>("nLimiterIter", 3);
69 
70  tol =
71  nIter == 1
72  ? 0
73  : MULEScontrols.lookupOrDefault<scalar>("MULEStolerance", 0);
74  }
75 }
76 
77 
79 {
80  forAll(phiPsiCorrs[0], facei)
81  {
82  scalar sumPos = 0;
83  scalar sumNeg = 0;
84 
85  forAll(phiPsiCorrs, phasei)
86  {
87  if (phiPsiCorrs[phasei][facei] > 0)
88  {
89  sumPos += phiPsiCorrs[phasei][facei];
90  }
91  else
92  {
93  sumNeg += phiPsiCorrs[phasei][facei];
94  }
95  }
96 
97  const scalar sum = sumPos + sumNeg;
98 
99  if (sum > 0 && sumPos > vSmall)
100  {
101  const scalar lambda = -sumNeg/sumPos;
102 
103  forAll(phiPsiCorrs, phasei)
104  {
105  if (phiPsiCorrs[phasei][facei] > 0)
106  {
107  phiPsiCorrs[phasei][facei] *= lambda;
108  }
109  }
110  }
111  else if (sum < 0 && sumNeg < -vSmall)
112  {
113  const scalar lambda = -sumPos/sumNeg;
114 
115  forAll(phiPsiCorrs, phasei)
116  {
117  if (phiPsiCorrs[phasei][facei] < 0)
118  {
119  phiPsiCorrs[phasei][facei] *= lambda;
120  }
121  }
122  }
123  }
124 }
125 
126 
128 (
129  UPtrList<scalarField>& phiPsiCorrs,
130  const UPtrList<scalarField>& phiPsiFixedCorrs
131 )
132 {
133  forAll(phiPsiCorrs[0], facei)
134  {
135  scalar sumFixed = 0;
136 
137  forAll(phiPsiFixedCorrs, i)
138  {
139  sumFixed += phiPsiFixedCorrs[i][facei];
140  }
141 
142  scalar sumPos = 0;
143  scalar sumNeg = 0;
144 
145  forAll (phiPsiCorrs, i)
146  {
147  if (phiPsiCorrs[i][facei] > 0)
148  {
149  sumPos += phiPsiCorrs[i][facei];
150  }
151  else
152  {
153  sumNeg += phiPsiCorrs[i][facei];
154  }
155  }
156 
157  const scalar sum = sumPos + sumNeg;
158 
159  if (sum > 0 && sumPos > vSmall)
160  {
161  const scalar lambda = -(sumNeg + sumFixed)/sumPos;
162 
163  forAll (phiPsiCorrs, i)
164  {
165  if (phiPsiCorrs[i][facei] > 0)
166  {
167  phiPsiCorrs[i][facei] *= lambda;
168  }
169  }
170  }
171  else if (sum < 0 && sumNeg < -vSmall)
172  {
173  const scalar lambda = -(sumPos + sumFixed)/sumNeg;
174 
175  forAll (phiPsiCorrs, i)
176  {
177  if (phiPsiCorrs[i][facei] < 0)
178  {
179  phiPsiCorrs[i][facei] *= lambda;
180  }
181  }
182  }
183  }
184 }
185 
186 
188 (
189  const UPtrList<const volScalarField>& psis,
190  UPtrList<surfaceScalarField>& psiPhiCorrs,
191  const surfaceScalarField& phi
192 )
193 {
194  {
195  UPtrList<scalarField> psiPhiCorrsInternal(psiPhiCorrs.size());
196 
197  forAll(psiPhiCorrsInternal, phasei)
198  {
199  psiPhiCorrsInternal.set(phasei, &psiPhiCorrs[phasei]);
200  }
201 
202  limitSumCorr(psiPhiCorrsInternal);
203  }
204 
205  const surfaceScalarField::Boundary& phibf = phi.boundaryField();
206 
207  forAll(phibf, patchi)
208  {
209  label nFixed = 0;
210 
211  forAll(psis, phasei)
212  {
213  if (!psis[phasei].boundaryField()[patchi].assignable())
214  {
215  nFixed++;
216  }
217  }
218 
219  if (nFixed == 0)
220  {
221  UPtrList<scalarField> psiPhiCorrsPatch(psiPhiCorrs.size());
222 
223  forAll(psiPhiCorrsPatch, phasei)
224  {
225  psiPhiCorrsPatch.set
226  (
227  phasei,
228  &psiPhiCorrs[phasei].boundaryFieldRef()[patchi]
229  );
230  }
231 
232  limitSumCorr(psiPhiCorrsPatch);
233  }
234  else if (nFixed < psiPhiCorrs.size())
235  {
236  UPtrList<scalarField> psiPhiCorrsPatch(psiPhiCorrs.size());
237  UPtrList<scalarField> psiPhiCorrsFixedPatch(psiPhiCorrs.size());
238 
239  label i = 0;
240  label fixedi = 0;
241 
242  forAll(psiPhiCorrsPatch, phasei)
243  {
244  if (!psis[phasei].boundaryField()[patchi].assignable())
245  {
246  psiPhiCorrsFixedPatch.set
247  (
248  fixedi++,
249  &psiPhiCorrs[phasei].boundaryFieldRef()[patchi]
250  );
251  }
252  else
253  {
254  psiPhiCorrsPatch.set
255  (
256  i++,
257  &psiPhiCorrs[phasei].boundaryFieldRef()[patchi]
258  );
259  }
260  }
261 
262  psiPhiCorrsPatch.setSize(i);
263  psiPhiCorrsFixedPatch.setSize(fixedi);
264 
265  limitSumCorr(psiPhiCorrsPatch, psiPhiCorrsFixedPatch);
266  }
267  }
268 }
269 
270 
272 (
273  const UPtrList<const volScalarField>& psis,
274  const PtrList<surfaceScalarField>& alphaPhiBDs,
276  const surfaceScalarField& phi
277 )
278 {
279  forAll(psiPhis, phasei)
280  {
281  psiPhis[phasei] -= alphaPhiBDs[phasei];
282  }
283 
284  limitSumCorr(psis, psiPhis, phi);
285 
286  forAll(psiPhis, phasei)
287  {
288  psiPhis[phasei] += alphaPhiBDs[phasei];
289  }
290 }
291 
292 
294 (
295  const UPtrList<const volScalarField>& psis,
297  const surfaceScalarField& phi
298 )
299 {
300  PtrList<surfaceScalarField> alphaPhiBDs(psiPhis.size());
301 
302  forAll(psiPhis, phasei)
303  {
304  alphaPhiBDs.set
305  (
306  phasei,
307  upwind<scalar>(phi.mesh(), phi).flux(psis[phasei])
308  );
309  }
310 
311  limitSum(psis, alphaPhiBDs, psiPhis, phi);
312 }
313 
314 
315 // ************************************************************************* //
MULES: Multidimensional universal limiter for explicit solution.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
const Mesh & mesh() const
Return mesh.
Generic GeometricBoundaryField class.
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
bool set(const label) const
Is element set.
Definition: PtrListI.H:62
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: UPtrList.H:66
bool set(const label) const
Is element set.
Definition: UPtrListI.H:87
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
void setSize(const label)
Reset size of UPtrList. This can only be used to set the size.
Definition: UPtrList.C:61
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
T lookupOrDefault(const word &, const T &, const bool writeDefault=writeOptionalEntries > 0) const
Find and return a T, if not found return the given default.
virtual tmp< SurfaceField< Type > > flux(const VolField< Type > &) const
Return the interpolation weighting factors.
label patchi
dimensionedScalar lambda(viscosity->lookup("lambda"))
void limitSum(const UPtrList< const volScalarField > &psis, const PtrList< surfaceScalarField > &alphaPhiBDs, UPtrList< surfaceScalarField > &psiPhis, const surfaceScalarField &phi)
Definition: MULES.C:272
void limitSumCorr(UPtrList< scalarField > &psiPhiCorrs)
Definition: MULES.C:78
Namespace for OpenFOAM.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
defineTypeNameAndDebug(combustionModel, 0)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dictionary dict
void read(const dictionary &dict)
Read dict and set the controls.
Definition: MULES.C:44
control()
Null constructor.
Definition: MULES.H:107