Adding cfMesh-v1.0 into the repository
[foam-extend-3.2.git] / src / meshLibrary / utilities / smoothers / geometry / meshOptimizer / optimizeMeshFV.C
blob2ab2988b35e26237eb942bec588221acf56ba9bf
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 "demandDrivenData.H"
29 #include "meshOptimizer.H"
30 #include "polyMeshGenAddressing.H"
31 #include "partTetMesh.H"
32 #include "HashSet.H"
34 #include "tetMeshOptimisation.H"
36 //#define DEBUGSmooth
38 # ifdef DEBUGSmooth
39 #include "helperFunctions.H"
40 #include "polyMeshGenModifier.H"
41 # endif
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 namespace Foam
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 void meshOptimizer::untangleMeshFV()
52     Info << "Starting untangling the mesh" << endl;
54     # ifdef DEBUGSmooth
55     partTetMesh tm(mesh_);
56     forAll(tm.tets(), tetI)
57         if( tm.tets()[tetI].mag(tm.points()) < 0.0 )
58             Info << "Tet " << tetI << " is inverted!" << endl;
59     polyMeshGen tetPolyMesh(mesh_.returnTime());
60     tm.createPolyMesh(tetPolyMesh);
61     polyMeshGenModifier(tetPolyMesh).removeUnusedVertices();
62     forAll(tm.smoothVertex(), pI)
63         if( !tm.smoothVertex()[pI] )
64             Info << "Point " << pI << " cannot be moved!" << endl;
66     const VRWGraph& pTets = tm.pointTets();
67     forAll(pTets, pointI)
68     {
69         const LongList<partTet>& tets = tm.tets();
70         forAllRow(pTets, pointI, i)
71             if( tets[pTets(pointI, i)].whichPosition(pointI) < 0 )
72                 FatalError << "Wrong partTet" << abort(FatalError);
74         partTetMeshSimplex simplex(tm, pointI);
75     }
77     boolList boundaryVertex(tetPolyMesh.points().size(), false);
78     const labelList& neighbour = tetPolyMesh.neighbour();
79     forAll(neighbour, faceI)
80         if( neighbour[faceI] == -1 )
81         {
82             const face& f = tetPolyMesh.faces()[faceI];
84             forAll(f, pI)
85                 boundaryVertex[f[pI]] = true;
86         }
88     forAll(boundaryVertex, pI)
89     {
90         if( boundaryVertex[pI] && tm.smoothVertex()[pI] )
91             FatalErrorIn
92             (
93                 "void meshOptimizer::untangleMeshFV()"
94             ) << "Boundary vertex should not be moved!" << abort(FatalError);
95     }
96     # endif
98     label nBadFaces, nGlobalIter(0), nIter;
99     const label maxNumGlobalIterations(10);
101     const faceListPMG& faces = mesh_.faces();
102     boolList changedFace(faces.size(), true);
104     labelHashSet badFaces;
106     do
107     {
108         nIter = 0;
110         label minNumBadFaces(10 * faces.size()), minIter(-1);
111         do
112         {
113             nBadFaces = findBadFaces(badFaces, changedFace);
115             Info << "Iteration " << nIter
116                 << ". Number of bad faces is " << nBadFaces << endl;
118             //- perform optimisation
119             if( nBadFaces == 0 )
120                 break;
122             if( nBadFaces < minNumBadFaces )
123             {
124                 minNumBadFaces = nBadFaces;
125                 minIter = nIter;
126             }
128             partTetMesh tetMesh(mesh_, badFaces, (nGlobalIter / 5) + 1);
130             tetMeshOptimisation tmo(tetMesh);
132             tmo.optimiseUsingKnuppMetric();
134             tmo.optimiseUsingMeshUntangler();
136             tmo.optimiseUsingVolumeOptimizer();
138             tetMesh.updateOrigMesh(&changedFace);
140         } while( (nIter < minIter+5) && (++nIter < 50) );
142         if( (nBadFaces == 0) || (++nGlobalIter >= maxNumGlobalIterations) )
143             break;
145         // move boundary vertices
146         nIter = 0;
148         do
149         {
150             nBadFaces = findBadFaces(badFaces, changedFace);
152             Info << "Iteration " << nIter
153                 << ". Number of bad faces is " << nBadFaces << endl;
155             //- perform optimisation
156             if( nBadFaces == 0 )
157                 break;
159             partTetMesh tetMesh(mesh_, badFaces, 0);
160             tetMeshOptimisation tmo(tetMesh);
162             if( nGlobalIter < 2 )
163             {
164                 //- the point stays in the plane determined by the point normal
165                 tmo.optimiseBoundaryVolumeOptimizer(true);
166             }
167             else if( nGlobalIter < 5 )
168             {
169                 //- move points without any constraints on the movement
170                 tmo.optimiseBoundarySurfaceLaplace();
171             }
172             else
173             {
174                 //- move boundary points without any constraints
175                 tmo.optimiseBoundaryVolumeOptimizer(false);
176             }
178             tetMesh.updateOrigMesh(&changedFace);
180         } while( ++nIter < 2 );
181     }
182     while( nBadFaces );
184     Info << "Finished untangling the mesh" << endl;
187 void meshOptimizer::optimizeLowQualityFaces()
189     label nBadFaces, nIter(0);
191     const faceListPMG& faces = mesh_.faces();
192     boolList changedFace(faces.size(), true);
194     label minNumBadFaces(10 * faces.size()), minIter(-1);
195     do
196     {
197         labelHashSet lowQualityFaces;
198         nBadFaces = findLowQualityFaces(lowQualityFaces, changedFace);
200         changedFace = false;
201         forAllConstIter(labelHashSet, lowQualityFaces, it)
202         changedFace[it.key()] = true;
204         Info << "Iteration " << nIter
205             << ". Number of bad faces is " << nBadFaces << endl;
207         //- perform optimisation
208         if( nBadFaces == 0 )
209             break;
211         if( nBadFaces < minNumBadFaces )
212         {
213             minNumBadFaces = nBadFaces;
214             minIter = nIter;
215         }
217         partTetMesh tetMesh(mesh_, lowQualityFaces, 2);
219         tetMeshOptimisation tmo(tetMesh);
221         tmo.optimiseUsingKnuppMetric();
223         tmo.optimiseUsingMeshUntangler();
225         tmo.optimiseUsingVolumeOptimizer();
227         tetMesh.updateOrigMesh(&changedFace);
229     } while( (nIter < minIter+2) && (++nIter < 10) );
232 void meshOptimizer::optimizeMeshFV()
234     Info << "Starting smoothing the mesh" << endl;
236     laplaceSmoother lps(mesh_, vertexLocation_);
237     lps.optimizeLaplacianPC(5);
239     untangleMeshFV();
241     Info << "Finished smoothing the mesh" << endl;
244 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
246 } // End namespace Foam
248 // ************************************************************************* //