mirrorFvMesh.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 | Copyright (C) 2011-2016 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 "mirrorFvMesh.H"
27 #include "Time.H"
28 #include "plane.H"
29 
30 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
31 
32 Foam::mirrorFvMesh::mirrorFvMesh(const IOobject& io)
33 :
34  fvMesh(io),
35  mirrorMeshDict_
36  (
37  IOobject
38  (
39  "mirrorMeshDict",
40  time().system(),
41  *this,
42  IOobject::MUST_READ_IF_MODIFIED,
43  IOobject::NO_WRITE
44  )
45  ),
46  mirrorMeshPtr_(NULL)
47 {
48  plane mirrorPlane(mirrorMeshDict_);
49 
50  scalar planeTolerance
51  (
52  readScalar(mirrorMeshDict_.lookup("planeTolerance"))
53  );
54 
55  const pointField& oldPoints = points();
56  const faceList& oldFaces = faces();
57  const cellList& oldCells = cells();
58  const label nOldInternalFaces = nInternalFaces();
59  const polyPatchList& oldPatches = boundaryMesh();
60 
61  // Mirror the points
62  Info<< "Mirroring points. Old points: " << oldPoints.size();
63 
64  pointField newPoints(2*oldPoints.size());
65  label nNewPoints = 0;
66 
67  labelList mirrorPointLookup(oldPoints.size(), -1);
68 
69  // Grab the old points
70  forAll(oldPoints, pointi)
71  {
72  newPoints[nNewPoints] = oldPoints[pointi];
73  nNewPoints++;
74  }
75 
76  forAll(oldPoints, pointi)
77  {
78  scalar alpha =
79  mirrorPlane.normalIntersect
80  (
81  oldPoints[pointi],
82  mirrorPlane.normal()
83  );
84 
85  // Check plane on tolerance
86  if (mag(alpha) > planeTolerance)
87  {
88  // The point gets mirrored
89  newPoints[nNewPoints] =
90  oldPoints[pointi] + 2.0*alpha*mirrorPlane.normal();
91 
92  // remember the point correspondence
93  mirrorPointLookup[pointi] = nNewPoints;
94  nNewPoints++;
95  }
96  else
97  {
98  // The point is on the plane and does not get mirrored
99  // Adjust plane location
100  newPoints[nNewPoints] =
101  oldPoints[pointi] + alpha*mirrorPlane.normal();
102 
103  mirrorPointLookup[pointi] = pointi;
104  }
105  }
106 
107  // Reset the size of the point list
108  Info<< " New points: " << nNewPoints << endl;
109  newPoints.setSize(nNewPoints);
110 
111  Info<< "Mirroring faces. Old faces: " << oldFaces.size();
112 
113  // Algorithm:
114  // During mirroring, the faces that were previously boundary faces
115  // in the mirror plane may become ineternal faces. In order to
116  // deal with the ordering of the faces, the algorithm is split
117  // into two parts. For original faces, the internal faces are
118  // distributed to their owner cells. Once all internal faces are
119  // distributed, the boundary faces are visited and if they are in
120  // the mirror plane they are added to the master cells (the future
121  // boundary faces are not touched). After the first phase, the
122  // internal faces are collected in the cell order and numbering
123  // information is added. Then, the internal faces are mirrored
124  // and the face numbering data is stored for the mirrored section.
125  // Once all the internal faces are mirrored, the boundary faces
126  // are added by mirroring the faces patch by patch.
127 
128  // Distribute internal faces
129  labelListList newCellFaces(oldCells.size());
130 
131  const labelUList& oldOwnerStart = lduAddr().ownerStartAddr();
132 
133  forAll(newCellFaces, celli)
134  {
135  labelList& curFaces = newCellFaces[celli];
136 
137  const label s = oldOwnerStart[celli];
138  const label e = oldOwnerStart[celli + 1];
139 
140  curFaces.setSize(e - s);
141 
142  forAll(curFaces, i)
143  {
144  curFaces[i] = s + i;
145  }
146  }
147 
148  // Distribute boundary faces. Remember the faces that have been inserted
149  // as internal
150  boolListList insertedBouFace(oldPatches.size());
151 
152  forAll(oldPatches, patchi)
153  {
154  const polyPatch& curPatch = oldPatches[patchi];
155 
156  if (curPatch.coupled())
157  {
159  << "Found coupled patch " << curPatch.name() << endl
160  << " Mirroring faces on coupled patches destroys"
161  << " the ordering. This might be fixed by running a dummy"
162  << " createPatch afterwards." << endl;
163  }
164 
165  boolList& curInsBouFace = insertedBouFace[patchi];
166 
167  curInsBouFace.setSize(curPatch.size());
168  curInsBouFace = false;
169 
170  // Get faceCells for face insertion
171  const labelUList& curFaceCells = curPatch.faceCells();
172  const label curStart = curPatch.start();
173 
174  forAll(curPatch, facei)
175  {
176  // Find out if the mirrored face is identical to the
177  // original. If so, the face needs to become internal and
178  // added to its owner cell
179  const face& origFace = curPatch[facei];
180 
181  face mirrorFace(origFace.size());
182  forAll(mirrorFace, pointi)
183  {
184  mirrorFace[pointi] = mirrorPointLookup[origFace[pointi]];
185  }
186 
187  if (origFace == mirrorFace)
188  {
189  // The mirror is identical to current face. This will
190  // become an internal face
191  const label oldSize = newCellFaces[curFaceCells[facei]].size();
192 
193  newCellFaces[curFaceCells[facei]].setSize(oldSize + 1);
194  newCellFaces[curFaceCells[facei]][oldSize] = curStart + facei;
195 
196  curInsBouFace[facei] = true;
197  }
198  }
199  }
200 
201  // Construct the new list of faces. Boundary faces are added
202  // last, cush that each patch is mirrored separately. The
203  // addressing is stored in two separate arrays: first for the
204  // original cells (face order has changed) and then for the
205  // mirrored cells.
206  labelList masterFaceLookup(oldFaces.size(), -1);
207  labelList mirrorFaceLookup(oldFaces.size(), -1);
208 
209  faceList newFaces(2*oldFaces.size());
210  label nNewFaces = 0;
211 
212  // Insert original (internal) faces
213  forAll(newCellFaces, celli)
214  {
215  const labelList& curCellFaces = newCellFaces[celli];
216 
217  forAll(curCellFaces, cfI)
218  {
219  newFaces[nNewFaces] = oldFaces[curCellFaces[cfI]];
220  masterFaceLookup[curCellFaces[cfI]] = nNewFaces;
221 
222  nNewFaces++;
223  }
224  }
225 
226  // Mirror internal faces
227  for (label facei = 0; facei < nOldInternalFaces; facei++)
228  {
229  const face& oldFace = oldFaces[facei];
230  face& nf = newFaces[nNewFaces];
231  nf.setSize(oldFace.size());
232 
233  nf[0] = mirrorPointLookup[oldFace[0]];
234 
235  for (label i = 1; i < oldFace.size(); i++)
236  {
237  nf[i] = mirrorPointLookup[oldFace[oldFace.size() - i]];
238  }
239 
240  mirrorFaceLookup[facei] = nNewFaces;
241  nNewFaces++;
242  }
243 
244  // Mirror boundary faces patch by patch
245 
246 
247  labelList newToOldPatch(boundary().size(), -1);
248  labelList newPatchSizes(boundary().size(), -1);
249  labelList newPatchStarts(boundary().size(), -1);
250  label nNewPatches = 0;
251 
253  {
254  const label curPatchSize = boundaryMesh()[patchi].size();
255  const label curPatchStart = boundaryMesh()[patchi].start();
256  const boolList& curInserted = insertedBouFace[patchi];
257 
258  newPatchStarts[nNewPatches] = nNewFaces;
259 
260  // Master side
261  for (label facei = 0; facei < curPatchSize; facei++)
262  {
263  // Check if the face has already been added. If not, add it and
264  // insert the numbering details.
265  if (!curInserted[facei])
266  {
267  newFaces[nNewFaces] = oldFaces[curPatchStart + facei];
268 
269  masterFaceLookup[curPatchStart + facei] = nNewFaces;
270  nNewFaces++;
271  }
272  }
273 
274  // Mirror side
275  for (label facei = 0; facei < curPatchSize; facei++)
276  {
277  // Check if the face has already been added. If not, add it and
278  // insert the numbering details.
279  if (!curInserted[facei])
280  {
281  const face& oldFace = oldFaces[curPatchStart + facei];
282  face& nf = newFaces[nNewFaces];
283  nf.setSize(oldFace.size());
284 
285  nf[0] = mirrorPointLookup[oldFace[0]];
286 
287  for (label i = 1; i < oldFace.size(); i++)
288  {
289  nf[i] = mirrorPointLookup[oldFace[oldFace.size() - i]];
290  }
291 
292  mirrorFaceLookup[curPatchStart + facei] = nNewFaces;
293  nNewFaces++;
294  }
295  else
296  {
297  // Grab the index of the master face for the mirror side
298  mirrorFaceLookup[curPatchStart + facei] =
299  masterFaceLookup[curPatchStart + facei];
300  }
301  }
302 
303  // If patch exists, grab the name and type of the original patch
304  if (nNewFaces > newPatchStarts[nNewPatches])
305  {
306  newToOldPatch[nNewPatches] = patchi;
307 
308  newPatchSizes[nNewPatches] =
309  nNewFaces - newPatchStarts[nNewPatches];
310 
311  nNewPatches++;
312  }
313  }
314 
315  // Tidy up the lists
316  newFaces.setSize(nNewFaces);
317  Info<< " New faces: " << nNewFaces << endl;
318 
319  newToOldPatch.setSize(nNewPatches);
320  newPatchSizes.setSize(nNewPatches);
321  newPatchStarts.setSize(nNewPatches);
322 
323  Info<< "Mirroring patches. Old patches: " << boundary().size()
324  << " New patches: " << nNewPatches << endl;
325 
326  Info<< "Mirroring cells. Old cells: " << oldCells.size()
327  << " New cells: " << 2*oldCells.size() << endl;
328 
329  cellList newCells(2*oldCells.size());
330  label nNewCells = 0;
331 
332  // Grab the original cells. Take care of face renumbering.
333  forAll(oldCells, celli)
334  {
335  const cell& oc = oldCells[celli];
336 
337  cell& nc = newCells[nNewCells];
338  nc.setSize(oc.size());
339 
340  forAll(oc, i)
341  {
342  nc[i] = masterFaceLookup[oc[i]];
343  }
344 
345  nNewCells++;
346  }
347 
348  // Mirror the cells
349  forAll(oldCells, celli)
350  {
351  const cell& oc = oldCells[celli];
352 
353  cell& nc = newCells[nNewCells];
354  nc.setSize(oc.size());
355 
356  forAll(oc, i)
357  {
358  nc[i] = mirrorFaceLookup[oc[i]];
359  }
360 
361  nNewCells++;
362  }
363 
364  // Mirror the cell shapes
365  Info<< "Mirroring cell shapes." << endl;
366 
367  Info<< nl << "Creating new mesh" << endl;
368  mirrorMeshPtr_ = new fvMesh
369  (
370  io,
371  xferMove(newPoints),
372  xferMove(newFaces),
373  xferMove(newCells)
374  );
375 
376  fvMesh& pMesh = *mirrorMeshPtr_;
377 
378  // Add the boundary patches
379  List<polyPatch*> p(newPatchSizes.size());
380 
381  forAll(p, patchi)
382  {
383  p[patchi] = boundaryMesh()[newToOldPatch[patchi]].clone
384  (
385  pMesh.boundaryMesh(),
386  patchi,
387  newPatchSizes[patchi],
388  newPatchStarts[patchi]
389  ).ptr();
390  }
391 
392  pMesh.addPatches(p);
393 }
394 
395 
396 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
397 
399 {}
400 
401 
402 // ************************************************************************* //
PtrList< polyPatch > polyPatchList
container classes for polyPatch
Definition: polyPatchList.H:45
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
#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
List< List< bool > > boolListList
Definition: boolList.H:51
List< face > faceList
Definition: faceListFwd.H:43
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
label size() const
Return number of elements in table.
const cellList & cells() const
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
UList< label > labelUList
Definition: UList.H:64
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Xfer< T > xferMove(T &)
Construct by transferring the contents of the arg.
Foam::autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:239
List< label > labelList
A List of labels.
Definition: labelList.H:56
faceListList boundary(nPatches)
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
static const char nl
Definition: Ostream.H:262
void setSize(const label)
Reset size of List.
Definition: List.C:295
label patchi
#define WarningInFunction
Report a warning using Foam::Warning.
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
volScalarField & p
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
label nInternalFaces() const
List< cell > cellList
list of cells
Definition: cellList.H:42
~mirrorFvMesh()
Destructor.
int system(const std::string &command)
Execute the specified command.
Definition: POSIX.C:1020
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29