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-2018 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 bool mustGet,
67  const bool applyOrientation
68 ) const
69 {
72 
73  if
74  (
75  regionType_ != regionTypes::sampledSurface
76  && obr_.foundObject<sf>(fieldName)
77  )
78  {
79  return filterField(obr_.lookupObject<sf>(fieldName), applyOrientation);
80  }
81  else if (obr_.foundObject<vf>(fieldName))
82  {
83  const vf& fld = obr_.lookupObject<vf>(fieldName);
84 
85  if (surfacePtr_.valid())
86  {
87  if (surfacePtr_().interpolate())
88  {
89  const interpolationCellPoint<Type> interp(fld);
90  tmp<Field<Type>> tintFld(surfacePtr_().interpolate(interp));
91  const Field<Type>& intFld = tintFld();
92 
93  // Average
94  const faceList& faces = surfacePtr_().faces();
95  tmp<Field<Type>> tavg
96  (
97  new Field<Type>(faces.size(), Zero)
98  );
99  Field<Type>& avg = tavg.ref();
100 
101  forAll(faces, facei)
102  {
103  const face& f = faces[facei];
104  forAll(f, fp)
105  {
106  avg[facei] += intFld[f[fp]];
107  }
108  avg[facei] /= f.size();
109  }
110 
111  return tavg;
112  }
113  else
114  {
115  return surfacePtr_().sample(fld);
116  }
117  }
118  else
119  {
120  return filterField(fld, applyOrientation);
121  }
122  }
123 
124  if (mustGet)
125  {
127  << "Field " << fieldName << " not found in database"
128  << abort(FatalError);
129  }
130 
131  return tmp<Field<Type>>(new Field<Type>(0));
132 }
133 
134 
135 template<class Type>
138 (
139  const Field<Type>& values,
140  const vectorField& Sf,
141  const scalarField& weightField
142 ) const
143 {
144  Type result = Zero;
145  switch (operation_)
146  {
147  case operationType::sum:
148  {
149  result = sum(values);
150  break;
151  }
152  case operationType::weightedSum:
153  {
154  if (weightField.size())
155  {
156  result = sum(weightField*values);
157  }
158  else
159  {
160  result = sum(values);
161  }
162  break;
163  }
165  {
166  result = sum(cmptMag(values));
167  break;
168  }
169  case operationType::sumDirection:
170  {
172  << "Operation " << operationTypeNames_[operation_]
173  << " not available for values of type "
175  << exit(FatalError);
176 
177  result = Zero;
178  break;
179  }
180  case operationType::sumDirectionBalance:
181  {
183  << "Operation " << operationTypeNames_[operation_]
184  << " not available for values of type "
186  << exit(FatalError);
187 
188  result = Zero;
189  break;
190  }
192  {
193  result = sum(values)/values.size();
194  break;
195  }
196  case operationType::weightedAverage:
197  {
198  if (weightField.size())
199  {
200  result = sum(weightField*values)/sum(weightField);
201  }
202  else
203  {
204  result = sum(values)/values.size();
205  }
206  break;
207  }
208  case operationType::areaAverage:
209  {
210  const scalarField magSf(mag(Sf));
211 
212  result = sum(magSf*values)/sum(magSf);
213  break;
214  }
215  case operationType::weightedAreaAverage:
216  {
217  const scalarField magSf(mag(Sf));
218 
219  if (weightField.size())
220  {
221  result = sum(weightField*magSf*values)/sum(magSf*weightField);
222  }
223  else
224  {
225  result = sum(magSf*values)/sum(magSf);
226  }
227  break;
228  }
229  case operationType::areaIntegrate:
230  {
231  const scalarField magSf(mag(Sf));
232 
233  result = sum(magSf*values);
234  break;
235  }
236  case operationType::weightedAreaIntegrate:
237  {
238  const scalarField magSf(mag(Sf));
239 
240  if (weightField.size())
241  {
242  result = sum(weightField*magSf*values);
243  }
244  else
245  {
246  result = sum(magSf*values);
247  }
248  break;
249  }
250  case operationType::min:
251  {
252  result = min(values);
253  break;
254  }
255  case operationType::max:
256  {
257  result = max(values);
258  break;
259  }
260  case operationType::CoV:
261  {
262  const scalarField magSf(mag(Sf));
263 
264  Type meanValue = sum(values*magSf)/sum(magSf);
265 
266  const label nComp = pTraits<Type>::nComponents;
267 
268  for (direction d=0; d<nComp; ++d)
269  {
270  scalarField vals(values.component(d));
271  scalar mean = component(meanValue, d);
272  scalar& res = setComponent(result, d);
273 
274  res = sqrt(sum(magSf*sqr(vals - mean))/sum(magSf))/mean;
275  }
276 
277  break;
278  }
279  case operationType::areaNormalAverage:
280  {}
281  case operationType::areaNormalIntegrate:
282  {}
283  case operationType::none:
284  {}
285  }
286 
287  return result;
288 }
289 
290 
291 template<class Type>
293 (
294  const Field<Type>& values,
295  const vectorField& Sf,
296  const scalarField& weightField
297 ) const
298 {
299  return processSameTypeValues(values, Sf, weightField);
300 }
301 
302 
303 
304 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
305 
306 template<class Type>
308 (
309  const word& fieldName,
310  const scalarField& weightField,
311  const bool orient
312 )
313 {
314  const bool ok = validField<Type>(fieldName);
315 
316  if (ok)
317  {
318  Field<Type> values(getFieldValues<Type>(fieldName, true, orient));
319 
320  vectorField Sf;
321  if (surfacePtr_.valid())
322  {
323  // Get oriented Sf
324  Sf = surfacePtr_().Sf();
325  }
326  else
327  {
328  // Get oriented Sf
329  Sf = filterField(mesh_.Sf(), true);
330  }
331 
332  // Combine onto master
333  combineFields(values);
334  combineFields(Sf);
335 
336  // Write raw values on surface if specified
337  if (surfaceWriterPtr_.valid())
338  {
339  faceList faces;
341 
342  if (surfacePtr_.valid())
343  {
344  combineSurfaceGeometry(faces, points);
345  }
346  else
347  {
348  combineMeshGeometry(faces, points);
349  }
350 
351  if (Pstream::master())
352  {
353  surfaceWriterPtr_->write
354  (
355  outputDir(),
356  regionTypeNames_[regionType_] + ("_" + regionName_),
357  points,
358  faces,
359  fieldName,
360  values,
361  false
362  );
363  }
364  }
365 
366  if (operation_ != operationType::none)
367  {
368  // Apply scale factor
369  values *= scaleFactor_;
370 
371  if (Pstream::master())
372  {
373  Type result = processValues(values, Sf, weightField);
374 
375  // Add to result dictionary, over-writing any previous entry
376  resultDict_.add(fieldName, result, true);
377 
378  file() << tab << result;
379 
380  Log << " " << operationTypeNames_[operation_]
381  << "(" << regionName_ << ") of " << fieldName
382  << " = " << result << endl;
383  }
384  }
385  }
386 
387  return ok;
388 }
389 
390 
391 template<class Type>
394 (
396  const bool applyOrientation
397 ) const
398 {
399  tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
400  Field<Type>& values = tvalues.ref();
401 
402  forAll(values, i)
403  {
404  label facei = faceId_[i];
405  label patchi = facePatchId_[i];
406  if (patchi >= 0)
407  {
408  values[i] = field.boundaryField()[patchi][facei];
409  }
410  else
411  {
413  << type() << " " << name() << ": "
414  << regionTypeNames_[regionType_] << "(" << regionName_ << "):"
415  << nl
416  << " Unable to process internal faces for volume field "
417  << field.name() << nl << abort(FatalError);
418  }
419  }
420 
421  if (applyOrientation)
422  {
423  forAll(values, i)
424  {
425  values[i] *= faceSign_[i];
426  }
427  }
428 
429  return tvalues;
430 }
431 
432 
433 template<class Type>
436 (
438  const bool applyOrientation
439 ) const
440 {
441  tmp<Field<Type>> tvalues(new Field<Type>(faceId_.size()));
442  Field<Type>& values = tvalues.ref();
443 
444  forAll(values, i)
445  {
446  label facei = faceId_[i];
447  label patchi = facePatchId_[i];
448  if (patchi >= 0)
449  {
450  values[i] = field.boundaryField()[patchi][facei];
451  }
452  else
453  {
454  values[i] = field[facei];
455  }
456  }
457 
458  if (applyOrientation)
459  {
460  forAll(values, i)
461  {
462  values[i] *= faceSign_[i];
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
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 word & name() const
Return name.
Definition: IOobject.H:295
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:264
error FatalError
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
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:174
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:163
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
Traits class for primitives.
Definition: pTraits.H:50
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))
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.
Type processValues(const Field< Type > &values, const vectorField &Sf, const scalarField &weightField) const
Apply the &#39;operation&#39; to the values. Wrapper around.
static const zero Zero
Definition: zero.H:97
tmp< Field< Type > > getFieldValues(const word &fieldName, const bool mustGet=false, const bool applyOrientation=false) 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:460
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
static const char nl
Definition: Ostream.H:265
tmp< Field< Type > > filterField(const GeometricField< Type, fvsPatchField, surfaceMesh > &field, const bool applyOrientation) const
Filter a surface field according to faceIds.
Type processSameTypeValues(const Field< Type > &values, const vectorField &Sf, const scalarField &weightField) const
Apply the &#39;operation&#39; to the values. Operation has to.
labelList f(nPoints)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
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.
label patchi
Given cell centre values and point (vertex) values decompose into tetrahedra and linear interpolate w...
bool writeValues(const word &fieldName, const scalarField &weightField, const bool orient)
Templated helper function to output field values.
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 > &)
mesh Sf()
A class for managing temporary objects.
Definition: PtrList.H:53
label & setComponent(label &l, const direction)
Definition: label.H:79
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)