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
27 \*---------------------------------------------------------------------------*/
29 #include "cellSplitter.H"
31 #include "polyTopoChange.H"
32 #include "polyAddCell.H"
33 #include "polyAddFace.H"
34 #include "polyAddPoint.H"
35 #include "polyModifyFace.H"
36 #include "mapPolyMesh.H"
37 #include "meshTools.H"
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 defineTypeNameAndDebug(cellSplitter, 0);
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 void Foam::cellSplitter::getFaceInfo
61 if (!mesh_.isInternalFace(faceI))
63 patchID = mesh_.boundaryMesh().whichPatch(faceI);
66 zoneID = mesh_.faceZones().whichZone(faceI);
72 const faceZone& fZone = mesh_.faceZones()[zoneID];
74 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
79 // Find the new owner of faceI (since the original cell has been split into
81 Foam::label Foam::cellSplitter::newOwner
84 const Map<labelList>& cellToCells
87 label oldOwn = mesh_.faceOwner()[faceI];
89 Map<labelList>::const_iterator fnd = cellToCells.find(oldOwn);
91 if (fnd == cellToCells.end())
98 // Look up index of face in the cells' faces.
100 const labelList& newCells = fnd();
102 const cell& cFaces = mesh_.cells()[oldOwn];
104 return newCells[findIndex(cFaces, faceI)];
109 Foam::label Foam::cellSplitter::newNeighbour
112 const Map<labelList>& cellToCells
115 label oldNbr = mesh_.faceNeighbour()[faceI];
117 Map<labelList>::const_iterator fnd = cellToCells.find(oldNbr);
119 if (fnd == cellToCells.end())
126 // Look up index of face in the cells' faces.
128 const labelList& newCells = fnd();
130 const cell& cFaces = mesh_.cells()[oldNbr];
132 return newCells[findIndex(cFaces, faceI)];
137 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
139 // Construct from components
140 Foam::cellSplitter::cellSplitter(const polyMesh& mesh)
147 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
149 Foam::cellSplitter::~cellSplitter()
153 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
155 void Foam::cellSplitter::setRefinement
157 const Map<point>& cellToMidPoint,
158 polyTopoChange& meshMod
161 addedPoints_.clear();
162 addedPoints_.resize(cellToMidPoint.size());
166 // Introduce cellToMidPoints.
169 forAllConstIter(Map<point>, cellToMidPoint, iter)
171 label cellI = iter.key();
173 label anchorPoint = mesh_.cellPoints()[cellI][0];
181 anchorPoint, // master point
182 -1, // zone for point
183 true // supports a cell
186 addedPoints_.insert(cellI, addedPointI);
188 //Pout<< "Added point " << addedPointI
189 // << iter() << " in cell " << cellI << " with centre "
190 // << mesh_.cellCentres()[cellI] << endl;
195 // Add cells (first one is modified original cell)
198 Map<labelList> cellToCells(cellToMidPoint.size());
200 forAllConstIter(Map<point>, cellToMidPoint, iter)
202 label cellI = iter.key();
204 const cell& cFaces = mesh_.cells()[cellI];
206 // Cells created for this cell.
207 labelList newCells(cFaces.size());
209 // First pyramid is the original cell
212 // Add other pyramids
213 for (label i = 1; i < cFaces.size(); i++)
223 cellI, // master cell
228 newCells[i] = addedCellI;
231 cellToCells.insert(cellI, newCells);
233 //Pout<< "Split cell " << cellI
234 // << " with centre " << mesh_.cellCentres()[cellI] << nl
235 // << " faces:" << cFaces << nl
236 // << " into :" << newCells << endl;
241 // Introduce internal faces. These go from edges of the cell to the mid
245 forAllConstIter(Map<point>, cellToMidPoint, iter)
247 label cellI = iter.key();
249 label midPointI = addedPoints_[cellI];
251 const cell& cFaces = mesh_.cells()[cellI];
253 const labelList& cEdges = mesh_.cellEdges()[cellI];
257 label edgeI = cEdges[i];
258 const edge& e = mesh_.edges()[edgeI];
260 // Get the faces on the cell using the edge
262 meshTools::getEdgeFaces(mesh_, cellI, edgeI, face0, face1);
264 // Get the cells on both sides of the face by indexing into cFaces.
265 // (since newly created cells are stored in cFaces order)
266 const labelList& newCells = cellToCells[cellI];
268 label cell0 = newCells[findIndex(cFaces, face0)];
269 label cell1 = newCells[findIndex(cFaces, face1)];
273 // Construct face to midpoint that is pointing away from
274 // (pyramid split off from) cellI
276 const face& f0 = mesh_.faces()[face0];
278 label index = findIndex(f0, e[0]);
280 bool edgeInFaceOrder = (f0[f0.fcIndex(index)] == e[1]);
282 // Check if cellI is the face owner
285 if (edgeInFaceOrder == (mesh_.faceOwner()[face0] == cellI))
287 // edge used in face order.
299 // Now newF points away from cell0
309 face0, // master face for addition
311 -1, // patch for face
313 false // face zone flip
319 // Construct face to midpoint that is pointing away from
320 // (pyramid split off from) cellI
322 const face& f1 = mesh_.faces()[face1];
324 label index = findIndex(f1, e[0]);
326 bool edgeInFaceOrder = (f1[f1.fcIndex(index)] == e[1]);
328 // Check if cellI is the face owner
331 if (edgeInFaceOrder == (mesh_.faceOwner()[face1] == cellI))
333 // edge used in face order.
345 // Now newF points away from cell1
355 face0, // master face for addition
357 -1, // patch for face
359 false // face zone flip
368 // Update all existing faces for split owner or neighbour.
372 // Mark off affected face.
373 boolList faceUpToDate(mesh_.nFaces(), true);
375 forAllConstIter(Map<point>, cellToMidPoint, iter)
377 label cellI = iter.key();
379 const cell& cFaces = mesh_.cells()[cellI];
383 label faceI = cFaces[i];
385 faceUpToDate[faceI] = false;
389 forAll(faceUpToDate, faceI)
391 if (!faceUpToDate[faceI])
393 const face& f = mesh_.faces()[faceI];
395 if (mesh_.isInternalFace(faceI))
397 label newOwn = newOwner(faceI, cellToCells);
398 label newNbr = newNeighbour(faceI, cellToCells);
411 -1, // patch for face
412 false, // remove from zone
414 false // face zone flip
429 -1, // patch for face
430 false, // remove from zone
432 false // face zone flip
440 label newOwn = newOwner(faceI, cellToCells);
442 label patchID, zoneID, zoneFlip;
443 getFaceInfo(faceI, patchID, zoneID, zoneFlip);
449 mesh_.faces()[faceI],
454 patchID, // patch for face
455 false, // remove from zone
456 zoneID, // zone for face
457 zoneFlip // face zone flip
462 faceUpToDate[faceI] = true;
468 void Foam::cellSplitter::updateMesh(const mapPolyMesh& morphMap)
470 // Create copy since we're deleting entries. Only if both cell and added
471 // point get mapped do they get inserted.
472 Map<label> newAddedPoints(addedPoints_.size());
474 forAllConstIter(Map<label>, addedPoints_, iter)
476 label oldCellI = iter.key();
478 label newCellI = morphMap.reverseCellMap()[oldCellI];
480 label oldPointI = iter();
482 label newPointI = morphMap.reversePointMap()[oldPointI];
484 if (newCellI >= 0 && newPointI >= 0)
486 newAddedPoints.insert(newCellI, newPointI);
491 addedPoints_.transfer(newAddedPoints);
495 // ************************************************************************* //