extrude2DMesh.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-2025 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 "extrude2DMesh.H"
27 #include "polyMesh.H"
28 #include "polyTopoChange.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34  defineTypeNameAndDebug(extrude2DMesh, 0);
35 }
36 
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 
39 void Foam::extrude2DMesh::check2D() const
40 {
41  const faceList& faces = mesh_.faces();
42  forAll(faces, facei)
43  {
44  if (faces[facei].size() != 2)
45  {
47  << "Face " << facei << " size " << faces[facei].size()
48  << " is not of size 2: mesh is not a valid two-dimensional "
49  << "mesh" << exit(FatalError);
50  }
51  }
52 }
53 
54 
55 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
56 
58 (
59  polyMesh& mesh,
60  const dictionary& dict,
61  const extrudeModel& model
62 )
63 :
64  mesh_(mesh),
65  model_(model),
66  patchType_(dict.lookup("patchType")),
67  frontPatchi_(-1),
68  backPatchi_(-1),
69  cellZonesAddedCells_(mesh.cellZones().size())
70 {
71  check2D();
72 }
73 
74 
75 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
76 
78 {}
79 
80 
81 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
82 
84 {
85  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
86 
87  frontPatchi_ = patches.findIndex("front");
88  backPatchi_ = patches.findIndex("back");
89 
90  // Add patch.
91  List<polyPatch*> newPatches(patches.size() + 2);
92 
94  {
95  const polyPatch& pp = patches[patchi];
96 
97  newPatches[patchi] =
98  pp.clone
99  (
100  patches,
101  newPatches.size(),
102  pp.size(),
103  pp.start()
104  ).ptr();
105  }
106 
107  if (frontPatchi_ == -1)
108  {
109  frontPatchi_ = patches.size();
110 
111  newPatches[frontPatchi_] =
113  (
114  patchType_,
115  "front",
116  0,
117  mesh_.nFaces(),
118  frontPatchi_,
119  patches
120  ).ptr();
121 
122  Info<< "Adding patch " << newPatches[frontPatchi_]->name()
123  << " at index " << frontPatchi_
124  << " for front faces." << nl << endl;
125  }
126 
127  if (backPatchi_ == -1)
128  {
129  backPatchi_ = patches.size() + 1;
130 
131  newPatches[backPatchi_] =
133  (
134  patchType_,
135  "back",
136  0,
137  mesh_.nFaces(),
138  backPatchi_,
139  patches
140  ).ptr();
141 
142  Info<< "Adding patch " << newPatches[backPatchi_]->name()
143  << " at index " << backPatchi_
144  << " for back faces." << nl << endl;
145  }
146 
147  mesh_.removeBoundary();
148  mesh_.addPatches(newPatches);
149 }
150 
151 
153 (
154  polyTopoChange& meshMod
155 )
156 {
157  const label nLayers = model_.nLayers();
158  const pointField& points = mesh_.points();
159  label nFaces = 0;
160 
161  for (label layer = 0; layer < nLayers; ++layer)
162  {
163  const label offset = layer*mesh_.nCells();
164 
165  forAll(mesh_.cells(), celli)
166  {
167  const label newCelli = meshMod.addCell
168  (
169  celli + offset // masterCellID
170  );
171 
172  const labelList zones(mesh_.cellZones().whichZones(celli));
173  forAll(zones, zonei)
174  {
175  cellZonesAddedCells_[zonei].insert(newCelli);
176  }
177  }
178  }
179 
180 
181  // Generate points
182  // ~~~~~~~~~~~~~~~
183 
184  for (label layer = 0; layer <= nLayers; ++layer)
185  {
186  label offset = layer * points.size();
187 
188  forAll(points, pointi)
189  {
190  // Don't need the surface normal for either linearDirection or
191  // wedge. Will need to add to be able to use others.
192  point newPoint = model_
193  (
194  points[pointi],
195  vector(),
196  layer
197  );
198 
199  meshMod.addPoint
200  (
201  newPoint,
202  pointi + offset,
203  true // inCell
204  );
205  }
206 
207  Pout<< "Added " << points.size() << " points to layer "
208  << layer << endl;
209  }
210 
211 
212  // Generate faces
213  // ~~~~~~~~~~~~~~
214 
215  const faceList& faces = mesh_.faces();
216  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
217 
218  for (label layer = 0; layer < nLayers; ++layer)
219  {
220  label currentLayerOffset = layer * mesh_.nPoints();
221  label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
222 
223  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
224  {
225  face newFace(4);
226  const face& f = faces[facei];
227  newFace[0] = f[0] + currentLayerOffset;
228  newFace[1] = f[1] + currentLayerOffset;
229  newFace[2] = f[1] + nextLayerOffset;
230  newFace[3] = f[0] + nextLayerOffset;
231 
232  label offset = layer * mesh_.nCells();
233 
234  meshMod.addFace
235  (
236  newFace,
237  mesh_.faceOwner()[facei] + offset, // own
238  mesh_.faceNeighbour()[facei] + offset, // nei
239  nFaces++, // masterFaceID
240  false, // flipFaceFlux
241  -1 // patchID
242  );
243 
244  if (debug)
245  {
246  Info<< newFace << " "
247  << mesh_.faceOwner()[facei] + offset << " "
248  << mesh_.faceNeighbour()[facei] + offset << " "
249  << nFaces - 1
250  << endl;
251  }
252  }
253  }
254 
256  {
257  for (label layer=0; layer < nLayers; layer++)
258  {
259  label currentLayerOffset = layer*mesh_.nPoints();
260  label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
261 
262  label startFacei = patches[patchi].start();
263  label endFacei = startFacei + patches[patchi].size();
264 
265  for (label facei = startFacei; facei < endFacei; facei++)
266  {
267  face newFace(4);
268  const face& f = faces[facei];
269  newFace[0] = f[0] + currentLayerOffset;
270  newFace[1] = f[1] + currentLayerOffset;
271  newFace[2] = f[1] + nextLayerOffset;
272  newFace[3] = f[0] + nextLayerOffset;
273 
274  label offset = layer * mesh_.nCells();
275 
276  meshMod.addFace
277  (
278  newFace,
279  mesh_.faceOwner()[facei] + offset, // own
280  -1, // nei
281  nFaces++, // masterFaceID
282  false, // flipFaceFlux
283  patchi // patchID
284  );
285 
286  if (debug)
287  {
288  Info<< newFace << " "
289  << mesh_.faceOwner()[facei] + offset << " "
290  << nFaces - 1
291  << endl;
292  }
293  }
294  }
295  }
296 
297  // Add extra internal faces that need special treatment for owners and
298  // neighbours.
299  forAll(mesh_.cells(), celli)
300  {
301  const cell& cFaces = mesh_.cells()[celli];
302 
303  face frontFace(cFaces.size());
304 
305  // Make a loop out of faces.
306  label nextFacei = cFaces[0];
307 
308  const face& f = faces[nextFacei];
309 
310  label nextPointi;
311  if (mesh_.faceOwner()[nextFacei] == celli)
312  {
313  frontFace[0] = f[0];
314  nextPointi = f[1];
315  }
316  else
317  {
318  frontFace[0] = f[1];
319  nextPointi = f[0];
320  }
321 
322 
323  for (label i = 1; i < frontFace.size(); i++)
324  {
325  frontFace[i] = nextPointi;
326 
327  // Find face containing pointi
328  forAll(cFaces, cFacei)
329  {
330  label facei = cFaces[cFacei];
331  if (facei != nextFacei)
332  {
333  const face& f = faces[facei];
334 
335  if (f[0] == nextPointi)
336  {
337  nextPointi = f[1];
338  nextFacei = facei;
339  break;
340  }
341  else if (f[1] == nextPointi)
342  {
343  nextPointi = f[0];
344  nextFacei = facei;
345  break;
346  }
347  }
348  }
349  }
350 
351  for (label layer = 0; layer < nLayers - 1; ++layer)
352  {
353  // Offset to create front face.
354  forAll(frontFace, fp)
355  {
356  frontFace[fp] += mesh_.nPoints();
357  }
358 
359  label offset = layer * mesh_.nCells();
360 
361  label nei = -1;
362  if (layer != nLayers - 1)
363  {
364  nei = celli + offset + mesh_.nCells();
365  }
366 
367  meshMod.addFace
368  (
369  frontFace,
370  celli + offset, // own
371  nei, // nei
372  nFaces++, // masterFaceID
373  false, // flipFaceFlux
374  -1 // patchID
375  );
376 
377  if (debug)
378  {
379  Info<< frontFace << " "
380  << celli + offset << " "
381  << nei << " "
382  << nFaces - 1
383  << endl;
384  }
385  }
386  }
387 
388  // Generate front and back faces
389  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
390 
391  forAll(mesh_.cells(), celli)
392  {
393  const cell& cFaces = mesh_.cells()[celli];
394 
395  face frontFace(cFaces.size());
396 
397  // Make a loop out of faces.
398  label nextFacei = cFaces[0];
399 
400  const face& f = faces[nextFacei];
401 
402  label nextPointi;
403  if (mesh_.faceOwner()[nextFacei] == celli)
404  {
405  frontFace[0] = f[0];
406  nextPointi = f[1];
407  }
408  else
409  {
410  frontFace[0] = f[1];
411  nextPointi = f[0];
412  }
413 
414 
415  for (label i = 1; i < frontFace.size(); i++)
416  {
417  frontFace[i] = nextPointi;
418 
419  // Find face containing pointi
420  forAll(cFaces, cFacei)
421  {
422  label facei = cFaces[cFacei];
423  if (facei != nextFacei)
424  {
425  const face& f = faces[facei];
426 
427  if (f[0] == nextPointi)
428  {
429  nextPointi = f[1];
430  nextFacei = facei;
431  break;
432  }
433  else if (f[1] == nextPointi)
434  {
435  nextPointi = f[0];
436  nextFacei = facei;
437  break;
438  }
439  }
440  }
441  }
442 
443  // Add back face.
444  meshMod.addFace
445  (
446  frontFace.reverseFace(),
447  celli, // own
448  -1, // nei
449  nFaces++, // masterFaceID
450  false, // flipFaceFlux
451  backPatchi_ // patchID
452  );
453 
454  if (debug)
455  {
456  Info<< nl<<frontFace.reverseFace() << " "
457  << celli << " "
458  << nFaces - 1
459  << endl;
460  }
461 
462  // Offset to create front face.
463  forAll(frontFace, fp)
464  {
465  frontFace[fp] += mesh_.nPoints()* (nLayers);
466  }
467 
468  label offset = (nLayers - 1) * mesh_.nCells();
469 
470  meshMod.addFace
471  (
472  frontFace,
473  celli + offset, // own
474  -1, // nei
475  nFaces++, // masterFaceID
476  false, // flipFaceFlux
477  frontPatchi_ // patchID
478  );
479 
480  if (debug)
481  {
482  Info<< frontFace << " "
483  << celli + offset << " "
484  << nFaces - 1
485  << endl;
486  }
487  }
488 }
489 
490 
492 {
493  // Add the cellZones to the merged mesh
494  mesh_.cellZones().insert(cellZonesAddedCells_);
495 }
496 
497 
498 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
extrude2DMesh(polyMesh &, const dictionary &dict, const extrudeModel &model)
void updateZones()
Update the mesh zones.
~extrude2DMesh()
Destructor.
void setRefinement(polyTopoChange &)
Play commands into polyTopoChange to extrude mesh.
void addFrontBackPatches()
Add front and back patches.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1344
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return a pointer to a new patch created on freestore from.
Definition: polyPatchNew.C:32
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const pointField & points
const fvPatchList & patches
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< label > labelList
A List of labels.
Definition: labelList.H:56
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:258
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
vector point
Point is a vector.
Definition: point.H:41
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
defineTypeNameAndDebug(combustionModel, 0)
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
error FatalError
void offset(label &lst, const label o)
List< face > faceList
Definition: faceListFwd.H:41
static const char nl
Definition: Ostream.H:267
labelList f(nPoints)
dictionary dict