Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
delaunay_3d.c
Go to the documentation of this file.
1/* =============================================================================
2** This file is part of the mmg software package for the tetrahedral
3** mesh modification.
4** Copyright (c) Bx INP/CNRS/Inria/UBordeaux/UPMC, 2004-
5**
6** mmg is free software: you can redistribute it and/or modify it
7** under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation, either version 3 of the License, or
9** (at your option) any later version.
10**
11** mmg is distributed in the hope that it will be useful, but WITHOUT
12** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14** License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public
17** License and of the GNU General Public License along with mmg (in
18** files COPYING.LESSER and COPYING). If not, see
19** <http://www.gnu.org/licenses/>. Please read their terms carefully and
20** use this copy of the mmg distribution only if you accept them.
21** =============================================================================
22*/
23
36
37#ifndef MMG_PATTERN
38
39#define MMG3D_EPSRAD 1.00005
40/* For Various_adpsol_hgrad1_M6Mach_Eps0.001_hmin0.001_hmax2 test case:
41 pbs with MMG3D_EPSCON=5e-4 (MMG3D does not insert enough vertex...)
42*/
43#define MMG3D_EPSCON 1e-5 //5.0e-4
44#define MMG3D_LONMAX 4096
45
46// uncomment to debug
47// int MMG_cas;
48// extern int MMG_npuiss,MMG_nvol,MMG_npres;
49
50#define MMG3D_KTA 7
51#define MMG3D_KTB 11
52#define MMG3D_KTC 13
53
54/* hash mesh edge v[0],v[1] (face i of iel) */
55int MMG5_hashEdgeDelone(MMG5_pMesh mesh,MMG5_Hash *hash,MMG5_int iel,int i,MMG5_int *v) {
56 MMG5_int key,*adja,iadr,jel,mins,maxs;
57 int j;
58 MMG5_hedge *ha;
59
60 /* compute key */
61 if ( v[0] < v[1] ) {
62 mins = v[0];
63 maxs = v[1];
64 }
65 else {
66 mins = v[1];
67 maxs = v[0];
68 }
69 key = (MMG3D_KTA*(int64_t)mins + MMG3D_KTB*(int64_t)maxs)%hash->siz;
70 ha = &hash->item[key];
71
72 if ( ha->a ) {
73 /* identical face */
74 if ( ha->a == mins && ha->b == maxs ) {
75 iadr = (iel-1)*4 + 1;
76 adja = &mesh->adja[iadr];
77 adja[i] = ha->k;
78
79 jel = ha->k >> 2;
80 j = ha->k % 4;
81 iadr = (jel-1)*4 + 1;
82 adja = &mesh->adja[iadr];
83 adja[j] = iel*4 + (MMG5_int)i;
84 return 1;
85 }
86 else {
87 while ( ha->nxt && ha->nxt < hash->max ) {
88 ha = &hash->item[ha->nxt];
89 if ( ha->a == mins && ha->b == maxs ) {
90 iadr = (iel-1)*4 + 1;
91 adja = &mesh->adja[iadr];
92 adja[i] = ha->k;
93
94 jel = ha->k >> 2;
95 j = ha->k % 4;
96 iadr = (jel-1)*4 + 1;
97 adja = &mesh->adja[iadr];
98 adja[j] = iel*4 + (MMG5_int)i;
99 return 1;
100 }
101 }
102 }
103 ha->nxt = hash->nxt;
104 ha = &hash->item[hash->nxt];
105 ha->a = mins;
106 ha->b = maxs;
107 ha->k = iel*4 + (MMG5_int)i;
108 hash->nxt = ha->nxt;
109 ha->nxt = 0;
110
111 if ( hash->nxt >= hash->max ) {
113 return 0;);
114 for (j=hash->nxt; j<hash->max; j++) hash->item[j].nxt = j+1;
115 }
116 return 1;
117 }
118
119 /* insert */
120 ha->a = mins;
121 ha->b = maxs;
122 ha->k = iel*4 + (MMG5_int)i;
123 ha->nxt = 0;
124
125 return 1;
126}
127
140int MMG5_delone(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int ip,int64_t *list,int ilist) {
141 MMG5_pPoint ppt;
142 MMG5_pTetra pt,pt1;
143 MMG5_xTetra xt;
144 MMG5_pxTetra pxt0;
145 MMG5_int base,*adja,*adjb,iel,jel,old,v[3],iadr;
146 int i,j,k,l,m,size;
147 MMG5_int vois[4],iadrold,ielnum[3*MMG3D_LONMAX+1];
148 short i1;
149 char alert;
150 int isused = 0,ixt;
151 MMG5_Hash hedg;
152#ifndef NDEBUG
153 MMG5_int tref;
154#endif
155
156 base = mesh->base;
157 /* external faces */
158 size = 0;
159 for (k=0; k<ilist; k++) {
160 old = list[k];
161 pt1 = &mesh->tetra[old];
162 iadr = (old-1)*4 + 1;
163 adja = &mesh->adja[iadr];
164 vois[0] = adja[0] >> 2;
165 vois[1] = adja[1] >> 2;
166 vois[2] = adja[2] >> 2;
167 vois[3] = adja[3] >> 2;
168 for (i=0; i<4; i++) {
169 jel = vois[i];
170 if ( (!jel) || mesh->tetra[jel].flag != base ) {
171 for (j=0; j<3; j++) {
172 i1 = MMG5_idir[i][j];
173 ppt = &mesh->point[ pt1->v[i1] ];
174 ppt->tagdel |= MG_NOM;
175 }
176 size++;
177 }
178 }
179 }
180 /* check isolated vertex */
181 alert = 0;
182 for (k=0; k<ilist; k++) {
183 old = list[k];
184 pt1 = &mesh->tetra[old];
185 for (i=0; i<4; i++) {
186 ppt = &mesh->point[ pt1->v[i] ];
187 if ( !(ppt->tagdel & MG_NOM) ) alert = 1;
188 }
189 }
190 /* reset tag */
191 for (k=0; k<ilist; k++) {
192 old = list[k];
193 pt1 = &mesh->tetra[old];
194 for (i=0; i<4; i++) {
195 ppt = &mesh->point[ pt1->v[i] ];
196 ppt->tagdel &= ~MG_NOM;
197 }
198 }
199 if ( alert ) {return 0;}
200 /* hash table params */
201 if ( size > 3*MMG3D_LONMAX ) return 0;
202 if ( !MMG5_hashNew(mesh,&hedg,size,3*size) ) { /*3*size suffit */
203 fprintf(stderr,"\n ## Error: %s: unable to complete mesh.\n",__func__);
204 return -1;
205 }
206
207 /*tetra allocation : we create "size" tetra*/
208 ielnum[0] = size;
209 for (k=1 ; k<=size ; k++) {
210 ielnum[k] = MMG3D_newElt(mesh);
211
212 if ( !ielnum[k] ) {
213 MMG3D_TETRA_REALLOC(mesh,ielnum[k],mesh->gap,
214 fprintf(stderr,"\n ## Error: %s: unable to allocate a"
215 " new element.\n",__func__);
216 return -1);
217 }
218 }
219
220 size = 1;
221 for (k=0; k<ilist; k++) {
222 old = list[k];
223
224 iadrold = (old-1)*4 + 1;
225 adja = &mesh->adja[iadrold];
226 vois[0] = adja[0];
227 vois[1] = adja[1];
228 vois[2] = adja[2];
229 vois[3] = adja[3];
230
231 pt = &mesh->tetra[old];
232 if(pt->xt) {
233 pxt0 = &mesh->xtetra[pt->xt];
234 memcpy(&xt,pxt0,sizeof(MMG5_xTetra));
235 isused=0;
236 ixt = 1;
237 } else {
238 ixt = 0;
239 }
240
241 for (i=0; i<4; i++) {
242 jel = vois[i] /4;
243 j = vois[i] % 4;
244
245 /* external face */
246 if ( !jel || (mesh->tetra[jel].flag != base) ) {
247 iel = ielnum[size++];
248 assert(iel);
249
250 pt1 = &mesh->tetra[iel];
251 memcpy(pt1,pt,sizeof(MMG5_Tetra));
252 pt1->v[i] = ip;
253 pt1->qual = MMG5_orcal(mesh,sol,iel);
254 pt1->ref = mesh->tetra[old].ref;
255 pt1->mark = mesh->mark;
256 iadr = (iel-1)*4 + 1;
257 adjb = &mesh->adja[iadr];
258 adjb[i] = adja[i];
259
260 if(ixt) {
261 if( xt.ref[i] || xt.ftag[i]) {
262 if(!isused) {
263 pt1->xt = pt->xt;
264 pt->xt = 0;
265 pxt0 = &mesh->xtetra[pt1->xt];
266 memset(pxt0,0,sizeof(MMG5_xTetra));
267 pxt0->ref[i] = xt.ref[i] ; pxt0->ftag[i] = xt.ftag[i];
268 pxt0->edg[MMG5_iarf[i][0]] = xt.edg[MMG5_iarf[i][0]];
269 pxt0->edg[MMG5_iarf[i][1]] = xt.edg[MMG5_iarf[i][1]];
270 pxt0->edg[MMG5_iarf[i][2]] = xt.edg[MMG5_iarf[i][2]];
271 pxt0->tag[MMG5_iarf[i][0]] = xt.tag[MMG5_iarf[i][0]];
272 pxt0->tag[MMG5_iarf[i][1]] = xt.tag[MMG5_iarf[i][1]];
273 pxt0->tag[MMG5_iarf[i][2]] = xt.tag[MMG5_iarf[i][2]];
274 pxt0->ori = xt.ori;
275 isused=1;
276 } else {
277 mesh->xt++;
278 if ( mesh->xt > mesh->xtmax ) {
280 "larger xtetra table",
281 mesh->xt--;
282 fprintf(stderr," Exit program.\n"); return -1;);
283 }
284 pt1->xt = mesh->xt;
285 pxt0 = &mesh->xtetra[pt1->xt];
286 pxt0->ref[i] = xt.ref[i] ; pxt0->ftag[i] = xt.ftag[i];
287 pxt0->edg[MMG5_iarf[i][0]] = xt.edg[MMG5_iarf[i][0]];
288 pxt0->edg[MMG5_iarf[i][1]] = xt.edg[MMG5_iarf[i][1]];
289 pxt0->edg[MMG5_iarf[i][2]] = xt.edg[MMG5_iarf[i][2]];
290 pxt0->tag[MMG5_iarf[i][0]] = xt.tag[MMG5_iarf[i][0]];
291 pxt0->tag[MMG5_iarf[i][1]] = xt.tag[MMG5_iarf[i][1]];
292 pxt0->tag[MMG5_iarf[i][2]] = xt.tag[MMG5_iarf[i][2]];
293 pxt0->ori = xt.ori;
294 }
295 }
296 else {
297 pt1->xt = 0;
298 }
299 }
300
301 if ( jel ) {
302 iadr = (jel-1)*4 + 1;
303 adjb = &mesh->adja[iadr];
304 adjb[j] = iel*4 + i;
305 }
306
307 /* internal faces (p1,p2,ip) */
308 for (j=0; j<4; j++) {
309 if ( j != i ) {
310 m = 0;
311 for (l=0; l<3; l++)
312 if ( pt1->v[ MMG5_idir[j][l] ] != ip ) {
313 v[m] = pt1->v[ MMG5_idir[j][l] ];
314 m++;
315 }
316 MMG5_hashEdgeDelone(mesh,&hedg,iel,j,v);
317 }
318 }
319 }
320 }
321 }
322
323 /* remove old tetra */
324#ifndef NDEBUG
325 tref = mesh->tetra[list[0]].ref;
326#endif
327 for (k=0; k<ilist; k++) {
328 assert(tref==mesh->tetra[list[k]].ref);
329 if ( !MMG3D_delElt(mesh,list[k]) ) return -1;
330 }
331
332 // ppt = &mesh->point[ip];
333 // ppt->flag = mesh->flag;
334 MMG5_DEL_MEM(mesh,hedg.item);
335 return 1;
336}
337
352static int MMG5_correction_ani(MMG5_pMesh mesh,MMG5_pSol met,int ip,int64_t* list,
353 int ilist,int nedep,double volmin) {
354 MMG5_pPoint ppt,p1,p2,p3;
355 MMG5_pTetra pt;
356 double dd,det,nn,eps,eps2,ux,uy,uz,vx,vy,vz,v1,v2,v3;
357 double *ma,*mb,*mc,*md,mm[6],h1,h2,h3;
358 MMG5_int *adja,i,j,iel,iadr,adj,ib,ic,id;
359 MMG5_int base,vois[4];
360 int ipil,lon,ncor;
361
362 ppt = &mesh->point[ip];
363 if ( ppt->tag & MG_NUL ) return ilist;
364 base = mesh->base;
365 lon = ilist;
366 eps = MMG3D_EPSCON;
367 eps2 = eps*eps;
368
369 /* average metric */
370 memset(mm,0,6*sizeof(double));
371 ma = &met->m[6*ip];
372
373 do {
374 ipil = lon-1;
375 ncor = 0;
376
377 while ( ipil >= 0 ) {
378 iel = list[ipil];
379 iadr = (iel-1)*4 + 1;
380 adja = &mesh->adja[iadr];
381 vois[0] = adja[0] >> 2;
382 vois[1] = adja[1] >> 2;
383 vois[2] = adja[2] >> 2;
384 vois[3] = adja[3] >> 2;
385 pt = &mesh->tetra[iel];
386
387 // MMG_cas=0; // uncomment to debug
388 for (i=0; i<4; i++) {
389 adj = vois[i];
390 // MMG_cas = 0;// uncomment to debug
391 if ( adj && mesh->tetra[adj].flag == base) continue;
392
393 ib = pt->v[ MMG5_idir[i][0] ];
394 ic = pt->v[ MMG5_idir[i][1] ];
395 id = pt->v[ MMG5_idir[i][2] ];
396
397 p1 = &mesh->point[ib];
398 p2 = &mesh->point[ic];
399 p3 = &mesh->point[id];
400
401 ux = p2->c[0] - p1->c[0];
402 uy = p2->c[1] - p1->c[1];
403 uz = p2->c[2] - p1->c[2];
404
405 vx = p3->c[0] - p1->c[0];
406 vy = p3->c[1] - p1->c[1];
407 vz = p3->c[2] - p1->c[2];
408
409 /* volume PABC */
410 v1 = uz*vy - uy*vz;
411 v2 = ux*vz - uz*vx;
412 v3 = uy*vx - ux*vy;
413 dd = v1*(ppt->c[0]-p1->c[0]) + v2*(ppt->c[1]-p1->c[1]) \
414 + v3*(ppt->c[2]-p1->c[2]);
415 // MMG_cas=1; // uncomment to debug
416
417 /*test sur le volume avec un eps local*/
418 h1 = ux*ux + uy*uy + uz*uz;
419 h2 = vx*vx + vy*vy + vz*vz;
420 h3 = (p2->c[0] - p3->c[0])*(p2->c[0] - p3->c[0]) + (p2->c[1] - p3->c[1])*(p2->c[1] - p3->c[1])
421 + (p2->c[2] - p3->c[2])*(p2->c[2] - p3->c[2]);
422 if ( dd < volmin*sqrt(h1*h2*h3) ) break;
423
424 /* average metric */
425 mb = &met->m[6*ib];
426 mc = &met->m[6*ic];
427 md = &met->m[6*id];
428 for (j=0; j<6; j++)
429 mm[j] = 0.25 * (ma[j]+mb[j]+mc[j]+md[j]);
430
431 det = mm[0] * ( mm[3]*mm[5] - mm[4]*mm[4]) \
432 - mm[1] * ( mm[1]*mm[5] - mm[2]*mm[4]) \
433 + mm[2] * ( mm[1]*mm[4] - mm[2]*mm[3]);
434 if ( det < MMG5_EPSOK ) break;
435
436 /* point close to face */
437 // MMG_cas=2; // uncomment to debug
438 nn = mm[0]*v1*v1 + mm[3]*v2*v2 + mm[5]*v3*v3 \
439 + 2.0*(mm[1]*v1*v2 + mm[2]*v1*v3 + mm[4]*v2*v3);
440
441 if ( det*dd*dd < nn * eps2 ) break;
442 // MMG_cas=0; // uncomment to debug
443 }
444 if ( i < 4 || pt->tag & MG_REQ ) {
445 if ( ipil <= nedep ) {
446 return 0;
447 }
448 /* remove iel from list */
449 pt->flag = base-1;
450 list[ipil] = list[--lon];
451 ncor = 1;
452 break;
453 }
454 else
455 ipil--;
456 }
457 }
458 while ( ncor > 0 && lon >= nedep );
459
460 return lon;
461}
462
463
478static int
479MMG5_correction_iso(MMG5_pMesh mesh,int ip,int64_t *list,int ilist,int nedep,double volmin) {
480 MMG5_pPoint ppt,p1,p2,p3;
481 MMG5_pTetra pt;
482 double dd,nn,eps,eps2,ux,uy,uz,vx,vy,vz,v1,v2,v3;
483 MMG5_int *adja,i,iel,iadr,adj,ib,ic,id;
484 MMG5_int base,vois[4];
485 int ncor,ipil,lon;
486
487 ppt = &mesh->point[ip];
488 if ( ppt->tag & MG_NUL ) return ilist;
489 base = mesh->base;
490 lon = ilist;
491 eps = MMG3D_EPSCON;
492 eps2 = eps*eps;
493 do {
494 ipil = lon-1;
495 ncor = 0;
496
497 while ( ipil >= 0 ) {
498 iel = list[ipil];
499 iadr = (iel-1)*4 + 1;
500 adja = &mesh->adja[iadr];
501 vois[0] = adja[0] >> 2;
502 vois[1] = adja[1] >> 2;
503 vois[2] = adja[2] >> 2;
504 vois[3] = adja[3] >> 2;
505 pt = &mesh->tetra[iel];
506 // MMG_cas=0; // uncomment to debug
507 for (i=0; i<4; i++) {
508 adj = vois[i];
509 // MMG_cas = 0; // uncomment to debug
510 if ( adj && mesh->tetra[adj].flag == base ) continue;
511
512 ib = pt->v[ MMG5_idir[i][0] ];
513 ic = pt->v[ MMG5_idir[i][1] ];
514 id = pt->v[ MMG5_idir[i][2] ];
515
516 p1 = &mesh->point[ib];
517 p2 = &mesh->point[ic];
518 p3 = &mesh->point[id];
519
520 ux = p2->c[0] - p1->c[0];
521 uy = p2->c[1] - p1->c[1];
522 uz = p2->c[2] - p1->c[2];
523
524 vx = p3->c[0] - p1->c[0];
525 vy = p3->c[1] - p1->c[1];
526 vz = p3->c[2] - p1->c[2];
527
528 /* volume PABC */
529 v1 = uz*vy - uy*vz;
530 v2 = ux*vz - uz*vx;
531 v3 = uy*vx - ux*vy;
532 dd = v1*(ppt->c[0]-p1->c[0]) + v2*(ppt->c[1]-p1->c[1]) \
533 + v3*(ppt->c[2]-p1->c[2]);
534 // MMG_cas=1; // uncomment to debug
535
536 if ( dd < volmin ) break;
537
538 /* point close to face */
539 nn = (v1*v1 + v2*v2 + v3*v3);
540
541 // MMG_cas=2; // uncomment to debug
542 if ( dd*dd < nn * eps2 ) break;
543 // MMG_cas=0; //uncomment to debug
544 }
545 if ( i < 4 || pt->tag & MG_REQ ) {
546 if ( ipil <= nedep ) {
547 return 0;
548 }
549
550 /* remove iel from list */
551 pt->flag = base-1;
552 list[ipil] = list[--lon];
553
554 ncor = 1;
555 break;
556 }
557 else
558 ipil--;
559 }
560 }
561 while ( ncor > 0 && lon >= nedep );
562
563 return lon;
564}
565
566
581int MMG5_cavity_ani(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int iel,int ip,int64_t* list,int lon,double volmin) {
582 MMG5_pPoint ppt;
583 MMG5_pTetra pt,pt1;
584 double c[3],eps,dd,ray,ux,uy,uz,crit;
585 double *mj,*mp,ct[12];
586 MMG5_int *adja,*adjb,adj,adi,ia,jel,iadr;
587 MMG5_int base,vois[4],tref;
588 int k,voy,ilist,ipil,i,j,isreq,l;
589
590 if ( lon < 1 ) return 0;
591 ppt = &mesh->point[ip];
592 if ( ppt->tag & MG_NUL ) return 0;
593 base = ++mesh->base;
594
595 isreq = 0;
596
597 tref = mesh->tetra[list[0]/6].ref;
598 for (k=0; k<lon; k++) {
599 mesh->tetra[list[k]/6].flag = base;
600
601 if ( !mesh->info.opnbdy ) {
602 if ( tref != mesh->tetra[list[k]/6].ref ) {
603 return 0;
604 }
605 }
606 else {
607 pt = &mesh->tetra[list[k]/6];
608 if ( pt->xt ) {
609 l = list[k]%6;
610 if ( (mesh->xtetra[pt->xt].ftag[MMG5_ifar[l][0]] & MG_BDY) ||
611 (mesh->xtetra[pt->xt].ftag[MMG5_ifar[l][1]] & MG_BDY) )
612 return 0;
613 }
614 }
615 }
616 for (k=0; k<lon; k++)
617 list[k] = list[k] / 6;
618
619 /* grow cavity by adjacency */
621 ilist = lon;
622 ipil = 0;
623 iadr = ip*6;
624 mp = &met->m[iadr];
625
626 do {
627 jel = list[ipil];
628 iadr = (jel-1)*4 + 1;
629 adja = &mesh->adja[iadr];
630 vois[0] = adja[0];
631 vois[1] = adja[1];
632 vois[2] = adja[2];
633 vois[3] = adja[3];
634
635 for (i=0; i<4; i++) {
636 adj = vois[i];
637
638 if ( !adj ) continue;
639
640 adj >>= 2;
641 voy = vois[i] % 4;
642 pt = &mesh->tetra[adj];
643
644 /* boundary face */
645 if ( pt->flag == base ) continue;
646 if ( pt->xt && (mesh->xtetra[pt->xt].ftag[voy] & MG_BDY) ) continue;
647
648 for (j=0,l=0; j<4; j++,l+=3) {
649 memcpy(&ct[l],mesh->point[pt->v[j]].c,3*sizeof(double));
650 }
651
652
653 /* Delaunay kernel */
654 if ( !MMG5_cenrad_ani(mesh,ct,mp,c,&ray) ) continue;
655
656 ux = ppt->c[0] - c[0];
657 uy = ppt->c[1] - c[1];
658 uz = ppt->c[2] - c[2];
659 dd = mp[0]*ux*ux + mp[3]*uy*uy + mp[5]*uz*uz \
660 + 2.0*(mp[1]*ux*uy + mp[2]*ux*uz + mp[4]*uy*uz);
661 crit = eps * ray;
662 if ( dd > crit ) continue;
663
664 /* mixed metrics */
665 crit = sqrt(dd/ray);
666 for (j=0; j<4; j++) {
667 ia = pt->v[j];
668 iadr = 6*ia;
669 mj = &met->m[iadr];
670 if ( !MMG5_cenrad_ani(mesh,ct,mj,c,&ray) ) continue;
671 ux = ppt->c[0] - c[0];
672 uy = ppt->c[1] - c[1];
673 uz = ppt->c[2] - c[2];
674 dd = mj[0]*ux*ux + mj[3]*uy*uy + mj[5]*uz*uz \
675 + 2.0*(mj[1]*ux*uy + mj[2]*ux*uz + mj[4]*uy*uz);
676 crit += sqrt(dd/ray);
677 }
678 crit *= MMG3D_EPSRAD;
679 if ( crit > 5.0 ) continue;
680
681 /* lost face(s) */
682 iadr = (adj-1)*4 + 1;
683 adjb = &mesh->adja[iadr];
684
685 for (j=0; j<4; j++) {
686 if ( j == voy ) continue;
687 adi = adjb[j];
688
689 if ( !adi ) continue;
690
691 adi >>= 2;
692 assert(adi !=jel);
693
694 pt1 = &mesh->tetra[adi];
695 if ( pt1->flag == base ) {
696 if ( pt1->xt && (mesh->xtetra[pt1->xt].ftag[adjb[j]%4] & MG_BDY) ) break;
697 }
698 }
699 /* store tetra */
700 if ( j == 4 ) {
701 if ( pt->tag & MG_REQ ) isreq = 1;
702 pt->flag = base;
703 list[ilist++] = adj;
704 }
705 }
706 if ( ilist > MMG3D_LONMAX - 3 ) return -1;
707 ++ipil;
708 }
709 while ( ipil < ilist );
710
711 /* global overflow */
712 ilist = MMG5_correction_ani(mesh,met,ip,list,ilist,lon,volmin);
713
714 if ( isreq ) ilist = -abs(ilist);
715
716 // uncomment to debug
717 /* if(MMG_cas==1) MMG_nvol++; */
718 /* else if(MMG_cas==2 || MMG_cas>20) { */
719 /* MMG_npuiss++; */
720 /* if(MMG_cas>20) MMG_npres++; */
721 /* } */
722
723 return ilist;
724}
725
726
741int MMG5_cavity_iso(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int iel,int ip,int64_t *list,int lon,double volmin) {
742 MMG5_pPoint ppt;
743 MMG5_pTetra pt,pt1;
744 double c[3],crit,dd,eps,ray,ct[12];
745 MMG5_int *adja,*adjb,adj,adi,jel,iadr;
746 MMG5_int tref,base,vois[4],l;
747 int isreq;
748 int voy,i,j,k,ipil,ilist;
749
750 if ( lon < 1 ) return 0;
751 ppt = &mesh->point[ip];
752 if ( ppt->tag & MG_NUL ) return 0;
753 base = ++mesh->base;
754
755 isreq = 0;
756
757 tref = mesh->tetra[list[0]/6].ref;
758 for (k=0; k<lon; k++) {
759 mesh->tetra[list[k]/6].flag = base;
760
761 if ( !mesh->info.opnbdy ) {
762 if ( tref != mesh->tetra[list[k]/6].ref ) {
763 return 0;
764 }
765 }
766 else {
767 pt = &mesh->tetra[list[k]/6];
768 if ( pt->xt ) {
769 l = list[k]%6;
770 if ( (mesh->xtetra[pt->xt].ftag[MMG5_ifar[l][0]] & MG_BDY) ||
771 (mesh->xtetra[pt->xt].ftag[MMG5_ifar[l][1]] & MG_BDY) )
772 return 0;
773 }
774 }
775 }
776
777 for (k=0; k<lon; k++)
778 list[k] = list[k] / 6;
779
780 /* grow cavity by adjacency */
782 ilist = lon;
783 ipil = 0;
784
785 do {
786 jel = list[ipil];
787 iadr = (jel-1)*4 + 1;
788 adja = &mesh->adja[iadr];
789 vois[0] = adja[0];
790 vois[1] = adja[1];
791 vois[2] = adja[2];
792 vois[3] = adja[3];
793
794 for (i=0; i<4; i++) {
795 adj = vois[i];
796 if ( !adj ) continue;
797
798 adj >>= 2;
799 voy = vois[i] % 4;
800 pt = &mesh->tetra[adj];
801 /* boundary face */
802 if ( pt->flag == base ) continue;
803 if ( pt->xt && (mesh->xtetra[pt->xt].ftag[voy] & MG_BDY) ) continue;
804
805 for (j=0,l=0; j<4; j++,l+=3) {
806 memcpy(&ct[l],mesh->point[pt->v[j]].c,3*sizeof(double));
807 }
808
809 if ( !MMG5_cenrad_iso(mesh,ct,c,&ray) ) continue;
810 crit = eps * ray;
811
812 /* Delaunay criterion */
813 dd = (ppt->c[0] - c[0]) * (ppt->c[0] - c[0]) \
814 + (ppt->c[1] - c[1]) * (ppt->c[1] - c[1]) \
815 + (ppt->c[2] - c[2]) * (ppt->c[2] - c[2]);
816 if ( dd > crit ) continue;
817
818 /* lost face(s) */
819 iadr = (adj-1)*4 + 1;
820 adjb = &mesh->adja[iadr];
821
822 for (j=0; j<4; j++) {
823 if ( j == voy ) continue;
824 adi = adjb[j];
825 if ( !adi ) continue;
826
827 adi >>= 2;
828 assert(adi !=jel);
829
830 pt1 = &mesh->tetra[adi];
831 if ( pt1->flag == base )
832 if ( pt1->xt && (mesh->xtetra[pt1->xt].ftag[adjb[j]%4] & MG_BDY) ) break;
833 }
834 /* store tetra */
835 if ( j == 4 ) {
836 if ( pt->tag & MG_REQ ) isreq = 1;
837 pt->flag = base;
838 list[ilist++] = adj;
839 }
840 }
841 if ( ilist > MMG3D_LONMAX - 3 ) return -1;
842
843 ++ipil;
844 }
845 while ( ipil < ilist );
846
847 /* global overflow: obsolete avec la reallocation */
848 ilist = MMG5_correction_iso(mesh,ip,list,ilist,lon,volmin);
849
850 if ( isreq ) ilist = -abs(ilist);
851
852 // uncomment to debug
853 /* if(MMG_cas==1) MMG_nvol++; */
854 /* else if(MMG_cas==2 || MMG_cas>20) { */
855 /* MMG_npuiss++; */
856 /* if(MMG_cas>20) MMG_npres++; */
857 /* } */
858 return ilist;
859}
860
861#endif
MMG5_pMesh MMG5_pSol * sol
if(!ier) exit(EXIT_FAILURE)
MMG5_pMesh * mesh
int MMG5_cenrad_iso(MMG5_pMesh mesh, double *ct, double *c, double *rad)
Definition: cenrad_3d.c:45
int MMG5_cenrad_ani(MMG5_pMesh mesh, double *ct, double *m, double *c, double *rad)
Definition: cenrad_3d.c:142
#define MMG3D_EPSCON
Definition: delaunay_3d.c:43
int MMG5_cavity_iso(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int iel, int ip, int64_t *list, int lon, double volmin)
Definition: delaunay_3d.c:741
static int MMG5_correction_iso(MMG5_pMesh mesh, int ip, int64_t *list, int ilist, int nedep, double volmin)
Definition: delaunay_3d.c:479
#define MMG3D_LONMAX
Definition: delaunay_3d.c:44
int MMG5_hashEdgeDelone(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int iel, int i, MMG5_int *v)
Definition: delaunay_3d.c:55
#define MMG3D_EPSRAD
Definition: delaunay_3d.c:39
static int MMG5_correction_ani(MMG5_pMesh mesh, MMG5_pSol met, int ip, int64_t *list, int ilist, int nedep, double volmin)
Definition: delaunay_3d.c:352
#define MMG3D_KTA
Definition: delaunay_3d.c:50
#define MMG3D_KTB
Definition: delaunay_3d.c:51
int MMG5_delone(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int ip, int64_t *list, int ilist)
Definition: delaunay_3d.c:140
int MMG5_cavity_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int ip, int64_t *list, int lon, double volmin)
Definition: delaunay_3d.c:581
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:526
static double MMG5_orcal(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel)
MMG5_int MMG3D_newElt(MMG5_pMesh mesh)
Definition: zaldy_3d.c:99
int MMG3D_delElt(MMG5_pMesh mesh, MMG5_int iel)
Definition: zaldy_3d.c:122
static const int8_t MMG5_iarf[4][3]
iarf[i]: edges of face opposite to vertex i
static const uint8_t MMG5_ifar[6][2]
ifar[i][]: faces sharing the ith edge of the tetra
#define MMG3D_TETRA_REALLOC(mesh, jel, wantedGap, law)
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
#define MG_REQ
#define MMG5_EPSOK
#define MG_NUL
#define MMG5_GAP
#define MMG5_TAB_RECALLOC(mesh, ptr, initSize, wantedGap, type, message, law)
#define MG_BDY
#define MG_NOM
#define MMG5_DEL_MEM(mesh, ptr)
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:595
MMG5_int max
Definition: libmmgtypes.h:596
MMG5_int nxt
Definition: libmmgtypes.h:596
MMG5_hedge * item
Definition: libmmgtypes.h:597
MMG5_int siz
Definition: libmmgtypes.h:596
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int xt
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int mark
Definition: libmmgtypes.h:618
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_int xtmax
Definition: libmmgtypes.h:612
double gap
Definition: libmmgtypes.h:608
MMG5_int base
Definition: libmmgtypes.h:616
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
int8_t tagdel
Definition: libmmgtypes.h:286
double c[3]
Definition: libmmgtypes.h:271
double * m
Definition: libmmgtypes.h:671
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int flag
Definition: libmmgtypes.h:409
MMG5_int ref
Definition: libmmgtypes.h:404
MMG5_int mark
Definition: libmmgtypes.h:406
double qual
Definition: libmmgtypes.h:402
int16_t tag
Definition: libmmgtypes.h:410
Used to hash edges (memory economy compared to MMG5_hgeom).
Definition: libmmgtypes.h:584
MMG5_int b
Definition: libmmgtypes.h:585
MMG5_int a
Definition: libmmgtypes.h:585
MMG5_int k
Definition: libmmgtypes.h:586
MMG5_int nxt
Definition: libmmgtypes.h:585
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
int8_t ori
Definition: libmmgtypes.h:427
MMG5_int edg[6]
Definition: libmmgtypes.h:421
MMG5_int ref[4]
Definition: libmmgtypes.h:419