cellDecomposer.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) 2024-2025 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "cellDecomposer.H"
30 #include "polyTopoChange.H"
31 #include "mapPolyMesh.H"
32 #include "tetDecomposer.H"
33 #include "syncTools.H"
34 #include "dummyTransform.H"
35 #include "ReadFields.H"
36 #include "surfaceFields.H"
37 #include "fvMeshTools.H"
38 #include "cellSetOption.H"
39 #include "cellBitSet.H"
40 #include "cellSet.H"
41 #include "hexMatcher.H"
42 #include "prismMatcher.H"
43 #include "pyrMatcher.H"
44 #include "tetMatcher.H"
45 
46 #include "OBJstream.H"
47 
48 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
49 
50 namespace Foam
51 {
52 namespace functionObjects
53 {
54  defineTypeNameAndDebug(cellDecomposer, 0);
55  addToRunTimeSelectionTable(functionObject, cellDecomposer, dictionary);
56 }
57 }
58 
59 
60 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
61 
62 void Foam::functionObjects::cellDecomposer::makeMesh
63 (
64  const dictionary& dict,
65  const word& regionName
66 )
67 {
68  Info<< name() << ':' << nl
69  << " Decomposing cells to region " << regionName << endl;
70 
71  Info<< incrIndent;
72 
73  const fv::cellSetOption::selectionModeType selectionMode
74  (
76  (
77  "selectionMode",
78  dict
79  )
80  );
81 
82 
83  // Start off from existing mesh
84  polyTopoChange meshMod(mesh_);
85 
86  tetDecompPtr_.reset(new Foam::tetDecomposer(mesh_));
87 
88  // Default values
89  bitSet decomposeCell(mesh_.nCells());
90  autoPtr<bitSet> decomposeFacePtr;
92  (
94  );
95 
96 
97  switch (selectionMode)
98  {
100  {
101  Info<< indent << "- selecting all cells" << endl;
102 
103  decomposeCell = true;
104  break;
105  }
107  {
108  Info<< indent << "- selecting cells geometrically" << endl;
109 
110  decomposeCell =
111  cellBitSet::select(mesh_, dict.subDict("selection"), true);
112  break;
113  }
115  {
116  const word selectionName(dict.get<word>("cellSet"));
117 
118  Info<< indent
119  << "- selecting cells using cellSet "
120  << selectionName << endl;
121 
122  decomposeCell.set
123  (
124  cellSet(mesh_, selectionName, IOobject::MUST_READ).toc()
125  );
126  break;
127  }
129  {
130  wordRes selectionNames;
131  if
132  (
133  !dict.readIfPresent("cellZones", selectionNames)
134  || selectionNames.empty()
135  )
136  {
137  selectionNames.resize(1);
138  dict.readEntry("cellZone", selectionNames.first());
139  }
140 
141  Info<< indent
142  << "- selecting cells using cellZones "
143  << flatOutput(selectionNames) << nl;
144 
145  const auto& zones = mesh_.cellZones();
146 
147  // Also handles groups, multiple zones etc ...
148  labelList zoneIDs = zones.indices(selectionNames);
149 
150  if (zoneIDs.empty())
151  {
153  << "No matching cellZones: "
154  << flatOutput(selectionNames) << nl
155  << "Valid zones : "
156  << flatOutput(zones.names()) << nl
157  << "Valid groups: "
158  << flatOutput(zones.groupNames())
159  << nl
160  << exit(FatalError);
161  }
162 
163  if (zoneIDs.size() == 1)
164  {
165  decomposeCell.set(zones[zoneIDs.first()]);
166  // TBD: Foam::sort(cells_);
167  }
168  else
169  {
170  decomposeCell.set(zones.selection(zoneIDs).sortedToc());
171  }
172  break;
173  }
174  default:
175  {
177  << "Unsupported selectionMode "
179  << ". Valid selectionMode types are "
181  << exit(FatalError);
182  }
183  }
184 
185  word decompTypeName;
186  if (dict.readIfPresent("decomposeType", decompTypeName))
187  {
188  if (decompTypeName == "polyhedral")
189  {
190  // Automatic selection to generate hex/prism/tet only
191  // - subset decomposeCell to exclude hex/prism/tet
192  // - set faces to FACE_DIAG_QUADS
193  // Usually start with cellSetOption::smAll
194  decomposeFacePtr.reset(new bitSet(mesh_.nFaces()));
195  auto& decomposeFace = decomposeFacePtr();
196 
197  decompType = tetDecomposer::FACE_DIAG_QUADS;
198  bitSet oldDecomposeCell(decomposeCell);
199  decomposeCell = false;
200 
201  // Construct shape recognizers
202  prismMatcher prism;
203 
204  for (const label celli : oldDecomposeCell)
205  {
206  if
207  (
208  !hexMatcher::test(mesh_, celli)
209  && !tetMatcher::test(mesh_, celli)
210  && !pyrMatcher::test(mesh_, celli)
211  && !prism.isA(mesh_, celli)
212  )
213  {
214  decomposeCell.set(celli);
215  decomposeFace.set(mesh_.cells()[celli]);
216  }
217  }
218 
219  // Sync boundary info
221  (
222  mesh_,
223  decomposeFace,
224  orEqOp<unsigned int>()
225  );
226  }
227  else
228  {
229  decompType = tetDecomposer::decompositionTypeNames[decompTypeName];
230  }
231  }
232 
233 
234  // Insert all changes to create tets
235  if (decomposeFacePtr)
236  {
237  if (debug)
238  {
239  OBJstream os(mesh_.time().path()/"orig_faces.obj");
240  os.write
241  (
242  UIndirectList<face>
243  (
244  mesh_.faces(),
245  decomposeFacePtr().sortedToc()
246  )(),
247  mesh_.points(),
248  false
249  );
250  Pout<< "Written " << meshMod.faces().size()
251  << " faces to " << os.name() << endl;
252  }
253 
254  tetDecompPtr_().setRefinement
255  (
256  decompType, //Foam::tetDecomposer::FACE_CENTRE_TRIS,
257  decomposeCell,
258  decomposeFacePtr(),
259  meshMod
260  );
261  }
262  else
263  {
264  tetDecompPtr_().setRefinement
265  (
266  decompType, //Foam::tetDecomposer::FACE_CENTRE_TRIS,
267  decomposeCell,
268  meshMod
269  );
270  }
271 
272 
273  if (debug)
274  {
275  OBJstream os(mesh_.time().path()/"faces.obj");
276  os.write(meshMod.faces(), pointField(meshMod.points()), false);
277  Pout<< "Written " << meshMod.faces().size()
278  << " faces to " << os.name() << endl;
279  }
280 
281 
282  autoPtr<fvMesh> tetMeshPtr;
283 
284  mapPtr_ = meshMod.makeMesh
285  (
286  tetMeshPtr,
287  IOobject
288  (
289  regionName,
290  mesh_.facesInstance(), // same instance as original mesh
291  mesh_.time(), //? why same database? TBD.
292  IOobject::READ_IF_PRESENT, // Read fv* if present
295  ),
296  mesh_
297  );
298 
299 
300  //- Update numbering on tet-decomposition engine
301  tetDecompPtr_().updateMesh(mapPtr_());
302 
303  Info<< indent << "Writing decomposed mesh to "
304  << tetMeshPtr().objectRegistry::objectRelPath()
305  << endl;
306  tetMeshPtr().write();
307 
309 
310  // Store new mesh on object registry
311  tetMeshPtr.ptr()->polyMesh::store();
312 
313  Info<< decrIndent;
314 }
316 
317 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
318 
320 (
321  const word& name,
322  const Time& runTime,
323  const dictionary& dict
324 )
325 :
327 {
328  read(dict);
329 }
330 
331 
332 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
333 
335 {
337  {
338  // Generate new tet equivalent mesh. TBD: why meshObject?
339  //meshObjects::tetDecomposition::New(mesh, dict);
340 
341  dict_ = dict.optionalSubDict(typeName + "Coeffs");
342  dict_.readEntry("mapRegion", mapRegion_);
343  dict_.readEntry("fields", fieldNames_);
344  makeMesh(dict_, mapRegion_);
345  }
347  return true;
348 }
349 
350 
352 {
353  Log << type() << " " << name() << " execute:" << nl;
354 
355  bool ok = false;
356 
357  if (mesh_.changing())
358  {
359  // Re-do mesh. Currently rebuilds whole mesh. Could move points only
360  // for mesh motion.
361  tetDecompPtr_.clear();
362  mapPtr_.clear();
363  const_cast<Time&>(this->mesh_.time()).erase(mapRegion_);
364  makeMesh(dict_, mapRegion_);
365  }
366 
367 
368  // Look up
369  ok = mapFieldType<scalar>() || ok;
370  ok = mapFieldType<vector>() || ok;
371  ok = mapFieldType<sphericalTensor>() || ok;
372  ok = mapFieldType<symmTensor>() || ok;
373  ok = mapFieldType<tensor>() || ok;
374 
375 
376  if (!ok)
377  {
378  Log << " none" << nl;
379  }
380 
381  Log << endl;
383  return true;
384 }
385 
386 
388 {
389  Log << type() << " " << name() << " write:" << nl;
390 
391  bool ok = false;
392 
393  ok = writeFieldType<scalar>() || ok;
394  ok = writeFieldType<vector>() || ok;
395  ok = writeFieldType<sphericalTensor>() || ok;
396  ok = writeFieldType<symmTensor>() || ok;
397  ok = writeFieldType<tensor>() || ok;
398 
399 
400  if (!ok)
401  {
402  Log << " none" << nl;
403  }
404 
405  Log << endl;
406 
407  return true;
408 }
409 
410 
411 // ************************************************************************* //
Foam::surfaceFields.
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const bool parRun=UPstream::parRun())
Synchronize values on all mesh faces.
Definition: syncTools.H:465
dictionary dict
defineTypeNameAndDebug(ObukhovLength, 0)
const labelIOList & zoneIDs
Definition: correctPhi.H:59
fileName path() const
Return path = rootPath/caseName. Same as TimePaths::path()
Definition: Time.H:503
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:491
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:844
srcOptions erase("case")
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
const cellList & cells() const
Field reading functions for post-processing utilities.
static bool test(const UList< face > &faces)
Test if given list of faces satisfies criteria for HEX. (6 quad)
Definition: hexMatcher.C:80
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:360
label nFaces() const noexcept
Number of mesh faces.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
static const Enum< selectionModeType > selectionModeTypeNames_
List of selection mode type names.
Decomposes polyMesh into tets (or pyramids)
Definition: tetDecomposer.H:60
Macros for easy insertion into run-time selection tables.
const word & name() const noexcept
Return the name of this functionObject.
static const Enum< decompositionType > decompositionTypeNames
Definition: tetDecomposer.H:74
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1063
Dummy transform to be used with syncTools.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:801
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
cellDecomposer(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
A class for handling words, derived from Foam::string.
Definition: word.H:63
Reading is optional [identical to LAZY_READ].
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1088
static void createDummyFvMeshFiles(const objectRegistry &parent, const word &regionName, const bool verbose=false)
Create additional fvSchemes/fvSolution files.
Definition: fvMeshTools.C:1212
static bitSet select(const polyMesh &mesh, const dictionary &dict, const bool verbosity=false)
Return a cell selection according to the dictionary specification of actions.
Definition: cellBitSet.C:84
OBJstream os(runTime.globalPath()/outputName)
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:509
selectionModeType
Enumeration for selection mode types.
virtual bool read(const dictionary &dict)
Read the cellDecomposer data.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
label nCells() const noexcept
Number of mesh cells.
#define Log
Definition: PDRblock.C:28
Automatically write from objectRegistry::writeObject()
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:679
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool read(const dictionary &dict)
Read optional controls.
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
List< label > labelList
A List of labels.
Definition: List.H:61
static bool test(const UList< face > &faces)
Test if given list of faces satisfies criteria for PYR. (4 tri, 1 quad)
Definition: pyrMatcher.C:107
static bool test(const UList< face > &faces)
Test if given list of faces satisfies criteria for TET. (4 tri)
Definition: tetMatcher.C:82
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:500
Request registration (bool: true)
List< label > toc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:158
const fvMesh & mesh_
Reference to the fvMesh.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Namespace for OpenFOAM.
static int debug
Flag to execute debug content.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225