cutLayerAverage.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) 2025-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 "cutLayerAverage.H"
27 #include "OSspecific.H"
28 #include "cellCutPlot.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::cutLayerAverage::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::cutLayerAverage::calcWeights()
67 {
68  const pointField& points = mesh_.points();
69 
70  // Calculate or lookup the point coordinates
71  tmp<pointScalarField> tdistance =
72  distanceName_ == word::null
73  ? tmp<pointScalarField>(nullptr)
74  : mesh_.foundObject<volScalarField>(distanceName_)
75  ? volPointInterpolation::New(mesh_).interpolate
76  (
77  mesh_.lookupObject<volScalarField>(distanceName_)
78  )
79  : tmp<pointScalarField>
80  (
81  mesh_.lookupObject<pointScalarField>(distanceName_)
82  );
83  tmp<scalarField> tpointXs =
84  distanceName_ == word::null
85  ? points & direction_
86  : tmp<scalarField>(tdistance().primitiveField());
87  const scalarField& pointXs = tpointXs();
88 
89  // Calculate the cut coordinates and the weights
90  const scalarField cutXs
91  (
93  (
94  mesh(),
95  zone_,
96  pointXs,
97  interpolate_,
98  interpolate_ ? nLayers_ : nLayers_ + 1,
99  nOptimiseIter_,
100  debug,
101  name(),
102  formatter_()
103  )
104  );
105  weights_.reset
106  (
108  (
110  (
111  mesh(),
112  zone_,
113  pointXs,
114  cutXs,
115  interpolate_
116  )
117  )
118  );
119 
120  // Calculate plot coordinates and widths
121  if (interpolate_)
122  {
123  layerDistances_.reset(new scalarField(cutXs));
124  }
125  else
126  {
127  const SubField<scalar> distance0s(cutXs, nLayers_);
128  const SubField<scalar> distance1s(cutXs, nLayers_, 1);
129  layerDistances_.reset(((distance0s + distance1s)/2).ptr());
130  layerThicknesses_.reset((distance1s - distance0s).ptr());
131  }
132 
133  // Calculate the layer positions
134  layerPositions_.reset
135  (
136  cutPlot::applyWeights<vector>
137  (
138  nLayers_,
139  weights_,
140  mesh().cellCentres()
141  ).ptr()
142  );
143 
144  if (debug)
145  {
147  (
148  mesh(),
150  (
151  mesh(),
152  zone_,
153  pointXs,
154  cutXs,
155  interpolate_,
156  false
157  ),
158  name()
159  );
160  }
161 }
162 
163 
164 void Foam::functionObjects::cutLayerAverage::clear()
165 {
166  weights_.clear();
167  layerDistances_.clear();
168  layerThicknesses_.clear();
169  layerPositions_.clear();
170 }
171 
172 
173 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
174 
176 (
177  const word& name,
178  const Time& runTime,
179  const dictionary& dict
180 )
181 :
182  fvMeshFunctionObject(name, runTime, dict),
183  zone_(mesh())
184 {
185  read(dict);
186 }
187 
188 
189 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
190 
192 {}
193 
194 
195 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
196 
198 {
199  zone_.read(dict);
200 
201  const bool haveDirection = dict.found("direction");
202  const bool haveDistance = dict.found("distance");
203  if (haveDirection == haveDistance)
204  {
206  << "keywords direction and distance both "
207  << (haveDirection ? "" : "un") << "defined in "
208  << "dictionary " << dict.name()
209  << exit(FatalIOError);
210  }
211  else if (haveDirection)
212  {
213  direction_ = normalised(dict.lookup<vector>("direction"));
214  distanceName_ = word::null;
215  }
216  else if (haveDistance)
217  {
218  direction_ = vector::nan;
219  distanceName_ = dict.lookup<word>("distance");
220  }
221 
222  nLayers_ = dict.lookup<label>("nPoints");
223 
224  interpolate_ = dict.lookupOrDefault<bool>("interpolate", false);
225 
226  fields_ = dict.lookup<wordList>("fields");
227 
228  axis_ =
230  [
231  dict.lookupOrDefault<word>
232  (
233  "axis",
235  )
236  ];
237 
238  formatter_ = setWriter::New(dict.lookup("setFormat"), dict);
239 
240  nOptimiseIter_ = dict.lookupOrDefault("nOptimiseIter", 2);
241 
242  clear();
243 
244  return true;
245 }
246 
247 
249 {
250  wordList result(fields_);
251 
252  if (distanceName_ != word::null)
253  {
254  result.append(distanceName_);
255  }
256 
257  return result;
258 }
259 
260 
262 {
263  return true;
264 }
265 
266 
268 {
269  zone_.regenerate();
270 
271  if (!weights_.valid())
272  {
273  calcWeights();
274  }
275 
276  const bool writeThickness =
277  !interpolate_
278  && (
280  || axis_ == coordSet::axisType::DISTANCE
281  );
282 
283  // Create list of field names
285  if (writeThickness)
286  {
287  fieldNames.append("thickness");
288  }
289  forAll(fields_, fieldi)
290  {
291  if
292  (
293  false
294  #define FoundTypeField(Type, nullArg) \
295  || foundObject<VolField<Type>>(fields_[fieldi])
297  #undef FoundTypeField
298  )
299  {
300  fieldNames.append(fields_[fieldi]);
301  }
302  else
303  {
304  cannotFindObject(fields_[fieldi]);
305  }
306  }
307 
308  // Calculate the field values
309  #define DeclareTypeFieldValues(Type, nullArg) \
310  PtrList<Field<Type>> Type##FieldValues(fieldNames.size());
312  #undef DeclareTypeFieldValues
313  if (writeThickness)
314  {
315  scalarFieldValues.set(0, new scalarField(layerThicknesses_));
316  }
317  for (label fieldi = writeThickness; fieldi < fieldNames.size(); ++ fieldi)
318  {
319  #define CollapseTypeFields(Type, GeoField) \
320  if (mesh_.foundObject<GeoField<Type>>(fieldNames[fieldi])) \
321  { \
322  const GeoField<Type>& field = \
323  mesh_.lookupObject<GeoField<Type>>(fieldNames[fieldi]); \
324  \
325  Type##FieldValues.set \
326  ( \
327  fieldi, \
328  cutPlot::applyWeights<Type>(nLayers_, weights_, field) \
329  ); \
330  }
333  #undef CollapseTypeFields
334  }
335 
336  // Write
337  if (Pstream::master() && layerPositions_->size())
338  {
339  mkDir(outputPath());
340 
341  formatter_->write
342  (
343  outputPath(),
344  typeName,
345  coordSet
346  (
347  identityMap(layerPositions_->size()),
348  word::null,
349  layerPositions_,
351  layerDistances_,
353  ),
354  fieldNames
355  #define TypeFieldValuesParameter(Type, nullArg) , Type##FieldValues
358  );
359  }
360 
361  return true;
362 }
363 
364 
366 (
367  const polyMesh& mesh
368 )
369 {
370  if (&mesh == &mesh_)
371  {
372  zone_.movePoints();
373  clear();
374  }
375 }
376 
377 
379 (
380  const polyTopoChangeMap& map
381 )
382 {
383  if (&map.mesh() == &mesh_)
384  {
385  zone_.topoChange(map);
386  clear();
387  }
388 }
389 
390 
392 (
393  const polyMeshMap& map
394 )
395 {
396  if (&map.mesh() == &mesh_)
397  {
398  zone_.mapMesh(map);
399  clear();
400  }
401 }
402 
403 
405 (
406  const polyDistributionMap& map
407 )
408 {
409  if (&map.mesh() == &mesh_)
410  {
411  zone_.distribute(map);
412  clear();
413  }
414 }
415 
416 
417 // ************************************************************************* //
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.
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.
This function object writes graphs of cell values, volume-averaged in planes perpendicular to a given...
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.
cutLayerAverage(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
virtual bool execute()
Execute, currently does nothing.
virtual bool write()
Write the cutLayerAverage.
virtual bool read(const dictionary &)
Read the cutLayerAverage data.
Specialisation of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
const fvMesh & mesh_
Reference to the fvMesh.
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
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...
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 TypeFieldValuesParameter(Type, nullArg)
#define CollapseTypeFields(Type, GeoField)
#define FoundTypeField(Type, nullArg)
#define DeclareTypeFieldValues(Type, nullArg)
#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
void writeLayers(const fvMesh &mesh, const List< cellCutPlot::weight > &weights, const word &functionName)
Write the layers as components of a tensor field for debugging.
Definition: cellCutPlot.C:1130
tmp< scalarField > calcCutXs(const polyMesh &mesh, const generatedCellZone &zone, const scalarField &pointXs, const bool interpolate, const label nCuts, const label nIter, const bool debug=false, const word &functionName=word::null, const setWriter &functionFormatter=NullObjectRef< setWriter >())
Compute and return evenly-spaced cut coordinates.
Definition: cellCutPlot.C:941
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
addToRunTimeSelectionTable(functionObject, fvModel, dictionary)
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
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
typename VolField< Type >::Internal VolInternalField
Definition: volFieldsFwd.H:59
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
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
dictionary dict