surfaceFieldValueTemplates.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-2023 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 "surfaceFieldValue.H"
27 #include "surfaceFields.H"
28 #include "volFields.H"
29 #include "sampledSurface.H"
30 #include "surfaceWriter.H"
31 #include "interpolationCellPoint.H"
32 
33 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const word& fieldName
39 ) const
40 {
41  if
42  (
44  && obr_.foundObject<SurfaceField<Type>>(fieldName)
45  )
46  {
47  return true;
48  }
49  else if (obr_.foundObject<VolField<Type>>(fieldName))
50  {
51  return true;
52  }
53 
54  return false;
55 }
56 
57 
58 template<class Type>
61 (
62  const word& fieldName
63 ) const
64 {
65  if (selectionType_ == selectionTypes::sampledSurface)
66  {
67  if (obr_.foundObject<VolField<Type>>(fieldName))
68  {
69  const VolField<Type>& fld =
70  obr_.lookupObject<VolField<Type>>(fieldName);
71 
72  if (surfacePtr_().interpolate())
73  {
74  // Interpolate the field to the surface points
75  const interpolationCellPoint<Type> interp(fld);
76  tmp<Field<Type>> tintFld(surfacePtr_().interpolate(interp));
77  const Field<Type>& intFld = tintFld();
78 
79  // Average the interpolated field onto the surface faces
80  const faceList& faces = surfacePtr_().faces();
81  tmp<Field<Type>> tavg(new Field<Type>(faces.size(), Zero));
82  Field<Type>& avg = tavg.ref();
83  forAll(faces, facei)
84  {
85  const face& f = faces[facei];
86  forAll(f, fp)
87  {
88  avg[facei] += intFld[f[fp]];
89  }
90  avg[facei] /= f.size();
91  }
92 
93  return tavg;
94  }
95  else
96  {
97  return surfacePtr_().sample(fld);
98  }
99  }
100  else if (obr_.foundObject<SurfaceField<Type>>(fieldName))
101  {
103  << "Surface field " << fieldName
104  << " cannot be sampled onto surface " << surfacePtr_().name()
105  << ". Only vol fields can be sampled onto surfaces."
106  << abort(FatalError);
107  }
108  }
109  else
110  {
111  if (obr_.foundObject<VolField<Type>>(fieldName))
112  {
113  const VolField<Type>& fld =
114  obr_.lookupObject<VolField<Type>>(fieldName);
115  return filterField(fld);
116  }
117  else if (obr_.foundObject<SurfaceField<Type>>(fieldName))
118  {
119  const SurfaceField<Type>& fld =
120  obr_.lookupObject<SurfaceField<Type>>(fieldName);
121  return filterField(fld);
122  }
123  }
124 
126  << "Field " << fieldName << " not found in database"
127  << abort(FatalError);
128 
129  return tmp<Field<Type>>(nullptr);
130 }
131 
132 
133 template<class Type, class ResultType>
135 (
136  const Field<Type>& values,
137  const scalarField& signs,
138  const scalarField& weights,
139  const vectorField& Sf,
140  ResultType& result
141 ) const
142 {
143  return false;
144 }
145 
146 
147 template<class Type>
149 (
150  const Field<Type>& values,
151  const scalarField& signs,
152  const scalarField& weights,
153  const vectorField& Sf,
154  Type& result
155 ) const
156 {
157  return processValuesTypeType(values, signs, weights, Sf, result);
158 }
159 
160 
161 template<class Type>
163 (
164  const Field<Type>& values,
165  const scalarField& signs,
166  const scalarField& weights,
167  const vectorField& Sf,
168  scalar& result
169 ) const
170 {
171  switch (operation_)
172  {
173  case operationType::minMag:
174  {
175  result = gMin(mag(values));
176  return true;
177  }
178  case operationType::maxMag:
179  {
180  result = gMax(mag(values));
181  return true;
182  }
183  default:
184  {
185  return false;
186  }
187  }
188 }
189 
190 
191 template<class Type>
194 (
195  const Field<Type>& values,
196  const scalarField& signs,
197  const scalarField& weights,
198  const vectorField& Sf,
199  Type& result
200 ) const
201 {
202  switch (operation_)
203  {
204  case operationType::sum:
205  {
206  result = gSum(weights*values);
207  return true;
208  }
210  {
211  result = gSum(weights*cmptMag(values));
212  return true;
213  }
214  case operationType::orientedSum:
215  {
216  result = gSum(signs*weights*values);
217  return true;
218  }
220  {
221  result =
222  gSum(weights*values)
223  /stabilise(gSum(weights), vSmall);
224  return true;
225  }
226  case operationType::areaAverage:
227  {
228  const scalarField magSf(mag(Sf));
229  result =
230  gSum(weights*magSf*values)
231  /stabilise(gSum(weights*magSf), vSmall);
232  return true;
233  }
234  case operationType::areaIntegrate:
235  {
236  const scalarField magSf(mag(Sf));
237  result = gSum(weights*magSf*values);
238  return true;
239  }
240  case operationType::min:
241  {
242  result = gMin(values);
243  return true;
244  }
245  case operationType::max:
246  {
247  result = gMax(values);
248  return true;
249  }
250  case operationType::CoV:
251  {
252  const scalarField magSf(mag(Sf));
253 
254  Type meanValue = gSum(values*magSf)/gSum(magSf);
255 
256  const label nComp = pTraits<Type>::nComponents;
257 
258  for (direction d=0; d<nComp; ++d)
259  {
260  scalarField vals(values.component(d));
261  scalar mean = component(meanValue, d);
262  scalar& res = setComponent(result, d);
263 
264  res = sqrt(gSum(magSf*sqr(vals - mean))/gSum(magSf))/mean;
265  }
266 
267  return true;
268  }
269  case operationType::none:
270  {
271  return true;
272  }
273  default:
274  {
275  return false;
276  }
277  }
278 }
279 
280 
281 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
282 
283 template<class Type>
285 (
286  const word& fieldName,
287  const scalarField& signs,
288  const scalarField& weights,
289  const vectorField& Sf
290 )
291 {
292  const bool ok = validField<Type>(fieldName);
293 
294  if (ok)
295  {
296  // Get the values
297  Field<Type> values(getFieldValues<Type>(fieldName));
298 
299  // Write raw values on surface if specified
300  if (writeFields_)
301  {
302  faceList faces;
304 
305  if (selectionType_ == selectionTypes::sampledSurface)
306  {
307  combineSurfaceGeometry(faces, points);
308  }
309  else
310  {
311  combineMeshGeometry(faces, points);
312  }
313 
314  Field<Type> writeValues(weights*values);
315  combineFields(writeValues);
316 
317  if (Pstream::master())
318  {
319  surfaceWriterPtr_->write
320  (
321  outputDir(),
322  fieldName
323  + '_' + selectionTypeNames[selectionType_]
324  + '_' + selectionName_,
325  points,
326  faces,
327  false,
328  fieldName,
329  writeValues
330  );
331  }
332  }
333 
334  // Do the operation
335  if (operation_ != operationType::none)
336  {
337  // Apply scale factor
338  values *= scaleFactor_;
339 
340  bool ok = false;
341 
342  #define writeValuesFieldType(fieldType, none) \
343  ok = \
344  ok \
345  || writeValues<Type, fieldType> \
346  ( \
347  fieldName, \
348  values, \
349  signs, \
350  weights, \
351  Sf \
352  );
354  #undef writeValuesFieldType
355 
356  if (!ok)
357  {
359  << "Operation " << operationTypeNames_[operation_]
360  << " not available for values of type "
362  << exit(FatalError);
363  }
364  }
365  }
366 
367  return ok;
368 }
369 
370 
371 template<class Type, class ResultType>
373 (
374  const word& fieldName,
375  const Field<Type>& values,
376  const scalarField& signs,
377  const scalarField& weights,
378  const vectorField& Sf
379 )
380 {
381  ResultType result;
382 
383  if (processValues(values, signs, weights, Sf, result))
384  {
385  // Add to result dictionary, over-writing any previous entry
386  resultDict_.add(fieldName, result, true);
387 
388  if (Pstream::master())
389  {
390  file() << tab << result;
391 
392  Log << " " << operationTypeNames_[operation_]
393  << "(" << selectionName_ << ") of " << fieldName
394  << " = " << result << endl;
395  }
396 
397  return true;
398  }
399 
400  return false;
401 }
402 
403 
404 template<class Type>
407 (
408  const VolField<Type>& field
409 ) const
410 {
411  tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
412  Field<Type>& values = tvalues.ref();
413 
414  forAll(values, i)
415  {
416  const label facei = faceId_[i];
417  const label patchi = facePatchId_[i];
418 
419  if (patchi >= 0)
420  {
421  values[i] = field.boundaryField()[patchi][facei];
422  }
423  else
424  {
426  << type() << " " << name() << ": "
427  << selectionTypeNames[selectionType_]
428  << "(" << selectionName_ << "):"
429  << nl
430  << " Unable to process internal faces for volume field "
431  << field.name() << nl << abort(FatalError);
432  }
433  }
434 
435  return tvalues;
436 }
437 
438 
439 template<class Type>
442 (
443  const SurfaceField<Type>& field
444 ) const
445 {
446  tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
447  Field<Type>& values = tvalues.ref();
448 
449  forAll(values, i)
450  {
451  const label facei = faceId_[i];
452  const label patchi = facePatchId_[i];
453 
454  if (patchi >= 0)
455  {
456  values[i] = field.boundaryField()[patchi][facei];
457  }
458  else
459  {
460  values[i] = field[facei];
461  }
462  }
463 
464  return tvalues;
465 }
466 
467 
468 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Pre-declare SubField and related Field type.
Definition: Field.H:82
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:455
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
const word & name() const
Return name.
Definition: IOobject.H:310
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
tmp< Field< Type > > getFieldValues(const word &fieldName) const
Return field values by looking up field name.
bool writeValues(const word &fieldName, const scalarField &signs, const scalarField &weights, const vectorField &Sf)
Templated helper function to output field values.
bool processValuesTypeType(const Field< Type > &values, const scalarField &signs, const scalarField &weights, const vectorField &Sf, Type &result) const
Apply a Type -> Type operation to the values.
bool validField(const word &fieldName) const
Return true if the field name is valid.
bool processValues(const Field< Type > &values, const scalarField &signs, const scalarField &weights, const vectorField &Sf, ResultType &result) const
Apply the operation to the values, and return true if successful.
tmp< Field< Type > > filterField(const SurfaceField< Type > &field) const
Filter a surface field according to faceIds.
const objectRegistry & obr_
Reference to the region objectRegistry.
Given cell centre values and point (vertex) values decompose into tetrahedra and linear interpolate w...
bool foundObject(const word &name) const
Is the named Type in registry.
Traits class for primitives.
Definition: pTraits.H:53
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:181
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
label patchi
const pointField & points
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define Log
Report write to Foam::Info if the local log switch is true.
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
tmp< VolField< Type > > average(const SurfaceField< Type > &ssf)
Area-weighted average a surfaceField creating a volField.
Definition: fvcAverage.C:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
Type gSum(const FieldField< Field, Type > &f)
tmp< DimensionedField< scalar, GeoMesh > > stabilise(const DimensionedField< scalar, GeoMesh > &dsf, const dimensioned< scalar > &ds)
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
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
label & setComponent(label &l, const direction)
Definition: label.H:86
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
static const char tab
Definition: Ostream.H:259
errorManip< error > abort(error &err)
Definition: errorManip.H:131
FOR_ALL_FIELD_TYPES(DefineContiguousFvWallLocationDataType)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
dimensionSet cmptMag(const dimensionSet &)
Definition: dimensionSet.C:275
error FatalError
Type gMin(const FieldField< Field, Type > &f)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static const char nl
Definition: Ostream.H:260
Type gMax(const FieldField< Field, Type > &f)
uint8_t direction
Definition: direction.H:45
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
dimensioned< scalar > sumMag(const DimensionedField< Type, GeoMesh > &df)
labelList f(nPoints)
#define writeValuesFieldType(fieldType, none)
Foam::surfaceFields.