1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "cellSplitter.H"
28 #include "polyTopoChange.H"
29 #include "polyAddCell.H"
30 #include "polyAddFace.H"
31 #include "polyAddPoint.H"
32 #include "polyModifyFace.H"
33 #include "mapPolyMesh.H"
34 #include "meshTools.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(Foam::cellSplitter, 0);
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 void Foam::cellSplitter::getFaceInfo
54 if (!mesh_.isInternalFace(faceI))
56 patchID = mesh_.boundaryMesh().whichPatch(faceI);
59 zoneID = mesh_.faceZones().whichZone(faceI);
65 const faceZone& fZone = mesh_.faceZones()[zoneID];
67 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
72 // Find the new owner of faceI (since the original cell has been split into
74 Foam::label Foam::cellSplitter::newOwner
77 const Map<labelList>& cellToCells
80 label oldOwn = mesh_.faceOwner()[faceI];
82 Map<labelList>::const_iterator fnd = cellToCells.find(oldOwn);
84 if (fnd == cellToCells.end())
91 // Look up index of face in the cells' faces.
93 const labelList& newCells = fnd();
95 const cell& cFaces = mesh_.cells()[oldOwn];
97 return newCells[findIndex(cFaces, faceI)];
102 Foam::label Foam::cellSplitter::newNeighbour
105 const Map<labelList>& cellToCells
108 label oldNbr = mesh_.faceNeighbour()[faceI];
110 Map<labelList>::const_iterator fnd = cellToCells.find(oldNbr);
112 if (fnd == cellToCells.end())
119 // Look up index of face in the cells' faces.
121 const labelList& newCells = fnd();
123 const cell& cFaces = mesh_.cells()[oldNbr];
125 return newCells[findIndex(cFaces, faceI)];
130 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
132 // Construct from components
133 Foam::cellSplitter::cellSplitter(const polyMesh& mesh)
140 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
142 Foam::cellSplitter::~cellSplitter()
146 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
148 void Foam::cellSplitter::setRefinement
150 const Map<point>& cellToMidPoint,
151 polyTopoChange& meshMod
154 addedPoints_.clear();
155 addedPoints_.resize(cellToMidPoint.size());
159 // Introduce cellToMidPoints.
162 forAllConstIter(Map<point>, cellToMidPoint, iter)
164 label cellI = iter.key();
166 label anchorPoint = mesh_.cellPoints()[cellI][0];
174 anchorPoint, // master point
175 -1, // zone for point
176 true // supports a cell
179 addedPoints_.insert(cellI, addedPointI);
181 //Pout<< "Added point " << addedPointI
182 // << iter() << " in cell " << cellI << " with centre "
183 // << mesh_.cellCentres()[cellI] << endl;
188 // Add cells (first one is modified original cell)
191 Map<labelList> cellToCells(cellToMidPoint.size());
193 forAllConstIter(Map<point>, cellToMidPoint, iter)
195 label cellI = iter.key();
197 const cell& cFaces = mesh_.cells()[cellI];
199 // Cells created for this cell.
200 labelList newCells(cFaces.size());
202 // First pyramid is the original cell
205 // Add other pyramids
206 for (label i = 1; i < cFaces.size(); i++)
216 cellI, // master cell
221 newCells[i] = addedCellI;
224 cellToCells.insert(cellI, newCells);
226 //Pout<< "Split cell " << cellI
227 // << " with centre " << mesh_.cellCentres()[cellI] << nl
228 // << " faces:" << cFaces << nl
229 // << " into :" << newCells << endl;
234 // Introduce internal faces. These go from edges of the cell to the mid
238 forAllConstIter(Map<point>, cellToMidPoint, iter)
240 label cellI = iter.key();
242 label midPointI = addedPoints_[cellI];
244 const cell& cFaces = mesh_.cells()[cellI];
246 const labelList& cEdges = mesh_.cellEdges()[cellI];
250 label edgeI = cEdges[i];
251 const edge& e = mesh_.edges()[edgeI];
253 // Get the faces on the cell using the edge
255 meshTools::getEdgeFaces(mesh_, cellI, edgeI, face0, face1);
257 // Get the cells on both sides of the face by indexing into cFaces.
258 // (since newly created cells are stored in cFaces order)
259 const labelList& newCells = cellToCells[cellI];
261 label cell0 = newCells[findIndex(cFaces, face0)];
262 label cell1 = newCells[findIndex(cFaces, face1)];
266 // Construct face to midpoint that is pointing away from
267 // (pyramid split off from) cellI
269 const face& f0 = mesh_.faces()[face0];
271 label index = findIndex(f0, e[0]);
273 bool edgeInFaceOrder = (f0[f0.fcIndex(index)] == e[1]);
275 // Check if cellI is the face owner
278 if (edgeInFaceOrder == (mesh_.faceOwner()[face0] == cellI))
280 // edge used in face order.
292 // Now newF points away from cell0
302 face0, // master face for addition
304 -1, // patch for face
306 false // face zone flip
312 // Construct face to midpoint that is pointing away from
313 // (pyramid split off from) cellI
315 const face& f1 = mesh_.faces()[face1];
317 label index = findIndex(f1, e[0]);
319 bool edgeInFaceOrder = (f1[f1.fcIndex(index)] == e[1]);
321 // Check if cellI is the face owner
324 if (edgeInFaceOrder == (mesh_.faceOwner()[face1] == cellI))
326 // edge used in face order.
338 // Now newF points away from cell1
348 face0, // master face for addition
350 -1, // patch for face
352 false // face zone flip
361 // Update all existing faces for split owner or neighbour.
365 // Mark off affected face.
366 boolList faceUpToDate(mesh_.nFaces(), true);
368 forAllConstIter(Map<point>, cellToMidPoint, iter)
370 label cellI = iter.key();
372 const cell& cFaces = mesh_.cells()[cellI];
376 label faceI = cFaces[i];
378 faceUpToDate[faceI] = false;
382 forAll(faceUpToDate, faceI)
384 if (!faceUpToDate[faceI])
386 const face& f = mesh_.faces()[faceI];
388 if (mesh_.isInternalFace(faceI))
390 label newOwn = newOwner(faceI, cellToCells);
391 label newNbr = newNeighbour(faceI, cellToCells);
404 -1, // patch for face
405 false, // remove from zone
407 false // face zone flip
422 -1, // patch for face
423 false, // remove from zone
425 false // face zone flip
433 label newOwn = newOwner(faceI, cellToCells);
435 label patchID, zoneID, zoneFlip;
436 getFaceInfo(faceI, patchID, zoneID, zoneFlip);
442 mesh_.faces()[faceI],
447 patchID, // patch for face
448 false, // remove from zone
449 zoneID, // zone for face
450 zoneFlip // face zone flip
455 faceUpToDate[faceI] = true;
461 void Foam::cellSplitter::updateMesh(const mapPolyMesh& morphMap)
463 // Create copy since we're deleting entries. Only if both cell and added
464 // point get mapped do they get inserted.
465 Map<label> newAddedPoints(addedPoints_.size());
467 forAllConstIter(Map<label>, addedPoints_, iter)
469 label oldCellI = iter.key();
471 label newCellI = morphMap.reverseCellMap()[oldCellI];
473 label oldPointI = iter();
475 label newPointI = morphMap.reversePointMap()[oldPointI];
477 if (newCellI >= 0 && newPointI >= 0)
479 newAddedPoints.insert(newCellI, newPointI);
484 addedPoints_.transfer(newAddedPoints);
488 // ************************************************************************* //