patchCutLayerAverage.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) 2022-2026 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 "patchCutLayerAverage.H"
27 #include "OSspecific.H"
28 #include "patchCutPlot.H"
29 #include "volPointInterpolation.H"
30 #include "writeFile.H"
31 #include "polyTopoChangeMap.H"
32 #include "polyMeshMap.H"
33 #include "polyDistributionMap.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace functionObjects
41 {
44  (
48  );
49 }
50 }
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 Foam::fileName Foam::functionObjects::patchCutLayerAverage::outputPath() const
56 {
57  return
60  /(mesh_.name() != polyMesh::defaultRegion ? mesh_.name() : word())
61  /name()
62  /time_.name();
63 }
64 
65 
66 void Foam::functionObjects::patchCutLayerAverage::calcWeights()
67 {
68  const polyPatch& pp = mesh_.poly().boundary()[patchName_];
69  const pointField& points = pp.localPoints();
70 
71  // Calculate or lookup the point coordinates
72  tmp<scalarField> tpointXs =
73  distanceName_ == word::null
74  ? points & direction_
75  : (
76  mesh_.foundObject<volScalarField>(distanceName_)
78  (
79  mesh_.lookupObject<volScalarField>(distanceName_)
80  )
81  : tmp<pointScalarField>
82  (
83  mesh_.lookupObject<pointScalarField>(distanceName_)
84  )
85  )().boundaryField()[pp.index()].patchInternalField();
86  const scalarField& pointXs = tpointXs();
87 
88  // Calculate the cut coordinates and the weights
89  const scalarField cutXs
90  (
92  (
93  pp,
94  pointXs,
95  interpolate_,
96  interpolate_ ? nLayers_ : nLayers_ + 1,
97  nOptimiseIter_,
98  debug,
99  name(),
100  mesh(),
101  formatter_()
102  )
103  );
104  weights_.reset
105  (
107  (
109  (
110  pp,
111  pointXs,
112  cutXs,
113  interpolate_
114  )
115  )
116  );
117 
118  // Calculate layer coordinates and widths
119  if (interpolate_)
120  {
121  layerDistances_.reset(new scalarField(cutXs));
122  }
123  else
124  {
125  const SubField<scalar> distance0s(cutXs, nLayers_);
126  const SubField<scalar> distance1s(cutXs, nLayers_, 1);
127  layerDistances_.reset(((distance0s + distance1s)/2).ptr());
128  layerThicknesses_.reset((distance1s - distance0s).ptr());
129  }
130 
131  // Calculate the layer positions
132  layerPositions_.reset
133  (
135  (
136  nLayers_,
137  weights_,
138  pointField(pp.faceCentres())
139  ).ptr()
140  );
141 
142  // Write the layers as a tensor field for debugging
143  if (debug)
144  {
146  (
147  pp,
149  (
150  pp,
151  pointXs,
152  cutXs,
153  interpolate_,
154  false
155  ),
156  name(),
157  mesh()
158  );
159  }
160 }
161 
162 
163 void Foam::functionObjects::patchCutLayerAverage::clear()
164 {
165  weights_.clear();
166  layerDistances_.clear();
167  layerThicknesses_.clear();
168  layerPositions_.clear();
169 }
170 
171 
172 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
173 
175 (
176  const word& name,
177  const Time& runTime,
178  const dictionary& dict
179 )
180 :
181  fvMeshFunctionObject(name, runTime, dict)
182 {
183  read(dict);
184 }
185 
186 
187 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
188 
190 {}
191 
192 
193 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
194 
196 {
197  patchName_ = dict.lookup<word>("patch");
198 
199  const bool haveDirection = dict.found("direction");
200  const bool haveDistance = dict.found("distance");
201  if (haveDirection == haveDistance)
202  {
204  << "keywords direction and distance both "
205  << (haveDirection ? "" : "un") << "defined in "
206  << "dictionary " << dict.name()
207  << exit(FatalIOError);
208  }
209  else if (haveDirection)
210  {
211  direction_ = normalised(dict.lookup<vector>("direction"));
212  distanceName_ = word::null;
213  }
214  else if (haveDistance)
215  {
216  direction_ = vector::nan;
217  distanceName_ = dict.lookup<word>("distance");
218  }
219 
220  nLayers_ = dict.lookup<label>("nPoints");
221 
222  interpolate_ = dict.lookupOrDefault<bool>("interpolate", false);
223 
224  fields_ = dict.lookup<wordList>("fields");
225 
226  axis_ =
228  [
229  dict.lookupOrDefault<word>
230  (
231  "axis",
233  )
234  ];
235 
236  formatter_ = setWriter::New(dict.lookup("setFormat"), dict);
237 
238  nOptimiseIter_ = dict.lookupOrDefault("nOptimiseIter", 2);
239 
240  clear();
241 
242  return true;
243 }
244 
245 
247 {
248  wordList result(fields_);
249 
250  if (distanceName_ != word::null)
251  {
252  result.append(distanceName_);
253  }
254 
255  return result;
256 }
257 
258 
260 {
261  return true;
262 }
263 
264 
266 {
267  if (!weights_.valid())
268  {
269  calcWeights();
270  }
271 
272  const polyPatch& pp = mesh_.poly().boundary()[patchName_];
273 
274  const bool writeThickness =
275  !interpolate_
276  && (
278  || axis_ == coordSet::axisType::DISTANCE
279  );
280 
281  // Create list of field names
283  if (writeThickness)
284  {
285  fieldNames.append("thickness");
286  }
287  forAll(fields_, fieldi)
288  {
289  if
290  (
291  false
292  #define FoundTypeField(Type, nullArg) \
293  || foundObject<VolField<Type>>(fields_[fieldi])
295  #undef FoundTypeField
296  )
297  {
298  fieldNames.append(fields_[fieldi]);
299  }
300  else
301  {
302  cannotFindObject(fields_[fieldi]);
303  }
304  }
305 
306  // Calculate the field values
307  #define DeclareTypeFieldValues(Type, nullArg) \
308  PtrList<Field<Type>> Type##FieldValues(fieldNames.size());
310  #undef DeclareTypeFieldValues
311  if (writeThickness)
312  {
313  scalarFieldValues.set(0, new scalarField(layerThicknesses_));
314  }
315  for (label fieldi = writeThickness; fieldi < fieldNames.size(); ++ fieldi)
316  {
317  #define CollapseTypeFields(Type, nullArg) \
318  if (mesh_.foundObject<VolField<Type>>(fieldNames[fieldi])) \
319  { \
320  const VolField<Type>& field = \
321  mesh_.lookupObject<VolField<Type>>(fieldNames[fieldi]); \
322  \
323  Type##FieldValues.set \
324  ( \
325  fieldi, \
326  cutPlot::applyWeights \
327  ( \
328  nLayers_, \
329  weights_, \
330  field.boundaryField()[pp.index()] \
331  ) \
332  ); \
333  }
335  #undef CollapseTypeFields
336  }
337 
338  // Write
339  if (Pstream::master() && layerPositions_->size())
340  {
341  mkDir(outputPath());
342 
343  formatter_->write
344  (
345  outputPath(),
346  typeName,
347  coordSet
348  (
349  identityMap(layerPositions_->size()),
350  word::null,
351  layerPositions_,
353  layerDistances_,
355  ),
356  fieldNames
357  #define TypeFieldValuesParameter(Type, nullArg) , Type##FieldValues
360  );
361  }
362 
363  return true;
364 }
365 
366 
368 (
369  const polyMesh& mesh
370 )
371 {
372  if (&mesh == &mesh_)
373  {
374  clear();
375  }
376 }
377 
378 
380 (
381  const polyTopoChangeMap& map
382 )
383 {
384  if (&map.mesh() == &mesh_)
385  {
386  clear();
387  }
388 }
389 
390 
392 (
393  const polyMeshMap& map
394 )
395 {
396  if (&map.mesh() == &mesh_)
397  {
398  clear();
399  }
400 }
401 
402 
404 (
405  const polyDistributionMap& map
406 )
407 {
408  if (&map.mesh() == &mesh_)
409  {
410  clear();
411  }
412 }
413 
414 
415 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
static volPointInterpolation & New(const word &name, const fvMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
Generic GeometricField class.
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
fileName globalPath() const
Return the global path.
Definition: TimePaths.H:132
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static const Form nan
Definition: VectorSpace.H:124
Holds list of sampling positions.
Definition: coordSet.H:51
static const NamedEnum< axisType, 6 > axisTypeNames_
String representation of axis enums.
Definition: coordSet.H:69
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
const word & name() const
Return const reference to name.
A class for handling file names.
Definition: fileName.H:82
Abstract base-class for Time/database functionObjects.
const Time & time_
Reference to time.
const word & name() const
Return the name of this functionObject.
Specialisation of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
const fvMesh & mesh_
Reference to the fvMesh.
This function object writes graphs of patch face values, area-averaged in planes perpendicular to a g...
patchCutLayerAverage(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
virtual wordList fields() const
Return the list of fields required.
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
virtual void movePoints(const polyMesh &)
Update for mesh point-motion.
virtual bool execute()
Execute, currently does nothing.
virtual bool write()
Write the patchCutLayerAverage.
virtual bool read(const dictionary &)
Read the patchCutLayerAverage data.
static const word outputPrefix
Directory prefix.
Definition: writeFile.H:72
const word & name() const
Return reference to name.
Definition: fvMesh.H:447
Motion of the mesh specified as a list of pointMeshMovers.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
const polyMesh & mesh() const
Return polyMesh.
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
const polyMesh & mesh() const
Return polyMesh.
Definition: polyMeshMap.H:75
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:260
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:71
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
const polyMesh & mesh() const
Return polyMesh.
static autoPtr< setWriter > New(const word &writeType, const IOstream::streamFormat writeFormat=IOstream::ASCII, const IOstream::compressionType writeCompression=IOstream::UNCOMPRESSED)
Select given write options.
Definition: setWriter.C:286
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
tmp< PointField< Type > > interpolate(const VolField< Type > &) const
Interpolate volField using inverse distance weighting.
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
static List< word > fieldNames
Definition: globalFoam.H:46
const pointField & points
tUEqn clear()
List< weight > calcWeights(const polyMesh &mesh, const generatedCellZone &zone, const scalarField &pointXs, const scalarField &cellMinXs, const scalarField &cellMaxXs, const labelList &cellMinOrder, const scalarField &cutXs, const bool interpolate, const bool normalise)
Definition: cellCutPlot.C:848
tmp< Field< Type > > applyWeights(const label n, const List< cutPlot::weight > &weights, const Field< Type > &cellValues)
Construct plot values from cell values given a set of weights.
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
addToRunTimeSelectionTable(functionObject, fvModel, dictionary)
void writeLayers(const SubList< face > &faces, const List< patchCutPlot::weight > &weights, const word &functionName, const fvMesh &functionMesh)
Write the layers as components of a tensor field for debugging.
Definition: patchCutPlot.C:675
List< weight > calcWeights(const faceList &faces, const UList< vector > &faceAreas, const UList< vector > &faceNormals, const pointField &points, const scalarField &pointXs, const scalarField &faceMinXs, const scalarField &faceMaxXs, const labelList &faceMinOrder, const scalarField &cutXs, const bool interpolate, const bool normalise)
Definition: patchCutPlot.C:397
tmp< scalarField > calcCutXs(const faceList &faces, const Field< vector > &faceAreas, const Field< vector > &faceNormals, const pointField &points, const scalarField &pointXs, const bool interpolate, const label nCuts, const label nIter, const bool debug=false, const word &functionName=word::null, const polyMesh &functionMesh=NullObjectRef< polyMesh >(), const setWriter &functionFormatter=NullObjectRef< setWriter >())
Compute and return evenly-spaced cut coordinates.
Definition: patchCutPlot.C:488
Namespace for OpenFOAM.
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
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
FOR_ALL_FIELD_TYPES(makeDimensionedPointFieldFunctions)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
PointField< scalar > pointScalarField
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
dimensionSet normalised(const dimensionSet &)
Definition: dimensionSet.C:509
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
#define TypeFieldValuesParameter(Type, nullArg)
#define FoundTypeField(Type, nullArg)
#define DeclareTypeFieldValues(Type, nullArg)
#define CollapseTypeFields(Type, nullArg)
dictionary dict