cell_LagrangianAverage.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) 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 "cell_LagrangianAverage.H"
27 #include "LagrangianFields.H"
28 
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
30 
31 template<class Type>
33 {
34  forAll(d.cellAvgCell_, cellAvgi)
35  {
36  d.cellCellAvg_[d.cellAvgCell_[cellAvgi]] = -1;
37  }
38  d.cellAvgCell_.clear();
39  d.cellAvgCount_.clear();
40  if (d.cellAvgWeightSumPtr_.valid()) d.cellAvgWeightSumPtr_->clear();
41  d.cellAvgSum_.clear();
42 }
43 
44 
45 template<class Type>
47 (
48  const LagrangianSubSubField<scalar>& weightOrNull,
49  const LagrangianSubSubField<Type>& psiOrWeightPsi,
50  data& d
51 )
52 {
53  const LagrangianSubMesh& subMesh = psiOrWeightPsi.mesh();
54 
55  //Info<< "*** Removing sub mesh with " << subMesh.size()
56  // << " elements" << endl;
57 
58  if (notNull(weightOrNull) != d.cellAvgWeightSumPtr_.valid())
59  {
61  << "Inconsistent weight specification for average of field "
62  << psiOrWeightPsi.name() << exit(FatalError);
63  }
64 
65  forAll(psiOrWeightPsi, subi)
66  {
67  const label celli = subMesh.mesh().celli()[subMesh.start() + subi];
68  const label cellAvgi = d.cellCellAvg_[celli];
69 
70  //Info<< " -> Remove from cell #" << celli << ", leaving "
71  // << d.cellAvgCount_[cellAvgi] - 1 << " samples" << endl;
72 
73  if (cellAvgi == -1 || d.cellAvgCount_[cellAvgi] == 0)
74  {
76  << "Negative count for average of field "
77  << psiOrWeightPsi.name() << exit(FatalError);
78  }
79 
80  // Remove from the cell average
81  d.cellAvgCount_[cellAvgi] --;
82  if (notNull(weightOrNull))
83  {
84  d.cellAvgWeightSumPtr_()[cellAvgi] -= weightOrNull[subi];
85  d.cellAvgSum_[cellAvgi] -= weightOrNull[subi]*psiOrWeightPsi[subi];
86  }
87  else
88  {
89  d.cellAvgSum_[cellAvgi] -= psiOrWeightPsi[subi];
90  }
91  }
92 
93  //forAll(dcellAvgCell__, cellAvgi)
94  //{
95  // Info<< " !! Cell #" << d.cellAvgCell_[cellAvgi] << " has "
96  // << d.cellAvgCount_[cellAvgi] << " samples" << endl;
97  //}
98 }
99 
100 
101 template<class Type>
103 (
104  const LagrangianSubSubField<scalar>& weightOrNull,
105  const LagrangianSubSubField<Type>& psiOrWeightPsi,
106  data& d
107 )
108 {
109  const LagrangianSubMesh& subMesh = psiOrWeightPsi.mesh();
110 
111  //Info<< "*** Adding sub mesh with " << subMesh.size()
112  // << " elements" << endl;
113 
114  if (notNull(weightOrNull) != d.cellAvgWeightSumPtr_.valid())
115  {
117  << "Inconsistent weight specification for average of field "
118  << psiOrWeightPsi.name() << exit(FatalError);
119  }
120 
121  forAll(psiOrWeightPsi, subi)
122  {
123  const label celli = subMesh.mesh().celli()[subMesh.start() + subi];
124  label cellAvgi = d.cellCellAvg_[celli];
125 
126  // Initialise this cell if it is newly a part of the average
127  if (cellAvgi == -1)
128  {
129  cellAvgi = d.cellAvgCell_.size();
130  d.cellCellAvg_[celli] = cellAvgi;
131  d.cellAvgCell_.append(celli);
132  d.cellAvgCount_.append(label(0));
133  if (notNull(weightOrNull))
134  {
135  d.cellAvgWeightSumPtr_().append(scalar(0));
136  }
137  d.cellAvgSum_.append(pTraits<Type>::zero);
138  }
139 
140  //Info<< " -> Add to cell #" << celli << ", giving "
141  // << d.cellAvgCount_[cellAvgi] + 1 << " samples" << endl;
142 
143  // Add to the cell average
144  d.cellAvgCount_[cellAvgi] ++;
145  if (notNull(weightOrNull))
146  {
147  d.cellAvgWeightSumPtr_()[cellAvgi] += weightOrNull[subi];
148  d.cellAvgSum_[cellAvgi] += weightOrNull[subi]*psiOrWeightPsi[subi];
149  }
150  else
151  {
152  d.cellAvgSum_[cellAvgi] += psiOrWeightPsi[subi];
153  }
154  }
155 
156  //forAll(d.cellAvgCell_, cellAvgi)
157  //{
158  // Info<< " !! Cell #" << d.cellAvgCell_[cellAvgi] << " has "
159  // << d.cellAvgCount_[cellAvgi] << " samples" << endl;
160  //}
161 }
162 
163 
164 template<class Type>
166 (
167  LagrangianSubField<Type>& result
168 ) const
169 {
170  const LagrangianSubMesh& subMesh = result.mesh();
171 
172  forAll(subMesh, subi)
173  {
174  const label celli = subMesh.mesh().celli()[subMesh.start() + subi];
175  const label cellAvgi = data_.cellCellAvg_[celli];
176  const label dCellAvgi = dData_.cellCellAvg_[celli];
177  const bool haveData =
178  cellAvgi != -1 && data_.cellAvgCount_[cellAvgi] != 0;
179  const bool haveDData =
180  dCellAvgi != -1 && dData_.cellAvgCount_[dCellAvgi] != 0;
181 
182  if (!haveData && !haveDData)
183  {
185  << "Interpolated value requested for a cell in which no "
186  << "elements have been averaged"
187  << exit(FatalError);
188  }
189 
190  static const Type& z = pTraits<Type>::zero;
191 
192  result[subi] =
193  (
194  (haveData ? data_.cellAvgSum_[cellAvgi] : z)
195  + (haveDData ? dData_.cellAvgSum_[dCellAvgi] : z)
196  )
197  /(
198  isNull(weightSum_)
199  ? (haveData ? data_.cellAvgWeightSumPtr_()[cellAvgi] : 0)
200  + (haveDData ? dData_.cellAvgWeightSumPtr_()[dCellAvgi] : 0)
201  : weightSum_[celli]
202  );
203  }
204 }
205 
206 
207 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
208 
209 template<class Type>
211 (
212  const label nCells,
213  const bool hasWeightSum
214 )
215 :
216  cellCellAvg_(nCells, label(-1)),
217  cellAvgCell_(),
218  cellAvgCount_(),
219  cellAvgWeightSumPtr_(hasWeightSum ? new DynamicList<scalar>() : nullptr),
220  cellAvgSum_()
221 {}
222 
223 
224 template<class Type>
226 (
227  const word& name,
228  const LagrangianMesh& mesh,
229  const dimensionSet& dimensions,
230  const Field<scalar>& weightSum
231 )
232 :
234  weightSum_(weightSum),
235  data_(mesh.mesh().nCells(), isNull(weightSum)),
236  dDataIsValid_(false),
237  dData_(mesh.mesh().nCells(), isNull(weightSum))
238 {}
239 
240 
241 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
242 
243 template<class Type>
245 {}
246 
247 
248 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
249 
250 template<class Type>
252 (
253  const LagrangianSubSubField<scalar>& weightOrNull,
254  const LagrangianSubSubField<Type>& psiOrWeightPsi
255 )
256 {
257  if (dDataIsValid_)
258  {
260  << "Cannot remove from an average with a cached difference"
261  << exit(FatalError);
262  }
263 
264  remove(weightOrNull, psiOrWeightPsi, data_);
265 }
266 
267 
268 template<class Type>
270 (
271  const LagrangianSubSubField<scalar>& weightOrNull,
272  const LagrangianSubSubField<Type>& psiOrWeightPsi,
273  const bool cache
274 )
275 {
276  if (dDataIsValid_)
277  {
279  << "Cannot add to an average with a cached difference"
280  << exit(FatalError);
281  }
282 
283  dDataIsValid_ = cache;
284 
285  add(weightOrNull, psiOrWeightPsi, cache ? dData_ : data_);
286 }
287 
288 
289 template<class Type>
291 (
292  const LagrangianSubSubField<scalar>& weightOrNull,
293  const LagrangianSubSubField<Type>& psiOrWeightPsi,
294  const bool cache
295 )
296 {
297  if (!dDataIsValid_)
298  {
300  << "Cannot correct an average without a cached difference"
301  << exit(FatalError);
302  }
303 
304  clear(dData_);
305 
306  dDataIsValid_ = cache;
307 
308  add(weightOrNull, psiOrWeightPsi, cache ? dData_ : data_);
309 }
310 
311 
312 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Basic Lagrangian averaging process in which values are averaged in the cells and then interpolated as...
cell(const word &name, const LagrangianMesh &mesh, const dimensionSet &dimensions, const Field< scalar > &weightSum)
Construct with a name, for a mesh and with given dimensions.
virtual void correct(const LagrangianSubSubField< scalar > &weight, const LagrangianSubSubField< Type > &psi, const bool cache)
Correct weighted values in the average.
Class containing Lagrangian geometry and topology.
Dimension set for the base types.
Definition: dimensionSet.H:125
A class for handling words, derived from string.
Definition: word.H:62
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
tUEqn clear()
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
const HashTable< dimensionSet > & dimensions()
Get the table of dimension sets.
Definition: dimensionSets.C:96
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:64
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
Definition: nullObjectI.H:58
error FatalError
void add(LagrangianPatchField< typename typeOfSum< Type1, Type2 >::type > &f, const LagrangianPatchField< Type1 > &f1, const LagrangianPatchField< Type2 > &f2)