1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "cellSplitter.H"
30 #include "directTopoChange.H"
31 #include "polyAddCell.H"
32 #include "polyAddFace.H"
33 #include "polyAddPoint.H"
34 #include "polyModifyFace.H"
35 #include "mapPolyMesh.H"
36 #include "meshTools.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(cellSplitter, 0);
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 void Foam::cellSplitter::getFaceInfo
60 if (!mesh_.isInternalFace(faceI))
62 patchID = mesh_.boundaryMesh().whichPatch(faceI);
65 zoneID = mesh_.faceZones().whichZone(faceI);
71 const faceZone& fZone = mesh_.faceZones()[zoneID];
73 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
78 // Find the new owner of faceI (since the original cell has been split into
80 Foam::label Foam::cellSplitter::newOwner
83 const Map<labelList>& cellToCells
86 label oldOwn = mesh_.faceOwner()[faceI];
88 Map<labelList>::const_iterator fnd = cellToCells.find(oldOwn);
90 if (fnd == cellToCells.end())
97 // Look up index of face in the cells' faces.
99 const labelList& newCells = fnd();
101 const cell& cFaces = mesh_.cells()[oldOwn];
103 return newCells[findIndex(cFaces, faceI)];
108 Foam::label Foam::cellSplitter::newNeighbour
111 const Map<labelList>& cellToCells
114 label oldNbr = mesh_.faceNeighbour()[faceI];
116 Map<labelList>::const_iterator fnd = cellToCells.find(oldNbr);
118 if (fnd == cellToCells.end())
125 // Look up index of face in the cells' faces.
127 const labelList& newCells = fnd();
129 const cell& cFaces = mesh_.cells()[oldNbr];
131 return newCells[findIndex(cFaces, faceI)];
136 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
138 // Construct from components
139 Foam::cellSplitter::cellSplitter(const polyMesh& mesh)
146 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
148 Foam::cellSplitter::~cellSplitter()
152 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
154 void Foam::cellSplitter::setRefinement
156 const Map<point>& cellToMidPoint,
157 directTopoChange& meshMod
160 addedPoints_.clear();
161 addedPoints_.resize(cellToMidPoint.size());
165 // Introduce cellToMidPoints.
168 forAllConstIter(Map<point>, cellToMidPoint, iter)
170 label cellI = iter.key();
172 label anchorPoint = mesh_.cellPoints()[cellI][0];
180 anchorPoint, // master point
181 -1, // zone for point
182 true // supports a cell
185 addedPoints_.insert(cellI, addedPointI);
187 //Pout<< "Added point " << addedPointI
188 // << iter() << " in cell " << cellI << " with centre "
189 // << mesh_.cellCentres()[cellI] << endl;
194 // Add cells (first one is modified original cell)
197 Map<labelList> cellToCells(cellToMidPoint.size());
199 forAllConstIter(Map<point>, cellToMidPoint, iter)
201 label cellI = iter.key();
203 const cell& cFaces = mesh_.cells()[cellI];
205 // Cells created for this cell.
206 labelList newCells(cFaces.size());
208 // First pyramid is the original cell
211 // Add other pyramids
212 for (label i = 1; i < cFaces.size(); i++)
222 cellI, // master cell
227 newCells[i] = addedCellI;
230 cellToCells.insert(cellI, newCells);
232 //Pout<< "Split cell " << cellI
233 // << " with centre " << mesh_.cellCentres()[cellI] << nl
234 // << " faces:" << cFaces << nl
235 // << " into :" << newCells << endl;
240 // Introduce internal faces. These go from edges of the cell to the mid
244 forAllConstIter(Map<point>, cellToMidPoint, iter)
246 label cellI = iter.key();
248 label midPointI = addedPoints_[cellI];
250 const cell& cFaces = mesh_.cells()[cellI];
252 const labelList& cEdges = mesh_.cellEdges()[cellI];
256 label edgeI = cEdges[i];
257 const edge& e = mesh_.edges()[edgeI];
259 // Get the faces on the cell using the edge
261 meshTools::getEdgeFaces(mesh_, cellI, edgeI, face0, face1);
263 // Get the cells on both sides of the face by indexing into cFaces.
264 // (since newly created cells are stored in cFaces order)
265 const labelList& newCells = cellToCells[cellI];
267 label cell0 = newCells[findIndex(cFaces, face0)];
268 label cell1 = newCells[findIndex(cFaces, face1)];
272 // Construct face to midpoint that is pointing away from
273 // (pyramid split off from) cellI
275 const face& f0 = mesh_.faces()[face0];
277 label index = findIndex(f0, e[0]);
279 bool edgeInFaceOrder = (f0[f0.fcIndex(index)] == e[1]);
281 // Check if cellI is the face owner
284 if (edgeInFaceOrder == (mesh_.faceOwner()[face0] == cellI))
286 // edge used in face order.
298 // Now newF points away from cell0
308 face0, // master face for addition
310 -1, // patch for face
312 false // face zone flip
318 // Construct face to midpoint that is pointing away from
319 // (pyramid split off from) cellI
321 const face& f1 = mesh_.faces()[face1];
323 label index = findIndex(f1, e[0]);
325 bool edgeInFaceOrder = (f1[f1.fcIndex(index)] == e[1]);
327 // Check if cellI is the face owner
330 if (edgeInFaceOrder == (mesh_.faceOwner()[face1] == cellI))
332 // edge used in face order.
344 // Now newF points away from cell1
354 face0, // master face for addition
356 -1, // patch for face
358 false // face zone flip
367 // Update all existing faces for split owner or neighbour.
371 // Mark off affected face.
372 boolList faceUpToDate(mesh_.nFaces(), true);
374 forAllConstIter(Map<point>, cellToMidPoint, iter)
376 label cellI = iter.key();
378 const cell& cFaces = mesh_.cells()[cellI];
382 label faceI = cFaces[i];
384 faceUpToDate[faceI] = false;
388 forAll(faceUpToDate, faceI)
390 if (!faceUpToDate[faceI])
392 const face& f = mesh_.faces()[faceI];
394 if (mesh_.isInternalFace(faceI))
396 label newOwn = newOwner(faceI, cellToCells);
397 label newNbr = newNeighbour(faceI, cellToCells);
410 -1, // patch for face
411 false, // remove from zone
413 false // face zone flip
428 -1, // patch for face
429 false, // remove from zone
431 false // face zone flip
439 label newOwn = newOwner(faceI, cellToCells);
441 label patchID, zoneID, zoneFlip;
442 getFaceInfo(faceI, patchID, zoneID, zoneFlip);
448 mesh_.faces()[faceI],
453 patchID, // patch for face
454 false, // remove from zone
455 zoneID, // zone for face
456 zoneFlip // face zone flip
461 faceUpToDate[faceI] = true;
467 void Foam::cellSplitter::updateMesh(const mapPolyMesh& morphMap)
469 // Create copy since we're deleting entries. Only if both cell and added
470 // point get mapped do they get inserted.
471 Map<label> newAddedPoints(addedPoints_.size());
473 forAllConstIter(Map<label>, addedPoints_, iter)
475 label oldCellI = iter.key();
477 label newCellI = morphMap.reverseCellMap()[oldCellI];
479 label oldPointI = iter();
481 label newPointI = morphMap.reversePointMap()[oldPointI];
483 if (newCellI >= 0 && newPointI >= 0)
485 newAddedPoints.insert(newCellI, newPointI);
490 addedPoints_.transfer(newAddedPoints);
494 // ************************************************************************* //