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