1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "mirrorFvMesh.H"
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 const Foam::label Foam::mirrorFvMesh::cellRenumber[8][8] =
35 {-1, -1, -1, -1, -1, -1, -1, -1}, // unknown
36 {-1, -1, -1, -1, -1, -1, -1, -1}, //
37 {-1, -1, -1, -1, -1, -1, -1, -1}, //
38 { 0, 3, 2, 1, 4, 7, 6, 5}, // hex
39 { 2, 1, 0, 5, 4, 3, 6, -1}, // wedge
40 { 0, 2, 1, 3, 5, 4, -1, -1}, // prism
41 { 0, 3, 2, 1, 4, -1, -1, -1}, // pyramid
42 { 2, 1, 0, 3, -1, -1, -1, -1}, // tet
45 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
47 Foam::mirrorFvMesh::mirrorFvMesh(const IOobject& io)
63 plane mirrorPlane(mirrorMeshDict_);
67 readScalar(mirrorMeshDict_.lookup("planeTolerance"))
70 const pointField& oldPoints = points();
71 const faceList& oldFaces = faces();
72 const cellList& oldCells = cells();
73 const label nOldInternalFaces = nInternalFaces();
74 const polyPatchList& oldPatches = boundaryMesh();
77 Info << "Mirroring points. Old points: " << oldPoints.size();
79 pointField newPoints(2*oldPoints.size());
82 labelList mirrorPointLookup(oldPoints.size(), -1);
84 // Grab the old points
85 forAll (oldPoints, pointI)
87 newPoints[nNewPoints] = oldPoints[pointI];
91 forAll (oldPoints, pointI)
94 mirrorPlane.normalIntersect
100 // Check plane on tolerance
101 if (mag(alpha) > planeTolerance)
103 // The point gets mirrored
104 newPoints[nNewPoints] =
105 oldPoints[pointI] + 2.0*alpha*mirrorPlane.normal();
107 // remember the point correspondence
108 mirrorPointLookup[pointI] = nNewPoints;
113 // The point is on the plane and does not get mirrored
114 // Adjust plane location
115 newPoints[nNewPoints] =
116 oldPoints[pointI] + alpha*mirrorPlane.normal();
118 mirrorPointLookup[pointI] = pointI;
122 // Reset the size of the point list
123 Info << " New points: " << nNewPoints << endl;
124 newPoints.setSize(nNewPoints);
126 Info << "Mirroring faces. Old faces: " << oldFaces.size();
129 // During mirroring, the faces that were previously boundary faces
130 // in the mirror plane may become ineternal faces. In order to
131 // deal with the ordering of the faces, the algorithm is split
132 // into two parts. For original faces, the internal faces are
133 // distributed to their owner cells. Once all internal faces are
134 // distributed, the boundary faces are visited and if they are in
135 // the mirror plane they are added to the master cells (the future
136 // boundary faces are not touched). After the first phase, the
137 // internal faces are collected in the cell order and numbering
138 // information is added. Then, the internal faces are mirrored
139 // and the face numbering data is stored for the mirrored section.
140 // Once all the internal faces are mirrored, the boundary faces
141 // are added by mirroring the faces patch by patch.
143 // Distribute internal faces
144 labelListList newCellFaces(oldCells.size());
146 const unallocLabelList& oldOwnerStart = lduAddr().ownerStartAddr();
148 forAll (newCellFaces, cellI)
150 labelList& curFaces = newCellFaces[cellI];
152 const label s = oldOwnerStart[cellI];
153 const label e = oldOwnerStart[cellI + 1];
155 curFaces.setSize(e - s);
163 // Distribute boundary faces. Remember the faces that have been inserted
165 boolListList insertedBouFace(oldPatches.size());
167 forAll (oldPatches, patchI)
169 const polyPatch& curPatch = oldPatches[patchI];
170 boolList& curInsBouFace = insertedBouFace[patchI];
172 curInsBouFace.setSize(curPatch.size());
173 curInsBouFace = false;
175 // Get faceCells for face insertion
176 const unallocLabelList& curFaceCells = curPatch.faceCells();
177 const label curStart = curPatch.start();
179 forAll (curPatch, faceI)
181 // Find out if the mirrored face is identical to the
182 // original. If so, the face needs to become internal and
183 // added to its owner cell
184 const face& origFace = curPatch[faceI];
186 face mirrorFace(origFace.size());
187 forAll (mirrorFace, pointI)
189 mirrorFace[pointI] = mirrorPointLookup[origFace[pointI]];
192 if (origFace == mirrorFace)
194 // The mirror is identical to current face. This will
195 // become an internal face
196 const label oldSize = newCellFaces[curFaceCells[faceI]].size();
198 newCellFaces[curFaceCells[faceI]].setSize(oldSize + 1);
199 newCellFaces[curFaceCells[faceI]][oldSize] = curStart + faceI;
201 curInsBouFace[faceI] = true;
206 // Construct the new list of faces. Boundary faces are added
207 // last, cush that each patch is mirrored separately. The
208 // addressing is stored in two separate arrays: first for the
209 // original cells (face order has changed) and then for the
211 labelList masterFaceLookup(oldFaces.size(), -1);
212 labelList mirrorFaceLookup(oldFaces.size(), -1);
214 faceList newFaces(2*oldFaces.size());
217 // Insert original (internal) faces
218 forAll (newCellFaces, cellI)
220 const labelList& curCellFaces = newCellFaces[cellI];
222 forAll (curCellFaces, cfI)
224 newFaces[nNewFaces] = oldFaces[curCellFaces[cfI]];
225 masterFaceLookup[curCellFaces[cfI]] = nNewFaces;
231 // Mirror internal faces
232 for (label faceI = 0; faceI < nOldInternalFaces; faceI++)
234 const face& oldFace = oldFaces[faceI];
235 face& nf = newFaces[nNewFaces];
236 nf.setSize(oldFace.size());
238 nf[0] = mirrorPointLookup[oldFace[0]];
240 for (label i = 1; i < oldFace.size(); i++)
242 nf[i] = mirrorPointLookup[oldFace[oldFace.size() - i]];
245 mirrorFaceLookup[faceI] = nNewFaces;
249 // Mirror boundary faces patch by patch
251 wordList newPatchTypes(boundary().size());
252 wordList newPatchNames(boundary().size());
253 labelList newPatchSizes(boundary().size(), -1);
254 labelList newPatchStarts(boundary().size(), -1);
255 label nNewPatches = 0;
257 forAll (boundaryMesh(), patchI)
259 const label curPatchSize = boundaryMesh()[patchI].size();
260 const label curPatchStart = boundaryMesh()[patchI].start();
261 const boolList& curInserted = insertedBouFace[patchI];
263 newPatchStarts[nNewPatches] = nNewFaces;
266 for (label faceI = 0; faceI < curPatchSize; faceI++)
268 // Check if the face has already been added. If not, add it and
269 // insert the numbering details.
270 if (!curInserted[faceI])
272 newFaces[nNewFaces] = oldFaces[curPatchStart + faceI];
274 masterFaceLookup[curPatchStart + faceI] = nNewFaces;
280 for (label faceI = 0; faceI < curPatchSize; faceI++)
282 // Check if the face has already been added. If not, add it and
283 // insert the numbering details.
284 if (!curInserted[faceI])
286 const face& oldFace = oldFaces[curPatchStart + faceI];
287 face& nf = newFaces[nNewFaces];
288 nf.setSize(oldFace.size());
290 nf[0] = mirrorPointLookup[oldFace[0]];
292 for (label i = 1; i < oldFace.size(); i++)
294 nf[i] = mirrorPointLookup[oldFace[oldFace.size() - i]];
297 mirrorFaceLookup[curPatchStart + faceI] = nNewFaces;
302 // Grab the index of the master face for the mirror side
303 mirrorFaceLookup[curPatchStart + faceI] =
304 masterFaceLookup[curPatchStart + faceI];
308 // If patch exists, grab the name and type of the original patch
309 if (nNewFaces > newPatchStarts[nNewPatches])
311 newPatchTypes[nNewPatches] = boundaryMesh()[patchI].type();
312 newPatchNames[nNewPatches] = boundaryMesh()[patchI].name();
313 newPatchSizes[nNewPatches] =
314 nNewFaces - newPatchStarts[nNewPatches];
321 newFaces.setSize(nNewFaces);
322 Info << " New faces: " << nNewFaces << endl;
324 newPatchTypes.setSize(nNewPatches);
325 newPatchNames.setSize(nNewPatches);
326 newPatchSizes.setSize(nNewPatches);
327 newPatchStarts.setSize(nNewPatches);
329 Info << "Mirroring patches. Old patches: " << boundary().size()
330 << " New patches: " << nNewPatches << endl;
332 Info<< "Mirroring cells. Old cells: " << oldCells.size()
333 << " New cells: " << 2*oldCells.size() << endl;
335 cellList newCells(2*oldCells.size());
338 // Grab the original cells. Take care of face renumbering.
339 forAll (oldCells, cellI)
341 const cell& oc = oldCells[cellI];
343 cell& nc = newCells[nNewCells];
344 nc.setSize(oc.size());
348 nc[i] = masterFaceLookup[oc[i]];
355 forAll (oldCells, cellI)
357 const cell& oc = oldCells[cellI];
359 cell& nc = newCells[nNewCells];
360 nc.setSize(oc.size());
364 nc[i] = mirrorFaceLookup[oc[i]];
370 // Mirror the cell shapes
371 Info << "Mirroring cell shapes." << endl;
373 Info << nl << "Creating new mesh" << endl;
374 mirrorMeshPtr_ = new fvMesh
382 fvMesh& pMesh = *mirrorMeshPtr_;
384 // Add the boundary patches
385 List<polyPatch*> p(newPatchTypes.size());
389 p[patchI] = polyPatch::New
391 newPatchTypes[patchI],
392 newPatchNames[patchI],
393 newPatchSizes[patchI],
394 newPatchStarts[patchI],
404 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
406 Foam::mirrorFvMesh::~mirrorFvMesh()
410 // ************************************************************************* //