FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

mergeCoupleFacePoints.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025     Merge duplicate points created by arbitrary face coupling and remove unused
00026     points.
00027 
00028 \*---------------------------------------------------------------------------*/
00029 
00030 #include "starMesh.H"
00031 #include <OpenFOAM/demandDrivenData.H>
00032 
00033 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00034 
00035 void starMesh::mergeCoupleFacePoints()
00036 {
00037     // mark all used points by looping through all faces in two goes.
00038     // First, go into every cell and find min edge length.  Use a
00039     // fraction of that as a merge tolerance.  Loop through all the
00040     // points of the cell and query a merge against every other point
00041     // of the same cell based on the current tolerance.  If two points
00042     // merge, find out if any of them already belongs to a "merge set"
00043     // (group of points that merge together.  If so, add the current
00044     // points into the merge set and make sure that the merge label
00045     // for the whole set is the lowest of all encountered vertices.
00046     // This is stored in a mergeSetID list, under the index of the
00047     // merge set.  Once all cells (and thus points) are visited, go
00048     // through the renumbering list and for each merging point use the
00049     // label of the merge set as the new point label.
00050     // This is VERY fancy. Use care if/when changing. 
00051 
00052     Info << endl << "Creating merge sets" << endl;
00053 
00054     // Create a renumbering list for points
00055     // In the first instance the renumbering list is used as a
00056     // mergeSetID storage
00057     labelList renumberPoints(points_.size(), -1);
00058 
00059     // create storage of mergeSetIDs
00060     label mergeIncrement = points_.size()/10;
00061     labelList mergeSetID(mergeIncrement, -1);
00062 
00063     label nMergeSets = 0;
00064 
00065     forAll (cellFaces_, cellI)
00066     {
00067         const faceList& curFaces = cellFaces_[cellI];
00068 
00069         // create a list of all points for the cell with duplicates
00070         // and find the shortest edge length
00071 
00072         label nPointsInCell = 0;
00073 
00074         scalar pointMergeTol = GREAT;
00075 
00076         forAll (curFaces, faceI)
00077         {
00078             nPointsInCell += curFaces[faceI].size();
00079 
00080             edgeList curEdges = curFaces[faceI].edges();
00081 
00082             forAll (curEdges, edgeI)
00083             {
00084                 scalar length = curEdges[edgeI].mag(points_);
00085 
00086                 if (length < pointMergeTol)
00087                 {
00088                     pointMergeTol = length;
00089                 }
00090             }
00091         }
00092 
00093         // set merge tolerance as a fraction of the shortest edge
00094         pointMergeTol /= 100.0;
00095 
00096         // create a list of points
00097         labelList cellPoints(nPointsInCell);
00098         label nAddedPoints = 0;
00099 
00100         forAll (curFaces, faceI)
00101         {
00102             const face& f = curFaces[faceI];
00103 
00104             forAll (f, fI)
00105             {
00106                 cellPoints[nAddedPoints] = f[fI];
00107                 nAddedPoints++;
00108             }
00109         }
00110 
00111         // loop n-squared through the local points and merge them up
00112         for (label firstPI = 0; firstPI < cellPoints.size() - 1; firstPI++)
00113         {
00114             for
00115             (
00116                 label otherPI = firstPI;
00117                 otherPI < cellPoints.size();
00118                 otherPI++
00119             )
00120             {
00121                 if (cellPoints[firstPI] != cellPoints[otherPI])
00122                 {
00123                     label a = cellPoints[firstPI];
00124                     label b = cellPoints[otherPI];
00125 
00126                     if (edge (a, b).mag(points_) < pointMergeTol)
00127                     {
00128                         // found a pair of points to merge
00129 #                       ifdef DEBUG_MERGE
00130                         Info<< "Merging points " << a << " and " << b << endl;
00131 #                       endif
00132 
00133                         // are the two points in a merge group?
00134                         label mergeSetA = -1;
00135                         label mergeSetB = -1;
00136 
00137                         if (renumberPoints[a] > -1)
00138                         {
00139                             mergeSetA = renumberPoints[a];
00140                         }
00141 
00142                         if (renumberPoints[b] > -1)
00143                         {
00144                             mergeSetB = renumberPoints[b];
00145                         }
00146 
00147                         if (mergeSetA == -1 && mergeSetB == -1)
00148                         {
00149                             // add new merge group
00150 #                           ifdef DEBUG_MERGE
00151                             Info<< "adding new merge group " << nMergeSets
00152                                 << endl;
00153 #                           endif
00154 
00155                             // mark points as belonging to a new merge set
00156                             renumberPoints[a] = nMergeSets;
00157                             renumberPoints[b] = nMergeSets;
00158 
00159                             mergeSetID[nMergeSets] = min(a, b);
00160                             nMergeSets++;
00161 
00162                             if (nMergeSets >= mergeSetID.size())
00163                             {
00164                                 Info << "Resizing mergeSetID" << endl;
00165 
00166                                 mergeSetID.setSize
00167                                     (mergeSetID.size() + mergeIncrement);
00168                             }
00169                         }
00170                         else if (mergeSetA == -1 && mergeSetB != -1)
00171                         {
00172 #                           ifdef DEBUG_MERGE
00173                             Info<< "adding point a into the merge set of b. "
00174                                 << "a: " << a << endl;
00175 #                           endif
00176 
00177                             // add point a into the merge set of b
00178                             renumberPoints[a] = mergeSetB;
00179 
00180                             // reset the min label of the mergeSet
00181                             mergeSetID[mergeSetB] =
00182                                 min(a, mergeSetID[mergeSetB]);
00183                         }
00184                         else if  (mergeSetA != -1 && mergeSetB == -1)
00185                         {
00186 #                           ifdef DEBUG_MERGE
00187                             Info<< "adding point b into the merge set of a. "
00188                                 << "b: " << b << endl;
00189 #                           endif
00190 
00191                             // add point b into the merge set of a
00192                             renumberPoints[b] = mergeSetA;
00193 
00194                             // reset the min label of the mergeSet
00195                             mergeSetID[mergeSetA] =
00196                                 min(b, mergeSetID[mergeSetA]);
00197                         }
00198                         else if (mergeSetA != mergeSetB)
00199                         {
00200                             // Points already belong to two different merge
00201                             // sets. Eliminate the higher merge set
00202                             label minMerge = min(mergeSetA, mergeSetB);
00203                             label maxMerge = max(mergeSetA, mergeSetB);
00204 
00205 #                           ifdef DEBUG_MERGE
00206                             Info<< "Points already belong to two "
00207                                 << "different merge sets. "
00208                                 << "Eliminate the higher merge set. Sets: "
00209                                 << minMerge << " and " << maxMerge << endl;
00210 #                           endif
00211 
00212                             forAll (renumberPoints, elimI)
00213                             {
00214                                 if (renumberPoints[elimI] == maxMerge)
00215                                 {
00216                                     renumberPoints[elimI] = minMerge;
00217                                 }
00218                             }
00219 
00220                             // set the lower label
00221                             mergeSetID[minMerge] =
00222                                 min(mergeSetID[minMerge], mergeSetID[maxMerge]);
00223                         }
00224                     }
00225                 }
00226             }
00227         }
00228     }
00229 
00230     mergeSetID.setSize(nMergeSets);
00231 
00232     Info<< "Finished creating merge sets.  Number of merge sets: "
00233         << nMergeSets << "." << endl;
00234 
00235     // Insert the primary point renumbering into the list
00236     // Take care of possibly unused points in the list
00237     forAll (renumberPoints, pointI)
00238     {
00239         if (renumberPoints[pointI] < 0)
00240         {
00241             // point not merged
00242             renumberPoints[pointI] = pointI;
00243         }
00244         else
00245         {
00246             renumberPoints[pointI] = mergeSetID[renumberPoints[pointI]];
00247         }
00248     }
00249 
00250     // Now every point carries either its own label or the lowest of
00251     // the labels of the points it is merged with. Now do PRELIMINARY
00252     // renumbering of all faces.  This will only be used to see which
00253     // points are still used!
00254 
00255     forAll (cellFaces_, cellI)
00256     {
00257         faceList& prelimFaces = cellFaces_[cellI];
00258 
00259         forAll (prelimFaces, faceI)
00260         {
00261             face oldFacePoints = prelimFaces[faceI];
00262 
00263             face& prelimFacePoints = prelimFaces[faceI];
00264 
00265             forAll (prelimFacePoints, pointI)
00266             {
00267                 if (renumberPoints[oldFacePoints[pointI]] < 0)
00268                 {
00269                     FatalErrorIn("starMesh::mergeCoupleFacePoints()")
00270                         << "Error in point renumbering. Old face: "
00271                         << oldFacePoints << endl
00272                         << "prelim face: " << prelimFacePoints
00273                         << abort(FatalError);
00274                 }
00275 
00276                 prelimFacePoints[pointI] =
00277                     renumberPoints[oldFacePoints[pointI]];
00278             }
00279         }
00280     }
00281 
00282     // First step complete. Reset the renumbering list, mark all used points,
00283     // re-create the point list and renumber the whole lot
00284     renumberPoints = 0;
00285 
00286     forAll (cellFaces_, cellI)
00287     {
00288         const faceList& curFaces = cellFaces_[cellI];
00289 
00290         forAll (curFaces, faceI)
00291         {
00292             const face& curFacePoints = curFaces[faceI];
00293 
00294             forAll (curFacePoints, pointI)
00295             {
00296                 renumberPoints[curFacePoints[pointI]]++;
00297             }
00298         }
00299     }
00300 
00301     forAll (cellShapes_, cellI)
00302     {
00303         const labelList& curLabels = cellShapes_[cellI];
00304 
00305         forAll (curLabels, pointI)
00306         {
00307             if (renumberPoints[curLabels[pointI]] == 0)
00308             {
00309                 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
00310                     << "Error in point merging for cell "
00311                     << cellI << ". STAR index: " << starCellID_[cellI]
00312                     << ". " << endl
00313                     << "Point index: " << curLabels[pointI] << " STAR index "
00314                     << starPointID_[curLabels[pointI]] << endl
00315                     << "Please check the geometry for the cell." << endl;
00316             }
00317         }
00318     }
00319 
00320     label nUsedPoints = 0;
00321 
00322     forAll (renumberPoints, pointI)
00323     {
00324         if (renumberPoints[pointI] > 0)
00325         {
00326             // This should be OK as the compressed points list will always
00327             // have less points that the original lists.  Even if there is
00328             // no points removed, this will copy the list back onto itself
00329             // 
00330             renumberPoints[pointI] = nUsedPoints;
00331             points_[nUsedPoints] = points_[pointI];
00332 
00333             nUsedPoints++;
00334         }
00335         else
00336         {
00337             renumberPoints[pointI] = -1;
00338         }
00339     }
00340 
00341     Info<< "Total number of points: " << points_.size() << endl
00342         << "Number of used points: " << nUsedPoints << endl;
00343 
00344     // reset number of points which need to be sorted
00345     points_.setSize(nUsedPoints);
00346 
00347     Info << "Renumbering all faces" << endl;
00348 
00349     forAll (cellFaces_, cellI)
00350     {
00351         faceList& newFaces = cellFaces_[cellI];
00352 
00353         forAll (newFaces, faceI)
00354         {
00355             face oldFacePoints = newFaces[faceI];
00356 
00357             face& newFacePoints = newFaces[faceI];
00358 
00359             forAll (newFacePoints, pointI)
00360             {
00361                 if (renumberPoints[oldFacePoints[pointI]] < 0)
00362                 {
00363                     FatalErrorIn("starMesh::mergeCoupleFacePoints()")
00364                         << "Error in point renumbering for point "
00365                         << oldFacePoints[pointI]
00366                         << ". Renumbering index is -1." << endl
00367                         << "Old face: " << oldFacePoints << endl
00368                         << "New face: " << newFacePoints << abort(FatalError);
00369                 }
00370 
00371                 newFacePoints[pointI] = renumberPoints[oldFacePoints[pointI]];
00372             }
00373         }
00374     }
00375 
00376     Info << "Renumbering all cell shapes" << endl;
00377 
00378     forAll (cellShapes_, cellI)
00379     {
00380         labelList oldLabels = cellShapes_[cellI];
00381 
00382         labelList& curLabels = cellShapes_[cellI];
00383 
00384         forAll (curLabels, pointI)
00385         {
00386             if (renumberPoints[curLabels[pointI]] < 0)
00387             {
00388                 FatalErrorIn("starMesh::mergeCoupleFacePoints()")
00389                     << "Error in point renumbering for cell "
00390                     << cellI << ". STAR index: " << starCellID_[cellI]
00391                     << ". " << endl
00392                     << "Point index: " << curLabels[pointI] << " STAR index "
00393                     << starPointID_[curLabels[pointI]] << " returns invalid "
00394                     << "renumbering index: "
00395                     << renumberPoints[curLabels[pointI]] << "." << endl
00396                     << "Old cellShape:  " << oldLabels << endl
00397                     << "New cell shape: " << curLabels << abort(FatalError);
00398                 }
00399 
00400             curLabels[pointI] = renumberPoints[oldLabels[pointI]];
00401         }
00402     }
00403 
00404     Info << "Renumbering STAR point lookup" << endl;
00405 
00406     labelList oldStarPointID = starPointID_;
00407 
00408     starPointID_ = -1;
00409 
00410     forAll (starPointID_, pointI)
00411     {
00412         if (renumberPoints[pointI] > -1)
00413         {
00414             starPointID_[renumberPoints[pointI]] = oldStarPointID[pointI];
00415         }
00416     }
00417 
00418     // point-cell addressing has changed. Force it to be re-created
00419     deleteDemandDrivenData(pointCellsPtr_);
00420 }
00421 
00422 
00423 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines