refineMesh.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-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 Application
25  refineMesh
26 
27 Description
28  Utility to refine cells in multiple directions.
29 
30  Command-line option handling:
31  - If -all specified or no refineMeshDict exists or, refine all cells
32  - If -dict <file> specified refine according to <file>
33  - If refineMeshDict exists refine according to refineMeshDict
34 
35  When the refinement or all cells is selected apply 3D refinement for 3D
36  cases and 2D refinement for 2D cases.
37 
38 \*---------------------------------------------------------------------------*/
39 
40 #include "argList.H"
41 #include "Time.H"
42 #include "polyMesh.H"
43 #include "zoneGenerator.H"
44 #include "cellSet.H"
45 #include "hexRef8.H"
46 #include "multiDirRefinement.H"
47 #include "polyTopoChange.H"
48 #include "syncTools.H"
49 #include "systemDict.H"
50 
51 using namespace Foam;
52 
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 
55 // Max cos angle for edges to be considered aligned with axis.
56 static const scalar edgeTol = 1e-3;
57 
58 // Print edge statistics on mesh.
59 void printEdgeStats(const polyMesh& mesh)
60 {
61  label nX = 0;
62  label nY = 0;
63  label nZ = 0;
64 
65  scalar minX = great;
66  scalar maxX = -great;
67  static const vector x(1, 0, 0);
68 
69  scalar minY = great;
70  scalar maxY = -great;
71  static const vector y(0, 1, 0);
72 
73  scalar minZ = great;
74  scalar maxZ = -great;
75  static const vector z(0, 0, 1);
76 
77  scalar minOther = great;
78  scalar maxOther = -great;
79 
81 
82  const edgeList& edges = mesh.edges();
83 
84  forAll(edges, edgeI)
85  {
86  if (isMasterEdge[edgeI])
87  {
88  const edge& e = edges[edgeI];
89 
90  vector eVec(e.vec(mesh.points()));
91 
92  scalar eMag = mag(eVec);
93 
94  eVec /= eMag;
95 
96  if (mag(eVec & x) > 1-edgeTol)
97  {
98  minX = min(minX, eMag);
99  maxX = max(maxX, eMag);
100  nX++;
101  }
102  else if (mag(eVec & y) > 1-edgeTol)
103  {
104  minY = min(minY, eMag);
105  maxY = max(maxY, eMag);
106  nY++;
107  }
108  else if (mag(eVec & z) > 1-edgeTol)
109  {
110  minZ = min(minZ, eMag);
111  maxZ = max(maxZ, eMag);
112  nZ++;
113  }
114  else
115  {
116  minOther = min(minOther, eMag);
117  maxOther = max(maxOther, eMag);
118  }
119  }
120  }
121 
122  label nEdges = mesh.nEdges();
123  reduce(nEdges, sumOp<label>());
124  reduce(nX, sumOp<label>());
125  reduce(nY, sumOp<label>());
126  reduce(nZ, sumOp<label>());
127 
128  reduce(minX, minOp<scalar>());
129  reduce(maxX, maxOp<scalar>());
130 
131  reduce(minY, minOp<scalar>());
132  reduce(maxY, maxOp<scalar>());
133 
134  reduce(minZ, minOp<scalar>());
135  reduce(maxZ, maxOp<scalar>());
136 
137  reduce(minOther, minOp<scalar>());
138  reduce(maxOther, maxOp<scalar>());
139 
140  Info<< "Mesh edge statistics:" << nl;
141  if (minX > great || maxX > -great)
142  {
143  Info<< " x aligned : number:" << nX << "\tminLen:" << minX
144  << "\tmaxLen:" << maxX << nl;
145  }
146  if (minY > great || maxY > -great)
147  {
148  Info<< " y aligned : number:" << nY << "\tminLen:" << minY
149  << "\tmayLen:" << maxY << nl;
150  }
151  if (minZ > great || maxZ > -great)
152  {
153  Info<< " z aligned : number:" << nZ << "\tminLen:" << minZ
154  << "\tmazLen:" << maxZ << nl;
155  }
156  if (minOther > great || maxOther > -great)
157  {
158  Info<< " other : number:" << nEdges - nX - nY - nZ
159  << "\tminLen:" << minOther
160  << "\tmaxLen:" << maxOther << nl;
161  }
162 
163  Info<< endl;
164 }
165 
166 
167 void refineZone
168 (
169  polyMesh& mesh,
170  const labelList& refCells,
171  hexRef8* meshCutterPtr,
172  const dictionary& refineDict,
173  const dictionary& zoneDict
174 )
175 {
176  const label nCells0 = mesh.globalData().nTotalCells();
177 
178  if (meshCutterPtr)
179  {
180  hexRef8& meshCutter = *meshCutterPtr;
181 
182  // Maintain 2:1 ratio
183  const labelList newCellsToRefine
184  (
185  meshCutter.consistentRefinement
186  (
187  refCells,
188  true // extend set
189  )
190  );
191 
192  // Mesh changing engine.
193  polyTopoChange meshMod(mesh);
194 
195  // Play refinement commands into mesh changer.
196  meshCutter.setRefinement(newCellsToRefine, meshMod);
197 
198  // Create mesh, return map from old to new mesh.
199  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh);
200 
201  // Update mesh objects
202  mesh.topoChange(map);
203  }
204  else
205  {
207  (
208  mesh,
209  refCells,
210  refineDict,
211  zoneDict.isDict("coordinates")
212  ? zoneDict.subDict("coordinates")
213  : refineDict.subDict("coordinates")
214  );
215  }
216 
217  Info<< " total number of cell increased from " << nCells0
218  << " to " << mesh.globalData().nTotalCells()
219  << nl << endl;
220 }
221 
222 
223 int main(int argc, char *argv[])
224 {
225  argList::addNote("Refine cells in multiple directions");
226 
227  #include "addNoOverwriteOption.H"
228  #include "addMeshOption.H"
229  #include "addRegionOption.H"
230  #include "addDictOption.H"
231 
233  (
234  "all",
235  "Refine all cells"
236  );
237 
240  #include "createSpecifiedPolyMesh.H"
241  const word oldInstance = mesh.pointsInstance();
242 
243  // Some stats
244  Info<< "Read mesh:" << nl
245  << " cells:" << mesh.globalData().nTotalCells() << nl
246  << " faces:" << mesh.globalData().nTotalFaces() << nl
247  << " points:" << mesh.globalData().nTotalPoints() << nl << endl;
248  printEdgeStats(mesh);
249 
250  const bool refineAllCells = args.optionFound("all");
251  #include "setNoOverwrite.H"
252 
253  hexRef8* meshCutterPtr = nullptr;
254 
255  if (refineAllCells)
256  {
257  Info<< "Refining all cells" << nl << endl;
258 
259  // Select all cells
260  labelList refCells(identityMap(mesh.nCells()));
261 
262  dictionary refineDict;
263 
264  if (mesh.nGeometricD() == 3)
265  {
266  Info<< "3D case; refining all directions" << nl << endl;
267 
268  wordList directions(3);
269  directions[0] = "e1";
270  directions[1] = "e2";
271  directions[2] = "e3";
272  refineDict.add("directions", directions);
273 
274  // Use hex cutter
275  refineDict.add("useHexTopology", "true");
276  }
277  else
278  {
279  const Vector<label> dirs(mesh.geometricD());
280 
281  wordList directions(2);
282 
283  if (dirs.x() == -1)
284  {
285  Info<< "2D case; refining in directions y,z\n" << endl;
286  directions[0] = "e2";
287  directions[1] = "e3";
288  }
289  else if (dirs.y() == -1)
290  {
291  Info<< "2D case; refining in directions x,z\n" << endl;
292  directions[0] = "e1";
293  directions[1] = "e3";
294  }
295  else
296  {
297  Info<< "2D case; refining in directions x,y\n" << endl;
298  directions[0] = "e1";
299  directions[1] = "e2";
300  }
301 
302  refineDict.add("directions", directions);
303 
304  // Use standard cutter
305  refineDict.add("useHexTopology", "false");
306  }
307 
308  refineDict.add("coordinateSystem", "global");
309 
310  dictionary coeffDict;
311  coeffDict.add("e1", vector(1, 0, 0));
312  coeffDict.add("e2", vector(0, 1, 0));
313  refineDict.add("global", coeffDict);
314 
315  refineDict.add("geometricCut", "false");
316  refineDict.add("writeMesh", "false");
317 
318  multiDirRefinement multiRef(mesh, refCells, refineDict, refineDict);
319  }
320  else
321  {
322  const dictionary refineDict
323  (
324  systemDict("refineMeshDict", args, mesh)
325  );
326 
327  const bool hexRef8Refine(refineDict.lookupOrDefault("hexRef8", false));
328 
329  // Construct refiner without unrefinement.
330  // Read existing point/cell level.
331  if (hexRef8Refine)
332  {
333  meshCutterPtr = &hexRef8::New(mesh);
334  hexRef8& meshCutter = *meshCutterPtr;
335 
336  Info<< "Refining using hexRef8" << nl
337  << " cellLevel :"
338  << " min:" << gMin(meshCutter.cellLevel())
339  << " max:" << gMax(meshCutter.cellLevel()) << nl
340  << " pointLevel :"
341  << " min:" << gMin(meshCutter.pointLevel())
342  << " max:" << gMax(meshCutter.pointLevel()) << nl
343  << endl;
344  }
345 
346  if (refineDict.found("set"))
347  {
348  const word setName(refineDict.lookup("set"));
349  const cellSet cells(mesh, setName);
350 
351  Info<< "Refining "
353  << " cells in set "
354  << cells.instance()/cells.local()/cells.name()
355  << endl;
356 
357  refineZone
358  (
359  mesh,
360  cells.toc(),
361  meshCutterPtr,
362  refineDict,
363  refineDict
364  );
365  }
366  else if (refineDict.found("zone"))
367  {
368  labelList refCells;
369 
370  if (refineDict.isDict("zone"))
371  {
373  (
375  (
376  "zone",
378  mesh,
379  refineDict.subDict("zone")
380  )
381  );
382 
383  refCells = zg->generate().cZone();
384 
385  Info<< "Refining "
386  << returnReduce(refCells.size(), sumOp<label>())
387  << " cells in zone " << zg->zoneName()
388  << " of type " << zg->type() << endl;
389  }
390  else
391  {
392  const word cellZoneName(refineDict.lookup("zone"));
393  refCells = mesh.cellZones()[cellZoneName];
394 
395  Info<< "Refining "
396  << returnReduce(refCells.size(), sumOp<label>())
397  << " cells in zone " << cellZoneName << endl;
398  }
399 
400  refineZone
401  (
402  mesh,
403  refCells,
404  meshCutterPtr,
405  refineDict,
406  refineDict.isDict("zone")
407  ? refineDict.subDict("zone")
408  : refineDict
409  );
410  }
411  else if (refineDict.found("zones"))
412  {
413  const dictionary& zones = refineDict.subDict("zones");
414 
415  forAllConstIter(dictionary, zones, iter)
416  {
417  const word& name = iter().keyword();
418  const dictionary& zoneDict = iter().dict();
419 
421  (
423  (
424  name,
426  mesh,
427  zoneDict
428  )
429  );
430 
431  const labelList refCells(zg->generate().cZone());
432 
433  Info<< "Refining "
434  << returnReduce(refCells.size(), sumOp<label>())
435  << " cells in zone " << zg->zoneName()
436  << " of type " << zg->type() << endl;
437 
438  refineZone
439  (
440  mesh,
441  refCells,
442  meshCutterPtr,
443  refineDict,
444  zoneDict
445  );
446  }
447  }
448  }
449 
450  printEdgeStats(mesh);
451 
452  if (overwrite)
453  {
454  mesh.setInstance(oldInstance);
455 
456  if (meshCutterPtr)
457  {
458  meshCutterPtr->setInstance(oldInstance);
459  }
460  }
461  else
462  {
463  runTime++;
464  }
465 
466  Info<< "Writing mesh to ";
467  mesh.write();
469 
470  Info<< "\nEnd\n" << endl;
471 
472  return 0;
473 }
474 
475 
476 // ************************************************************************* //
scalar y
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
static hexRef8 & New(const word &name, const polyMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A bit-packed bool list.
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:152
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:111
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A collection of cell labels.
Definition: cellSet.H:51
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
T lookupOrDefault(const word &, const T &) const
Find and return a T, if not found return the given default.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:669
bool isDict(const word &) const
Check if entry is a sub-dictionary.
Definition: dictionary.C:732
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:778
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1019
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
Set of directions for each cell in the mesh. Either uniform and size=1 or one set of directions per c...
Definition: directions.H:67
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
virtual void topoChange(const polyTopoChangeMap &map)
Update mesh corresponding to the given map.
Definition: fvMesh.C:1335
label nTotalFaces() const
Return total number of faces in decomposed mesh. Not.
label nTotalPoints() const
Return total number of points in decomposed mesh. Not.
label nTotalCells() const
Return total number of cells in decomposed mesh.
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef8.H:73
void setInstance(const fileName &inst)
Definition: hexRef8.C:1595
Cuts (splits) cells.
Definition: meshCutter.H:131
void setRefinement(const cellCuts &cuts, polyTopoChange &meshMod)
Do actual cutting with cut description. Inserts mesh changes.
Definition: meshCutter.C:470
Does multiple pass refinement to refine cells in multiple directions.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:1012
label nGeometricD() const
Return the number of valid geometric dimensions in the mesh.
Definition: polyMesh.C:1041
const cellZoneList & cellZones() const
Return cell zones.
Definition: polyMesh.H:438
fileName meshDir() const
Return the local mesh directory (dbDir()/meshSubDir)
Definition: polyMesh.C:1000
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1471
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:1006
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1295
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:102
const Vector< label > & geometricD() const
Return the vector of geometric directions in mesh.
Definition: polyMesh.C:1030
Direct mesh changes based on v1.3 polyTopoChange syntax.
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
label nCells() const
label nEdges() const
virtual bool write(const bool write=true) const
Write using setting from DB.
static PackedBoolList getMasterEdges(const polyMesh &)
Get per edge whether it is uncoupled or a master of a.
Definition: syncTools.C:109
A class for handling words, derived from string.
Definition: word.H:63
static autoPtr< zoneGenerator > New(const word &name, const polyMesh &mesh, const dictionary &dict)
Select constructed from name, mesh and dictionary.
Definition: zoneGenerator.C:66
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
int main(int argc, char *argv[])
Definition: financialFoam.C:44
const cellShapeList & cells
Namespace for OpenFOAM.
Type gMin(const UList< Type > &f, const label comm)
const doubleScalar e
Definition: doubleScalar.H:106
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Type gMax(const UList< Type > &f, const label comm)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
IOdictionary systemDict(const word &dictName, const argList &args, const objectRegistry &ob, const word &regionName=polyMesh::defaultRegion, const fileName &path=fileName::null)
Definition: systemDict.C:93
static const char nl
Definition: Ostream.H:297
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const bool overwrite
Definition: setNoOverwrite.H:1
Foam::argList args(argc, argv)