Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
librnbg_s.c
Go to the documentation of this file.
1/* =============================================================================
2** This file is part of the mmg software package for the tetrahedral
3** mesh modification.
4** Copyright (c) Bx INP/CNRS/Inria/UBordeaux/UPMC, 2004-
5**
6** mmg is free software: you can redistribute it and/or modify it
7** under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation, either version 3 of the License, or
9** (at your option) any later version.
10**
11** mmg is distributed in the hope that it will be useful, but WITHOUT
12** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14** License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public
17** License and of the GNU General Public License along with mmg (in
18** files COPYING.LESSER and COPYING). If not, see
19** <http://www.gnu.org/licenses/>. Please read their terms carefully and
20** use this copy of the mmg distribution only if you accept them.
21** =============================================================================
22*/
23
33#include "libmmgs_private.h"
34#include "libmmgs.h"
35
36#ifdef USE_SCOTCH
37
38#include "librnbg_private.h"
39
50static inline
51void MMG5_swapTri(MMG5_pTria trias, MMG5_int* perm, MMG5_int ind1, MMG5_int ind2) {
52 MMG5_Tria pttmp;
53 MMG5_int tmp;
54
55 /* 2-- swap the triangles */
56 memcpy(&pttmp ,&trias[ind2],sizeof(MMG5_Tria));
57 memcpy(&trias[ind2],&trias[ind1],sizeof(MMG5_Tria));
58 memcpy(&trias[ind1],&pttmp ,sizeof(MMG5_Tria));
59
60 /* 3-- swap the permutation table */
61 tmp = perm[ind2];
62 perm[ind2] = perm[ind1];
63 perm[ind1] = tmp;
64}
65
81 MMG5_pSol fields,MMG5_int* permNodGlob) {
82 MMG5_pPoint ppt;
83 MMG5_pTria ptri;
84 SCOTCH_Num edgeNbr;
85 SCOTCH_Num *vertTab, *edgeTab, *permVrtTab;
86 SCOTCH_Graph graf ;
87 MMG5_int vertNbr, nodeGlbIdx, triaIdx, ballTriIdx;
88 MMG5_int j, k, edgeSiz;
89 MMG5_int *vertOldTab, *permNodTab, ntreal, npreal;
90 MMG5_int *adja,iadr;
91 int i;
92
93
94 /* Computing the number of vertices and a contiguous tabular of vertices */
95 vertNbr = 0;
96
97 MMG5_ADD_MEM(mesh,(mesh->nt+1)*sizeof(MMG5_int),"vertOldTab",return 1);
98 MMG5_SAFE_CALLOC(vertOldTab,mesh->nt+1,MMG5_int,return 1);
99
100 for(triaIdx = 1 ; triaIdx < mesh->nt + 1 ; triaIdx++) {
101
102 /* Testing if the tria exists */
103 if (!mesh->tria[triaIdx].v[0]) continue;
104 vertOldTab[triaIdx] = ++vertNbr;
105 }
106
107 if ( vertNbr/2 < MMG5_BOXSIZE ) {
108 /* not enough tetra to renum */
109 MMG5_DEL_MEM(mesh,vertOldTab);
110 return 1;
111 }
112 /* Allocating memory to compute adjacency lists */
113 MMG5_ADD_MEM(mesh,(vertNbr+2)*sizeof(SCOTCH_Num),"vertTab",
114 MMG5_DEL_MEM(mesh,vertOldTab);
115 return 1);
116 MMG5_SAFE_CALLOC(vertTab,vertNbr+2,SCOTCH_Num,return 1);
117
118 if (!memset(vertTab, ~0, sizeof(SCOTCH_Num)*(vertNbr + 2))) {
119 perror(" ## Memory problem: memset");
120 MMG5_DEL_MEM(mesh,vertOldTab);
121 MMG5_DEL_MEM(mesh,vertTab);
122 return 1;
123 }
124
125 edgeNbr = 1;
126 /* Euler-Poincare formulae edgeSiz = 20*mesh->np~4*mesh->nt;
127 (2*(12*mesh->np (triangles)-2*mesh->np (boundary triangles))) */
128 edgeSiz = vertNbr*4;
129
130 MMG5_ADD_MEM(mesh,edgeSiz*sizeof(SCOTCH_Num),"edgeTab",
131 MMG5_DEL_MEM(mesh,vertOldTab);
132 MMG5_DEL_MEM(mesh,vertTab);
133 return 1);
134 MMG5_SAFE_CALLOC(edgeTab,edgeSiz,SCOTCH_Num,return 1);
135
136
137 /* Computing the adjacency list for each vertex */
138 for(triaIdx = 1 ; triaIdx < mesh->nt + 1 ; triaIdx++) {
139
140 /* Testing if the tria exists */
141 if (!mesh->tria[triaIdx].v[0]) continue;
142
143 iadr = 3*(triaIdx-1) + 1;
144 adja = &mesh->adja[iadr];
145 for (i=0; i<3; i++) {
146 ballTriIdx = adja[i] / 3;
147
148 if (!ballTriIdx) continue;
149
150 /* Testing if one neighbour of triaIdx has already been added */
151 if (vertTab[vertOldTab[triaIdx]] < 0)
152 vertTab[vertOldTab[triaIdx]] = edgeNbr;
153
154 /* Testing if edgeTab memory is enough */
155 if (edgeNbr >= edgeSiz) {
156 int oldsize = edgeSiz;
157 MMG5_ADD_MEM(mesh,0.2*sizeof(SCOTCH_Num),"edgeTab",
158 MMG5_DEL_MEM(mesh,vertOldTab);
159 MMG5_DEL_MEM(mesh,vertTab);
160 return 1);
161 edgeSiz *= 1.2;
162 MMG5_SAFE_REALLOC(edgeTab,oldsize,edgeSiz,SCOTCH_Num,"scotch table",return 1);
163 }
164
165 edgeTab[edgeNbr++] = vertOldTab[ballTriIdx];
166 }
167 }
168 vertTab[vertNbr+1] = edgeNbr;
169 edgeNbr--;
170 /*check if some tria are alone*/
171 for(triaIdx = 1 ; triaIdx < mesh->nt + 1 ; triaIdx++) {
172
173 /* Testing if the tria exists */
174 if (!mesh->tria[triaIdx].v[0]) continue;
175 if (vertTab[vertOldTab[triaIdx]] < 0) {
176 if(vertOldTab[triaIdx] == vertNbr) {
177 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
178 __func__);
179 MMG5_DEL_MEM(mesh,edgeTab);
180 MMG5_DEL_MEM(mesh,vertTab);
181 return 1;
182 }
183 if(vertTab[vertOldTab[triaIdx] + 1] > 0)
184 vertTab[vertOldTab[triaIdx]] = vertTab[vertOldTab[triaIdx] + 1];
185 else {
186 if(vertOldTab[triaIdx]+1 == vertNbr) {
187 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
188 __func__);
189 MMG5_DEL_MEM(mesh,edgeTab);
190 MMG5_DEL_MEM(mesh,vertTab);
191 return 1;
192 }
193 i = 1;
194 do {
195 i++;
196 } while((vertTab[vertOldTab[triaIdx] + i] < 0) && ((vertOldTab[triaIdx] + i) < vertNbr));
197 if(vertOldTab[triaIdx] + i == vertNbr) {
198 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
199 __func__);
200 MMG5_DEL_MEM(mesh,edgeTab);
201 MMG5_DEL_MEM(mesh,vertTab);
202 return 1;
203 }
204 vertTab[vertOldTab[triaIdx]] = vertTab[vertOldTab[triaIdx] + i];
205 }
206 }
207 }
208
209 /* free adjacents to gain memory space */
211
212 /* Building the graph by calling Scotch functions */
213 SCOTCH_graphInit(&graf) ;
214 CHECK_SCOTCH(SCOTCH_graphBuild(&graf, (SCOTCH_Num) 1, vertNbr, vertTab+1,
215 NULL, NULL, NULL, edgeNbr, edgeTab+1, NULL),
216 "scotch_graphbuild", 0) ;
217
218#ifndef NDEBUG
219 /* don't check in release mode */
220 if ( mesh->info.imprim > 6 || mesh->info.ddebug )
221 fprintf(stdout,"checking graph...\n");
222
223 CHECK_SCOTCH(SCOTCH_graphCheck(&graf), "scotch_graphcheck", 0);
224#endif
225
226 MMG5_ADD_MEM(mesh,(vertNbr+1)*sizeof(SCOTCH_Num),"permVrtTab",
227 MMG5_DEL_MEM(mesh,vertOldTab);
228 MMG5_DEL_MEM(mesh,vertTab);
229 MMG5_DEL_MEM(mesh,edgeTab);
230 if( !MMGS_hashTria(mesh) ) return 0;
231 return 1);
232 MMG5_SAFE_CALLOC(permVrtTab,vertNbr+1,SCOTCH_Num,return 1);
233
234 CHECK_SCOTCH(MMG5_kPartBoxCompute(&graf, vertNbr, boxVertNbr, permVrtTab, mesh),
235 "boxCompute", 0);
236
237 SCOTCH_graphExit(&graf) ;
238
239 MMG5_DEL_MEM(mesh,edgeTab);
240 MMG5_DEL_MEM(mesh,vertTab);
241
242 /* Computing the new point list and modifying the adja strcuture */
243 ntreal = 0;
244 npreal = 0;
245
246 /* Create the final permutation table for trias (stored in vertOldTab) */
247 for (j=1; j<= mesh->nt; j++) {
248 if ( !mesh->tria[triaIdx].v[0] ) continue;
249
250 vertOldTab[triaIdx] = permVrtTab[vertOldTab[triaIdx]];
251 }
252 MMG5_DEL_MEM(mesh,permVrtTab);
253
254 /* Permute triangles */
255 for(triaIdx = 1 ; triaIdx < mesh->nt + 1 ; triaIdx++) {
256 while ( vertOldTab[triaIdx] != triaIdx && vertOldTab[triaIdx] )
257 MMG5_swapTri(mesh->tria,vertOldTab,triaIdx,vertOldTab[triaIdx]);
258 }
259 MMG5_DEL_MEM(mesh,vertOldTab);
260
261 MMG5_ADD_MEM(mesh,(mesh->np+1)*sizeof(MMG5_int),"permNodTab",
262 if( !MMGS_hashTria(mesh) ) return 0;
263 return 1);
264 MMG5_SAFE_CALLOC(permNodTab,mesh->np+1,MMG5_int,return 1);
265
266 for(triaIdx = 1 ; triaIdx < mesh->nt + 1 ; triaIdx++) {
267 ptri = &mesh->tria[triaIdx];
268
269 /* Testing if the tria exists */
270 if (!ptri->v[0]) continue;
271
272 ntreal++;
273
274 for(j = 0 ; j <= 2 ; j++) {
275
276 nodeGlbIdx = ptri->v[j];
277
278 if ( permNodTab[nodeGlbIdx] ) continue;
279
280 ppt = &mesh->point[nodeGlbIdx];
281
282 if ( !(ppt->tag & MG_NUL) )
283 /* Building the new point list */
284 permNodTab[nodeGlbIdx] = ++npreal;
285 }
286 }
287
288 /* Append unseen required points for orphan points preservation */
289 for ( k=1; k<=mesh->np; ++k) {
290 ppt = &mesh->point[k];
291 if ( !MG_VOK(ppt) ) {
292 continue;
293 }
294 if ( permNodTab[k] ) continue;
295
296
297 if ( ppt->tag & MG_REQ ) {
298 /* Add orphan required point to permnodtab */
299 permNodTab[k] = ++npreal;
300 }
301 }
302
303 /* Create the final permutation table for trias (stored in vertOldTab) and *
304 modify the numbering of the nodes of each tria */
305 for( triaIdx = 1; triaIdx < ntreal + 1; triaIdx++) {
306 for(j = 0 ; j < 3 ; j++) {
307 mesh->tria[triaIdx].v[j] = permNodTab[mesh->tria[triaIdx].v[j]];
308 }
309 }
310
311 /* If needed, store update the global permutation for point array */
312 if ( permNodGlob ) {
313 for ( k=1; k<=mesh->np; ++k ) {
314 permNodGlob[k] = permNodTab[permNodGlob[k]];
315 }
316 }
317
318 /* Permute nodes and sol */
319 for (j=1; j<= mesh->np; j++) {
320 while ( permNodTab[j] != j && permNodTab[j] )
321 MMG5_swapNod(mesh,mesh->point,sol->m,fields,permNodTab,j,permNodTab[j],sol->size);
322 }
323 MMG5_DEL_MEM(mesh,permNodTab);
324
325 mesh->nt = ntreal;
326 mesh->np = npreal;
327
328 if ( mesh->np == mesh->npmax )
329 mesh->npnil = 0;
330 else
331 mesh->npnil = mesh->np + 1;
332
333 if ( mesh->nt == mesh->ntmax )
334 mesh->nenil = 0;
335 else
336 mesh->nenil = mesh->nt + 1;
337
338 if ( mesh->npnil ) {
339 for (k=mesh->npnil; k<mesh->npmax-1; k++) {
340 mesh->point[k].tmp = k+1;
341 }
342 mesh->point[mesh->npmax-1].tmp = 0;
343 mesh->point[mesh->npmax ].tmp = 0;
344 }
345
346 if ( mesh->nenil ) {
347 for (k=mesh->nenil; k<mesh->ntmax-1; k++) {
348 mesh->tria[k].v[2] = k+1;
349 }
350 mesh->tria[mesh->ntmax-1].v[2] = 0;
351 mesh->tria[mesh->ntmax ].v[2] = 0;
352 }
353
354 if( !MMGS_hashTria(mesh) ) return 0;
355
356 return 1;
357}
358#endif
tmp[*strlen0]
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMGS_hashTria(MMG5_pMesh mesh)
Definition: hash_s.c:77
API headers for the mmgs library.
int MMG5_kPartBoxCompute(SCOTCH_Graph *graf, MMG5_int vertNbr, MMG5_int boxVertNbr, SCOTCH_Num *permVrtTab, MMG5_pMesh mesh)
Definition: librnbg.c:53
void MMG5_swapNod(MMG5_pMesh mesh, MMG5_pPoint points, double *sols, MMG5_pSol field, MMG5_int *perm, MMG5_int ind1, MMG5_int ind2, int solsiz)
Definition: librnbg.c:158
#define CHECK_SCOTCH(t, m, e)
static void MMG5_swapTri(MMG5_pTria trias, MMG5_int *perm, MMG5_int ind1, MMG5_int ind2)
Definition: librnbg_s.c:51
int MMG5_mmgsRenumbering(int boxVertNbr, MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol fields, MMG5_int *permNodGlob)
Definition: librnbg_s.c:80
#define MG_REQ
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_NUL
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MMG5_SAFE_REALLOC(ptr, prevSize, newSize, type, message, law)
#define MMG5_BOXSIZE
#define MG_VOK(ppt)
#define MMG5_DEL_MEM(mesh, ptr)
int8_t ddebug
Definition: libmmgtypes.h:532
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_int ntmax
Definition: libmmgtypes.h:612
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_int npmax
Definition: libmmgtypes.h:612
MMG5_int nenil
Definition: libmmgtypes.h:622
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_int npnil
Definition: libmmgtypes.h:621
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
MMG5_int tmp
Definition: libmmgtypes.h:280
MMG5_int v[3]
Definition: libmmgtypes.h:334