surfaceFieldValueTemplates.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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "surfaceFieldValue.H"
30 #include "surfaceFields.H"
31 #include "polySurfaceFields.H"
32 #include "volFields.H"
33 #include "sampledSurface.H"
34 #include "surfaceWriter.H"
35 #include "interpolationCell.H"
36 #include "interpolationCellPoint.H"
37 
38 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
39 
40 template<class WeightType>
42 (
43  const Field<WeightType>& weightField
44 ) const
45 {
46  return
47  (
48  usesWeight()
49  && returnReduce(!weightField.empty(), orOp<bool>()) // On some processor
50  );
51 }
52 
53 
54 template<class Type>
56 (
57  const word& fieldName
58 ) const
59 {
63 
64  return
65  (
66  foundObject<smt>(fieldName)
67  || foundObject<vf>(fieldName)
68  || (withSurfaceFields() && foundObject<sf>(fieldName))
69  );
70 }
71 
72 
73 template<class Type>
76 (
77  const word& fieldName,
78  const bool mandatory
79 ) const
80 {
84 
85  if (foundObject<smt>(fieldName))
86  {
87  return lookupObject<smt>(fieldName);
88  }
89  else if (withSurfaceFields() && foundObject<sf>(fieldName))
90  {
91  return filterField(lookupObject<sf>(fieldName));
92  }
93  else if (foundObject<vf>(fieldName))
94  {
95  const vf& fld = lookupObject<vf>(fieldName);
96 
97  if (sampledPtr_)
98  {
99  if (sampledPtr_->interpolate())
100  {
101  const interpolationCellPoint<Type> interp(fld);
102 
103  return sampledPtr_->interpolate(interp);
104  }
105  else
106  {
107  const interpolationCell<Type> interp(fld);
108 
109  return sampledPtr_->sample(interp);
110  }
111  }
112  else
113  {
114  return filterField(fld);
115  }
116  }
117 
118  if (mandatory)
119  {
121  << "Field " << fieldName << " not found in database" << nl
122  << abort(FatalError);
123  }
124 
125  return tmp<Field<Type>>::New();
126 }
127 
128 
129 template<class Type, class WeightType>
132 (
133  const Field<Type>& values,
134  const vectorField& Sf,
135  const Field<WeightType>& weightField
136 ) const
137 {
138  Type result = Zero;
139  switch (operation_)
140  {
141  case opNone:
142  {
143  break;
144  }
145  case opMin:
146  {
147  result = gMin(values);
148  break;
149  }
150  case opMax:
151  {
152  result = gMax(values);
153  break;
154  }
155  case opSumMag:
156  {
157  result = gSum(cmptMag(values));
158  break;
159  }
160  case opSum:
161  case opWeightedSum:
162  case opAbsWeightedSum:
163  {
164  if (canWeight(weightField))
165  {
166  tmp<scalarField> weight(weightingFactor(weightField));
167  result = gSum(weight*values);
168  }
169  else
170  {
171  // Unweighted form
172  result = gSum(values);
173  }
174  break;
175  }
176  case opSumDirection:
177  case opSumDirectionBalance:
178  {
180  << "Operation " << operationTypeNames_[operation_]
181  << " not available for values of type "
183  << exit(FatalError);
184 
185  break;
186  }
187  case opAverage:
188  case opWeightedAverage:
189  case opAbsWeightedAverage:
190  {
191  if (canWeight(weightField))
192  {
193  const scalarField factor(weightingFactor(weightField));
194 
195  result = gSum(factor*values)/(gSum(factor) + ROOTVSMALL);
196  }
197  else
198  {
199  // Unweighted form
200  const label n = returnReduce(values.size(), sumOp<label>());
201  result = gSum(values)/(scalar(n) + ROOTVSMALL);
202  }
203  break;
204  }
205  case opAreaAverage:
206  case opWeightedAreaAverage:
207  case opAbsWeightedAreaAverage:
208  {
209  if (canWeight(weightField))
210  {
211  const scalarField factor(weightingFactor(weightField, Sf));
212 
213  result = gSum(factor*values)/gSum(factor + ROOTVSMALL);
214  }
215  else
216  {
217  // Unweighted form
218  const scalarField factor(mag(Sf));
219  result = gSum(factor*values)/gSum(factor);
220  }
221  break;
222  }
223  case opAreaIntegrate:
224  case opWeightedAreaIntegrate:
225  case opAbsWeightedAreaIntegrate:
226  {
227  if (canWeight(weightField))
228  {
229  tmp<scalarField> factor(weightingFactor(weightField, Sf));
230  result = gSum(factor*values);
231  }
232  else
233  {
234  // Unweighted form
235  tmp<scalarField> factor(mag(Sf));
236  result = gSum(factor*values);
237  }
238  break;
239  }
240  case opCoV:
241  {
242  const scalarField magSf(mag(Sf));
243  const scalar gSumMagSf = gSum(magSf);
244 
245  Type meanValue = gSum(values*magSf)/gSumMagSf;
246 
247  for (direction d=0; d < pTraits<Type>::nComponents; ++d)
248  {
249  tmp<scalarField> vals(values.component(d));
250  const scalar mean = component(meanValue, d);
251  scalar& res = setComponent(result, d);
252 
253  res =
254  sqrt(gSum(magSf*sqr(vals - mean))/gSumMagSf)
255  /(mean + ROOTVSMALL);
256  }
257 
258  break;
259  }
260 
261  case opAreaNormalAverage:
262  case opAreaNormalIntegrate:
263  case opUniformity:
264  {
265  // Handled in specializations only
266  break;
267  }
268 
269  case opWeightedUniformity:
270  case opAbsWeightedUniformity:
271  {
272  if (canWeight(weightField))
273  {
274  // Change weighting from vector -> scalar and dispatch again
275  return processValues<Type, scalar>
276  (
277  values,
278  Sf,
279  weightingFactor(weightField)
280  );
281  }
282 
283  break;
284  }
285  }
286 
287  return result;
288 }
289 
290 
291 template<class Type, class WeightType>
293 (
294  const Field<Type>& values,
295  const vectorField& Sf,
296  const Field<WeightType>& weightField
297 ) const
298 {
299  return processSameTypeValues(values, Sf, weightField);
300 }
301 
302 
303 template<class WeightType>
306 (
307  const Field<WeightType>& weightField
308 ) const
309 {
310  // The scalar form is specialized.
311  // For other types always need mag() to generate a scalar field.
312  return mag(weightField);
313 }
314 
315 
316 template<class WeightType>
318 (
319  const vectorField& Sf,
320  const Field<WeightType>& weightField,
321  const pointField& points,
322  const faceList& faces
323 )
324 {
325  label nProcessed = 0;
326 
327  for (const word& fieldName : fields_)
328  {
329  if
330  (
331  writeValues<scalar>(fieldName, Sf, weightField, points, faces)
332  || writeValues<vector>(fieldName, Sf, weightField, points, faces)
333  || writeValues<sphericalTensor>
334  (
335  fieldName, Sf, weightField, points, faces
336  )
337  || writeValues<symmTensor>(fieldName, Sf, weightField, points, faces)
338  || writeValues<tensor>(fieldName, Sf, weightField, points, faces)
339  )
340  {
341  ++nProcessed;
342  }
343  else
344  {
346  << "Requested field " << fieldName
347  << " not found in database and not processed"
348  << endl;
349  }
350  }
351 
352  return nProcessed;
353 }
354 
355 
356 template<class Type, class WeightType>
358 (
359  const word& fieldName,
360  const vectorField& Sf,
361  const Field<WeightType>& weightField,
362  const pointField& points,
363  const faceList& faces
364 )
365 {
366  const bool ok = validField<Type>(fieldName);
367 
368  if (ok)
369  {
370  Field<Type> values(getFieldValues<Type>(fieldName, true));
371 
372  // Write raw values on surface if specified
373  if (surfaceWriterPtr_ && surfaceWriterPtr_->enabled())
374  {
375  Field<Type> allValues(values);
376  combineFields(allValues);
377 
378  if (Pstream::master())
379  {
380  surfaceWriterPtr_->open
381  (
382  points,
383  faces,
384  (
385  outputDir()
386  / regionTypeNames_[regionType_] + ("_" + regionName_)
387  ),
388  false // serial - already merged
389  );
390 
391  surfaceWriterPtr_->write(fieldName, allValues);
392 
393  surfaceWriterPtr_->clear();
394  }
395  }
396 
397  if (operation_ != opNone)
398  {
399  // Apply scale factor
400  values *= scaleFactor_;
401 
402  Type result = processValues(values, Sf, weightField);
403 
404  switch (postOperation_)
405  {
406  case postOpSqrt:
407  {
408  // sqrt: component-wise - does not change the type
409  for (direction d=0; d < pTraits<Type>::nComponents; ++d)
410  {
411  setComponent(result, d)
412  = sqrt(mag(component(result, d)));
413  }
414  break;
415  }
416  default:
417  {
418  break;
419  }
420  }
421 
422  // Write state/results information
423  word prefix, suffix;
424  {
425  if (postOperation_ != postOpNone)
426  {
427  // Adjust result name to include post-operation
428  prefix += postOperationTypeNames_[postOperation_];
429  prefix += '(';
430  suffix += ')';
431  }
432 
433  prefix += operationTypeNames_[operation_];
434  prefix += '(';
435  suffix += ')';
436  }
437 
438  word resultName = prefix + regionName_ + ',' + fieldName + suffix;
439 
440  // Write state/results information
441 
442  Log << " " << prefix << regionName_ << suffix
443  << " of " << fieldName << " = ";
444 
445 
446  // Operation or post-operation returns scalar?
447 
448  scalar sresult{0};
449 
450  bool alwaysScalar(operation_ & typeScalar);
451 
452  if (alwaysScalar)
453  {
454  sresult = component(result, 0);
455 
456  if (postOperation_ == postOpMag)
457  {
458  sresult = mag(sresult);
459  }
460  }
461  else if (postOperation_ == postOpMag)
462  {
463  sresult = mag(result);
464  alwaysScalar = true;
465  }
466 
467 
468  if (alwaysScalar)
469  {
470  file()<< tab << sresult;
471 
472  Log << sresult << endl;
473 
474  this->setResult(resultName, sresult);
475  }
476  else
477  {
478  file()<< tab << result;
479 
480  Log << result << endl;
481 
482  this->setResult(resultName, result);
483  }
484  }
485  }
486 
487  return ok;
488 }
489 
490 
491 template<class Type>
494 (
496 ) const
497 {
498  const labelList& own = field.mesh().faceOwner();
499  const labelList& nei = field.mesh().faceNeighbour();
500 
501  auto tvalues = tmp<Field<Type>>::New(faceId_.size());
502  auto& values = tvalues.ref();
503 
504  forAll(values, i)
505  {
506  const label facei = faceId_[i];
507  const label patchi = facePatchId_[i];
508 
509  if (patchi >= 0)
510  {
511  // Boundary face - face id is the patch-local face id
512  values[i] = field.boundaryField()[patchi][facei];
513  }
514  else
515  {
516  // Internal face
517  values[i] = 0.5*(field[own[facei]] + field[nei[facei]]);
518  }
519  }
520 
521  // No need to flip values - all boundary faces point outwards
522 
523  return tvalues;
524 }
525 
526 
527 template<class Type>
530 (
532 ) const
533 {
534  auto tvalues = tmp<Field<Type>>::New(faceId_.size());
535  auto& values = tvalues.ref();
536 
537  forAll(values, i)
538  {
539  const label facei = faceId_[i];
540  const label patchi = facePatchId_[i];
541 
542  if (patchi >= 0)
543  {
544  values[i] = field.boundaryField()[patchi][facei];
545  }
546  else
547  {
548  values[i] = field[facei];
549  }
550  }
551 
552  if (debug)
553  {
554  Pout<< "field " << field.name() << " oriented: "
555  << field.oriented()() << endl;
556  }
557 
558  if (field.oriented()())
559  {
560  forAll(values, i)
561  {
562  if (faceFlip_[i])
563  {
564  values[i] *= -1;
565  }
566  }
567  }
568 
569  return tvalues;
570 }
571 
572 
573 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
volFields.H
Foam::setComponent
label & setComponent(label &l, const direction)
Definition: label.H:123
Log
#define Log
Definition: PDRblock.C:35
Foam::component
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
Definition: FieldFieldFunctions.C:44
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::HashTableOps::values
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:149
polySurfaceFields.H
Fields for polySurface.
interpolationCell.H
Foam::functionObjects::fieldValues::surfaceFieldValue::processSameTypeValues
Type processSameTypeValues(const Field< Type > &values, const vectorField &Sf, const Field< WeightType > &weightField) const
Apply the 'operation' to the values. Operation must preserve Type.
Definition: surfaceFieldValueTemplates.C:132
Foam::functionObjects::fieldValues::surfaceFieldValue::canWeight
bool canWeight(const Field< WeightType > &weightField) const
True if operation variant uses a weight-field that is available.
Definition: surfaceFieldValueTemplates.C:42
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
surfaceFields.H
Foam::surfaceFields.
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
surfaceWriter.H
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
tmp< Field< Type > > filterField(const GeometricField< Type, fvsPatchField, surfaceMesh > &field) const
Filter a surface field according to faceIds.
Foam::functionObjects::fieldValues::surfaceFieldValue::writeAll
label writeAll(const vectorField &Sf, const Field< WeightType > &weightField, const pointField &points, const faceList &faces)
Templated helper function to output field values.
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
interpolationCellPoint.H
Foam::interpolationCell
Uses the cell value for any point in the cell.
Definition: interpolationCell.H:50
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
tmp< scalarField > weightingFactor(const Field< WeightType > &weightField) const
Weighting factor.
Foam::cmptMag
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:400
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::interpolationCellPoint
Given cell centre values and point (vertex) values decompose into tetrahedra and linear interpolate w...
Definition: interpolationCellPoint.H:50
sampledSurface.H
Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
tmp< Field< Type > > getFieldValues(const word &fieldName, const bool mandatory=false) const
Return field values by looking up field name.
field
rDeltaTY field()
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::FatalError
error FatalError
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
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
Foam::functionObjects::fieldValues::surfaceFieldValue::validField
bool validField(const word &fieldName) const
Return true if the field name is known and a valid type.
Definition: surfaceFieldValueTemplates.C:56
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::tab
constexpr char tab
Definition: Ostream.H:384
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::List< face >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::pTraits
Traits class for primitives.
Definition: pTraits.H:54
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::direction
uint8_t direction
Definition: direction.H:52
surfaceFieldValue.H
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::GeometricField
Generic GeometricField class.
Definition: areaFieldsFwd.H:53
Foam::orOp
Definition: ops.H:234
Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
bool writeValues(const word &fieldName, const vectorField &Sf, const Field< WeightType > &weightField, const pointField &points, const faceList &faces)
Templated helper function to output field values.
Definition: surfaceFieldValueTemplates.C:358
Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
Type processValues(const Field< Type > &values, const vectorField &Sf, const Field< WeightType > &weightField) const
Apply the 'operation' to the values. Wrapper around.
Definition: surfaceFieldValueTemplates.C:293
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54