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-2018 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 //void Foam::extrude2DMesh::findExtrudeDirection()
56 //{
57 // scalar minRange = great;
58 
59 // for (direction dir = 0; dir < 3; dir++)
60 // {
61 // scalarField cmpts(mesh_.points().component(dir));
62 
63 // scalar range = max(cmpts)-min(cmpts);
64 
65 // Info<< "Direction:" << dir << " range:" << range << endl;
66 
67 // if (range < minRange)
68 // {
69 // minRange = range;
70 // extrudeDir_ = dir;
71 // }
72 // }
73 
74 // Info<< "Extruding in direction " << extrudeDir_
75 // << " with thickness " << thickness_ << nl
76 // << endl;
77 //}
78 
79 
80 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
81 
82 Foam::extrude2DMesh::extrude2DMesh
83 (
84  polyMesh& mesh,
85  const dictionary& dict,
86  const extrudeModel& model
87 )
88 :
89  mesh_(mesh),
90  dict_(dict),
91  // patchDict_(dict.subDict("patchInfo")),
92  model_(model),
93  modelType_(dict.lookup("extrudeModel")),
94  patchType_(dict.lookup("patchType")),
95  frontPatchi_(-1),
96  backPatchi_(-1)
97 {
98  check2D();
99 }
100 
101 
102 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
103 
105 {}
106 
107 
108 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
109 
111 {
112  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
113 
114  frontPatchi_ = patches.findPatchID("front");
115  backPatchi_ = patches.findPatchID("back");
116 
117  // Add patch.
118  List<polyPatch*> newPatches(patches.size() + 2);
119 
120  forAll(patches, patchi)
121  {
122  const polyPatch& pp = patches[patchi];
123 
124  newPatches[patchi] =
125  pp.clone
126  (
127  patches,
128  newPatches.size(),
129  pp.size(),
130  pp.start()
131  ).ptr();
132  }
133 
134  if (frontPatchi_ == -1)
135  {
136  frontPatchi_ = patches.size();
137 
138  newPatches[frontPatchi_] =
140  (
141  patchType_,
142  "front",
143  0,
144  mesh_.nFaces(),
145  frontPatchi_,
146  patches
147  ).ptr();
148 
149 // newPatches[frontPatchi_] = polyPatch::New
150 // (
151 // "front",
152 // patchDict_,
153 // frontPatchi_,
154 // patches
155 // ).ptr();
156 
157  Info<< "Adding patch " << newPatches[frontPatchi_]->name()
158  << " at index " << frontPatchi_
159  << " for front faces." << nl << endl;
160  }
161 
162  if (backPatchi_ == -1)
163  {
164  backPatchi_ = patches.size() + 1;
165 
166  newPatches[backPatchi_] =
168  (
169  patchType_,
170  "back",
171  0,
172  mesh_.nFaces(),
173  backPatchi_,
174  patches
175  ).ptr();
176 
177 // newPatches[frontPatchi_] = polyPatch::New
178 // (
179 // "back",
180 // patchDict_,
181 // backPatchi_,
182 // patches
183 // ).ptr();
184 
185  Info<< "Adding patch " << newPatches[backPatchi_]->name()
186  << " at index " << backPatchi_
187  << " for back faces." << nl << endl;
188  }
189 
190  mesh_.removeBoundary();
191  mesh_.addPatches(newPatches);
192 }
193 
194 
196 (
197  polyTopoChange& meshMod
198 )
199 {
200  const label nLayers = model_.nLayers();
201  const pointField& points = mesh_.points();
202  label nFaces = 0;
203 
204  for (label layer = 0; layer < nLayers; ++layer)
205  {
206  label offset = layer * mesh_.nCells();
207 
208  forAll(mesh_.cells(), celli)
209  {
210  meshMod.addCell
211  (
212  -1, // masterPointID,
213  -1, // masterEdgeID,
214  -1, // masterFaceID,
215  celli + offset, // masterCellID,
216  mesh_.cellZones().whichZone(celli) // zoneID
217  );
218  }
219  }
220 
221 
222  // Generate points
223  // ~~~~~~~~~~~~~~~
224 
225  for (label layer = 0; layer <= nLayers; ++layer)
226  {
227  label offset = layer * points.size();
228 
229  forAll(points, pointi)
230  {
231  // Don't need the surface normal for either linearDirection or
232  // wedge. Will need to add to be able to use others.
233  point newPoint = model_
234  (
235  points[pointi],
236  vector(),
237  layer
238  );
239 
240  meshMod.addPoint
241  (
242  newPoint,
243  pointi + offset,
244  -1, // zoneID
245  true // inCell
246  );
247  }
248 
249  Pout<< "Added " << points.size() << " points to layer "
250  << layer << endl;
251  }
252 
253 
254  // Generate faces
255  // ~~~~~~~~~~~~~~
256 
257  const faceList& faces = mesh_.faces();
258  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
259 
260  for (label layer = 0; layer < nLayers; ++layer)
261  {
262  label currentLayerOffset = layer * mesh_.nPoints();
263  label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
264 
265  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
266  {
267  label zoneID = mesh_.faceZones().whichZone(facei);
268  bool zoneFlip = false;
269  if (zoneID != -1)
270  {
271  const faceZone& fZone = mesh_.faceZones()[zoneID];
272  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
273  }
274 
275  face newFace(4);
276  const face& f = faces[facei];
277  newFace[0] = f[0] + currentLayerOffset;
278  newFace[1] = f[1] + currentLayerOffset;
279  newFace[2] = f[1] + nextLayerOffset;
280  newFace[3] = f[0] + nextLayerOffset;
281 
282 //{
283 // vector n = newFace.normal(pointField(meshMod.points()));
284 // label own = mesh_.faceOwner()[facei];
285 // const labelList& ownPoints = mesh_.cellPoints()[own];
286 // point ownCc = sum(pointField(mesh_.points(), ownPoints))/ownPoints.size();
287 // label nei = mesh_.faceNeighbour()[facei];
288 // const labelList& neiPoints = mesh_.cellPoints()[nei];
289 // point neiCc = sum(pointField(mesh_.points(), neiPoints))/neiPoints.size();
290 // vector d = neiCc - ownCc;
291 
292 // Pout<< "face:" << facei << " at:" << f.centre(mesh_.points()) << endl
293 // << " own:" << own << " at:" << ownCc << endl
294 // << " nei:" << nei << " at:" << neiCc << endl
295 // << " sign:" << (n & d) << endl
296 // << endl;
297 //}
298 
299  label offset = layer * mesh_.nCells();
300 
301  meshMod.addFace
302  (
303  newFace,
304  mesh_.faceOwner()[facei] + offset, // own
305  mesh_.faceNeighbour()[facei] + offset, // nei
306  -1, // masterPointID
307  -1, // masterEdgeID
308  nFaces++, // masterFaceID
309  false, // flipFaceFlux
310  -1, // patchID
311  zoneID, // zoneID
312  zoneFlip // zoneFlip
313  );
314 
315  if (debug)
316  {
317  Info<< newFace << " "
318  << mesh_.faceOwner()[facei] + offset << " "
319  << mesh_.faceNeighbour()[facei] + offset << " "
320  << nFaces - 1
321  << endl;
322  }
323  }
324  }
325 
326  forAll(patches, patchi)
327  {
328  for (label layer=0; layer < nLayers; layer++)
329  {
330  label currentLayerOffset = layer*mesh_.nPoints();
331  label nextLayerOffset = currentLayerOffset + mesh_.nPoints();
332 
333  label startFacei = patches[patchi].start();
334  label endFacei = startFacei + patches[patchi].size();
335 
336  for (label facei = startFacei; facei < endFacei; facei++)
337  {
338  label zoneID = mesh_.faceZones().whichZone(facei);
339  bool zoneFlip = false;
340  if (zoneID != -1)
341  {
342  const faceZone& fZone = mesh_.faceZones()[zoneID];
343  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
344  }
345 
346  face newFace(4);
347  const face& f = faces[facei];
348  newFace[0] = f[0] + currentLayerOffset;
349  newFace[1] = f[1] + currentLayerOffset;
350  newFace[2] = f[1] + nextLayerOffset;
351  newFace[3] = f[0] + nextLayerOffset;
352 
353  label offset = layer * mesh_.nCells();
354 
355  meshMod.addFace
356  (
357  newFace,
358  mesh_.faceOwner()[facei] + offset, // own
359  -1, // nei
360  -1, // masterPointID
361  -1, // masterEdgeID
362  nFaces++, // masterFaceID
363  false, // flipFaceFlux
364  patchi, // patchID
365  zoneID, // zoneID
366  zoneFlip // zoneFlip
367  );
368 
369  if (debug)
370  {
371  Info<< newFace << " "
372  << mesh_.faceOwner()[facei] + offset << " "
373  << nFaces - 1
374  << endl;
375  }
376  }
377  }
378  }
379 
380  // Add extra internal faces that need special treatment for owners and
381  // neighbours.
382  forAll(mesh_.cells(), celli)
383  {
384  const cell& cFaces = mesh_.cells()[celli];
385 
386  face frontFace(cFaces.size());
387 
388  // Make a loop out of faces.
389  label nextFacei = cFaces[0];
390 
391  const face& f = faces[nextFacei];
392 
393  label nextPointi;
394  if (mesh_.faceOwner()[nextFacei] == celli)
395  {
396  frontFace[0] = f[0];
397  nextPointi = f[1];
398  }
399  else
400  {
401  frontFace[0] = f[1];
402  nextPointi = f[0];
403  }
404 
405 
406  for (label i = 1; i < frontFace.size(); i++)
407  {
408  frontFace[i] = nextPointi;
409 
410  // Find face containing pointi
411  forAll(cFaces, cFacei)
412  {
413  label facei = cFaces[cFacei];
414  if (facei != nextFacei)
415  {
416  const face& f = faces[facei];
417 
418  if (f[0] == nextPointi)
419  {
420  nextPointi = f[1];
421  nextFacei = facei;
422  break;
423  }
424  else if (f[1] == nextPointi)
425  {
426  nextPointi = f[0];
427  nextFacei = facei;
428  break;
429  }
430  }
431  }
432  }
433 
434  for (label layer = 0; layer < nLayers - 1; ++layer)
435  {
436  // Offset to create front face.
437  forAll(frontFace, fp)
438  {
439  frontFace[fp] += mesh_.nPoints();
440  }
441 
442  label offset = layer * mesh_.nCells();
443 
444  label nei = -1;
445  if (layer != nLayers - 1)
446  {
447  nei = celli + offset + mesh_.nCells();
448  }
449 
450  meshMod.addFace
451  (
452  frontFace,
453  celli + offset, // own
454  nei, // nei
455  -1, // masterPointID
456  -1, // masterEdgeID
457  nFaces++, // masterFaceID
458  false, // flipFaceFlux
459  -1, // patchID
460  -1, // zoneID
461  false // zoneFlip
462  );
463 
464  if (debug)
465  {
466  Info<< frontFace << " "
467  << celli + offset << " "
468  << nei << " "
469  << nFaces - 1
470  << endl;
471  }
472  }
473  }
474 
475  // Generate front and back faces
476  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
477 
478  forAll(mesh_.cells(), celli)
479  {
480  const cell& cFaces = mesh_.cells()[celli];
481 
482  face frontFace(cFaces.size());
483 
484  // Make a loop out of faces.
485  label nextFacei = cFaces[0];
486 
487  const face& f = faces[nextFacei];
488 
489  label nextPointi;
490  if (mesh_.faceOwner()[nextFacei] == celli)
491  {
492  frontFace[0] = f[0];
493  nextPointi = f[1];
494  }
495  else
496  {
497  frontFace[0] = f[1];
498  nextPointi = f[0];
499  }
500 
501 
502  for (label i = 1; i < frontFace.size(); i++)
503  {
504  frontFace[i] = nextPointi;
505 
506  // Find face containing pointi
507  forAll(cFaces, cFacei)
508  {
509  label facei = cFaces[cFacei];
510  if (facei != nextFacei)
511  {
512  const face& f = faces[facei];
513 
514  if (f[0] == nextPointi)
515  {
516  nextPointi = f[1];
517  nextFacei = facei;
518  break;
519  }
520  else if (f[1] == nextPointi)
521  {
522  nextPointi = f[0];
523  nextFacei = facei;
524  break;
525  }
526  }
527  }
528  }
529 
530  // Add back face.
531  meshMod.addFace
532  (
533  frontFace.reverseFace(),
534  celli, // own
535  -1, // nei
536  -1, // masterPointID
537  -1, // masterEdgeID
538  nFaces++, // masterFaceID
539  false, // flipFaceFlux
540  backPatchi_, // patchID
541  -1, // zoneID
542  false // zoneFlip
543  );
544 
545  if (debug)
546  {
547  Info<< nl<<frontFace.reverseFace() << " "
548  << celli << " "
549  << nFaces - 1
550  << endl;
551  }
552 
553  // Offset to create front face.
554  forAll(frontFace, fp)
555  {
556  frontFace[fp] += mesh_.nPoints()* (nLayers);
557  }
558 
559  label offset = (nLayers - 1) * mesh_.nCells();
560 
561  meshMod.addFace
562  (
563  frontFace,
564  celli + offset, // own
565  -1, // nei
566  -1, // masterPointID
567  -1, // masterEdgeID
568  nFaces++, // masterFaceID
569  false, // flipFaceFlux
570  frontPatchi_, // patchID
571  -1, // zoneID
572  false // zoneFlip
573  );
574 
575  if (debug)
576  {
577  Info<< frontFace << " "
578  << celli + offset << " "
579  << nFaces - 1
580  << endl;
581  }
582  }
583 }
584 
585 
586 // ************************************************************************* //
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
List< face > faceList
Definition: faceListFwd.H:43
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
patches[0]
void addFrontBackPatches()
Add front and back patches.
~extrude2DMesh()
Destructor.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
stressControl lookup("compactNormalStress") >> compactNormalStress
dynamicFvMesh & mesh
label nLayers() const
Definition: extrudeModel.C:59
static const char nl
Definition: Ostream.H:265
defineTypeNameAndDebug(combustionModel, 0)
label patchi
vector point
Point is a vector.
Definition: point.H:41
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
messageStream Info
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
void setRefinement(polyTopoChange &)
Play commands into polyTopoChange to extrude mesh.
Namespace for OpenFOAM.