Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmgs1.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
35#include "libmmgs_private.h"
36#include "mmgsexterns_private.h"
37#include "mmgexterns_private.h"
39
40extern int8_t ddb;
41
52int MMGS_dichoto(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int *vx) {
53 MMG5_pTria pt;
54 MMG5_pPoint pa,pb,ps;
55 double o[3][3],p[3][3];
56 float to,tp,t;
57 MMG5_int ia,ib;
58 int i1,i2,ier,it,maxit;
59 int8_t i,j;
60
61 pt = &mesh->tria[k];
62 /* get point on surface and along segment for edge split */
63 for (i=0; i<3; i++) {
64 memset(p[i],0,3*sizeof(double));
65 memset(o[i],0,3*sizeof(double));
66 if ( vx[i] > 0 ) {
67 i1 = MMG5_inxt2[i];
68 i2 = MMG5_inxt2[i1];
69 ia = pt->v[i1];
70 ib = pt->v[i2];
71 pa = &mesh->point[ia];
72 pb = &mesh->point[ib];
73 ps = &mesh->point[vx[i]];
74 o[i][0] = 0.5 * (pa->c[0] + pb->c[0]);
75 o[i][1] = 0.5 * (pa->c[1] + pb->c[1]);
76 o[i][2] = 0.5 * (pa->c[2] + pb->c[2]);
77 p[i][0] = ps->c[0];
78 p[i][1] = ps->c[1];
79 p[i][2] = ps->c[2];
80 }
81 }
82 maxit = 4;
83 it = 0;
84 tp = 1.0;
85 to = 0.0;
86 j = 10;
87 do {
88 /* compute new position */
89 t = 0.5 * (tp + to);
90 for (i=0; i<3; i++) {
91 if ( vx[i] > 0 ) {
92 ps = &mesh->point[vx[i]];
93 ps->c[0] = o[i][0] + t*(p[i][0] - o[i][0]);
94 ps->c[1] = o[i][1] + t*(p[i][1] - o[i][1]);
95 ps->c[2] = o[i][2] + t*(p[i][2] - o[i][2]);
96 j=i;
97 }
98 }
99 switch (pt->flag) {
100 case 1: case 2: case 4:
101 ier = MMGS_split1_sim(mesh,met,k,j,vx);
102 break;
103 case 7:
104 ier = MMGS_split3_sim(mesh,met,k,vx);
105 break;
106 default:
107 ier = MMG5_split2_sim(mesh,met,k,vx);
108 break;
109 }
110 if ( ier )
111 to = t;
112 else
113 tp = t;
114 }
115 while ( ++it < maxit );
116 /* restore coords of last valid pos. */
117 if ( !ier ) {
118 t = to;
119 for (i=0; i<3; i++) {
120 if ( vx[i] > 0 ) {
121 ps = &mesh->point[vx[i]];
122 ps->c[0] = o[i][0] + t*(p[i][0] - o[i][0]);
123 ps->c[1] = o[i][1] + t*(p[i][1] - o[i][1]);
124 ps->c[2] = o[i][2] + t*(p[i][2] - o[i][2]);
125 }
126 }
127 }
128
129 /* For very ill-shaped elements we can have no valid position */
130 assert ( j< 10 );
131 switch (pt->flag) {
132 case 1: case 2: case 4:
133 ier = MMGS_split1_sim(mesh,met,k,j,vx);
134 break;
135 case 7:
136 ier = MMGS_split3_sim(mesh,met,k,vx);
137 break;
138 default:
139 ier = MMG5_split2_sim(mesh,met,k,vx);
140 break;
141 }
142 return ier;
143}
144
156int MMGS_dichoto1b(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int ia, MMG5_int ip) {
157 MMG5_pTria pt;
158 MMG5_pPoint p0,p1,ppt;
159 MMG5_int np,nq;
160 int it,maxit,i1,i2;
161 double m[3],o[3],tp,to,t;
162 int8_t ier;
163
164 pt = &mesh->tria[iel];
165
166 i1 = MMG5_inxt2[ia];
167 i2 = MMG5_inxt2[i1];
168 np = pt->v[i1];
169 nq = pt->v[i2];
170 p0 = &mesh->point[np];
171 p1 = &mesh->point[nq];
172
173 /* initial coordinates for new point */
174 ppt = &mesh->point[ip];
175 o[0] = ppt->c[0];
176 o[1] = ppt->c[1];
177 o[2] = ppt->c[2];
178
179 /* midpoint along edge */
180 m[0] = 0.5*(p0->c[0] + p1->c[0]);
181 m[1] = 0.5*(p0->c[1] + p1->c[1]);
182 m[2] = 0.5*(p0->c[2] + p1->c[2]);
183
184 maxit = 4;
185 it = 0;
186 tp = 1.0;
187 to = 0.0;
188 do {
189 t = 0.5*(to + tp);
190 ppt->c[0] = m[0] + t*(o[0]-m[0]);
191 ppt->c[1] = m[1] + t*(o[1]-m[1]);
192 ppt->c[2] = m[2] + t*(o[2]-m[2]);
193
194 ier = MMGS_simbulgept(mesh,met,iel,ia,ip);
195 if ( ier )
196 to = t;
197 else
198 tp = t;
199 }
200 while ( ++it < maxit );
201 if ( !ier ) t = to;
202
203 /* For very ill-shaped elements, we can have no valid position */
204 ppt->c[0] = m[0] + t*(o[0]-m[0]);
205 ppt->c[1] = m[1] + t*(o[1]-m[1]);
206 ppt->c[2] = m[2] + t*(o[2]-m[2]);
207
208 return MMGS_simbulgept(mesh,met,iel,ia,ip) ;
209}
210
211/* check if edge need to be split and return a binary coding the numbers of the
212 * edges of tria iel that should be split according to a hausdorff distance
213 * criterion */
214int chkedg(MMG5_pMesh mesh,MMG5_int iel) {
215 MMG5_pTria pt;
216 MMG5_pPoint p[3];
217 MMG5_pPar par;
218 double n[3][3],t[3][3],nt[3],c1[3],c2[3],*n1,*n2,t1[3],t2[3];
219 double ps,ps2,cosn,ux,uy,uz,ll,li,dd,hausd,hmax;
220 int l,isloc;
221 int8_t i,i1,i2;
222 static int8_t mmgWarn0 = 0, mmgWarn1 = 0;
223
224 pt = &mesh->tria[iel];
225 p[0] = &mesh->point[pt->v[0]];
226 p[1] = &mesh->point[pt->v[1]];
227 p[2] = &mesh->point[pt->v[2]];
228
229 /* normal recovery */
230 for (i=0; i<3; i++) {
231 if ( MS_SIN(p[i]->tag) ) {
232 MMG5_nortri(mesh,pt,n[i]);
233 }
234 else if ( MG_EDG(p[i]->tag) ) {
235 MMG5_nortri(mesh,pt,nt);
236 n1 = &mesh->xpoint[p[i]->xp].n1[0];
237 n2 = &mesh->xpoint[p[i]->xp].n2[0];
238 ps = n1[0]*nt[0] + n1[1]*nt[1] + n1[2]*nt[2];
239 ps2 = n2[0]*nt[0] + n2[1]*nt[1] + n2[2]*nt[2];
240 if ( fabs(ps) > fabs(ps2) )
241 memcpy(&n[i],n1,3*sizeof(double));
242 else
243 memcpy(&n[i],n2,3*sizeof(double));
244 memcpy(&t[i],p[i]->n,3*sizeof(double));
245 }
246 else
247 memcpy(&n[i],p[i]->n,3*sizeof(double));
248 }
249
250 /* analyze edges */
251 for (i=0; i<3; i++) {
252 if ( pt->tag[i] & MG_REQ) continue;
253
254 i1 = MMG5_inxt2[i];
255 i2 = MMG5_iprv2[i];
256
257 /* local parameters */
258 hmax = mesh->info.hmax;
259 hausd = mesh->info.hausd;
260 isloc = 0;
261 for (l=0; l<mesh->info.npar; l++) {
262 par = &mesh->info.par[l];
263 if ( /*((par->elt == MMG5_Vertex) &&
264 ( (p[i1]->ref == par->ref ) || (p[i2]->ref == par->ref) ))
265 || */ ((par->elt == MMG5_Triangle) && (pt->ref == par->ref) ) ) {
266 if ( !isloc ) {
267 hmax = par->hmax;
268 hausd = par->hausd;
269 isloc = 1;
270 }
271 else {
272 hausd = MG_MIN(par->hausd,hausd);
273 hmax = MG_MIN(par->hmax,hmax);
274 }
275 }
276 }
277
278 /* check length */
279 ux = p[i2]->c[0] - p[i1]->c[0];
280 uy = p[i2]->c[1] - p[i1]->c[1];
281 uz = p[i2]->c[2] - p[i1]->c[2];
282 ll = ux*ux + uy*uy + uz*uz;
283 if ( ll > hmax*hmax ) {
284 MG_SET(pt->flag,i);
285 continue;
286 }
287 else if ( !MG_EDG(pt->tag[i]) && p[i1]->tag > MG_NOTAG && p[i2]->tag > MG_NOTAG ) {
288 MG_SET(pt->flag,i);
289 continue;
290 }
291
292 /* Hausdorff w/r tangent direction */
293 if ( MG_EDG(pt->tag[i]) ) {
294 if ( MS_SIN(p[i1]->tag) ) {
295 li = 1.0 / sqrt(ll);
296 t1[0] = li*ux;
297 t1[1] = li*uy;
298 t1[2] = li*uz;
299 }
300 else{
301 if(!((p[i1]->tag & MG_NOM) || MG_EDG(p[i1]->tag) ) ) {
302 // if(t[i1][0] > 10) {
303 if ( !mmgWarn0 ) {
304 fprintf(stderr,"\n ## Warning: %s: a- at least 1 geometrical"
305 " problem\n",__func__);
306 mmgWarn0 = 1;
307 }
308 return 0;
309 }
310 memcpy(t1,t[i1],3*sizeof(double));
311 }
312
313 if ( MS_SIN(p[i2]->tag) ) {
314 li = 1.0 / sqrt(ll);
315 t2[0] = li*ux;
316 t2[1] = li*uy;
317 t2[2] = li*uz;
318 }
319 else{
320 if(!((p[i2]->tag & MG_NOM) || MG_EDG(p[i2]->tag) ) ) {
321 if ( !mmgWarn1 ) {
322 fprintf(stderr,"\n ## Warning: %s: b- at least 1 geometrical"
323 " problem\n",__func__);
324 mmgWarn1 = 1;
325 }
326 return 0;
327 }
328 memcpy(t2,t[i2],3*sizeof(double));
329 }
330
331 ps = t1[0]*ux + t1[1]*uy + t1[2]*uz;
332 ps *= ps;
333 cosn = ps/ll ;
334 cosn *= (1.0-cosn);
335 cosn *= (0.25*ll);
336 if ( cosn > hausd*hausd ) {
337 MG_SET(pt->flag,i);
338 continue;
339 }
340
341 ps = -(t2[0]*ux + t2[1]*uy + t2[2]*uz);
342 ps *= ps;
343 cosn = ps/ll ;
344 cosn *= (1.0-cosn);
345 cosn *= (0.25*ll);
346 if ( cosn > hausd*hausd ) {
347 MG_SET(pt->flag,i);
348 continue;
349 }
350 }
351 else {
352 n1 = n[i1];
353 n2 = n[i2];
354
355 ps = ux*n1[0] + uy*n1[1] + uz*n1[2];
356 c1[0] = (2.0*p[i1]->c[0] + p[i2]->c[0] - ps*n1[0]) / 3.0 - p[i1]->c[0];
357 c1[1] = (2.0*p[i1]->c[1] + p[i2]->c[1] - ps*n1[1]) / 3.0 - p[i1]->c[1];
358 c1[2] = (2.0*p[i1]->c[2] + p[i2]->c[2] - ps*n1[2]) / 3.0 - p[i1]->c[2];
359
360 ps = -(ux*n2[0] + uy*n2[1] + uz*n2[2]);
361 c2[0] = (2.0*p[i2]->c[0] + p[i1]->c[0] - ps*n2[0]) / 3.0 - p[i2]->c[0];
362 c2[1] = (2.0*p[i2]->c[1] + p[i1]->c[1] - ps*n2[1]) / 3.0 - p[i2]->c[1];
363 c2[2] = (2.0*p[i2]->c[2] + p[i1]->c[2] - ps*n2[2]) / 3.0 - p[i2]->c[2];
364
365 /* squared cosines */
366 ps = c1[0]*ux + c1[1]*uy + c1[2]*uz;
367 ps *= ps;
368 dd = c1[0]*c1[0] + c1[1]*c1[1] + c1[2]*c1[2];
369 cosn = ps / (dd*ll);
370 cosn *= (1.0-cosn);
371 cosn *= (0.25*ll);
372 if ( cosn > hausd*hausd ) {
373 MG_SET(pt->flag,i);
374 continue;
375 }
376
377 ps = -c2[0]*ux - c2[1]*uy - c2[2]*uz;
378 ps *= ps;
379 dd = c2[0]*c2[0]+c2[1]*c2[1]+c2[2]*c2[2];
380 cosn = ps / (dd*ll);
381 cosn *= (1.0-cosn);
382 cosn *= (0.25*ll);
383 if ( cosn > hausd*hausd ) {
384 MG_SET(pt->flag,i);
385 continue;
386 }
387 }
388 }
389
390 return pt->flag;
391}
392
405static inline
406void MMGS_set_localFunc ( MMG5_pSol met, int8_t typchk,
407 double (**MMGS_lenEdg)(MMG5_pMesh,MMG5_pSol,MMG5_int ,MMG5_int,int8_t),
408 double (**MMGS_caltri)(MMG5_pMesh,MMG5_pSol,MMG5_pTria)) {
409
410 if ( met->m ) {
411 if ( (typchk == 1) && (met->size == 6) ) {
412 *MMGS_lenEdg = MMG5_lenSurfEdg33_ani;
413 *MMGS_caltri = MMG5_caltri33_ani;
414 }
415 else if ( typchk == 2 ) {
416 *MMGS_lenEdg = MMG5_lenSurfEdg;
417 *MMGS_caltri = MMG5_calelt;
418 }
419 else {
420 *MMGS_lenEdg = MMG5_lenSurfEdg_iso;
421 *MMGS_caltri = MMG5_caltri_iso;
422 }
423 }
424
425}
426
427
428static int swpmsh(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) {
429 MMG5_pTria pt;
430 int it,maxit;
431 MMG5_int k,ns,nns;
432 int8_t i;
433
434 /* Local function pointer toward the suitable functions to use for edge length
435 * and quality computation depending on the adaptation phase */
436 double (*MMGS_lenEdg)(MMG5_pMesh mesh,MMG5_pSol sol ,MMG5_int ,MMG5_int, int8_t ) = NULL;
437 double (*MMGS_caltri)(MMG5_pMesh mesh,MMG5_pSol sol ,MMG5_pTria pt ) = MMG5_caltri_iso;
438
439 MMGS_set_localFunc ( met, typchk, &MMGS_lenEdg, &MMGS_caltri);
440
441 it = nns = 0;
442 maxit = 2;
443 mesh->base++;
444 do {
445 ns = 0;
446 for (k=1; k<=mesh->nt; k++) {
447 pt = &mesh->tria[k];
448 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
449
450 for (i=0; i<3; i++) {
451 if ( MS_SIN(pt->tag[i]) || MG_EDG(pt->tag[i]) ) continue;
452 else if ( chkswp(mesh,met,k,i,typchk,
453 MMGS_lenEdg,MMGS_caltri) ) {
454 ns += swapar(mesh,k,i);
455 break;
456 }
457 }
458 }
459 nns += ns;
460 }
461 while ( ns > 0 && ++it < maxit );
462 if ( (abs(mesh->info.imprim) > 5 || mesh->info.ddebug) && nns > 0 )
463 fprintf(stdout," %8" MMG5_PRId " edge swapped\n",nns);
464
465 return nns;
466}
467
468/* Analyze triangles and move points to make mesh more uniform */
469static int movtri(MMG5_pMesh mesh,MMG5_pSol met,int maxit) {
470 MMG5_pTria pt;
471 MMG5_pPoint ppt;
472 int it,ier,ilist;
473 MMG5_int k,base,list[MMG5_TRIA_LMAX+2],nm,ns,nnm;
474 int8_t i;
475
476 if ( abs(mesh->info.imprim) > 5 || mesh->info.ddebug )
477 fprintf(stdout," ** OPTIMIZING MESH\n");
478
479 base = 1;
480 for (k=1; k<=mesh->np; k++) mesh->point[k].flag = base;
481
482 it = nnm = 0;
483 do {
484 base++;
485 nm = ns = 0;
486 for (k=1; k<=mesh->nt; k++) {
487 pt = &mesh->tria[k];
488 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
489
490 for (i=0; i<3; i++) {
491 ppt = &mesh->point[pt->v[i]];
492
493 if ( ppt->flag == base || MS_SIN(ppt->tag) || ppt->tag & MG_NOM )
494 continue;
495
496 int8_t dummy;
497 ilist = MMG5_boulet(mesh,k,i,list,1,&dummy);
498
499 if ( ilist < 1 ) continue;
500
501 if ( MG_EDG(ppt->tag) ) {
502 ier = movridpt(mesh,met,list,ilist);
503 if ( ier ) {
504 ns++;
505 }
506 }
507 else {
508 ier = movintpt(mesh,met,list,ilist);
509 }
510
511 if ( ier ) {
512 nm++;
513 ppt->flag = base;
514 }
515 }
516 }
517 nnm += nm;
518 if ( mesh->info.ddebug ) fprintf(stdout," %8" MMG5_PRId " moved, %" MMG5_PRId " geometry\n",nm,ns);
519 }
520 while ( ++it < maxit && nm > 0);
521
522 if ( (abs(mesh->info.imprim) > 5 || mesh->info.ddebug) && nnm > 0 )
523 fprintf(stdout," %8" MMG5_PRId " vertices moved, %d iter.\n",nnm,it);
524
525 return nnm;
526}
527
536static inline
538{
539 MMG5_pTria pt;
540 MMG5_int vx[3],k;
541 int i,i1,i2;
542
543 /* Delete the useless added points */
544 for (k=1; k<=mesh->nt; k++) {
545 pt = &mesh->tria[k];
546 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
547
548 for (i=0; i<3; i++) {
549 i1 = MMG5_inxt2[i];
550 i2 = MMG5_inxt2[i1];
551 vx[i] = MMG5_hashGet(&hash,pt->v[i1],pt->v[i2]);
552
553 if ( vx[i] > 0 ) {
554 MMGS_delPt(mesh,vx[i]);
555 if ( !MMG5_hashUpdate(&hash,pt->v[i1],pt->v[i2],0) ) {
556 fprintf(stderr,"\n ## Error: %s: unable to delete point idx"
557 " along edge %" MMG5_PRId " %" MMG5_PRId ".\n", __func__,
558 MMGS_indPt(mesh,pt->v[i1]),
559 MMGS_indPt(mesh,pt->v[i2]));
560 MMG5_DEL_MEM(mesh,hash.item);
561 return 0;
562 }
563 }
564 }
565 }
566 return 1;
567}
568
579static int anaelt(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) {
580 MMG5_pTria pt;
581 MMG5_pPoint ppt,p1,p2;
582 MMG5_Hash hash;
583 MMG5_Bezier pb;
584 MMG5_pxPoint go;
585 double s,o[3],no[3],to[3],dd,len;
586 int i,ier,it;
587 MMG5_int ns,nc,ni,ic;
588 MMG5_int k,nt,vx[3],j,ip,ip1,ip2;
589 int8_t i1,i2;
590 static double uv[3][2] = { {0.5,0.5}, {0.,0.5}, {0.5,0.} };
591 static int8_t mmgWarn0=0,mmgWarn1=0,mmgWarn2=0,mmgWarn3=0;
592
593 if ( !MMG5_hashNew(mesh,&hash,mesh->np,3*mesh->np) ) return -1;
594 ns = 0;
595 s = 0.5;
596 for (k=1; k<=mesh->nt; k++) {
597 pt = &mesh->tria[k];
598
599 if ( !MG_EOK(pt) ) {
600 continue;
601 }
602
603 pt->flag = 0;
604
605 if ( pt->ref < 0 ) {
606 continue;
607 }
608
609 /* Required triangle */
610 if ( MS_SIN(pt->tag[0]) && MS_SIN(pt->tag[1]) && MS_SIN(pt->tag[2]) ) continue;
611
612 /* check element cut */
613 if ( typchk == 1 ) {
614 if ( !chkedg(mesh,k) ) continue;
615 }
616 else if ( typchk == 2 ) {
617 for (i=0; i<3; i++) {
618 if ( pt->tag[i] & MG_REQ) continue;
619
620 i1 = MMG5_inxt2[i];
621 i2 = MMG5_iprv2[i];
622 len = MMG5_lenSurfEdg(mesh,met,pt->v[i1],pt->v[i2],0);
623 if ( !len ) return -1;
624 else if ( len > MMGS_LLONG ) {
625 MG_SET(pt->flag,i);
626 }
627 }
628 if ( !pt->flag ) continue;
629 }
630 ns++;
631
632 /* geometric support */
633 ier = MMG5_bezierCP(mesh,pt,&pb,1);
634 assert(ier);
635
636 /* scan edges to split */
637 for (i=0; i<3; i++) {
638 if ( !MG_GET(pt->flag,i) ) continue;
639 i1 = MMG5_inxt2[i];
640 i2 = MMG5_iprv2[i];
641 ip1 = pt->v[i1];
642 ip2 = pt->v[i2];
643 ip = MMG5_hashGet(&hash,ip1,ip2);
644
645 /* do not compute the point twice except along special edges */
646 if ( !MG_EDG(pt->tag[i]) && ip > 0 ) continue;
647
648 /* new point along edge */
649 ier = MMGS_bezierInt(&pb,uv[i],o,no,to);
650 if ( !ip ) {
651 ip = MMGS_newPt(mesh,o,MG_EDG(pt->tag[i]) ? to : no);
652
653 if ( !ip ) {
654 /* reallocation of point table */
656 fprintf(stderr,"\n ## Error: %s: unable to"
657 " allocate a new point.\n",__func__);
659 MMGS_delPatternPts( mesh, hash);
660 return -1
661 ,o,MG_EDG(pt->tag[i]) ? to : no);
662 // Now pb->p contain a wrong memory address.
663 pb.p[0] = &mesh->point[pt->v[0]];
664 pb.p[1] = &mesh->point[pt->v[1]];
665 pb.p[2] = &mesh->point[pt->v[2]];
666 }
667
668 MMG5_hashEdge(mesh,&hash,ip1,ip2,ip);
669 p1 = &mesh->point[ip1];
670 p2 = &mesh->point[ip2];
671 ppt = &mesh->point[ip];
672
673 if ( MG_EDG(pt->tag[i]) ) {
674 ++mesh->xp;
675 if(mesh->xp > mesh->xpmax){
676 /* reallocation of xpoint table */
678 "larger xpoint table",
679 return -1);
680 }
681 ppt->xp = mesh->xp;
682 ppt->tag = pt->tag[i];
683 if ( p1->ref == pt->edg[i] || p2->ref == pt->edg[i] )
684 ppt->ref = pt->edg[i];
685 ppt->xp = mesh->xp;
686 go = &mesh->xpoint[mesh->xp];
687 memset(go->n2,0x00,3*sizeof(double));
688 memcpy(go->n1,no,3*sizeof(double));
689
690 dd = go->n1[0]*ppt->n[0] + go->n1[1]*ppt->n[1] + go->n1[2]*ppt->n[2];
691 ppt->n[0] -= dd*go->n1[0];
692 ppt->n[1] -= dd*go->n1[1];
693 ppt->n[2] -= dd*go->n1[2];
694 dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
695 if ( dd > MMG5_EPSD2 ) {
696 dd = 1.0 / sqrt(dd);
697 ppt->n[0] *= dd;
698 ppt->n[1] *= dd;
699 ppt->n[2] *= dd;
700 }
701 }
702 if ( met->m ) {
703 if ( typchk == 1 && (met->size>1) )
704 ier = MMGS_intmet33_ani(mesh,met,k,i,ip,s);
705 else
706 ier = intmet(mesh,met,k,i,ip,s);
707 }
708
709 if ( !ier ) {
710 if ( !mmgWarn0 ) {
711 fprintf(stderr,"\n ## Error: %s: unable to interpolate at least"
712 " 1 metric.\n",__func__);
713 mmgWarn0 = 1;
714 }
715 return -1;
716 }
717 }
718 else if ( pt->tag[i] & MG_GEO && !(pt->tag[i] & MG_NOM) ) {
719 ppt = &mesh->point[ip];
720 go = &mesh->xpoint[ppt->xp];
721 memcpy(go->n2,no,3*sizeof(double));
722
723 /* a computation of the tangent with respect to these two normals is possible */
724 ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
725 ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
726 ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
727 dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
728 if ( dd > MMG5_EPSD2 ) {
729 dd = 1.0 / sqrt(dd);
730 ppt->n[0] *= dd;
731 ppt->n[1] *= dd;
732 ppt->n[2] *= dd;
733 }
734 else {
735 if ( !mmgWarn1 ) {
736 mmgWarn1 = 1;
737 fprintf(stderr,"\n ## Warning: %s: flattened angle around ridge."
738 " Unable to split it.\n",__func__);
739 }
740 /* Remove the point */
741 MMGS_delPt(mesh,ip);
742 MMG5_hashUpdate(&hash,ip1,ip2,0);
743 }
744 }
745 }
746 }
747 if ( !ns ) {
748 MMG5_DEL_MEM(mesh,hash.item);
749 return ns;
750 }
751
752 /* step 2. checking if split by adjacent */
753 for (k=1; k<=mesh->nt; k++) {
754 pt = &mesh->tria[k];
755 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
756 else if ( pt->flag == 7 ) continue;
757
758 /* geometric support */
759 ier = MMG5_bezierCP(mesh,pt,&pb,1);
760 assert(ier);
761 nc = 0;
762
763 for (i=0; i<3; i++) {
764 i1 = MMG5_inxt2[i];
765 i2 = MMG5_inxt2[i1];
766 if ( !MG_GET(pt->flag,i) ) {
767 ip = MMG5_hashGet(&hash,pt->v[i1],pt->v[i2]);
768 if ( ip > 0 ) {
769 MG_SET(pt->flag,i);
770 nc++;
771 if ( pt->tag[i] & MG_GEO ) {
772 /* new point along edge */
773 ier = MMGS_bezierInt(&pb,uv[i],o,no,to);
774 assert(ier);
775
776 ppt = &mesh->point[ip];
777 go = &mesh->xpoint[ppt->xp];
778 memcpy(go->n2,no,3*sizeof(double));
779
780 /* a computation of the tangent with respect to these two normals is possible */
781 ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
782 ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
783 ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
784 dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
785 if ( dd > MMG5_EPSD2 ) {
786 dd = 1.0 / sqrt(dd);
787 ppt->n[0] *= dd;
788 ppt->n[1] *= dd;
789 ppt->n[2] *= dd;
790 }
791 }
792 }
793 }
794 }
795 if ( nc > 0 ) ++ns;
796 }
797 if ( mesh->info.ddebug && ns ) {
798 fprintf(stdout," %" MMG5_PRId " analyzed %" MMG5_PRId " proposed\n",mesh->nt,ns);
799 fflush(stdout);
800 }
801
803 for (k=1; k<=mesh->np; k++)
804 mesh->point[k].flag = 0;
805
806 it = 1;
807 nc = 0;
808 j = 0; // To remove maybe-uninitialized warning on arm
809 do {
810 ni = 0;
811 for (k=1; k<=mesh->nt; k++) {
812 pt = &mesh->tria[k];
813 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
814 else if ( pt->flag == 0 ) continue;
815
816 vx[0] = vx[1] = vx[2] = 0;
817 pt->flag = ic = 0;
818
819 for (i=0; i<3; i++) {
820 i1 = MMG5_inxt2[i];
821 i2 = MMG5_inxt2[i1];
822 vx[i] = MMG5_hashGet(&hash,pt->v[i1],pt->v[i2]);
823 if ( vx[i] > 0 ) {
824 MG_SET(pt->flag,i);
825 if ( mesh->point[vx[i]].flag > 2 ) ic = 1;
826 j = i;
827 }
828 }
829 if ( !pt->flag ) continue;
830 switch (pt->flag) {
831 case 1: case 2: case 4:
832 ier = MMGS_split1_sim(mesh,met,k,j,vx);
833 break;
834 case 7:
835 ier = MMGS_split3_sim(mesh,met,k,vx);
836 break;
837 default:
838 ier = MMG5_split2_sim(mesh,met,k,vx);
839 break;
840 }
841 if ( ier ) continue;
842
843 ni++;
844 if ( ic == 0 && MMGS_dichoto(mesh,met,k,vx) ) {
845 for (i=0; i<3; i++)
846 if ( vx[i] > 0 ) mesh->point[vx[i]].flag++;
847 }
848 else {
849 if ( it < 20 ) {
850 for (i=0; i<3; i++) {
851 if ( vx[i] > 0 ) {
852 p1 = &mesh->point[pt->v[MMG5_iprv2[i]]];
853 p2 = &mesh->point[pt->v[MMG5_inxt2[i]]];
854 ppt = &mesh->point[vx[i]];
855 ppt->c[0] = 0.5 * (p1->c[0] + p2->c[0]);
856 ppt->c[1] = 0.5 * (p1->c[1] + p2->c[1]);
857 ppt->c[2] = 0.5 * (p1->c[2] + p2->c[2]);
858 }
859 }
860 }
861 else {
862 if ( it==20 && (mesh->info.ddebug || mesh->info.imprim > 5) ) {
863 if ( !mmgWarn2 ) {
864 fprintf(stderr,"\n ## Warning: %s: surfacic pattern: unable to"
865 " find a valid split for at least 1 point. Point(s)"
866 " deletion.",__func__ );
867 mmgWarn2 = 1;
868 }
869 }
870 for (i=0; i<3; i++) {
871 if ( vx[i] > 0 ) {
872 if ( !MMG5_hashUpdate(&hash,pt->v[MMG5_iprv2[i]],
873 pt->v[MMG5_inxt2[i]],0) ) {
874 fprintf(stderr,"\n ## Error: %s: unable to delete point"
875 " idx along edge %" MMG5_PRId " %" MMG5_PRId ".\n",
876 __func__,MMGS_indPt(mesh,pt->v[MMG5_iprv2[i]]),
877 MMGS_indPt(mesh,pt->v[MMG5_inxt2[i]]));
878 MMG5_DEL_MEM(mesh,hash.item);
879 return -1;
880 }
881 MMGS_delPt(mesh,vx[i]);
882 }
883 }
884 }
885 }
886 }
887 nc += ni;
888 }
889 while( ni > 0 && ++it < 40 );
890
891 if ( mesh->info.ddebug && nc ) {
892 fprintf(stdout," %" MMG5_PRId " corrected, %" MMG5_PRId " invalid\n",nc,ni);
893 fflush(stdout);
894 }
895
896 /* step 4. splitting */
897 ns = 0;
898 nt = mesh->nt;
899 for (k=1; k<=nt; k++) {
900 pt = &mesh->tria[k];
901 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
902 else if ( pt->flag == 0 ) continue;
903
904 j = -1;
905 vx[0] = vx[1] = vx[2] = 0;
906 for (i=0; i<3; i++) {
907 i1 = MMG5_inxt2[i];
908 i2 = MMG5_inxt2[i1];
909 if ( MG_GET(pt->flag,i) ) {
910 vx[i] = MMG5_hashGet(&hash,pt->v[i1],pt->v[i2]);
911 if ( !vx[i] ) {
912 if ( !mmgWarn3 ) {
913 mmgWarn3 = 1;
914 fprintf(stderr,"\n ## Error: %s: unable to create point on"
915 " at least 1 edge.\n Exit program.\n",__func__);
916 }
917 return -1;
918 }
919 j = i;
920 }
921 }
922 if ( pt->flag == 1 || pt->flag == 2 || pt->flag == 4 ) {
923 ier = MMGS_split1(mesh,met,k,j,vx);
924 ns++;
925 }
926 else if ( pt->flag == 7 ) {
927 ier = MMGS_split3(mesh,met,k,vx);
928 ns++;
929 }
930 else {
931 ier = MMGS_split2(mesh,met,k,vx);
932 ns++;
933 }
934 if ( !ier ) return -1;
935 }
936 if ( (mesh->info.ddebug || abs(mesh->info.imprim) > 5) && ns > 0 )
937 fprintf(stdout," %7" MMG5_PRId " splitted\n",ns);
938 MMG5_DEL_MEM(mesh,hash.item);
939
940 return ns;
941}
942
954MMG5_int chkspl(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,int i) {
955 MMG5_pTria pt,pt1;
956 MMG5_pPoint ppt;
957 MMG5_pxPoint go;
958 MMG5_Bezier b;
959 double s,uv[2],o[3],no[3],to[3];
960 int ier;
961 MMG5_int ip,*adja,jel;
962 int8_t i1,i2,j,jj,j2;
963
964 if ( mesh->xp > mesh->xpmax-2 ) return 0;
965 pt = &mesh->tria[k];
966 i1 = MMG5_inxt2[i];
967 i2 = MMG5_iprv2[i];
968 if ( MS_SIN(pt->tag[i1]) || MS_SIN(pt->tag[i2]) ) return 0;
969 adja = &mesh->adja[3*(k-1)+1];
970 jel = adja[i] / 3;
971 if ( jel ) {
972 j = adja[i] % 3;
973 jj = MMG5_inxt2[j];
974 j2 = MMG5_iprv2[j];
975 pt1 = &mesh->tria[jel];
976 if ( MS_SIN(pt1->tag[jj]) || MS_SIN(pt1->tag[j2]) ) return 0;
977 }
978
979 ier = MMG5_bezierCP(mesh,pt,&b,1);
980 assert ( ier );
981
982 /* create midedge point */
983 uv[0] = 0.5;
984 uv[1] = 0.5;
985 if (i == 1) uv[0] = 0.0;
986 else if ( i == 2 ) uv[1] = 0.0;
987
988 ier = MMGS_bezierInt(&b,uv,o,no,to);
989 assert(ier);
990 ip = MMGS_newPt(mesh,o,MG_EDG(pt->tag[i]) ? to : no);
991 if ( !ip ) {
992 /* reallocation of point table */
995 return -1
996 ,o,MG_EDG(pt->tag[i]) ? to : no);
997 }
998
999 if ( MG_EDG(pt->tag[i]) ) {
1000 ++mesh->xp;
1001 ppt = &mesh->point[ip];
1002 ppt->tag = pt->tag[i];
1003 ppt->xp = mesh->xp;
1004 go = &mesh->xpoint[mesh->xp];
1005 memcpy(go->n1,no,3*sizeof(double));
1006 }
1007 s = 0.5;
1008
1009 ier = intmet(mesh,met,k,i,ip,s);
1010 if ( !ier ) return 0;
1011
1012 return ip;
1013}
1014
1025static MMG5_int colelt(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) {
1026 MMG5_pTria pt;
1027 MMG5_pPoint p1,p2;
1028 MMG5_pPar par;
1029 double ll,ux,uy,uz,hmin;
1030 MMG5_int nc,list[MMG5_TRIA_LMAX+2],k;
1031 int l,isloc,ier,ilist;
1032 int8_t i,i1,i2;
1033
1034 /* Local function pointer toward the suitable functions to use for edge length
1035 * and quality computation depending on the adaptation phase */
1036 double (*MMGS_lenEdg)(MMG5_pMesh mesh,MMG5_pSol sol ,MMG5_int ,MMG5_int, int8_t ) = NULL;
1037 double (*MMGS_caltri)(MMG5_pMesh mesh,MMG5_pSol sol ,MMG5_pTria pt ) = MMG5_caltri_iso;
1038
1039 MMGS_set_localFunc ( met, typchk, &MMGS_lenEdg, &MMGS_caltri);
1040
1041 nc = 0;
1042 for (k=1; k<=mesh->nt; k++) {
1043 pt = &mesh->tria[k];
1044 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
1045
1046 /* check edge length */
1047 pt->flag = 0;
1048
1049 for (i=0; i<3; i++) {
1050 if ( MS_SIN(pt->tag[i]) ) continue;
1051
1052 i1 = MMG5_inxt2[i];
1053 i2 = MMG5_iprv2[i];
1054 p1 = &mesh->point[pt->v[i1]];
1055 p2 = &mesh->point[pt->v[i2]];
1056 if ( p1->tag & MG_NOM || p2->tag & MG_NOM ) continue;
1057 else if ( MS_SIN(p1->tag) ) continue;
1058 else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] ) continue;
1059
1060 /* check length */
1061 if ( typchk == 1 ) {
1062 ux = p2->c[0] - p1->c[0];
1063 uy = p2->c[1] - p1->c[1];
1064 uz = p2->c[2] - p1->c[2];
1065 ll = ux*ux + uy*uy + uz*uz;
1066
1067 /* local parameters*/
1068 hmin = mesh->info.hmin;
1069 isloc = 0;
1070 for (l=0; l<mesh->info.npar; l++) {
1071 par = &mesh->info.par[l];
1072 if ( /*((par->elt == MMG5_Vertex) &&
1073 ( (p1->ref == par->ref ) || (p2->ref == par->ref) ))
1074 || */((par->elt == MMG5_Triangle) && (pt->ref == par->ref) ) ) {
1075 if ( !isloc ) {
1076 hmin = par->hmin;
1077 isloc = 1;
1078 }
1079 else {
1080 hmin = MG_MAX(par->hmin,hmin);
1081 }
1082 }
1083 }
1084 if ( ll > hmin*hmin ) continue;
1085 }
1086 else {
1087 ll = MMG5_lenSurfEdg(mesh,met,pt->v[i1],pt->v[i2],0);
1088 if ( !ll ) return -1;
1089 if ( ll > MMGS_LSHRT ) continue;
1090 }
1091
1092 /* check if geometry preserved */
1093 ilist = chkcol(mesh,met,k,i,list,typchk,MMGS_lenEdg,MMGS_caltri);
1094
1095 int8_t open = (mesh->adja[3*(k-1)+1+i] == 0);
1096
1097 if ( ilist+open > 3 ) {
1098 ier = colver(mesh,list,ilist);
1099 if ( !ier ) return -1;
1100 nc += ier;
1101 break;
1102 }
1103 else if ( ilist == 3 ) {
1104 ier = colver3(mesh,list);
1105 if ( !ier ) return -1;
1106 nc += ier;
1107 break;
1108 }
1109 else if ( ilist == 2 ) {
1110 ier = colver2(mesh,list);
1111 if ( !ier ) return -1;
1112 nc += ier;
1113 break;
1114 }
1115 }
1116 }
1117 if ( nc > 0 && (abs(mesh->info.imprim) > 5 || mesh->info.ddebug) )
1118 fprintf(stdout," %8" MMG5_PRId " vertices removed\n",nc);
1119
1120 return nc;
1121}
1122
1132static MMG5_int adpspl(MMG5_pMesh mesh,MMG5_pSol met) {
1133 MMG5_pTria pt;
1134 MMG5_pPoint p1,p2;
1135 double len,lmax;
1136 int ier;
1137 MMG5_int ip,ns,k;
1138 int8_t i,i1,i2,imax;
1139
1140 ns = 0;
1141 for (k=1; k<=mesh->nt; k++) {
1142 pt = &mesh->tria[k];
1143 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
1144
1145 /* check edge length */
1146 pt->flag = 0;
1147 imax = -1;
1148 lmax = -1.0;
1149 for (i=0; i<3; i++) {
1150 i1 = MMG5_inxt2[i];
1151 i2 = MMG5_iprv2[i];
1152 len = MMG5_lenSurfEdg(mesh,met,pt->v[i1],pt->v[i2],0);
1153
1154 if ( !len ) return -1;
1155
1156 if ( len > lmax ) {
1157 lmax = len;
1158 imax = i;
1159 }
1160 }
1161 if ( lmax < MMGS_LOPTL ) continue;
1162 else if ( MS_SIN(pt->tag[imax]) ) continue;
1163
1164 /* check length */
1165 i1 = MMG5_inxt2[imax];
1166 i2 = MMG5_iprv2[imax];
1167 p1 = &mesh->point[pt->v[i1]];
1168 p2 = &mesh->point[pt->v[i2]];
1169 if ( p1->tag & MG_NOM || p2->tag & MG_NOM ) continue;
1170
1171 ip = chkspl(mesh,met,k,imax);
1172 if ( ip < 0 ) {
1173 /* Lack of memory, go to collapse step. */
1174 return (ns);
1175 }
1176 else if ( ip > 0 ) {
1177 ier = MMGS_simbulgept(mesh,met,k,imax,ip);
1178 if ( !ier ) {
1179 ier = MMGS_dichoto1b(mesh,met,k,imax,ip);
1180 if ( !ier ) {
1181 MMGS_delPt(mesh,ip);
1182 continue;
1183 }
1184 }
1185 ier = split1b(mesh,k,imax,ip);
1186
1187 if ( !ier ) {
1188 /* Lack of memory, go to collapse step. */
1189 MMGS_delPt(mesh,ip);
1190 return ns;
1191 }
1192 /* if we realloc memory in split1b pt pointer is not valid anymore. */
1193 ns += ier;
1194 }
1195 }
1196 return ns;
1197}
1198
1208static MMG5_int adpcol(MMG5_pMesh mesh,MMG5_pSol met) {
1209 MMG5_pTria pt;
1210 MMG5_pPoint p1,p2;
1211 double len;
1212 MMG5_int nc,k,list[MMG5_TRIA_LMAX+2];
1213 int ier,ilist;
1214 int8_t i,i1,i2;
1215
1216 nc = 0;
1217 for (k=1; k<=mesh->nt; k++) {
1218 pt = &mesh->tria[k];
1219 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
1220
1221 /* check edge length */
1222 pt->flag = 0;
1223 for (i=0; i<3; i++) {
1224 if ( MS_SIN(pt->tag[i]) ) continue;
1225
1226 /* check length */
1227 i1 = MMG5_inxt2[i];
1228 i2 = MMG5_iprv2[i];
1229 p1 = &mesh->point[pt->v[i1]];
1230 p2 = &mesh->point[pt->v[i2]];
1231 if ( p1->tag & MG_NOM || p2->tag & MG_NOM ) continue;
1232
1233 len = MMG5_lenSurfEdg(mesh,met,pt->v[i1],pt->v[i2],0);
1234 if ( !len ) return -1;
1235 else if ( len > MMGS_LOPTS ) continue;
1236
1237 p1 = &mesh->point[pt->v[i1]];
1238 p2 = &mesh->point[pt->v[i2]];
1239 if ( MS_SIN(p1->tag) ) continue;
1240 else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] ) continue;
1241
1242 /* check if geometry preserved */
1243 ilist = chkcol(mesh,met,k,i,list,2,MMG5_lenSurfEdg,MMG5_calelt);
1244
1245 int8_t open = (mesh->adja[3*(k-1)+1+i] == 0);
1246
1247 if ( ilist+open > 3 ) {
1248 ier = colver(mesh,list,ilist);;
1249 nc += ier;
1250 if ( !ier ) return -1;
1251 break;
1252 }
1253 else if ( ilist == 3 ) {
1254 ier = colver3(mesh,list);
1255 nc += ier;
1256 if ( !ier ) return -1;
1257 break;
1258 }
1259 else if ( ilist == 2 ) {
1260 ier = colver2(mesh,list);
1261 nc += ier;
1262 if ( !ier ) return -1;
1263 break;
1264 }
1265 }
1266 }
1267 return nc;
1268}
1269
1270
1271/* analyze triangles and split or collapse to match gradation */
1272static int adptri(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int* permNodGlob) {
1273 int it,maxit;
1274 int64_t nnc,nns,nnf,nnm;
1275 MMG5_int nc,ns,nf,nm;
1276
1277 /* iterative mesh modifications */
1278 it = nnc = nns = nnf = nnm = 0;
1279 maxit = 10;
1280 do {
1281 if ( !mesh->info.noinsert ) {
1282 ns = adpspl(mesh,met);
1283 if ( ns < 0 ) {
1284 fprintf(stderr,"\n ## Unable to complete mesh. Exit program.\n");
1285 return 0;
1286 }
1287
1288 /* renumbering if available and needed */
1289 if ( it==1 && !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
1290 return 0;
1291
1292 nc = adpcol(mesh,met);
1293 if ( nc < 0 ) {
1294 fprintf(stderr,"\n ## Unable to complete mesh. Exit program.\n");
1295 return 0;
1296 }
1297 }
1298 else {
1299 ns = 0;
1300 nc = 0;
1301 }
1302
1303 if ( !mesh->info.noswap ) {
1304 nf = swpmsh(mesh,met,2);
1305 if ( nf < 0 ) {
1306 fprintf(stderr,"\n ## Unable to improve mesh. Exiting.\n");
1307 return 0;
1308 }
1309 }
1310 else nf = 0;
1311
1312 if ( !mesh->info.nomove ) {
1313 nm = movtri(mesh,met,1);
1314 if ( nm < 0 ) {
1315 fprintf(stderr,"\n ## Unable to improve mesh. Exiting.\n");
1316 return 0;
1317 }
1318 }
1319 else nm = 0;
1320
1321 nnc += nc;
1322 nns += ns;
1323 nnf += nf;
1324 nnm += nm;
1325 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && ns+nc+nf+nm > 0 )
1326 fprintf(stdout," %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed, %8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",ns,nc,nf,nm);
1327 if ( ns < 10 && MMG5_abs(nc-ns) < 3 ) break;
1328 else if ( it > 3 && MMG5_abs(nc-ns) < 0.3 * MG_MAX(nc,ns) ) break;
1329 }
1330 while( ++it < maxit && nc+ns > 0 );
1331
1332 /* renumbering if available */
1333 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
1334 return 0;
1335
1336 /*shape optim*/
1337 it = 0;
1338 maxit = 2;
1339 do {
1340
1341 if ( !mesh->info.nomove ) {
1342 nm = movtri(mesh,met,5);
1343 if ( nm < 0 ) {
1344 fprintf(stderr,"\n ## Unable to improve mesh.\n");
1345 return 0;
1346 }
1347 nnm += nm;
1348 }
1349 else nm = 0;
1350
1351 if ( !mesh->info.noswap ) {
1352 nf = swpmsh(mesh,met,2);
1353 if ( nf < 0 ) {
1354 fprintf(stderr,"\n ## Unable to improve mesh. Exiting.\n");
1355 return 0;
1356 }
1357 nnf += nf;
1358 }
1359 else nf = 0;
1360
1361 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nf+nm > 0 ){
1362 fprintf(stdout," ");
1363 fprintf(stdout,"%8" MMG5_PRId " swapped, %8" MMG5_PRId " moved\n",nf,nm);
1364 }
1365 }
1366 while( ++it < maxit && nm+nf > 0 );
1367
1368 if ( !mesh->info.nomove ) {
1369 nm = movtri(mesh,met,5);
1370 if ( nm < 0 ) {
1371 fprintf(stderr,"\n ## Unable to improve mesh.\n");
1372 return 0;
1373 }
1374 }
1375 else nm = 0;
1376 nnm += nm;
1377 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && nm > 0 ) {
1378 fprintf(stdout," %8" MMG5_PRId " moved\n",nm);
1379 }
1380
1381 if ( mesh->info.imprim > 0 ) {
1382 if ( abs(mesh->info.imprim) < 5 && (nnc > 0 || nns > 0) )
1383 fprintf(stdout," %8" PRId64 " splitted, %8" PRId64 " collapsed, %8" PRId64 " swapped, %8" PRId64 " moved, %d iter. \n",nns,nnc,nnf,nnm,it);
1384 }
1385 return 1;
1386}
1387
1388/* analyze tetrahedra and split if needed */
1389static int anatri(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) {
1390 MMG5_int nc,ns,nf,nnc,nns,nnf;
1391 int it,maxit;
1392
1393 /* analyze tetras : initial splitting */
1394 nns = nnc = nnf = it = 0;
1395 maxit = 5;
1396 do {
1397 if ( !mesh->info.noinsert ) {
1398 /* memory free */
1400 mesh->adja = 0;
1401
1402 /* analyze surface */
1403 ns = anaelt(mesh,met,typchk);
1404 if ( ns < 0 ) {
1405 fprintf(stderr,"\n ## Unable to complete surface mesh. Exit program.\n");
1406 return 0;
1407 }
1408
1409 if ( !MMGS_hashTria(mesh) ) {
1410 fprintf(stderr,"\n ## Hashing problem. Exit program.\n");
1411 return 0;
1412 }
1413
1414 /* collapse short edges */
1415 nc = colelt(mesh,met,typchk);
1416 if ( nc < 0 ) {
1417 fprintf(stderr,"\n ## Unable to collapse mesh. Exiting.\n");
1418 return 0;
1419 }
1420 }
1421 else {
1422 ns = 0;
1423 nc = 0;
1424 }
1425
1426 /* attempt to swap */
1427 if ( !mesh->info.noswap ) {
1428 nf = swpmsh(mesh,met,typchk);
1429 if ( nf < 0 ) {
1430 fprintf(stderr,"\n ## Unable to improve mesh. Exiting.\n");
1431 return 0;
1432 }
1433 }
1434 else nf = 0;
1435
1436 nnc += nc;
1437 nns += ns;
1438 nnf += nf;
1439 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && ns+nc > 0 )
1440 fprintf(stdout," %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed, %8" MMG5_PRId " swapped\n",ns,nc,nf);
1441 if ( it > 3 && MMG5_abs(nc-ns) < 0.1 * MG_MAX(nc,ns) ) break;
1442 }
1443 while ( ++it < maxit && ns+nc+nf > 0 );
1444
1445 if ( mesh->info.imprim > 0 ) {
1446 if ( (abs(mesh->info.imprim) < 5 || mesh->info.ddebug ) && nns+nnc > 0 )
1447 fprintf(stdout," %8" MMG5_PRId " splitted, %8" MMG5_PRId " collapsed, %8" MMG5_PRId " swapped, %d iter.\n",nns,nnc,nnf,it);
1448 }
1449
1450 return 1;
1451}
1452
1462int MMG5_mmgs1(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int *permNodGlob) {
1463
1464 /* renumbering if available */
1465 if ( abs(mesh->info.imprim) > 4 )
1466 fprintf(stdout," ** MESH ANALYSIS\n");
1467
1468 /*--- stage 1: geometric mesh */
1469 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
1470 fprintf(stdout," ** GEOMETRIC MESH\n");
1471
1472 if ( !anatri(mesh,met,1) ) {
1473 fprintf(stderr,"\n ## Unable to split mesh-> Exiting.\n");
1474 return 0;
1475 }
1476
1477 /* Debug: export variable MMG_SAVE_ANATRI1 to save adapted mesh at the end of
1478 * anatri wave */
1479 if ( getenv("MMG_SAVE_ANATRI1") ) {
1480 printf(" ## WARNING: EXIT AFTER ANATRI-1."
1481 " (MMG_SAVE_ANATRI1 env variable is exported).\n");
1482 return 1;
1483 }
1484
1485 /* renumbering if available */
1486 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
1487 return 0;
1488
1489 /*--- stage 2: computational mesh */
1490 if ( abs(mesh->info.imprim) > 4 || mesh->info.ddebug )
1491 fprintf(stdout," ** COMPUTATIONAL MESH\n");
1492
1493 /* define metric map */
1494 if ( !MMGS_defsiz(mesh,met) ) {
1495 fprintf(stderr,"\n ## Metric undefined. Exit program.\n");
1496 return 0;
1497 }
1498
1499 /* Debug: export variable MMG_SAVE_DEFSIZ to save adapted mesh at the end of
1500 * anatet wave */
1501 if ( getenv("MMG_SAVE_DEFSIZ") ) {
1502 printf(" ## WARNING: EXIT AFTER DEFSIZ."
1503 " (MMG_SAVE_DEFSIZ env variable is exported).\n");
1504 return 1;
1505 }
1506
1508 if ( mesh->info.hgrad > 0. ) {
1509 if (!MMGS_gradsiz(mesh,met) ) {
1510 fprintf(stderr,"\n ## Gradation problem. Exit program.\n");
1511 return 0;
1512 }
1513 }
1514
1515 if ( mesh->info.hgradreq > 0. ) {
1516 MMGS_gradsizreq(mesh,met);
1517 }
1518
1519 /* Debug: export variable MMG_SAVE_GRADSIZ to save adapted mesh at the end of
1520 * anatet wave */
1521 if ( getenv("MMG_SAVE_GRADSIZ") ) {
1522 printf(" ## WARNING: EXIT AFTER GRADSIZ."
1523 " (MMG_SAVE_GRADSIZ env variable is exported).\n");
1524 return 1;
1525 }
1526
1527 if ( !anatri(mesh,met,2) ) {
1528 fprintf(stderr,"\n ## Unable to proceed adaptation. Exit program.\n");
1529 return 0;
1530 }
1531 /* Debug: export variable MMG_SAVE_ANATRI1 to save adapted mesh at the end of
1532 * anatri wave */
1533 if ( getenv("MMG_SAVE_ANATRI2") ) {
1534 printf(" ## WARNING: EXIT AFTER ANATRI-2."
1535 " (MMG_SAVE_ANATRI2 env variable is exported).\n");
1536 return 1;
1537 }
1538
1539 /* renumbering if available */
1540 if ( !MMG5_scotchCall(mesh,met,NULL,permNodGlob) )
1541 return 0;
1542
1543 if ( !adptri(mesh,met,permNodGlob) ) {
1544 fprintf(stderr,"\n ## Unable to adapt. Exit program.\n");
1545 return 0;
1546 }
1547
1548 return 1;
1549}
int ier
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMGS_bezierInt(MMG5_pBezier pb, double uv[2], double o[3], double no[3], double to[3])
Definition: bezier_s.c:207
int MMG5_boulet(MMG5_pMesh mesh, MMG5_int start, int ip, MMG5_int *list, int8_t s, int8_t *opn)
Definition: boulep.c:363
int colver(MMG5_pMesh mesh, MMG5_int *list, int ilist)
Definition: colver_s.c:280
int colver3(MMG5_pMesh mesh, MMG5_int *list)
Definition: colver_s.c:370
int colver2(MMG5_pMesh mesh, MMG5_int *list)
Definition: colver_s.c:433
int chkcol(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int *list, int8_t typchk, double(*MMGS_lenEdg)(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_int, int8_t), double(*MMGS_caltri)(MMG5_pMesh, MMG5_pSol, MMG5_pTria))
Definition: colver_s.c:59
MMG5_int MMGS_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: gentools_s.c:139
int MMG5_hashUpdate(MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:400
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:526
MMG5_int MMG5_hashGet(MMG5_Hash *hash, MMG5_int a, MMG5_int b)
Definition: hash.c:495
int MMG5_hashEdge(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:345
int MMGS_hashTria(MMG5_pMesh mesh)
Definition: hash_s.c:77
static double MMG5_lenSurfEdg_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip1, MMG5_int ip2, int8_t isedg)
static double MMG5_lenSurfEdg33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int np0, MMG5_int np1, int8_t isedg)
int MMGS_intmet33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_s.c:144
void MMG5_gradation_info(MMG5_pMesh mesh)
Definition: isosiz.c:96
MMG5_int MMGS_newPt(MMG5_pMesh mesh, double c[3], double n[3])
Definition: zaldy_s.c:39
int MMG5_split2_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: split_s.c:383
int MMGS_split1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i, MMG5_int *vx)
Definition: split_s.c:109
int chkswp(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i, int8_t typchk, double(*MMGS_lenEdg)(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_int, int8_t), double(*MMGS_caltri)(MMG5_pMesh, MMG5_pSol, MMG5_pTria))
Definition: swapar_s.c:58
int MMGS_split3_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: split_s.c:532
#define MMGS_LOPTS
#define MMGS_LOPTL
#define MMGS_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag)
int swapar(MMG5_pMesh mesh, MMG5_int k, int i)
Definition: swapar_s.c:318
#define MMGS_LLONG
void MMGS_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_s.c:58
int MMGS_split3(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: split_s.c:620
int MMGS_simbulgept(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i, MMG5_int ip)
Definition: split_s.c:162
int MMGS_split1_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i, MMG5_int *vx)
Definition: split_s.c:52
int MMGS_split2(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: split_s.c:459
#define MMGS_LSHRT
#define MS_SIN(tag)
int split1b(MMG5_pMesh mesh, MMG5_int k, int8_t i, MMG5_int ip)
Definition: split_s.c:283
@ MMG5_Triangle
Definition: libmmgtypes.h:226
int MMG5_scotchCall(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pSol fields, MMG5_int *permNodGlob)
Definition: librnbg.c:231
#define MG_REQ
#define MG_GEO
#define MG_EOK(pt)
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MMG5_GAP
#define MG_EDG(tag)
#define MG_NOTAG
static const uint8_t MMG5_iprv2[3]
#define MMG5_TAB_RECALLOC(mesh, ptr, initSize, wantedGap, type, message, law)
#define MMG5_TRIA_LMAX
#define MG_GET(flag, bit)
static const uint8_t MMG5_inxt2[6]
int MMG5_nortri(MMG5_pMesh mesh, MMG5_pTria pt, double *n)
Definition: tools.c:209
#define MG_NOM
double MMG5_caltri_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria ptt)
Definition: quality.c:199
#define MMG5_EPSD2
double MMG5_caltri33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria pt)
Definition: quality.c:47
#define MMG5_DEL_MEM(mesh, ptr)
#define MG_SET(flag, bit)
static int movtri(MMG5_pMesh mesh, MMG5_pSol met, int maxit)
Definition: mmgs1.c:469
int MMG5_mmgs1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int *permNodGlob)
Definition: mmgs1.c:1462
int chkedg(MMG5_pMesh mesh, MMG5_int iel)
Definition: mmgs1.c:214
static void MMGS_set_localFunc(MMG5_pSol met, int8_t typchk, double(**MMGS_lenEdg)(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_int, int8_t), double(**MMGS_caltri)(MMG5_pMesh, MMG5_pSol, MMG5_pTria))
Definition: mmgs1.c:406
static int swpmsh(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk)
Definition: mmgs1.c:428
static int anaelt(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk)
Definition: mmgs1.c:579
static MMG5_int colelt(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk)
Definition: mmgs1.c:1025
int MMGS_dichoto(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: mmgs1.c:52
static int anatri(MMG5_pMesh mesh, MMG5_pSol met, int8_t typchk)
Definition: mmgs1.c:1389
static MMG5_int adpspl(MMG5_pMesh mesh, MMG5_pSol met)
Definition: mmgs1.c:1132
MMG5_int chkspl(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i)
Definition: mmgs1.c:954
int8_t ddb
Definition: mmg3d1_delone.c:42
static int MMGS_delPatternPts(MMG5_pMesh mesh, MMG5_Hash hash)
Definition: mmgs1.c:537
static int adptri(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int *permNodGlob)
Definition: mmgs1.c:1272
int MMGS_dichoto1b(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int ia, MMG5_int ip)
Definition: mmgs1.c:156
static MMG5_int adpcol(MMG5_pMesh mesh, MMG5_pSol met)
Definition: mmgs1.c:1208
MMG5_pPoint p[3]
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:595
MMG5_hedge * item
Definition: libmmgtypes.h:597
int8_t ddebug
Definition: libmmgtypes.h:532
uint8_t noswap
Definition: libmmgtypes.h:546
double hmin
Definition: libmmgtypes.h:518
double hgrad
Definition: libmmgtypes.h:518
uint8_t noinsert
Definition: libmmgtypes.h:546
double hmax
Definition: libmmgtypes.h:518
uint8_t nomove
Definition: libmmgtypes.h:546
MMG5_pPar par
Definition: libmmgtypes.h:517
double hgradreq
Definition: libmmgtypes.h:518
double hausd
Definition: libmmgtypes.h:518
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
MMG5_int xp
Definition: libmmgtypes.h:620
double gap
Definition: libmmgtypes.h:608
MMG5_int base
Definition: libmmgtypes.h:616
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_int xpmax
Definition: libmmgtypes.h:612
double hmin
Definition: libmmgtypes.h:258
double hmax
Definition: libmmgtypes.h:259
double hausd
Definition: libmmgtypes.h:260
MMG5_int ref
Definition: libmmgtypes.h:261
int8_t elt
Definition: libmmgtypes.h:262
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double n[3]
Definition: libmmgtypes.h:272
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
MMG5_int xp
Definition: libmmgtypes.h:279
MMG5_int ref
Definition: libmmgtypes.h:278
MMG5_int flag
Definition: libmmgtypes.h:282
double * m
Definition: libmmgtypes.h:671
MMG5_int edg[3]
Definition: libmmgtypes.h:339
int16_t tag[3]
Definition: libmmgtypes.h:342
MMG5_int ref
Definition: libmmgtypes.h:335
MMG5_int flag
Definition: libmmgtypes.h:341
MMG5_int v[3]
Definition: libmmgtypes.h:334
Structure to store surface points of a MMG mesh.
Definition: libmmgtypes.h:294
double n2[3]
Definition: libmmgtypes.h:295
double n1[3]
Definition: libmmgtypes.h:295