Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmg3d1_pattern.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
39#include "libmmg3d.h"
42
53static MMG5_int MMG5_adpspl(MMG5_pMesh mesh,MMG5_pSol met, int* warn) {
54 MMG5_pTetra pt;
55 MMG5_pxTetra pxt;
56 MMG5_pPoint p0,p1;
57 double len,lmax,o[3];
58 MMG5_int ns,src,k,ip,ip1,ip2;
59 int64_t list[MMG3D_LMAX+2];
60 int ier,ilist;
61 int8_t imax,j,i,i1,i2;
62 int8_t chkRidTet;
63 static int8_t mmgWarn = 0;
64
65 *warn=0;
66 ns = 0;
67
68 if ( met->size==6 ) chkRidTet=1;
69 else chkRidTet=0;
70
71 for (k=1; k<=mesh->ne; k++) {
72 pt = &mesh->tetra[k];
73 if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
74 pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;
75
76 /* find longest edge */
77 imax = -1; lmax = 0.0;
78 for (i=0; i<6; i++) {
79 if ( pt->xt && (pxt->tag[i] & MG_REQ) ) continue;
80 len = MMG5_lenedg(mesh,met,i,pt);
81
82 if ( len > lmax ) {
83 lmax = len;
84 imax = i;
85 }
86 }
87 if ( imax==-1 ) {
88 if ( !mmgWarn ) {
89 fprintf(stderr,
90 "\n ## Warning: %s: at least 1 tetra with 4 required"
91 " or null edges.\n",__func__);
92 mmgWarn = 1;
93 }
94 continue;
95 }
96 if ( lmax < MMG3D_LOPTL ) continue;
97
98 /* proceed edges according to lengths */
99 MMG3D_find_bdyface_from_edge(mesh,pt,imax,&i,&j,&i1,&i2,&ip1,&ip2,&p0,&p1);
100
101 if ( pt->xt && (pxt->ftag[i] & MG_BDY) ) {
102 /* Case of a boundary face */
103 if ( !(MG_GET(pxt->ori,i)) ) continue;
104
105 ier = MMG3D_splsurfedge( mesh,met,k,pt,pxt,imax,2,chkRidTet,warn );
106
107 if ( ier==-1 ) { return -1; }
108 else if ( !ier ) { continue; }
109 else if ( ier==2 ) {
110 /* Unable to split due to lack of memory */
111 return ns;
112 }
113
114 ++ns;
115 }
116 else {
117 /* Case of an internal face */
118
119 /* Skip only boundary edges but try to trat internal edges connecting bdy
120 * points */
121 int8_t isbdy;
122 ilist = MMG5_coquil(mesh,k,imax,list,&isbdy);
123 if ( !ilist ) continue;
124 else if ( isbdy ) {
125 continue;
126 }
127 else if ( ilist<0 ) {
128 return -1;
129 }
130
131 o[0] = 0.5*(p0->c[0] + p1->c[0]);
132 o[1] = 0.5*(p0->c[1] + p1->c[1]);
133 o[2] = 0.5*(p0->c[2] + p1->c[2]);
134
135#ifdef USE_POINTMAP
136 src = p0->src;
137#else
138 src = 1;
139#endif
140 ip = MMG3D_newPt(mesh,o,MG_NOTAG,src);
141
142 if ( !ip ) {
143 /* reallocation of point table */
145 *warn=1;
146 break
147 ,o,MG_NOTAG,src);
148 }
149
150 ier = 1;
151 if ( met && met->m ) {
152 ier = MMG5_intmet(mesh,met,k,imax,ip,0.5);
153 }
154 if ( !ier ) {
155 MMG3D_delPt(mesh,ip);
156 return -1;
157 }
158 else if (ier < 0 ) {
159 MMG3D_delPt(mesh,ip);
160 continue;
161 }
162
163 ier = MMG3D_simbulgept(mesh,met,list,ilist,ip);
164 if ( ier == 1 )
165 ier = MMG5_split1b(mesh,met,list,ilist,ip,1,1,0);
166
167 if ( ier < 0 ) {
168 fprintf(stderr,"\n ## Error: %s: unable to split.\n",__func__);
169 return -1;
170 }
171 else if ( ier == 0 || ier == 2 ) {
172 MMG3D_delPt(mesh,ip);
173 }
174 else {
175 ns++;
176 }
177 }
178 }
179
180 return ns;
181}
182
192static MMG5_int MMG5_adpcol(MMG5_pMesh mesh,MMG5_pSol met) {
193 MMG5_pTetra pt;
194 MMG5_pxTetra pxt;
195 double len,lmin;
196 MMG5_int k,nc;
197 int ier;
198 int8_t imin,i;
199 static int8_t mmgWarn = 0;
200
201 nc = 0;
202 for (k=1; k<=mesh->ne; k++) {
203 pt = &mesh->tetra[k];
204 if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
205 pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;
206
208 imin = -1; lmin = DBL_MAX;
209 for (i=0; i<6; i++) {
210 if ( pt->xt && (pxt->tag[i] & MG_REQ) ) continue;
211 len = MMG5_lenedg(mesh,met,i,pt);
212
213 if ( len < lmin ) {
214 lmin = len;
215 imin = i;
216 }
217 }
218 if ( imin==-1 ) {
219 if ( !mmgWarn ) {
220 fprintf(stderr,
221 "\n ## Warning: %s: at least 1 tetra with 4 required"
222 " or null edges.\n",__func__);
223 mmgWarn = 1;
224 }
225 continue;
226 }
227
229 ier = MMG3D_adpcoledg(mesh,met,NULL,k,imin,lmin,&nc);
230 switch ( ier ) {
231 case -1:
232 /* chkcol_bdy failure do to error in edge shell computation */
233 return -1;
234 default:
235 assert ( ier==0 || ier==2 || ier==3 );
236 /* Pass to next element for other return values:
237 * - 0: for colver failure or impossible collapse
238 * - 2: for successful Collapse
239 * - 3: if edge is large enough or chkcol_[int|bdy] refuse the collapse
240 * (due to normal deviation, hausdorff check ...) */
241 }
242 }
243
244 return nc;
245}
246
258static int MMG5_adptet(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int *permNodGlob) {
259 int it1,it,maxit;
260 MMG5_int nf,nnf,nnm,nm,nnc,nc,nns,ns;
261 int warn;//,nw;
262
263 /* Iterative mesh modifications */
264 it = nnc = nns = nnf = nnm = warn = 0;
265 maxit = 10;
266 do {
267 if ( !mesh->info.noinsert ) {
268 ns = MMG5_adpspl(mesh,met,&warn);
269 if ( ns < 0 ) {
270 fprintf(stderr,"\n ## Error: %s: unable to complete mesh."
271 " Exit program.\n",__func__);
272 return 0;
273 }
274 }
275 else ns = 0;
276
277 /* renumbering if available and needed */
278 if ( it==1 && !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
279 return 0;
280
281 if ( !mesh->info.noinsert ) {
282 nc = MMG5_adpcol(mesh,met);
283 if ( nc < 0 ) {
284 fprintf(stderr,"\n ## Error: %s: unable to complete mesh."
285 " Exit program.\n",__func__);
286 return 0;
287 }
288 }
289 else nc = 0;
290
291 if ( !mesh->info.nomove ) {
292 nm = MMG5_movtet(mesh,met,NULL,MMG3D_MAXKAL,MMG3D_MAXKAL,1,0,0,0,1,mesh->mark-2);
293 if ( nm < 0 ) {
294 fprintf(stderr,"\n ## Error: %s: unable to improve mesh."
295 " Exiting.\n",__func__);
296 return 0;
297 }
298 }
299 else nm = 0;
300
301 if ( !mesh->info.noswap ) {
302 nf = MMG5_swpmsh(mesh,met,NULL,2);
303 if ( nf < 0 ) {
304 fprintf(stderr,"\n ## Error: %s: unable to improve mesh."
305 " Exiting.\n",__func__);
306 return 0;
307 }
308 nnf += nf;
309
311 if ( nf < 0 ) {
312 fprintf(stderr,"\n ## Error: %s: unable to improve mesh."
313 " Exiting.\n",__func__);
314 return 0;
315 }
316 }
317 else nf = 0;
318
319 nnc += nc;
320 nns += ns;
321 nnf += nf;
322 nnm += nm;
323
324 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && ns+nc > 0 )
325 fprintf(stdout," %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",ns,nc,nf,nm);
326 if ( ns < 10 && MMG5_abs(nc-ns) < 3 ) break;
327 else if ( it > 3 && MMG5_abs(nc-ns) < 0.3 * MG_MAX(nc,ns) ) break;
328 }
329 while( ++it < maxit && nc+ns > 0 );
330
331 if ( warn ) {
332 fprintf(stderr,"\n ## Error: %s: unable to allocate a new point in last"
333 " call of MMG5_adpspl.\n",__func__);
335
336 fprintf(stderr,"\n ## Error: %s: uncomplete mesh."
337 " Exiting\n",__func__ );
338 return 0;
339 }
340
341 /* renumbering if available */
342 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
343 return 0;
344
345 /*shape optim*/
346 it1 = it;
347 it = 0;
348 maxit = 2;
349 do {
350/* /\* treatment of bad elements*\/ */
351/* if( 0 && it < 2) { */
352/* nw = MMG3D_opttyp(mesh,met,NULL); */
353/* } */
354/* else */
355/* nw = 0; */
356
357 if ( !mesh->info.nomove ) {
358 nm = MMG5_movtet(mesh,met,NULL,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,0,mesh->mark-2);
359 if ( nm < 0 ) {
360 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",
361 __func__);
362 return 0;
363 }
364 nnm += nm;
365 }
366 else nm = 0;
367
368 if ( !mesh->info.noswap ) {
369 nf = MMG5_swpmsh(mesh,met,NULL,2);
370 if ( nf < 0 ) {
371 fprintf(stderr,"\n ## Error: %s: unable to improve mesh."
372 " Exiting.\n",__func__);
373 return 0;
374 }
375 nnf += nf;
376
378 if ( nf < 0 ) {
379 fprintf(stderr,"\n ## Error: %s: Unable to improve mesh."
380 " Exiting.\n",__func__);
381 return 0;
382 }
383 }
384 else nf = 0;
385
386 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && /*nw+*/nf+nm > 0 ){
387 fprintf(stdout," ");
388 fprintf(stdout,"%8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",nf,nm);
389 }
390 }
391 while( ++it < maxit && /*nw+*/nm+nf > 0 );
392
393 if ( !mesh->info.nomove ) {
394 nm = MMG5_movtet(mesh,met,NULL,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,3,mesh->mark-2);
395 if ( nm < 0 ) {
396 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",
397 __func__);
398 return 0;
399 }
400 nnm += nm;
401 }
402 else nm = 0;
403
404 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nm > 0 ){
405 fprintf(stdout," ");
406 fprintf(stdout," %8" MMG5_PRId " moved\n",nm);
407 }
408
409 if ( mesh->info.imprim > 0 ) {
410 if ( abs(mesh->info.imprim) < 5 && (nnc > 0 || nns > 0) )
411 fprintf(stdout," %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved,"
412 " %d iter. \n",
413 nns,nnc,nnf,nnm,it+it1);
414 }
415 return 1;
416}
417
428int MMG5_mmg3d1_pattern(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int *permNodGlob) {
429
430 if ( abs(mesh->info.imprim) > 4 )
431 fprintf(stdout," ** MESH ANALYSIS\n");
432
433 if ( mesh->info.iso && !MMG3D_chkmani(mesh) ) {
434 fprintf(stderr,"\n ## Non orientable implicit surface. Exit program.\n");
435 return 0;
436 }
437
439 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
440 fprintf(stdout," ** GEOMETRIC MESH\n");
441
442 if ( !MMG5_anatet(mesh,met,1,1) ) {
443 fprintf(stderr,"\n ## Unable to split mesh. Exiting.\n");
444 return 0;
445 }
446
447 /* Debug: export variable MMG_SAVE_ANATET1 to save adapted mesh at the end of
448 * anatet wave */
449 if ( getenv("MMG_SAVE_ANATET1") ) {
450 printf(" ## WARNING: EXIT AFTER ANATET-1."
451 " (MMG_SAVE_ANATET1 env variable is exported).\n");
452 return 1;
453 }
454
455 /* renumbering if available */
456 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
457 return 0;
458
460 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
461 fprintf(stdout," ** COMPUTATIONAL MESH\n");
462
463 /* define metric map */
464 if ( !MMG3D_defsiz(mesh,met) ) {
465 fprintf(stderr,"\n ## Metric undefined. Exit program.\n");
466 return 0;
467 }
468
469 /* Debug: export variable MMG_SAVE_DEFSIZ to save adapted mesh at the end of
470 * anatet wave */
471 if ( getenv("MMG_SAVE_DEFSIZ") ) {
472 printf(" ## WARNING: EXIT AFTER DEFSIZ."
473 " (MMG_SAVE_DEFSIZ env variable is exported).\n");
474 return 1;
475 }
476
478
479 /* Debug: export variable MMG_SAVE_GRADSIZ to save adapted mesh at the end of
480 * anatet wave */
481 if ( getenv("MMG_SAVE_GRADSIZ") ) {
482 printf(" ## WARNING: EXIT AFTER GRADSIZ."
483 " (MMG_SAVE_GRADSIZ env variable is exported).\n");
484 return 1;
485 }
486
487 if ( mesh->info.hgrad > 0. ) {
488 if ( !MMG3D_gradsiz(mesh,met) ) {
489 fprintf(stderr,"\n ## Gradation problem. Exit program.\n");
490 return 0;
491 }
492 }
493 if ( mesh->info.hgradreq > 0. ) {
494 MMG3D_gradsizreq(mesh,met);
495 }
496
497 /* update quality*/
498 if ( !MMG3D_tetraQual(mesh,met,1) ) return 0;
499
500 if ( !MMG5_anatet(mesh,met,2,1) ) {
501 fprintf(stderr,"\n ## Unable to split mesh. Exiting.\n");
502 return 0;
503 }
504
505 /* Debug: export variable MMG_SAVE_ANATET2 to save adapted mesh at the end of
506 * anatet wave */
507 if ( getenv("MMG_SAVE_ANATET2") ) {
508 printf(" ## WARNING: EXIT AFTER ANATET-2."
509 " (MMG_SAVE_ANATET2 env variable is exported).\n");
510 return 1;
511 }
512
513 /* renumbering if available */
514 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
515 return 0;
516
517#ifdef DEBUG
518 puts("---------------------------Fin anatet---------------------");
520#endif
521 if ( !MMG5_adptet(mesh,met,permNodGlob) ) {
522 fprintf(stderr,"\n ## Unable to adapt. Exit program.\n");
523 return 0;
524 }
525
526#ifdef DEBUG
527 puts("---------------------Fin adptet-----------------");
529#endif
530 /* in test phase: check if no element with 2 bdry faces */
531 if ( !MMG5_chkfemtopo(mesh) ) {
532 fprintf(stderr,"\n ## Topology of mesh unsuited for fem computations. Exit program.\n");
533 return 0;
534 }
535
536 if ( mesh->info.iso && !MMG3D_chkmani(mesh) ) {
537 fprintf(stderr,"\n ## Non orientable implicit surface. Exit program.\n");
538 return 0;
539 }
540
541 return 1;
542}
int ier
MMG5_pMesh * mesh
int MMG5_coquil(MMG5_pMesh mesh, MMG5_int start, int ia, int64_t *list, int8_t *isbdy)
Definition: boulep_3d.c:1403
int MMG5_chkfemtopo(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:767
void MMG5_gradation_info(MMG5_pMesh mesh)
Definition: isosiz.c:96
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
#define MMG3D_SSWAPIMPROVE
MMG5_int MMG3D_newPt(MMG5_pMesh mesh, double c[3], int16_t tag, MMG5_int src)
Definition: zaldy_3d.c:39
int MMG5_split1b(MMG5_pMesh, MMG5_pSol, int64_t *, int, MMG5_int, int, int8_t, int8_t)
Definition: split_3d.c:617
MMG5_int MMG5_swpmsh(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, int)
Definition: mmg3d1.c:598
MMG5_int MMG5_swptet(MMG5_pMesh mesh, MMG5_pSol met, double, double, MMG3D_pPROctree, int, MMG5_int)
Definition: mmg3d1.c:668
MMG5_int MMG5_movtet(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, double clickSurf, double clickVol, int moveVol, int improveSurf, int improveVolSurf, int improveVol, int maxit, MMG5_int testmark)
Definition: mmg3d1.c:732
void MMG3D_find_bdyface_from_edge(MMG5_pMesh, MMG5_pTetra, int8_t, int8_t *, int8_t *, int8_t *, int8_t *, MMG5_int *, MMG5_int *, MMG5_pPoint *, MMG5_pPoint *)
Definition: mmg3d1.c:1868
#define MMG3D_MAXKAL
int MMG5_anatet(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk, int patternMode)
Definition: mmg3d1.c:3116
int MMG3D_simbulgept(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ilist, MMG5_int)
Definition: split_3d.c:324
void MMG3D_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_3d.c:80
int MMG3D_chkmani(MMG5_pMesh mesh)
Definition: mmg3d2.c:1527
int MMG3D_splsurfedge(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_pTetra, MMG5_pxTetra, int8_t, int8_t, int8_t, int *)
Definition: mmg3d1.c:1927
int MMG3D_tetraQual(MMG5_pMesh mesh, MMG5_pSol met, int8_t metRidTyp)
Definition: quality_3d.c:50
int MMG3D_outqua(MMG5_pMesh mesh, MMG5_pSol met)
Definition: quality_3d.c:764
#define MMG3D_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag, src)
int MMG3D_adpcoledg(MMG5_pMesh, MMG5_pSol, MMG3D_pPROctree *, MMG5_int, int8_t, double, MMG5_int *)
Definition: mmg3d1.c:1180
#define MMG3D_LOPTL
#define MMG3D_SWAP06
int MMG5_scotchCall(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pSol fields, MMG5_int *permNodGlob)
Definition: librnbg.c:231
static MMG5_int MMG5_adpspl(MMG5_pMesh mesh, MMG5_pSol met, int *warn)
static int MMG5_adptet(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int *permNodGlob)
static MMG5_int MMG5_adpcol(MMG5_pMesh mesh, MMG5_pSol met)
int MMG5_mmg3d1_pattern(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int *permNodGlob)
#define MG_REQ
#define MG_EOK(pt)
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MAX(a, b)
#define MG_NOTAG
#define MG_GET(flag, bit)
#define MG_BDY
int8_t iso
Definition: libmmgtypes.h:534
int8_t ddebug
Definition: libmmgtypes.h:532
uint8_t noswap
Definition: libmmgtypes.h:546
double hgrad
Definition: libmmgtypes.h:518
uint8_t noinsert
Definition: libmmgtypes.h:546
uint8_t nomove
Definition: libmmgtypes.h:546
uint8_t optimLES
Definition: libmmgtypes.h:546
double hgradreq
Definition: libmmgtypes.h:518
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_int mark
Definition: libmmgtypes.h:618
double gap
Definition: libmmgtypes.h:608
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
double * m
Definition: libmmgtypes.h:671
MMG5_int xt
Definition: libmmgtypes.h:407
int16_t tag
Definition: libmmgtypes.h:410
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
int8_t ori
Definition: libmmgtypes.h:427