Adding cfMesh-v1.0 into the repository
[foam-extend-3.2.git] / src / meshLibrary / utilities / smoothers / topology / topologicalCleaner / topologicalCleanerInvalidVertices.C
blob7e354438fe45a984378b4f443621b4b1057b766a
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | cfMesh: A library for mesh generation
4    \\    /   O peration     |
5     \\  /    A nd           | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6      \\/     M anipulation  | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9     This file is part of cfMesh.
11     cfMesh 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     cfMesh 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
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with cfMesh.  If not, see <http://www.gnu.org/licenses/>.
24 Description
26 \*---------------------------------------------------------------------------*/
28 #include "topologicalCleaner.H"
29 #include "polyMeshGenAddressing.H"
30 #include "DynList.H"
31 #include "meshSurfaceEngine.H"
33 #include <map>
35 //#define DEBUGCheck
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 namespace Foam
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 void topologicalCleaner::checkInvalidConnectionsForVerticesCells
46     labelHashSet* irregularNodesPtr
49     if( Pstream::parRun() )
50     {
51         return;
53         FatalErrorIn
54         (
55             "void topologicalCleaner::checkInvalidConnectionsForVerticesCells()"
56         ) << "This does not run in parallel!" << exit(FatalError);
57     }
59     polyMeshGenModifier meshModifier(mesh_);
61     label nPoints = mesh_.points().size();
62     pointFieldPMG& points = meshModifier.pointsAccess();
63     faceListPMG& faces = meshModifier.facesAccess();
64     const cellListPMG& cells = mesh_.cells();
66     const VRWGraph& pointCells = mesh_.addressingData().pointCells();
67     const VRWGraph& cellCells = mesh_.addressingData().cellCells();
69     meshSurfaceEngine mse(mesh_);
70     const labelList& bPoints = mse.boundaryPoints();
72     label nInvalidConnections(0);
74     forAll(bPoints, bpI)
75     {
76         const label pointI = bPoints[bpI];
78         # ifdef DEBUGCheck
79         Info << "Checking point " << pointI << endl;
80         # endif
82         label material(1);
84         labelList materialForCell(pointCells.sizeOfRow(pointI), 0);
86         forAllRow(pointCells, pointI, cI)
87         if( !materialForCell[cI] )
88         {
89             materialForCell[cI] = material;
91             DynList<label> frontCells;
92             frontCells.append(cI);
94             do
95             {
96                 DynList<label> newFrontCells;
98                 forAll(frontCells, fcI)
99                 {
100                     const label pointCellI =
101                     pointCells(pointI, frontCells[fcI]);
103                     forAllRow(cellCells, pointCellI, nI)
104                     {
105                         forAllRow(pointCells, pointI, pcI)
106                         {
107                             if( materialForCell[pcI] )
108                                 continue;
110                             if(
111                                 cellCells(pointCellI, nI) ==
112                                 pointCells(pointI, pcI)
113                             )
114                             {
115                                 newFrontCells.append(pcI);
116                                 materialForCell[pcI] = material;
117                                 break;
118                             }
119                         }
120                     }
121                 }
123                 frontCells = newFrontCells;
125             } while( frontCells.size() != 0 );
127             ++material;
128         }
130         # ifdef DEBUGCheck
131         Info << "Number of materials for vertex is " << material << endl;
132         # endif
134         if( material > 2 )
135         {
136             ++nInvalidConnections;
138             if( irregularNodesPtr )
139             {
140                 irregularNodesPtr->insert(pointI);
141                 continue;
142             }
144             forAllRow(pointCells, pointI, pcI)
145             {
146                 if( materialForCell[pcI] == 1 )
147                     continue;
149                 const cell& c = cells[pointCells(pointI, pcI)];
151                 forAll(c, fI)
152                 {
153                     face& f = faces[c[fI]];
155                     forAll(f, pI)
156                         if( f[pI] == pointI )
157                             f[pI] = nPoints + materialForCell[pcI] - 1;
158                 }
159             }
161             for(label i=1;i<material;++i)
162             {
163                 const point p = points[pointI];
164                 points.append(p);
165                 ++nPoints;
166             }
167         }
168     }
170     Info << "Found " << nInvalidConnections
171         << " invalid cell connections" << endl;
173     mesh_.clearAddressingData();
175     if( nInvalidConnections != 0 )
176         meshModifier.removeUnusedVertices();
179 void topologicalCleaner::checkInvalidConnectionsForVerticesFaces
181     labelHashSet* irregularNodesPtr
184     const meshSurfaceEngine mse(mesh_);
186     const VRWGraph& edgeFaces = mse.edgeFaces();
187     const labelList& faceOwner = mse.faceOwners();
189     boolList removeCell(mesh_.cells().size(), false);
190     bool changed(false);
192     # ifdef USE_OMP
193     # pragma omp parallel for schedule(static, 1)
194     # endif
195     forAll(edgeFaces, edgeI)
196         if( edgeFaces.sizeOfRow(edgeI) > 2 )
197         {
198             forAllRow(edgeFaces, edgeI, fI)
199                 removeCell[faceOwner[edgeFaces(edgeI, fI)]] = true;
201             changed = true;
202         }
204     if( Pstream::parRun() )
205     {
206         //- boundary edges at processor boundaries
207         Map<label> numFacesAtEdge;
208         const labelList& globalEdgeLabel = mse.globalBoundaryEdgeLabel();
209         const Map<label>& globalToLocal = mse.globalToLocalBndEdgeAddressing();
210         const VRWGraph& edgesAtProcs = mse.beAtProcs();
212         DynList<label> neiProcs;
213         std::map<label, labelLongList> exchangeData;
214         std::map<label, labelLongList>::iterator eIter;
216         forAll(edgeFaces, eI)
217         {
218             if( edgesAtProcs.sizeOfRow(eI) > 0 )
219             {
220                 numFacesAtEdge.insert
221                 (
222                     globalEdgeLabel[eI],
223                     edgeFaces.sizeOfRow(eI)
224                 );
226                 forAllRow(edgesAtProcs, eI, procI)
227                 {
228                     const label neiProc = edgesAtProcs(eI, procI);
230                     if( neiProc == Pstream::myProcNo() )
231                         continue;
233                     eIter = exchangeData.find(neiProc);
234                     if( eIter == exchangeData.end() )
235                     {
236                         neiProcs.append(neiProc);
237                         exchangeData.insert
238                         (
239                             std::pair<label, labelLongList>
240                             (
241                                 neiProc,
242                                 labelLongList()
243                             )
244                         );
246                         eIter = exchangeData.find(neiProc);
247                     }
249                     eIter->second.append(globalEdgeLabel[eI]);
250                     eIter->second.append(edgeFaces.sizeOfRow(eI));
251                 }
252             }
253         }
255         //- send data to other processors
256         forAll(neiProcs, procI)
257         {
258             eIter = exchangeData.find(neiProcs[procI]);
259             const labelLongList& dataToSend = eIter->second;
261             OPstream toOtherProc
262             (
263                 Pstream::blocking,
264                 neiProcs[procI],
265                 dataToSend.byteSize()
266             );
267             toOtherProc << dataToSend;
268         }
270         forAll(neiProcs, procI)
271         {
272             labelList receivedData;
273             IPstream fromOtherProc(Pstream::blocking, neiProcs[procI]);
274                 fromOtherProc >> receivedData;
276             label counter(0);
277             while( counter < receivedData.size() )
278             {
279                 const label geI = receivedData[counter++];
280                 const label nFaces = receivedData[counter++];
282                 numFacesAtEdge[geI] += nFaces;
284                 if( numFacesAtEdge[geI] > 2 )
285                 {
286                     const label edgeI = globalToLocal[geI];
287                     forAllRow(edgeFaces, edgeI, fI)
288                         removeCell[faceOwner[edgeFaces(edgeI, fI)]] = true;
290                     changed = true;
291                 }
292             }
293         }
294     }
296     reduce(changed, maxOp<bool>());
298     if( changed )
299     {
300         polyMeshGenModifier(mesh_).removeCells(removeCell);
302         decomposeCell_.setSize(mesh_.cells().size());
303         decomposeCell_ = false;
304     }
307 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
309 } // End namespace Foam
311 // ************************************************************************* //