Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
librnbg_3d.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
34#include "libmmg3d_private.h"
35#include "libmmg3d.h"
36
37#ifdef USE_SCOTCH
38
39#include "librnbg_private.h"
40
51static inline
52void MMG5_swapTet(MMG5_pTetra tetras/*, int* adja*/, MMG5_int* perm, MMG5_int ind1, MMG5_int ind2) {
53 MMG5_Tetra pttmp;
54 MMG5_int tmp;
55
56 /* Commentated part: swap for adja table if we don't free it in renumbering *
57 * function (faster but need of 4*mesh->nemax*sizeof(int) extra bytes ) */
58 /* int adjatmp,kadj,ifadj,j; */
59
60 /* /\* 1-- swap the adja table *\/ */
61 /* /\* First: replace ind2 by ind1 in adjacents tetras of ind2 *\/ */
62 /* for ( j=1; j<5; j++ ) { */
63 /* if ( adja[4*(ind2-1)+j]/4 ) { */
64 /* kadj = adja[4*(ind2-1)+j]/4; */
65 /* ifadj = adja[4*(ind2-1)+j]%4; */
66 /* adja[4*(kadj-1)+1+ifadj] = 4*ind1 + adja[4*(kadj-1)+1+ifadj]%4; */
67 /* } */
68 /* } */
69
70 /* /\* Second: replace ind1 by ind2 in adjacents tetras of ind1*\/ */
71 /* for ( j=1; j<5; j++ ) { */
72 /* if ( adja[4*(ind1-1)+j]/4 ) { */
73 /* kadj = adja[4*(ind1-1)+j]/4; */
74 /* ifadj = adja[4*(ind1-1)+j]%4; */
75 /* if ( kadj == ind1 ) */
76 /* adja[4*(ind2-1)+1+ifadj] = 4*ind2 + adja[4*(ind2-1)+1+ifadj]%4; */
77 /* else */
78 /* adja[4*(kadj-1)+1+ifadj] = 4*ind2 + adja[4*(kadj-1)+1+ifadj]%4; */
79 /* } */
80 /* } */
81
82 /* /\* Third: swap adjacents for ind1 and ind2 *\/ */
83 /* for ( j=1; j<5; j++ ) { */
84 /* adjatmp = adja[4*(ind2-1)+j]; */
85 /* adja[4*(ind2-1)+j] = adja[4*(ind1-1)+j]; */
86 /* adja[4*(ind1-1)+j] = adjatmp; */
87 /* } */
88
89 /* 2-- swap the tetrahedras */
90 memcpy(&pttmp ,&tetras[ind2],sizeof(MMG5_Tetra));
91 memcpy(&tetras[ind2],&tetras[ind1],sizeof(MMG5_Tetra));
92 memcpy(&tetras[ind1],&pttmp ,sizeof(MMG5_Tetra));
93
94 /* 3-- swap the permutation table */
95 tmp = perm[ind2];
96 perm[ind2] = perm[ind1];
97 perm[ind1] = tmp;
98}
99
115 MMG5_pSol fields,MMG5_int* permNodGlob) {
116 MMG5_pPoint ppt;
117 MMG5_pTetra ptet;
118 MMG5_pPrism pp;
119 SCOTCH_Num edgeNbr;
120 SCOTCH_Num *vertTab, *edgeTab, *permVrtTab;
121 SCOTCH_Graph graf ;
122 MMG5_int vertNbr, nodeGlbIdx, tetraIdx, ballTetIdx;
123 int i;
124 MMG5_int j, k;
125 MMG5_int edgeSiz;
126 MMG5_int *vertOldTab, *permNodTab, nereal, npreal;
127 MMG5_int *adja,iadr;
128
129
130 /* Computing the number of vertices and a contiguous tabular of vertices */
131 vertNbr = 0;
132
133 MMG5_ADD_MEM(mesh,(mesh->ne+1)*sizeof(MMG5_int),"vertOldTab",return 1);
134 MMG5_SAFE_CALLOC(vertOldTab,mesh->ne+1,MMG5_int,return 1);
135
136 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
137
138 /* Testing if the tetra exists */
139 if (!mesh->tetra[tetraIdx].v[0]) continue;
140 vertOldTab[tetraIdx] = ++vertNbr;
141 }
142
143 if ( vertNbr/2 < 0 /*MMG5_BOXSIZE*/ ) {
144 /* not enough tetra to renum */
145 MMG5_DEL_MEM(mesh,vertOldTab);
146 return 1;
147 }
148 /* Allocating memory to compute adjacency lists */
149 MMG5_ADD_MEM(mesh,(vertNbr+2)*sizeof(SCOTCH_Num),"vertTab",
150 MMG5_DEL_MEM(mesh,vertOldTab);
151 return 1);
152 MMG5_SAFE_CALLOC(vertTab,vertNbr+2,SCOTCH_Num,return 1);
153
154 if (!memset(vertTab, ~0, sizeof(SCOTCH_Num)*(vertNbr + 2))) {
155 perror(" ## Memory problem: memset");
156 MMG5_DEL_MEM(mesh,vertOldTab);
157 MMG5_DEL_MEM(mesh,vertTab);
158 return 1;
159 }
160
161 edgeNbr = 1;
162 /* Euler-Poincare formulae edgeSiz = 20*mesh->np~4*mesh->ne;
163 (2*(12*mesh->np (triangles)-2*mesh->np (boundary triangles))) */
164 edgeSiz = vertNbr*4;
165
166 MMG5_ADD_MEM(mesh,edgeSiz*sizeof(SCOTCH_Num),"edgeTab",
167 MMG5_DEL_MEM(mesh,vertOldTab);
168 MMG5_DEL_MEM(mesh,vertTab);
169 return 1);
170 MMG5_SAFE_CALLOC(edgeTab,edgeSiz,SCOTCH_Num,return 1);
171
172
173 /* Computing the adjacency list for each vertex */
174 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
175
176 /* Testing if the tetra exists */
177 if (!mesh->tetra[tetraIdx].v[0]) continue;
178
179 iadr = 4*(tetraIdx-1) + 1;
180 adja = &mesh->adja[iadr];
181 for (i=0; i<4; i++) {
182 ballTetIdx = adja[i];
183
184 if (!ballTetIdx) continue;
185
186 ballTetIdx /= 4;
187
188 /* Testing if one neighbour of tetraIdx has already been added */
189 if (vertTab[vertOldTab[tetraIdx]] < 0)
190 vertTab[vertOldTab[tetraIdx]] = edgeNbr;
191
192 /* Testing if edgeTab memory is enough */
193 if (edgeNbr >= edgeSiz) {
194 MMG5_int oldsize = edgeSiz;
195 MMG5_ADD_MEM(mesh,MMG5_GAP*sizeof(SCOTCH_Num),"edgeTab",
196 MMG5_DEL_MEM(mesh,vertOldTab);
197 MMG5_DEL_MEM(mesh,vertTab);
198 return 1);
199 edgeSiz *= 1.2;
200 MMG5_SAFE_REALLOC(edgeTab,oldsize,edgeSiz,SCOTCH_Num,"scotch table",return 1);
201 }
202
203 edgeTab[edgeNbr++] = vertOldTab[ballTetIdx];
204 }
205 }
206 vertTab[vertNbr+1] = edgeNbr;
207 edgeNbr--;
208 /* Check if some tetras are alone */
209 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
210
211 /* Testing if the tetra exists */
212 if (!mesh->tetra[tetraIdx].v[0]) continue;
213 if (vertTab[vertOldTab[tetraIdx]] < 0) {
214 if(vertOldTab[tetraIdx] == vertNbr) {
215 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
216 __func__);
217 MMG5_DEL_MEM(mesh,edgeTab);
218 MMG5_DEL_MEM(mesh,vertTab);
219 return 1;
220 }
221 if(vertTab[vertOldTab[tetraIdx] + 1] > 0)
222 vertTab[vertOldTab[tetraIdx]] = vertTab[vertOldTab[tetraIdx] + 1];
223 else {
224 if(vertOldTab[tetraIdx]+1 == vertNbr) {
225 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
226 __func__);
227 MMG5_DEL_MEM(mesh,edgeTab);
228 MMG5_DEL_MEM(mesh,vertTab);
229 return 1;
230 }
231 i = 1;
232 do {
233 i++;
234 } while((vertTab[vertOldTab[tetraIdx] + i] < 0) && ((vertOldTab[tetraIdx] + i) < vertNbr));
235 if(vertOldTab[tetraIdx] + i == vertNbr) {
236 fprintf(stderr," ## Warning: %s: graph error, no renumbering.\n",
237 __func__);
238 MMG5_DEL_MEM(mesh,edgeTab);
239 MMG5_DEL_MEM(mesh,vertTab);
240 return 1;
241 }
242 vertTab[vertOldTab[tetraIdx]] = vertTab[vertOldTab[tetraIdx] + i];
243 }
244 }
245 }
246
247 /* free adjacents to gain memory space */
249
250 /* Building the graph by calling Scotch functions */
251 SCOTCH_graphInit(&graf) ;
252 CHECK_SCOTCH(SCOTCH_graphBuild(&graf, (SCOTCH_Num) 1, vertNbr, vertTab+1,
253 NULL, NULL, NULL, edgeNbr, edgeTab+1, NULL),
254 "scotch_graphbuild", 0) ;
255#ifndef NDEBUG
256 /* don't check in release mode */
257 if ( mesh->info.imprim > 6 || mesh->info.ddebug )
258 fprintf(stdout,"** Checking scotch graph.\n");
259 CHECK_SCOTCH(SCOTCH_graphCheck(&graf), "scotch_graphcheck", 0);
260#endif
261
262 MMG5_ADD_MEM(mesh,(vertNbr+1)*sizeof(SCOTCH_Num),"permVrtTab",
263 MMG5_DEL_MEM(mesh,vertOldTab);
264 MMG5_DEL_MEM(mesh,vertTab);
265 MMG5_DEL_MEM(mesh,edgeTab);
266 if( !MMG3D_hashTetra(mesh,1) ) return 0;
267 return 1);
268 MMG5_SAFE_CALLOC(permVrtTab,vertNbr+1,SCOTCH_Num,return 1);
269
270 CHECK_SCOTCH(MMG5_kPartBoxCompute(&graf, vertNbr, boxVertNbr, permVrtTab, mesh),
271 "boxCompute", 0);
272
273 SCOTCH_graphExit(&graf) ;
274
275 MMG5_DEL_MEM(mesh,edgeTab);
276 MMG5_DEL_MEM(mesh,vertTab);
277
278 /* Computing the new point list and modifying the adja strcuture */
279 nereal = 0;
280 npreal = 0;
281 /* Create the final permutation table for tetras (stored in vertOldTab) */
282 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
283 if ( !mesh->tetra[tetraIdx].v[0] ) continue;
284 vertOldTab[tetraIdx] = permVrtTab[vertOldTab[tetraIdx]];
285 }
286 MMG5_DEL_MEM(mesh,permVrtTab);
287
288 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
289 while ( vertOldTab[tetraIdx] != tetraIdx && vertOldTab[tetraIdx] )
290 MMG5_swapTet(mesh->tetra/*,mesh->adja*/,vertOldTab,tetraIdx,vertOldTab[tetraIdx]);
291 }
292 MMG5_DEL_MEM(mesh,vertOldTab);
293
294 MMG5_ADD_MEM(mesh,(mesh->np+1)*sizeof(MMG5_int),"permNodTab",
295 if( !MMG3D_hashTetra(mesh,1) ) return 0;
296 return 1);
297 MMG5_SAFE_CALLOC(permNodTab,mesh->np+1,MMG5_int,return 1);
298
299 for(tetraIdx = 1 ; tetraIdx < mesh->ne + 1 ; tetraIdx++) {
300 ptet = &mesh->tetra[tetraIdx];
301
302 /* Testing if the tetra exists */
303 if (!ptet->v[0]) continue;
304
305 nereal++;
306
307 for(j = 0 ; j <= 3 ; j++) {
308
309 nodeGlbIdx = ptet->v[j];
310
311 if ( permNodTab[nodeGlbIdx] ) continue;
312
313 ppt = &mesh->point[nodeGlbIdx];
314
315 if ( !(ppt->tag & MG_NUL) )
316 /* Building the new point list */
317 permNodTab[nodeGlbIdx] = ++npreal;
318 }
319 }
320 for( k = 1; k <= mesh->nprism; ++k) {
321 pp = &mesh->prism[k];
322
323 if ( !MG_EOK(pp) ) continue;
324
325 for(j = 0; j<6 ; j++) {
326 nodeGlbIdx = pp->v[j];
327
328 if ( permNodTab[nodeGlbIdx] ) continue;
329
330 ppt = &mesh->point[nodeGlbIdx];
331
332 if ( !(ppt->tag & MG_NUL) )
333 /* Building the new point list */
334 permNodTab[nodeGlbIdx] = ++npreal;
335 }
336 }
337
338 /* Append unseen required points for orphan points preservation */
339 for ( k=1; k<=mesh->np; ++k) {
340 ppt = &mesh->point[k];
341 if ( !MG_VOK(ppt) ) {
342 continue;
343 }
344 if ( permNodTab[k] ) continue;
345
346
347 if ( ppt->tag & MG_REQ ) {
348 /* Add orphan required point to permnodtab */
349 permNodTab[k] = ++npreal;
350 }
351 }
352
353 /* Modify the numbering of the nodes of each tetra */
354 for( tetraIdx = 1; tetraIdx < nereal + 1; tetraIdx++) {
355 for(j = 0 ; j <= 3 ; j++) {
356 mesh->tetra[tetraIdx].v[j] = permNodTab[mesh->tetra[tetraIdx].v[j]];
357 }
358 }
359
360 /* Modify the numbering of the nodes of each prism */
361 for( k = 1; k <= mesh->nprism; ++k) {
362 for(j = 0; j<6 ; j++) {
363 mesh->prism[k].v[j] = permNodTab[mesh->prism[k].v[j]];
364 }
365 }
366
367 /* Modify the numbering of the nodes of each quadra */
368 for( k = 1; k <= mesh->nquad; ++k) {
369 for(j = 0; j<4 ; j++) {
370 mesh->quadra[k].v[j] = permNodTab[mesh->quadra[k].v[j]];
371 }
372 }
373
374 /* If needed, store update the global permutation for point array */
375 if ( permNodGlob ) {
376 for ( k=1; k<=mesh->npi; ++k ) {
377 if ( MG_VOK( &mesh->point[permNodGlob[k]] ) ) {
378 permNodGlob[k] = permNodTab[permNodGlob[k]];
379 assert ( permNodGlob[k] > 0 );
380 }
381 }
382 }
383
384 /* Permute nodes and sol */
385 for (j=1; j<= mesh->np; j++) {
386 while ( permNodTab[j] != j && permNodTab[j] )
387 MMG5_swapNod(mesh,mesh->point,sol->m,fields,permNodTab,j,permNodTab[j],sol->size);
388 }
389 MMG5_DEL_MEM(mesh,permNodTab);
390
391 mesh->ne = nereal;
392 mesh->np = npreal;
393
394 if ( mesh->np >= mesh->npmax-1 )
395 mesh->npnil = 0;
396 else
397 mesh->npnil = mesh->np + 1;
398
399 if ( mesh->ne >= mesh->nemax-1 )
400 mesh->nenil = 0;
401 else
402 mesh->nenil = mesh->ne + 1;
403
404 if ( mesh->npnil ) {
405 for (k=mesh->npnil; k<mesh->npmax-1; k++) {
406 mesh->point[k].tmp = k+1;
407 }
408 mesh->point[mesh->npmax-1].tmp = 0;
409 mesh->point[mesh->npmax ].tmp = 0;
410 }
411
412 if ( mesh->nenil ) {
413 for (k=mesh->nenil; k<mesh->nemax-1; k++) {
414 mesh->tetra[k].v[3] = k+1;
415 }
416 mesh->tetra[mesh->nemax-1].v[3] = 0;
417 mesh->tetra[mesh->nemax ].v[3] = 0;
418 }
419
420 if( !MMG3D_hashTetra(mesh,0) ) return 0;
421
422 return 1;
423}
424#endif
425
tmp[*strlen0]
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMG3D_hashTetra(MMG5_pMesh mesh, int pack)
Definition: hash_3d.c:122
API headers for the mmg3d 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
static void MMG5_swapTet(MMG5_pTetra tetras, MMG5_int *perm, MMG5_int ind1, MMG5_int ind2)
Definition: librnbg_3d.c:52
int MMG5_mmg3dRenumbering(int boxVertNbr, MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol fields, MMG5_int *permNodGlob)
Definition: librnbg_3d.c:114
#define CHECK_SCOTCH(t, m, e)
#define MG_REQ
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MG_NUL
#define MMG5_GAP
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MMG5_SAFE_REALLOC(ptr, prevSize, newSize, type, message, law)
#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_pQuad quadra
Definition: libmmgtypes.h:648
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pPrism prism
Definition: libmmgtypes.h:645
MMG5_int nquad
Definition: libmmgtypes.h:613
MMG5_int nemax
Definition: libmmgtypes.h:612
MMG5_int npmax
Definition: libmmgtypes.h:612
MMG5_int nenil
Definition: libmmgtypes.h:622
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_int npi
Definition: libmmgtypes.h:612
MMG5_int nprism
Definition: libmmgtypes.h:613
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[6]
Definition: libmmgtypes.h:463
MMG5_int v[4]
Definition: libmmgtypes.h:367
MMG5_int v[4]
Definition: libmmgtypes.h:403