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