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
26 Merge duplicate points created by arbitrary face coupling and remove unused
29 \*---------------------------------------------------------------------------*/
32 #include "demandDrivenData.H"
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 void starMesh::mergeCoupleFacePoints()
38 // mark all used points by looping through all faces in two goes.
39 // First, go into every cell and find min edge length. Use a
40 // fraction of that as a merge tolerance. Loop through all the
41 // points of the cell and query a merge against every other point
42 // of the same cell based on the current tolerance. If two points
43 // merge, find out if any of them already belongs to a "merge set"
44 // (group of points that merge together. If so, add the current
45 // points into the merge set and make sure that the merge label
46 // for the whole set is the lowest of all encountered vertices.
47 // This is stored in a mergeSetID list, under the index of the
48 // merge set. Once all cells (and thus points) are visited, go
49 // through the renumbering list and for each merging point use the
50 // label of the merge set as the new point label.
51 // This is VERY fancy. Use care if/when changing.
53 Info << endl << "Creating merge sets" << endl;
55 // Create a renumbering list for points
56 // In the first instance the renumbering list is used as a
58 labelList renumberPoints(points_.size(), -1);
60 // create storage of mergeSetIDs
61 label mergeIncrement = points_.size()/10;
62 labelList mergeSetID(mergeIncrement, -1);
66 forAll (cellFaces_, cellI)
68 const faceList& curFaces = cellFaces_[cellI];
70 // create a list of all points for the cell with duplicates
71 // and find the shortest edge length
73 label nPointsInCell = 0;
75 scalar pointMergeTol = GREAT;
77 forAll (curFaces, faceI)
79 nPointsInCell += curFaces[faceI].size();
81 edgeList curEdges = curFaces[faceI].edges();
83 forAll (curEdges, edgeI)
85 scalar length = curEdges[edgeI].mag(points_);
87 if (length < pointMergeTol)
89 pointMergeTol = length;
94 // set merge tolerance as a fraction of the shortest edge
95 pointMergeTol /= 100.0;
97 // create a list of points
98 labelList cellPoints(nPointsInCell);
99 label nAddedPoints = 0;
101 forAll (curFaces, faceI)
103 const face& f = curFaces[faceI];
107 cellPoints[nAddedPoints] = f[fI];
112 // loop n-squared through the local points and merge them up
113 for (label firstPI = 0; firstPI < cellPoints.size() - 1; firstPI++)
117 label otherPI = firstPI;
118 otherPI < cellPoints.size();
122 if (cellPoints[firstPI] != cellPoints[otherPI])
124 label a = cellPoints[firstPI];
125 label b = cellPoints[otherPI];
127 if (edge (a, b).mag(points_) < pointMergeTol)
129 // found a pair of points to merge
131 Info<< "Merging points " << a << " and " << b << endl;
134 // are the two points in a merge group?
135 label mergeSetA = -1;
136 label mergeSetB = -1;
138 if (renumberPoints[a] > -1)
140 mergeSetA = renumberPoints[a];
143 if (renumberPoints[b] > -1)
145 mergeSetB = renumberPoints[b];
148 if (mergeSetA == -1 && mergeSetB == -1)
150 // add new merge group
152 Info<< "adding new merge group " << nMergeSets
156 // mark points as belonging to a new merge set
157 renumberPoints[a] = nMergeSets;
158 renumberPoints[b] = nMergeSets;
160 mergeSetID[nMergeSets] = min(a, b);
163 if (nMergeSets >= mergeSetID.size())
165 Info << "Resizing mergeSetID" << endl;
168 (mergeSetID.size() + mergeIncrement);
171 else if (mergeSetA == -1 && mergeSetB != -1)
174 Info<< "adding point a into the merge set of b. "
175 << "a: " << a << endl;
178 // add point a into the merge set of b
179 renumberPoints[a] = mergeSetB;
181 // reset the min label of the mergeSet
182 mergeSetID[mergeSetB] =
183 min(a, mergeSetID[mergeSetB]);
185 else if (mergeSetA != -1 && mergeSetB == -1)
188 Info<< "adding point b into the merge set of a. "
189 << "b: " << b << endl;
192 // add point b into the merge set of a
193 renumberPoints[b] = mergeSetA;
195 // reset the min label of the mergeSet
196 mergeSetID[mergeSetA] =
197 min(b, mergeSetID[mergeSetA]);
199 else if (mergeSetA != mergeSetB)
201 // Points already belong to two different merge
202 // sets. Eliminate the higher merge set
203 label minMerge = min(mergeSetA, mergeSetB);
204 label maxMerge = max(mergeSetA, mergeSetB);
207 Info<< "Points already belong to two "
208 << "different merge sets. "
209 << "Eliminate the higher merge set. Sets: "
210 << minMerge << " and " << maxMerge << endl;
213 forAll (renumberPoints, elimI)
215 if (renumberPoints[elimI] == maxMerge)
217 renumberPoints[elimI] = minMerge;
221 // set the lower label
222 mergeSetID[minMerge] =
223 min(mergeSetID[minMerge], mergeSetID[maxMerge]);
231 mergeSetID.setSize(nMergeSets);
233 Info<< "Finished creating merge sets. Number of merge sets: "
234 << nMergeSets << "." << endl;
236 // Insert the primary point renumbering into the list
237 // Take care of possibly unused points in the list
238 forAll (renumberPoints, pointI)
240 if (renumberPoints[pointI] < 0)
243 renumberPoints[pointI] = pointI;
247 renumberPoints[pointI] = mergeSetID[renumberPoints[pointI]];
251 // Now every point carries either its own label or the lowest of
252 // the labels of the points it is merged with. Now do PRELIMINARY
253 // renumbering of all faces. This will only be used to see which
254 // points are still used!
256 forAll (cellFaces_, cellI)
258 faceList& prelimFaces = cellFaces_[cellI];
260 forAll (prelimFaces, faceI)
262 face oldFacePoints = prelimFaces[faceI];
264 face& prelimFacePoints = prelimFaces[faceI];
266 forAll (prelimFacePoints, pointI)
268 if (renumberPoints[oldFacePoints[pointI]] < 0)
270 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
271 << "Error in point renumbering. Old face: "
272 << oldFacePoints << endl
273 << "prelim face: " << prelimFacePoints
274 << abort(FatalError);
277 prelimFacePoints[pointI] =
278 renumberPoints[oldFacePoints[pointI]];
283 // First step complete. Reset the renumbering list, mark all used points,
284 // re-create the point list and renumber the whole lot
287 forAll (cellFaces_, cellI)
289 const faceList& curFaces = cellFaces_[cellI];
291 forAll (curFaces, faceI)
293 const face& curFacePoints = curFaces[faceI];
295 forAll (curFacePoints, pointI)
297 renumberPoints[curFacePoints[pointI]]++;
302 forAll (cellShapes_, cellI)
304 const labelList& curLabels = cellShapes_[cellI];
306 forAll (curLabels, pointI)
308 if (renumberPoints[curLabels[pointI]] == 0)
310 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
311 << "Error in point merging for cell "
312 << cellI << ". STAR index: " << starCellID_[cellI]
314 << "Point index: " << curLabels[pointI] << " STAR index "
315 << starPointID_[curLabels[pointI]] << endl
316 << "Please check the geometry for the cell." << endl;
321 label nUsedPoints = 0;
323 forAll (renumberPoints, pointI)
325 if (renumberPoints[pointI] > 0)
327 // This should be OK as the compressed points list will always
328 // have less points that the original lists. Even if there is
329 // no points removed, this will copy the list back onto itself
331 renumberPoints[pointI] = nUsedPoints;
332 points_[nUsedPoints] = points_[pointI];
338 renumberPoints[pointI] = -1;
342 Info<< "Total number of points: " << points_.size() << endl
343 << "Number of used points: " << nUsedPoints << endl;
345 // reset number of points which need to be sorted
346 points_.setSize(nUsedPoints);
348 Info << "Renumbering all faces" << endl;
350 forAll (cellFaces_, cellI)
352 faceList& newFaces = cellFaces_[cellI];
354 forAll (newFaces, faceI)
356 face oldFacePoints = newFaces[faceI];
358 face& newFacePoints = newFaces[faceI];
360 forAll (newFacePoints, pointI)
362 if (renumberPoints[oldFacePoints[pointI]] < 0)
364 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
365 << "Error in point renumbering for point "
366 << oldFacePoints[pointI]
367 << ". Renumbering index is -1." << endl
368 << "Old face: " << oldFacePoints << endl
369 << "New face: " << newFacePoints << abort(FatalError);
372 newFacePoints[pointI] = renumberPoints[oldFacePoints[pointI]];
377 Info << "Renumbering all cell shapes" << endl;
379 forAll (cellShapes_, cellI)
381 labelList oldLabels = cellShapes_[cellI];
383 labelList& curLabels = cellShapes_[cellI];
385 forAll (curLabels, pointI)
387 if (renumberPoints[curLabels[pointI]] < 0)
389 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
390 << "Error in point renumbering for cell "
391 << cellI << ". STAR index: " << starCellID_[cellI]
393 << "Point index: " << curLabels[pointI] << " STAR index "
394 << starPointID_[curLabels[pointI]] << " returns invalid "
395 << "renumbering index: "
396 << renumberPoints[curLabels[pointI]] << "." << endl
397 << "Old cellShape: " << oldLabels << endl
398 << "New cell shape: " << curLabels << abort(FatalError);
401 curLabels[pointI] = renumberPoints[oldLabels[pointI]];
405 Info << "Renumbering STAR point lookup" << endl;
407 labelList oldStarPointID = starPointID_;
411 forAll (starPointID_, pointI)
413 if (renumberPoints[pointI] > -1)
415 starPointID_[renumberPoints[pointI]] = oldStarPointID[pointI];
419 // point-cell addressing has changed. Force it to be re-created
420 deleteDemandDrivenData(pointCellsPtr_);
424 // ************************************************************************* //