Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmg3d1_delone.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
36#include "libmmg3d.h"
37#include "libmmg3d_private.h"
39
40#ifndef MMG_PATTERN
41
42int8_t ddb;
43
44#define MMG3D_THRES_DEL 1.6
45#define MMG3D_LOPTL_DEL 1.41
46#define MMG3D_LFILTS_DEL 0.7
47#define MMG3D_LFILTL_DEL 0.2
48
81static inline
83 MMG3D_pPROctree *PROctree,MMG5_int k,
84 int8_t imax,double lmax,double lmaxtet,
85 int8_t chkRidTet,MMG5_int *ifilt,MMG5_int *ns,
86 int *warn,int8_t *countMemFailure ) {
87 MMG5_pTetra pt;
88 MMG5_pxTetra pxt;
89 MMG5_pPoint p0,p1;
90 double o[3];
91 int64_t list[MMG3D_LMAX+2];
92 MMG5_int ip1,ip2;
93 MMG5_int src,ip;
94 int ilist;
95 int8_t j,i,i1,i2;
96
98 pt = &mesh->tetra[k];
99 pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;
100
101 MMG3D_find_bdyface_from_edge(mesh,pt,imax,&i,&j,&i1,&i2,&ip1,&ip2,&p0,&p1);
102
103 if ( pxt && (pxt->ftag[i] & MG_BDY) ) {
104
106 if ( lmax < MMG3D_LOPTL_DEL ) {
107 /* Edge is small enough: nothing to do */
108 return 3;
109 }
110
112 /* Construction of bezier edge */
113 double to[3],no1[3],no2[3];
114 MMG5_int ref;
115 uint16_t tag;
116 MMG5_pPoint ppt;
117
118 int8_t ier = MMG3D_build_bezierEdge(mesh,k,imax,i,j,pxt,ip1,ip2,p0,p1,
119 &ref,&tag,o,to,no1,no2,list,&ilist);
120 switch (ier) {
121 case -1:
122 /* Strong failure */
123 case 0:
124 /* Unable to split edge: pass to next elt */
125 case 1:
126 /* Unable to split edge: try to collapse shortest edge */
127
128 /* For all previous cases, return ier */
129 return ier;
130 }
131 assert ( ier==2 && "unexpected return value for build_bezierEdge");
132
134#ifdef USE_POINTMAP
135 src = mesh->point[ip1].src;
136#else
137 src = 1;
138#endif
139 ip = MMG3D_newPt(mesh,o,tag,src);
140 if ( !ip ){
141 /* reallocation of point table */
143 *warn=1;++(*countMemFailure);
144 return 1,
145 o,tag,src);
146 }
147
148 ier = 1;
149
150 /* Mark edge as bdy to avoid issue in intmet */
151 pxt->tag[imax] |= MG_BDY;
152
153 if ( met && met->m ) {
154 ier = MMG5_intmet(mesh,met,k,imax,ip,0.5);
155 }
156 if ( ier<=0 ) {
157 MMG3D_delPt(mesh,ip);
158 return 1;
159 }
160
161 /* Simulation only if intmet call is successful */
162 /* simbulgept needs a valid tangent at ridge point (to build ridge metric in
163 * order to comute edge lengths). Thus we need to store the geometric info of
164 * point here. */
165 ppt = &mesh->point[ip];
166 MMG3D_set_geom(mesh,ppt,tag,ref,pxt->ref[i],no1,no2,to);
167
168 ier = MMG3D_simbulgept(mesh,met,list,ilist,ip);
169
170 if ( ier == 2 || ier < 0 ) {
171 /* int met failure or sharp angle failure */
172 MMG3D_delPt(mesh,ip);
173 return 1;
174 }
175 if ( ier == 0 ) {
176 /* very bad quality failure */
177 ier = MMG3D_dichoto1b(mesh,met,list,ilist,ip);
178 }
179 if ( ier == 1 ) {
180 ier = MMG5_split1b(mesh,met,list,ilist,ip,1,1,chkRidTet);
181 }
182
183 /* if we realloc memory in MMG5_split1b pt and pxt pointers are not valid */
184 if ( ier < 0 ) {
185 fprintf(stderr,"\n ## Error: %s: unable to split.\n",__func__);
186 MMG3D_delPt(mesh,ip);
187 return -1;
188 }
189 if ( ier == 0 || ier == 2 ) {
190 MMG3D_delPt(mesh,ip);
191 return 1;
192 }
193
194 (*ns)++;
195
196 return 2;
197 /* End of case of a bdy face */
198 }
199 else {
202 /* Note that it is possible that non bdy tetra contains a bdy edge, here
203 * only non bdy edge are considered */
204
205 int8_t force_splt = 0;
206 const int8_t fem_mode = 2; // value of info.fem in case of fem mode
207
208 if ( mesh->info.fem == fem_mode ) {
209 /* Force splitting of internal edges connecting bdy points */
210 if ( MG_TRUE_BDY(p0->tag) && MG_TRUE_BDY(p1->tag) ) {
211 force_splt = 1;
212 }
213 }
214
215 if ( (!force_splt) && lmax < MMG3D_LOPTL_DEL ) {
216 /* Edge is small enough: nothing to do */
217 return 3;
218 }
219
220 int8_t isbdy;
221 ilist = MMG5_coquil(mesh,k,imax,list,&isbdy);
222
223 if ( !ilist ){
224 /* Unable to compute edge shell: treat next element */
225 return 0;
226 }
227 else if ( isbdy ) {
228 /* Edge is bdy: skip it (we want to treat it from a bdy tetra) */
229 return 0;
230 }
231 else if ( ilist<0 ) {
232 return -1;
233 }
234
235 o[0] = 0.5*(p0->c[0] + p1->c[0]);
236 o[1] = 0.5*(p0->c[1] + p1->c[1]);
237 o[2] = 0.5*(p0->c[2] + p1->c[2]);
238#ifdef USE_POINTMAP
239 src = mesh->point[ip1].src;
240#else
241 src = 1;
242#endif
243 ip = MMG3D_newPt(mesh,o,MG_NOTAG,src);
244
245 if ( !ip ) {
246 /* reallocation of point table */
248 *warn=1;++(*countMemFailure);
249 return 1,
250 o,MG_NOTAG,src);
251 }
252
253 int ier = 1;
254 if ( met && met->m ) {
255 ier = MMG5_intmet(mesh,met,k,imax,ip,0.5);
256 }
257 if ( ier<=0 ) {
258 MMG3D_delPt(mesh,ip);
259 return 1;
260 }
261
262 /* Delaunay */
263 double lfilt;
264 if ( lmaxtet< MMG3D_THRES_DEL ) {
265 lfilt = MMG3D_LFILTS_DEL;
266 }
267 else {
268 lfilt = MMG3D_LFILTL_DEL;
269 }
270
271 /* No filter for internal edges connecting boundary points: we want to force
272 * splitting */
273 if ( force_splt ) {
274 lfilt = 0;
275 }
276
277 ier = 1;
278 if ( *PROctree ) {
279 ier = MMG3D_PROctreein(mesh,met,*PROctree,ip,lfilt);
280 }
281
282 if ( ier == 0 ) {
283 /* PROctree allocated and PROctreein refuse the insertion */
284 MMG3D_delPt(mesh,ip);
285 (*ifilt)++;
286 return 1;
287 }
288
289 if ( ier < 0 ) {
290 /* PROctree allocated but PROctreein fail due to lack of memory */
291 MMG3D_freePROctree ( mesh,PROctree );
292 MMG3D_delPt(mesh,ip);
293 (*ifilt)++;
294 return 1;
295 }
296
297 int lon = MMG5_cavity(mesh,met,k,ip,list,ilist/2,MMG5_EPSOK);
298 if ( lon < 1 ) {
299 MMG3D_delPt(mesh,ip);
300 return 1;
301 }
302
303 int ret = MMG5_delone(mesh,met,ip,list,lon);
304 if ( ret > 0 ) {
305 if ( *PROctree ) {
306 MMG3D_addPROctree(mesh,*PROctree,ip);
307 }
308 (*ns)++;
309 return 2;
310 }
311 if ( ret == 0 ) {
312 MMG3D_delPt(mesh,ip);
313 return 1;
314 }
315
316 /* Allocation problem ==> savemesh */
317 MMG3D_delPt(mesh,ip);
318 return -2;
319 }
320
321 return 3;
322}
323
358static inline
360 MMG3D_pPROctree *PROctree,MMG5_int k,
361 int8_t imin,double lmin,
362 int8_t imax,double lmax,double lmaxtet,
363 int8_t chkRidTet,MMG5_int *ifilt,
364 MMG5_int *ns,MMG5_int *nc,
365 int *warn ) {
366
367 int ier;
368 int8_t countMemFailure = 0;
369
370 ier = MMG3D_mmg3d1_delone_split(mesh,met,PROctree,k,imax,lmax,lmaxtet,
371 chkRidTet,ifilt,ns,warn,&countMemFailure);
372
373 switch ( ier ) {
374 case -2:
375 /* Low failure: try to save mesh and exit lib */
376 case -1:
377 /* Strong failure: exit lib without saving mesh */
378 case 0:
379 /* Unable to treat too large edge: pass to next edge of element or to next
380 * elt */
381 case 2:
382 /* Edge has been splitted: pass to next element */
383
384 /* For all previous cases, return ier value */
385 return ier;
386 }
387
388 assert ( (ier==1 || ier==3) && "Check return val of delone_split");
389
390 if ( countMemFailure > 10 ) {
391 printf(" ## Error:%s: too much reallocation errors. Exit program.\n",__func__);
392 return -1;
393 }
394
401 ier = MMG3D_adpcoledg(mesh,met,PROctree,k,imin,lmin,nc);
402
403 /* Strong failure: ier==-1 */
404 /* Unable to treat too small edge: pass to next edge of element: ier==0 */
405 /* Edge has been collapsed: pass to next element: ier==2 */
406 return ier;
407}
408
426static inline
428 MMG5_int ne,MMG5_int* ifilt,MMG5_int* ns,MMG5_int* nc,int* warn) {
429 MMG5_pTetra pt;
430 MMG5_pxTetra pxt;
431 double len,lmax;
432 MMG5_int k,base;
433 double lmin;
434 double lmaxtet,lmintet;
435 int ier,imaxtet,imintet;
436 int8_t imin,imax,chkRidTet;
437 static int8_t mmgWarn0 = 0;
438
439 base = ++mesh->mark;
440
441 if ( met->size==6 ) chkRidTet=1;
442 else chkRidTet=0;
443
444 for (k=1; k<=ne; k++) {
445 pt = &mesh->tetra[k];
446 if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
447 else if ( pt->mark < base-2 ) continue;
448 pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;
449
451 imax = -1; lmax = 0.0;
452 imin = -1; lmin = DBL_MAX;
453 int ii;
454 for (ii=0; ii<6; ii++) {
455 if ( pt->xt && (pxt->tag[ii] & MG_REQ) ) continue;
456 len = MMG5_lenedg(mesh,met,ii,pt);
457
458 if ( len > lmax ) {
459 lmax = len;
460 imax = ii;
461 }
462 if ( len < lmin ) {
463 lmin = len;
464 imin = ii;
465 }
466 }
467 /* Check that we have found valid edges */
468 if ( imax==-1 ) {
469 if ( (mesh->info.ddebug || mesh->info.imprim > 5 ) ) {
470 if ( !mmgWarn0 ) {
471 mmgWarn0 = 1;
472 fprintf(stderr,"\n # Warning: %s: all edges of tetra %" MMG5_PRId " are"
473 " boundary and required.\n",
474 __func__,k);
475 }
476 }
477 continue;
478 }
479 if ( imin==-1 ) {
480 if ( (mesh->info.ddebug || mesh->info.imprim > 5 ) ) {
481 if ( !mmgWarn0 ) {
482 mmgWarn0 = 1;
483 fprintf(stderr,"\n # Warning: %s: all edges of tetra %" MMG5_PRId " are"
484 " boundary and required.\n",
485 __func__,k);
486 }
487 }
488 continue;
489 }
490
491 ier = MMG3D_mmg3d1_delone_splcol(mesh,met,PROctree,k,imin,lmin,imax,
492 lmax,lmax,chkRidTet,ifilt,ns,nc,warn);
493
494 switch ( ier ) {
495 case -2:
496 /* Low failure: try to save mesh and exit lib */
497 return 0;
498 case -1:
499 /* Strong failure: exit lib without saving mesh */
500 return -1;
501 case 0:
502 /* Unable to treat largest/smallest edge: pass to next element */
503 continue;
504 case 2:
505 /* Edge has been collapsed: pass to next element */
506 continue;
507 }
508
509 assert ( (ier==1 || ier==3) && "Check return val of delone_split");
510
512 imaxtet = imax;
513 imintet = imin;
514 lmaxtet = lmax;
515 lmintet = lmin;
516 assert(lmin);
517
518 for (ii=0; ii<6; ii++) {
519 if ( pt->xt && (pxt->tag[ii] & MG_REQ) ) continue;
520 if ( (ii==imintet) && (lmintet < MMG3D_LOPTS)) continue;
521 if ( (ii==imaxtet) && (lmaxtet > MMG3D_LOPTL_DEL) ) continue;
522
523 len = MMG5_lenedg(mesh,met,ii,pt);
524
525 imax = ii;
526 lmax = len;
527 imin = ii;
528 lmin = len;
529
531 ier = MMG3D_mmg3d1_delone_splcol(mesh,met,PROctree,k,imin,lmin,imax,
532 lmax,lmaxtet,chkRidTet,ifilt,ns,nc,warn);
533
534 switch ( ier ) {
535 case -2:
536 /* Low failure: try to save mesh and exit lib */
537 return 0;
538 case -1:
539 /* Strong failure: exit lib without saving mesh */
540 return -1;
541 case 0:
542 /* Unable to treat largest/smallest edge: pass to next edge of element */
543 continue;
544 case 3:
545 /* Edge has not been splitted: pass to next edge */
546 continue;
547 }
548 assert ( ier==2 );
549 /* Edge has been splitted: pass to next element */
550 break;
551 }
552 }
553 return 1;
554}
555
565static
567 int it,maxit;
568 MMG5_int nf,nnf,nnm,nm,nw;
569 double crit;
570
571 /* shape optim */
572 it = nnm = nnf = 0;
573 maxit = 3;
574 crit = 1.053;
575
576 do {
577 /* treatment of bad elements*/
578 nw = MMG3D_opttyp(mesh,met,PROctree,-1);
579 /* badly shaped process */
580 if ( !mesh->info.noswap ) {
581 nf = MMG5_swpmsh(mesh,met,PROctree,2);
582 if ( nf < 0 ) {
583 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
584 __func__);
585 return 0;
586 }
587 nnf += nf;
588
589 nf += MMG5_swptet(mesh,met,crit,MMG3D_SWAP06,PROctree,2,mesh->mark-1);
590 if ( nf < 0 ) {
591 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
592 __func__);
593 return 0;
594 }
595 }
596 else nf = 0;
597
598 if ( !mesh->info.nomove ) {
599 /* move for tria with qual<1., tetra with qual<1, internal move
600 * allowed, surface degradation forbidden, volume degradation during the
601 * surface move forbidden and volume degradation during volumic move
602 * forbidden. Perform 1 iter max (0). */
603 nm = MMG5_movtet(mesh,met,PROctree,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,0,mesh->mark-1);
604 if ( nm < 0 ) {
605 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",
606 __func__);
607 return 0;
608 }
609 }
610 else nm = 0;
611 nnm += nm;
612
613 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nw+nf+nm > 0 ){
614 fprintf(stdout," ");
615 fprintf(stdout," %8" MMG5_PRId " improved, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",nw,nf,nm);
616 }
617 }
618 while( ++it < maxit && nw+nm+nf > 0 );
619
620 if ( mesh->info.imprim > 0 ) {
621 if ( abs(mesh->info.imprim) < 5 && (nnf > 0 || nnm > 0) )
622 fprintf(stdout," "
623 " "
624 " %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved, %d iter. \n",nnf,nnm,it);
625 }
626 return 1;
627}
628
641static
642int MMG5_adpdel(MMG5_pMesh mesh,MMG5_pSol met,MMG3D_pPROctree *PROctree, int* warn) {
643 int ier;
644 int it,maxit,noptim;
645 MMG5_int ns,nc,ne,nnm,nm,nnf,nf,nnc,nns,nfilt,ifilt;
646 double maxgap,dd,declic,declicsurf;
647
648 /* Iterative mesh modifications */
649 it = nnc = nns = nnf = nnm = nfilt = 0;
650 noptim = 0;
651 maxit = 10;
652 mesh->gap = maxgap = 0.5;
653 declic = 0.5/MMG3D_ALPHAD;
654 declicsurf = 1./3.46;
655
656 do {
657 if ( !mesh->info.noinsert ) {
658 *warn=0;
659 ns = nc = 0;
660 ifilt = 0;
661 ne = mesh->ne;
662 ier = MMG5_adpsplcol(mesh,met,PROctree,ne,&ifilt,&ns,&nc,warn);
663 if ( ier<=0 ) return -1;
664 } /* End conditional loop on mesh->info.noinsert */
665 else ns = nc = ifilt = 0;
666
667 if ( !mesh->info.noswap ) {
668 nf = MMG5_swpmsh(mesh,met,*PROctree,2);
669 if ( nf < 0 ) {
670 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
671 __func__);
672 return 0;
673 }
674 nnf += nf;
675 nf += MMG5_swptet(mesh,met,MMG3D_SSWAPIMPROVE,declic,*PROctree,2,mesh->mark-2);
676
677 if ( nf < 0 ) {
678 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
679 __func__);
680 return 0;
681 }
682 } else {
683 nf = 0;
684 }
685
686
687 if ( !mesh->info.nomove ) {
688 /* move for tria with qual<declicsurf, tetra with qual<declic, internal
689 * move allowed, surface degradation forbidden, volume degradation during
690 * the surface move authorized and volume degradation during volumic move
691 * forbidden. Perform 2 iter max (1). */
692 nm = MMG5_movtet(mesh,met,*PROctree,declicsurf,declic,1,1,0,1,1,mesh->mark-2);
693
694 if ( nm < 0 ) {
695 fprintf(stderr,"\n ## Error: %s: Unable to improve mesh.\n",__func__);
696 return 0;
697 }
698 }
699 else nm = 0;
700
701 nnm += nm;
702 nnc += nc;
703 nns += ns;
704 nnf += nf;
705 nfilt += ifilt;
706
707 /* decrease size of gap for reallocation */
708
709 if ( mesh->gap > maxgap/(double)maxit )
710 mesh->gap -= maxgap/(double)maxit;
711 else
712 mesh->gap -= mesh->gap/(double)maxit;
713
714
715 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && ns+nc+nm+nf > 0)
716 fprintf(stdout," %8"MMG5_PRId" filtered, %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed,"
717 " %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",ifilt,ns,nc,nf,nm);
718
719 /*optimization*/
720 dd = MMG5_abs(nc-ns);
721 if ( !noptim && (it==5 || ((dd < 5) || (dd < 0.05*MG_MAX(nc,ns)) || !(ns+nc))) ) {
722 MMG5_optbad(mesh,met,*PROctree);
723 noptim = 1;
724 }
725
726 if( it > 5 ) {
727 // if ( ns < 10 && MMG5_abs(nc-ns) < 3 ) break;
728 //else if ( it > 3 && MMG5_abs(nc-ns) < 0.3 * MG_MAX(nc,ns) ) break;
729 dd = MMG5_abs(nc-ns);
730 if ( dd < 5 || dd < 0.05*MG_MAX(nc,ns) ) break;
731 //else if ( it > 12 && nc >= ns ) break;
732 }
733 }
734 while( ++it < maxit && (noptim || nc+ns > 0) );
735
736 if ( mesh->info.imprim > 0 ) {
737 if ( (abs(mesh->info.imprim) < 5) && ( nnc || nns ) ) {
738 fprintf(stdout," %8"MMG5_PRId" filtered, %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed,"
739 " %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved, %d iter.\n",nfilt,nns,nnc,nnf,nnm, it);
740 }
741 }
742
743 return 1;
744}
745
755static
757 int it,maxit;
758 MMG5_int nnf,nf,nw,nm,nnm;
759 double declic;
760
761 it = nnm = nnf = 0;
762 maxit = 10;
763 declic = 1.01;
764 ++mesh->mark;
765 do {
766 /* treatment of bad elements*/
767 if(it < 5) {
768 nw = MMG3D_opttyp(mesh,met,PROctree,mesh->mark-2);
769 }
770 else {
771 nw = 0;
772 }
773
774 /* badly shaped process */
775 if ( !mesh->info.noswap ) {
776 nf = MMG5_swptet(mesh,met,declic,MMG3D_SWAP06,PROctree,2,mesh->mark-2);
777 if ( nf < 0 ) {
778 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
779 __func__);
780 return 0;
781 }
782 }
783 else nf = 0;
784
785 if ( !mesh->info.nomove ) {
786 /* move for tria with qual<1, tetra with qual<1, internal
787 * move allowed, surface degradation forbidden, volume degradation during
788 * the surface move forbidden and volume degradation during volumic move
789 * forbidden. Perform 4 iter max (3). */
790 nm = MMG5_movtet(mesh,met,PROctree,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,3,mesh->mark-2);
791 if ( nm < 0 ) {
792 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",
793 __func__);
794 return 0;
795 }
796 }
797 else nm = 0;
798 nnm += nm;
799
800//be careful, this procedure can degrade the worst elt
801 if ( !mesh->info.nomove && (it==2)) {
802 MMG3D_optlap(mesh,met);
803 }
804
805 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nw+nf+nm > 0 ){
806 fprintf(stdout," ");
807 fprintf(stdout," %8" MMG5_PRId " improved, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",nw,nf,nm);
808 }
809 }
810 while( ++it < maxit && nw+nm+nf > 0 );
811
812 if ( !mesh->info.nomove ) {
813 /* move for tria with qual<declicsurf, tetra with qual<declic, internal
814 * move allowed, surface degradation forbidden, volume degradation during
815 * the surface move authorized and volume degradation during volumic move
816 * forbidden. Perform 4 iter max (3). */
817 nm = MMG5_movtet(mesh,met,PROctree,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,3,mesh->mark-2);
818 if ( nm < 0 ) {
819 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",__func__);
820 return 0;
821 }
822 }
823 else nm = 0;
824 nnm += nm;
825 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nm > 0 ) {
826 fprintf(stdout," "
827 " ");
828 fprintf(stdout," %8" MMG5_PRId " moved\n",nm);
829 }
830
831
832 if ( mesh->info.imprim > 0 ) {
833 if ( abs(mesh->info.imprim) < 5 && (nnf > 0 || nnm > 0) )
834 fprintf(stdout," "
835 " "
836 " %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved, %d iter. \n",nnf,nnm,it);
837 }
838 return 1;
839}
849static
851 MMG5_pTetra pt;
852 int it,maxit;
853 MMG5_int nnf,nf,nw,k,nnm,nm;
854 double crit,declic;
855
856 /* shape optim */
857 it = nnm = nnf = 0;
858 maxit = 10;
859 crit = MMG3D_SSWAPIMPROVE;
860 declic = 0.7/MMG3D_ALPHAD;
861 /* mark reinitialization in order to see at least one time each tetra */
862 for (k=1; k<=mesh->ne; k++) {
863 pt = &mesh->tetra[k];
864 pt->mark = mesh->mark;
865 }
866
867 do {
868 ++mesh->mark;
869
870 /* treatment of bad elements */
871 if(it < 5) {
872 nw = MMG3D_opttyp(mesh,met,PROctree,mesh->mark-1);
873 }
874 else
875 nw = 0;
876 /* badly shaped process */
877 if ( !mesh->info.noswap ) {
878 nf = MMG5_swpmsh(mesh,met,PROctree,2);
879 if ( nf < 0 ) {
880 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
881 __func__);
882 return 0;
883 }
884 nnf += nf;
885
886 nf += MMG5_swptet(mesh,met,crit,declic,PROctree,2,mesh->mark-1);
887 if ( nf < 0 ) {
888 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
889 __func__);
890 return 0;
891 }
892 }
893 else nf = 0;
894
895 if ( !mesh->info.nomove ) {
896 /* move for tria with qual<1., tetra with qual<declic, internal move
897 * allowed, surface degradation forbidden, volume degradation during the
898 * surface move forbidden and volume degradation during volumic move
899 * authorized. Perform 1 iter max (0). */
900 nm = MMG5_movtet(mesh,met,PROctree,MMG3D_MAXKAL,declic,1,1,1,1,0,mesh->mark-1);
901 if ( nm < 0 ) {
902 fprintf(stderr,"\n ## Error: %s: unable to improve mesh.\n",__func__);
903 return 0;
904 }
905 }
906 else nm = 0;
907 nnm += nm;
908
909 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nw+nf+nm > 0 ){
910 fprintf(stdout," ");
911 fprintf(stdout," %8" MMG5_PRId " improved, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",nw,nf,nm);
912 }
913
914 if ( it > 3 ) {
915 if ( !nw && (!nm || !nf) ) break;
916 }
917 }
918 while( ++it < maxit && nw+nm+nf > 0 );
919
920 if ( !mesh->info.nomove ) {
921 /* move for tria with qual<1., tetra with qual<1., internal move allowed,
922 * surface degradation forbidden, volume degradation during the surface and
923 * volume move forbidden. Perform 4 iter max. */
924 nm = MMG5_movtet(mesh,met,PROctree,MMG3D_MAXKAL,MMG3D_MAXKAL,1,1,1,1,3,mesh->mark-2);
925 if ( nm < 0 ) {
926 fprintf(stderr,"\n ## Error: %s: Unable to improve mesh.\n",__func__);
927 return 0;
928 }
929 }
930 else nm = 0;
931 nnm += nm;
932 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nm > 0 ) {
933 fprintf(stdout," "
934 " ");
935 fprintf(stdout," %8" MMG5_PRId " moved\n",nm);
936 }
937
938 if ( mesh->info.imprim > 0 ) {
939 if ( abs(mesh->info.imprim) < 5 && (nnf > 0 || nnm > 0) )
940 fprintf(stdout," "
941 " "
942 " %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved, %d iter. \n",nnf,nnm,it);
943 }
944 return 1;
945}
946
958static
960 MMG5_int * permNodGlob) {
961 MMG5_int nnf,nf;
962 int warn,ns;
963
965 if ( !mesh->info.noswap ) {
966 nnf = MMG5_swpmsh(mesh,met,*PROctree,2);
967 if ( nnf < 0 ) {
968 fprintf(stderr,"\n ## Error: %s: unable to improve mesh. Exiting.\n",
969 __func__);
970 return 0;
971 }
972 nf = MMG5_swptet(mesh,met,MMG3D_SSWAPIMPROVE,MMG3D_SWAP06,*PROctree,2,mesh->mark-2);
973 if ( nf < 0 ) {
974 fprintf(stderr,"\n ## Error: %s: Unable to improve mesh. Exiting.\n",
975 __func__);
976 return 0;
977 }
978 nnf+=nf;
979 } else {
980 nnf = nf = 0;
981 }
982
983 if ( mesh->info.ddebug ) {
984 fprintf(stdout," ------------- Delaunay: INITIAL SWAP %7"MMG5_PRId"\n",nnf);
985 MMG3D_outqua(mesh,met);
986 }
987
989 warn = 0;
990
991 ns = MMG5_adpdel(mesh,met,PROctree,&warn);
992
993 if ( ns < 0 ) {
994 fprintf(stderr,"\n ## Error: %s: unable to complete mesh. Exit program.\n",
995 __func__);
996 return 0;
997 }
998
999 if ( warn ) {
1000 fprintf(stderr,"\n ## Error: %s:",__func__);
1001 fprintf(stderr," unable to allocate a new point in last call of adpspl.\n");
1002 fprintf(stderr," ## Check the mesh size or ");
1003 fprintf(stderr,"increase the maximal authorized memory with the -m option.\n");
1004 fprintf(stderr," ## Uncomplete mesh. Exiting\n" );
1005 return 0;
1006 }
1007
1008 /* renumerotation if available */
1009 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
1010 return 0;
1011
1014 if(mesh->info.optimLES) {
1015 if(!MMG5_optetLES(mesh,met,*PROctree)) return 0;
1016 }
1017 else {
1018 if(!MMG5_optet(mesh,met,*PROctree)) return 0;
1019 }
1020 return 1;
1021}
1022
1032int MMG5_mmg3d1_delone(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int *permNodGlob) {
1033 MMG3D_pPROctree PROctree = NULL;
1034
1035 if ( abs(mesh->info.imprim) > 4 )
1036 fprintf(stdout," ** MESH ANALYSIS\n");
1037
1038 if ( mesh->info.iso && !MMG3D_chkmani(mesh) ) {
1039 fprintf(stderr,"\n ## Non orientable implicit surface before remeshing. Exit program.\n");
1040 return 0;
1041 }
1042
1044 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
1045 fprintf(stdout," ** GEOMETRIC MESH\n");
1046
1047 if ( !MMG5_anatet(mesh,met,1,0) ) {
1048 fprintf(stderr,"\n ## Unable to split mesh. Exiting.\n");
1049 return 0;
1050 }
1051
1052 /* Debug: export variable MMG_SAVE_ANATET1 to save adapted mesh at the end of
1053 * anatet wave */
1054 if ( getenv("MMG_SAVE_ANATET1") ) {
1055 printf(" ## WARNING: EXIT AFTER ANATET-1."
1056 " (MMG_SAVE_ANATET1 env variable is exported).\n");
1057 return 1;
1058 }
1059
1061 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
1062 fprintf(stdout," ** COMPUTATIONAL MESH\n");
1063
1064
1065 /* define metric map */
1066 if ( !MMG3D_defsiz(mesh,met) ) {
1067 fprintf(stderr,"\n ## Metric undefined. Exit program.\n");
1068 return 0;
1069 }
1070
1071 /* Debug: export variable MMG_SAVE_DEFSIZ to save adapted mesh at the end of
1072 * anatet wave */
1073 if ( getenv("MMG_SAVE_DEFSIZ") ) {
1074 printf(" ## WARNING: EXIT AFTER DEFSIZ."
1075 " (MMG_SAVE_DEFSIZ env variable is exported).\n");
1076 return 1;
1077 }
1078
1080
1081 if ( mesh->info.hgrad > 0. ) {
1082 if ( !MMG3D_gradsiz(mesh,met) ) {
1083 fprintf(stderr,"\n ## Gradation problem. Exit program.\n");
1084 return 0;
1085 }
1086 }
1087 if ( mesh->info.hgradreq > 0. ) {
1088 MMG3D_gradsizreq(mesh,met);
1089 }
1090
1091 /* Debug: export variable MMG_SAVE_GRADSIZ to save adapted mesh at the end of
1092 * anatet wave */
1093 if ( getenv("MMG_SAVE_GRADSIZ") ) {
1094 printf(" ## WARNING: EXIT AFTER GRADSIZ."
1095 " (MMG_SAVE_GRADSIZ env variable is exported).\n");
1096 return 1;
1097 }
1098
1099 /*update quality*/
1100 if ( !MMG3D_tetraQual(mesh,met,1) ) return 0;
1101
1102 if ( !MMG5_anatet(mesh,met,2,0) ) {
1103 fprintf(stderr,"\n ## Unable to split mesh. Exiting.\n");
1104 return 0;
1105 }
1106
1107 /* Debug: export variable MMG_SAVE_ANATET2 to save adapted mesh at the end of
1108 * anatet wave */
1109 if ( getenv("MMG_SAVE_ANATET2") ) {
1110 printf(" ## WARNING: EXIT AFTER ANATET-2."
1111 " (MMG_SAVE_ANATET2 env variable is exported).\n");
1112 return 1;
1113 }
1114
1115 /* renumerotation if available */
1116 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) ) {
1117 return 0;
1118 }
1119
1120 if ( mesh->info.PROctree > 0 ) {
1121 if ( !MMG3D_initPROctree(mesh,&PROctree,mesh->info.PROctree) ) {
1122 if ( PROctree ) {
1123 /*free PROctree*/
1124 MMG3D_freePROctree(mesh,&PROctree);
1125 }
1126 }
1127 }
1128
1129 if ( !MMG5_adptet_delone(mesh,met,&PROctree,permNodGlob) ) {
1130 fprintf(stderr,"\n ## Unable to adapt. Exit program.\n");
1131 if ( PROctree ) {
1132 /*free PROctree*/
1133 MMG3D_freePROctree(mesh,&PROctree);
1134 }
1135 return 0;
1136 }
1137
1138 /* in test phase: check if no element with 2 bdry faces */
1139 if ( !MMG5_chkfemtopo(mesh) ) {
1140 fprintf(stderr,"\n ## Topology of mesh unsuited for fem computations. Exit program.\n");
1141 if ( PROctree ) {
1142 /*free PROctree*/
1143 MMG3D_freePROctree(mesh,&PROctree);
1144 }
1145 return 0;
1146 }
1147
1148 if ( mesh->info.iso && !MMG3D_chkmani(mesh) ) {
1149 fprintf(stdout,"\n ## Warning: %s: Non orientable implicit surface after remeshing.\n",__func__);
1150 }
1151
1152 if ( PROctree ) {
1153 /*free PROctree*/
1154 MMG3D_freePROctree(mesh,&PROctree);
1155 }
1156
1157 return 1;
1158}
1159
1160#endif
int ier
MMG5_pMesh * mesh
void MMG3D_freePROctree(MMG5_pMesh mesh, MMG3D_pPROctree *q)
Definition: PRoctree_3d.c:164
int MMG3D_addPROctree(MMG5_pMesh mesh, MMG3D_pPROctree q, const MMG5_int no)
Definition: PRoctree_3d.c:775
int MMG3D_initPROctree(MMG5_pMesh mesh, MMG3D_pPROctree *q, int nv)
Definition: PRoctree_3d.c:65
int MMG5_coquil(MMG5_pMesh mesh, MMG5_int start, int ia, int64_t *list, int8_t *isbdy)
Definition: boulep_3d.c:1406
int MMG5_chkfemtopo(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:824
int MMG5_delone(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int ip, int64_t *list, int ilist)
Definition: delaunay_3d.c:140
void MMG5_gradation_info(MMG5_pMesh mesh)
Definition: isosiz.c:96
API headers and documentation for the mmg3d library, for volumetric meshes in 3D.
#define MMG3D_LMAX
Definition: libmmg3d.h:130
#define MMG3D_SSWAPIMPROVE
#define MMG3D_ALPHAD
int MMG5_split1b(MMG5_pMesh, MMG5_pSol, int64_t *, int, MMG5_int, int, int8_t, int8_t)
Definition: split_3d.c:629
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:672
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:736
#define MMG3D_LOPTS
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:1898
#define MMG3D_MAXKAL
int MMG5_anatet(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk, int patternMode)
Definition: mmg3d1.c:3159
int MMG3D_simbulgept(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ilist, MMG5_int)
Definition: split_3d.c:330
void MMG3D_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_3d.c:80
int MMG3D_chkmani(MMG5_pMesh mesh)
Definition: mmg3d2.c:1528
MMG5_int MMG3D_newPt(MMG5_pMesh mesh, double c[3], uint16_t tag, MMG5_int src)
Definition: zaldy_3d.c:39
int MMG3D_optlap(MMG5_pMesh, MMG5_pSol)
Definition: optlap_3d.c:46
int MMG3D_tetraQual(MMG5_pMesh mesh, MMG5_pSol met, int8_t metRidTyp)
Definition: quality_3d.c:50
void MMG3D_set_geom(MMG5_pMesh, MMG5_pPoint, uint16_t, MMG5_int, MMG5_int, double[3], double[3], double[3])
Definition: mmg3d1.c:59
int MMG3D_outqua(MMG5_pMesh mesh, MMG5_pSol met)
Definition: quality_3d.c:780
int MMG3D_dichoto1b(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ret, MMG5_int)
Definition: mmg3d1.c:293
#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:1210
#define MMG3D_SWAP06
MMG5_int MMG3D_opttyp(MMG5_pMesh, MMG5_pSol, MMG3D_pPROctree, MMG5_int)
Definition: opttyp_3d.c:472
int8_t MMG3D_build_bezierEdge(MMG5_pMesh, MMG5_int, int8_t, int8_t, int8_t, MMG5_pxTetra, MMG5_int, MMG5_int, MMG5_pPoint, MMG5_pPoint, MMG5_int *, uint16_t *, double[3], double[3], double[3], double[3], int64_t *, int *)
Definition: mmg3d1.c:1780
int MMG5_scotchCall(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pSol fields, MMG5_int *permNodGlob)
Definition: librnbg.c:231
static int MMG5_adpdel(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree *PROctree, int *warn)
static int MMG5_adpsplcol(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree *PROctree, MMG5_int ne, MMG5_int *ifilt, MMG5_int *ns, MMG5_int *nc, int *warn)
static int MMG5_optet(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree)
int MMG5_mmg3d1_delone(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int *permNodGlob)
#define MMG3D_LFILTS_DEL
Definition: mmg3d1_delone.c:46
#define MMG3D_LOPTL_DEL
Definition: mmg3d1_delone.c:45
static int MMG5_optbad(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree)
#define MMG3D_THRES_DEL
Definition: mmg3d1_delone.c:44
static int MMG3D_mmg3d1_delone_splcol(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree *PROctree, MMG5_int k, int8_t imin, double lmin, int8_t imax, double lmax, double lmaxtet, int8_t chkRidTet, MMG5_int *ifilt, MMG5_int *ns, MMG5_int *nc, int *warn)
static int MMG5_optetLES(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree)
int8_t ddb
Definition: mmg3d1_delone.c:42
static int MMG3D_mmg3d1_delone_split(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree *PROctree, MMG5_int k, int8_t imax, double lmax, double lmaxtet, int8_t chkRidTet, MMG5_int *ifilt, MMG5_int *ns, int *warn, int8_t *countMemFailure)
Definition: mmg3d1_delone.c:82
static int MMG5_adptet_delone(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree *PROctree, MMG5_int *permNodGlob)
#define MMG3D_LFILTL_DEL
Definition: mmg3d1_delone.c:47
#define MG_REQ
#define MMG5_EPSOK
#define MG_EOK(pt)
#define MG_MAX(a, b)
#define MG_NOTAG
#define MG_TRUE_BDY(tag)
#define MG_BDY
int8_t iso
Definition: libmmgtypes.h:541
int8_t ddebug
Definition: libmmgtypes.h:539
uint8_t noswap
Definition: libmmgtypes.h:553
double hgrad
Definition: libmmgtypes.h:525
uint8_t noinsert
Definition: libmmgtypes.h:553
int PROctree
Definition: libmmgtypes.h:534
uint8_t nomove
Definition: libmmgtypes.h:553
uint8_t optimLES
Definition: libmmgtypes.h:553
double hgradreq
Definition: libmmgtypes.h:525
int8_t fem
Definition: libmmgtypes.h:546
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_int ne
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int mark
Definition: libmmgtypes.h:626
double gap
Definition: libmmgtypes.h:616
MMG5_pTetra tetra
Definition: libmmgtypes.h:651
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:652
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double c[3]
Definition: libmmgtypes.h:277
uint16_t tag
Definition: libmmgtypes.h:290
double * m
Definition: libmmgtypes.h:680
Structure to store tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:407
MMG5_int xt
Definition: libmmgtypes.h:413
MMG5_int mark
Definition: libmmgtypes.h:412
uint16_t tag
Definition: libmmgtypes.h:417
Structure to store additional information for the surface tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:425
uint16_t tag[6]
Definition: libmmgtypes.h:432
MMG5_int ref[4]
Definition: libmmgtypes.h:426
uint16_t ftag[4]
Definition: libmmgtypes.h:430