Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
chkmsh_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#include "libmmg3d.h"
37#include "libmmg3d_private.h"
38
39#define MMG5_EPSLOC 1.00005
40#define IEDG(a,b) (((a) > 0) && ((b) > 0)) ? ((a)+(b)) : (((a)+(b))-(1))
41
42extern int8_t ddb;
43
52 MMG5_pTetra pt;
53 MMG5_int k;
54#ifdef DEBUG
55 int ier=1;
56#endif
57
58 for (k=1; k<=mesh->ne; k++) {
59 pt = &mesh->tetra[k];
60 if ( !MG_EOK(pt) ) continue;
61 if ( MMG5_orvol(mesh->point,pt->v) < MMG5_NULKAL ) {
62 fprintf(stderr,"\n ## Warning: %s: tetra %" MMG5_PRId " volume %e\n",__func__,
63 k,MMG5_orvol(mesh->point,pt->v));
64#ifdef DEBUG
65 ier = 0;
66#endif
67 }
68 }
69#ifdef DEBUG
70 assert(ier);
71#endif
72}
73
91static inline
92int MMG3D_chk_shellEdgeTag_oneDir(MMG5_pMesh mesh,MMG5_int start, MMG5_int na, MMG5_int nb,
93 uint16_t tag,MMG5_int ref, MMG5_int piv,MMG5_int adj) {
94 MMG5_pTetra pt;
95 MMG5_pxTetra pxt;
96 MMG5_int *adja;
97 int8_t i;
98
99 while ( adj && (adj != start) ) {
100 pt = &mesh->tetra[adj];
101
102 /* identification of edge number in tetra adj */
103 if ( !MMG3D_findEdge(mesh,pt,adj,na,nb,1,NULL,&i) ) return -1;
104
105 /* update edge ref and tag */
106 if ( pt->xt ) {
107 pxt = &mesh->xtetra[pt->xt];
108 /* Test only BDY edges */
109 if ( pxt->tag[i] & MG_BDY ) {
110 assert (pxt->tag[i] == tag && "non consistent tags");
111 assert (pxt->edg[i] == ref && "non consistent refs");
112 }
113 }
114
115 /* set new triangle for travel */
116 adja = &mesh->adja[4*(adj-1)+1];
117 if ( pt->v[ MMG5_ifar[i][0] ] == piv ) {
118 adj = adja[ MMG5_ifar[i][0] ] / 4;
119 piv = pt->v[ MMG5_ifar[i][1] ];
120 }
121 else {
122 adj = adja[ MMG5_ifar[i][1] ] /4;
123 piv = pt->v[ MMG5_ifar[i][0] ];
124 }
125 }
126
127 return adj;
128}
129
142int MMG3D_chk_shellEdgeTag(MMG5_pMesh mesh,MMG5_int start, int8_t ia,uint16_t tag,MMG5_int ref) {
143 MMG5_pTetra pt;
144 MMG5_pxTetra pxt;
145 MMG5_int piv,na,nb,adj,*adja;
146
147 pt = &mesh->tetra[start];
148
149 assert( start >= 1 && MG_EOK(pt) && "invalid tetra" );
150 assert ( tag & MG_BDY && "Unexpected non boundary tag");
151
152 pxt = NULL;
153 na = pt->v[MMG5_iare[ia][0]];
154 nb = pt->v[MMG5_iare[ia][1]];
155
156 if ( pt->xt ) {
157 pxt = &mesh->xtetra[pt->xt];
158 /* Test only BDY edges */
159 if ( pxt->tag[ia] & MG_BDY ) {
160 assert (pxt->tag[ia] == tag && "non consistent tags"); ;
161 assert (pxt->edg[ia] == ref && "non consistent refs"); ;
162 }
163 }
164
165 /* Travel in one direction */
166 adja = &mesh->adja[4*(start-1)+1];
167 adj = adja[MMG5_ifar[ia][0]] / 4;
168 piv = pt->v[MMG5_ifar[ia][1]];
169
170 adj = MMG3D_chk_shellEdgeTag_oneDir(mesh,start,na,nb,tag,ref,piv,adj);
171
172 /* If all shell has been travelled, stop, else, travel it the other sense */
173 if ( adj > 0 ) {
174 assert ( adj == start );
175 return 1;
176 }
177 else if ( adj < 0 ) return 0;
178
179 assert(!adj);
180
181 pt = &mesh->tetra[start];
182 adja = &mesh->adja[4*(start-1)+1];
183 adj = adja[MMG5_ifar[ia][1]] / 4;
184 piv = pt->v[MMG5_ifar[ia][0]];
185
186 adj = MMG3D_chk_shellEdgeTag_oneDir(mesh,start,na,nb,tag,ref,piv,adj);
187
188 if ( adj < 0 ) return 0;
189
190 return 1;
191}
192
201 MMG5_pTetra pt;
202 MMG5_pxTetra pxt;
203 MMG5_HGeom hash;
204 int i;
205 MMG5_int k,nt,ip1,ip2;
206
207 /* Rough eval of the number of boundary triangles */
208 nt = 0;
209 for (k=1; k<=mesh->ne; k++) {
210 pt = &mesh->tetra[k];
211 if ( !MG_EOK(pt) ) continue;
212 if ( !pt->xt ) continue;
213
214 pxt = &mesh->xtetra[pt->xt];
215 for (i=0; i<4; i++) {
216 if ( pxt->ftag[i] & MG_BDY ) {
217 ++nt;
218 }
219 }
220 }
221 nt = nt/2 + 1;
222
223 /* Travel mesh edges and hash boundary ones */
224 MMG5_hNew(mesh,&hash,nt,3*nt);
225
226 uint16_t ignored_tag = (~MG_PARBDYBDY) & (~MG_OLDPARBDY);
227
228 for (k=1; k<=mesh->ne; k++) {
229 pt = &mesh->tetra[k];
230 if ( !MG_EOK(pt) ) continue;
231 if ( !pt->xt ) continue;
232
233 pxt = &mesh->xtetra[pt->xt];
234
235 for (i=0; i<6; i++) {
236 if ( pxt->tag[i] & MG_BDY ) {
237 ip1 = pt->v[MMG5_iare[i][0]];
238 ip2 = pt->v[MMG5_iare[i][1]];
239
240 uint16_t tag = 0;
241 MMG5_int dummy = 0;
242 int ier = MMG5_hGet ( &hash,ip1,ip2,&dummy,&tag);
243
244 if ( !ier ) {
245 /* First time we meet the edge: store the its tag from the current
246 * tetra in the hash table. Ignore OLDPARBDY and PARBDYBDY tags
247 * because they are not consistent through meshes inside ParMmg and
248 * forbid the use of the current function to check tag consistency if
249 * not ignored. */
250 int ier2 = MMG5_hEdge ( mesh,&hash,ip1,ip2,0,(pxt->tag[i] & ignored_tag));
251 if ( !ier2 ) {
252 /* Realloc error */
253 fprintf(stderr,"Error: %s: %d: Unable to add to hash table the edge "
254 "%d:%" MMG5_PRId "--%" MMG5_PRId " from tetra %" MMG5_PRId
255 " (%" MMG5_PRId ").\n ",__func__,__LINE__,i,ip1,ip2,k,
256 MMG3D_indElt(mesh,k));
257 }
258 }
259 else {
260 /* Edge tag has been stored from another tet: check consistency.
261 Ignore OLDPARBDY and PARBDYBDY tags because they are not *
262 consistent through meshes inside ParMmg and forbid the use of the *
263 current function to check tag consistency if not ignored.
264 */
265 if ( tag != (pxt->tag[i] & ignored_tag) ) {
266 fprintf(stderr,"Error: %s: %d: Non consistency at tet %" MMG5_PRId
267 " (%" MMG5_PRId "), edge %d:%" MMG5_PRId "--%" MMG5_PRId "\n ",
268 __func__,__LINE__,k,MMG3D_indElt(mesh,k),i,ip1,ip2);
269 assert( tag == pxt->tag[i] && "edge tag error" );
270 }
271 }
272 }
273 }
274 }
275
276 MMG5_DEL_MEM(mesh,hash.geom);
277}
278
279
290void MMG3D_chkedgetag(MMG5_pMesh mesh, MMG5_int ip1, MMG5_int ip2, int tag) {
291 MMG5_pTetra pt;
292 MMG5_pxTetra pxt;
293 MMG5_int k,i1,i2;
294 int i;
295
296 for (k=1; k<=mesh->ne; k++) {
297 pt = &mesh->tetra[k];
298 if ( !MG_EOK(pt) ) continue;
299 if ( !pt->xt ) continue;
300
301 pxt = &mesh->xtetra[pt->xt];
302 for (i=0; i<6; i++) {
303 i1 = pt->v[MMG5_iare[i][0]];
304 i2 = pt->v[MMG5_iare[i][1]];
305
306 if ( ((i1==ip1) && (i2==ip2)) || ((i2==ip1) && (i1==ip2)) ) {
307 if ( pxt->tag[i] != tag ) {
308 fprintf(stderr,"Error: %s: %d: Non consistency at tet %" MMG5_PRId " (%" MMG5_PRId "), edge %d\n ",
309 __func__,__LINE__,k,MMG3D_indElt(mesh,k),i);
310 assert(0);
311 }
312 }
313 }
314 }
315}
316
324 MMG5_pTetra pt;
325 MMG5_pxTetra pxt;
326 MMG5_int k;
327 int i, tag;
328
329 for (k=1; k<=mesh->ne; k++) {
330 pt = &mesh->tetra[k];
331 if ( !MG_EOK(pt) ) continue;
332 if ( !pt->xt ) continue;
333
334 pxt = &mesh->xtetra[pt->xt];
335 for (i=0; i<4; i++) {
336 tag = pxt->ftag[i];
337 assert(!(tag & (MG_GEO | MG_NOM | MG_CRN)) && "Nonsensical tag on face");
338 }
339 }
340}
341
353static inline
354void MMG3D_consistency_error_message(MMG5_pMesh mesh,MMG5_pPoint ppt,MMG5_int k,int i,MMG5_int ip1,MMG5_int ip2) {
355
356 assert ( mesh->tetra && "no tetra array");
357 MMG5_pTetra pt = &mesh->tetra[k];
358
359 assert ( pt->xt && "no xtetra");
360 MMG5_pxTetra pxt = &mesh->xtetra[pt->xt];
361
362 fprintf(stderr,"Error: %s: %d: Tag error at point %" MMG5_PRId " (%" MMG5_PRId "), "
363 "tetra %" MMG5_PRId " (%" MMG5_PRId "), edge %d:%" MMG5_PRId "--%" MMG5_PRId " (%" MMG5_PRId
364 "--%" MMG5_PRId ").\n",__func__,__LINE__,
365 ip1,MMG3D_indPt(mesh,ip1),k,MMG3D_indElt(mesh,k),i,ip1,ip2,
366 MMG3D_indPt(mesh,ip1),MMG3D_indPt(mesh,ip2));
367 fprintf(stderr," point tag: %d; edge tag: %d\n",ppt->tag,pxt->tag[i]);
368
371 MMG3D_chkedgetag(mesh,ip1,ip2,pxt->tag[i]);
372 assert(0);
373}
374
384 MMG5_pTetra pt;
385 MMG5_pxTetra pxt;
386 MMG5_pPoint p1,p2;
387 int i,i1,i2;
388 MMG5_int k,ip1,ip2;
389
391 for (k=1; k<=mesh->ne; k++) {
392 pt = &mesh->tetra[k];
393 if ( !MG_EOK(pt) ) continue;
394 if ( !pt->xt ) continue;
395
396 pxt = &mesh->xtetra[pt->xt];
397
398 for ( i=0; i<6; ++i ) {
399 i1 = MMG5_iare[i][0];
400 i2 = MMG5_iare[i][1];
401 ip1 = pt->v[i1];
402 ip2 = pt->v[i2];
403 p1 = &mesh->point[ip1];
404 p2 = &mesh->point[ip2];
405
406 if ( MG_EDG(pxt->tag[i]) ) {
407 if ( !(MG_EDG(p1->tag) || MG_SIN(p1->tag)) ) {
409 }
410 if ( !(MG_EDG(p2->tag) || MG_SIN(p2->tag)) ) {
412 }
413 }
414
415 if ( pxt->tag[i] & MG_NOM ) {
416 if ( !MG_SIN_OR_NOM(p1->tag) ) {
418 }
419 if ( !MG_SIN_OR_NOM(p2->tag) ) {
421 }
422 }
423 }
424 }
425}
426
433 MMG5_pTria pt;
434 MMG5_int k,k1;
435 MMG5_int *adja,*adja1;
436 int8_t i,voy;
437
438 for (k=1; k<=mesh->nt; k++) {
439 pt = &mesh->tria[k];
440 adja = &mesh->adjt[3*(k-1)+1];
441 for (i=0; i<3; i++) {
442 if ( pt->tag[i] & MG_NOM ) continue;
443 k1 = adja[i] / 3;
444 voy = adja[i] % 3;
445
446 if(!k1) continue;
447 adja1 = &mesh->adjt[3*(k1-1)+1];
448
449 if(adja1[voy] / 3 != k){
450 fprintf(stderr,"\n ## Warning: %s: wrong adjacency relation"
451 " for triangles : %" MMG5_PRId " %" MMG5_PRId " \n",__func__,k,k1);
452 return 0;
453 }
454 }
455 }
456 return 1;
457}
458
465static inline
467 MMG5_pTetra pt;
468 MMG5_pxTetra pxt;
469 MMG5_int k,it1,it2;
470 int64_t list[MMG3D_LMAX+2];
471 int i,j,ret;
472 int8_t ia;
473
474 for (k=1; k<=mesh->ne; k++) {
475 pt = &mesh->tetra[k];
476 if ( (!MG_EOK(pt)) || pt->ref < 0 || (pt->tag & MG_REQ) ) continue;
477 else if ( !pt->xt ) continue;
478 pxt = &mesh->xtetra[pt->xt];
479
480 for (i=0; i<4; i++) {
481 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
482 for (j=0; j<3; j++) {
483 ia = MMG5_iarf[i][j];
484
485 /* No check for geom edge (I am not sure that it can works) */
486 if ( MG_EDG_OR_NOM(pxt->tag[ia]) || (pxt->tag[ia] & MG_REQ) )
487 {
488 continue;
489 }
490
491 ret = MMG5_coquilface(mesh,k,i,ia,list,&it1,&it2,0);
492 if ( ret < 0 ) return 0;
493 }
494 }
495 }
496 return 1;
497}
498
508int MMG5_mmg3dChkmsh(MMG5_pMesh mesh,int severe,MMG5_int base) {
509 MMG5_pTetra pt,pt1,pt2;
510 MMG5_pxTetra pxt;
511 MMG5_int *adja,*adja1,adj,adj1,k,iadr,iel;
512 MMG5_int a0,a1,a2,b0,b1,b2;
513 int i;
514 uint8_t voy,voy1;
515 static int8_t mmgErr0=0,mmgErr1=0,mmgErr2=0,mmgErr3=0,mmgErr4=0,mmgErr5=0;
516
517 /* Check edge tag consistency (between xtetra) */
519
520 /* Check that faces do not have nonsensical tags*/
522
523 /* Check point tags consistency with edge tag */
525
526 if ( !mesh->adja ) return 1;
527
528 /* Check edge tag consistency with number of boundary faces in the edge shell */
530
531 for (k=1; k<=mesh->ne; k++) {
532 pt1 = &mesh->tetra[k];
533 if ( !MG_EOK(pt1) || pt1->ref < 0 ) continue;
534 iadr = 4*(k-1) + 1;
535 adja = &mesh->adja[iadr];
536
537 for (i=0; i<4; i++) {
538 adj = adja[i];
539
540 if ( !adj ) continue;
541 adj /= 4;
542 voy = adja[i] % 4;
543
544 if ( adj == k ) {
545 if ( !mmgErr0 ) {
546 fprintf(stderr,"\n ## Error: %s: 1. at least 1 wrong adjacency %" MMG5_PRId " %" MMG5_PRId "\n",
547 __func__,MMG3D_indElt(mesh,k),MMG3D_indElt(mesh,adj));
548 fprintf(stderr,"triangle %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
549 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
550 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
551 fprintf(stderr,"adj (%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
552 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
553 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
554 mmgErr0 = 1;
555 }
556 return 0;
557 }
558 pt2 = &mesh->tetra[adj];
559 if ( !MG_EOK(pt2) || pt2->ref < 0 ){
560 if ( !mmgErr1 ) {
561 fprintf(stderr,"\n ## Error: %s: 4. at least 1 invalid adjacent %" MMG5_PRId " %" MMG5_PRId "\n",
562 __func__,MMG3D_indElt(mesh,adj),MMG3D_indElt(mesh,k));
563 fprintf(stderr,"vertices of k %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
564 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
565 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
566 fprintf(stderr,"vertices of adj %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
567 MMG3D_indPt(mesh,pt2->v[0]),MMG3D_indPt(mesh,pt2->v[1]),
568 MMG3D_indPt(mesh,pt2->v[2]),MMG3D_indPt(mesh,pt2->v[3]));
569 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
570 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
571 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
572 mmgErr1 = 1;
573 }
574 return 0;
575 }
576 iadr = (adj-1)*4 + 1;
577 adja1 = &mesh->adja[iadr];
578 adj1 = adja1[voy] / 4;
579 voy1 = adja1[voy] % 4;
580 if ( adj1 != k || voy1 != i ) {
581 if ( !mmgErr2 ) {
582 fprintf(stderr,"\n ## Error: %s: 2. at least 1 wrong adjacency %" MMG5_PRId " %" MMG5_PRId "\n",
583 __func__,MMG3D_indElt(mesh,k),MMG3D_indElt(mesh,adj1));
584 fprintf(stderr,"vertices of %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
585 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
586 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
587 fprintf(stderr,"vertices of adj %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
588 MMG3D_indPt(mesh,pt2->v[0]),MMG3D_indPt(mesh,pt2->v[1]),
589 MMG3D_indPt(mesh,pt2->v[2]),MMG3D_indPt(mesh,pt2->v[3]));
590 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
591 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
592 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
593 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
594 MMG3D_indElt(mesh,adja1[0]/4),MMG3D_indElt(mesh,adja1[1]/4),
595 MMG3D_indElt(mesh,adja1[2]/4),MMG3D_indElt(mesh,adja1[3]/4));
596 mmgErr2 = 1;
597 }
598 return 0;
599 }
600
601 a0 = pt1->v[MMG5_idir[i][0]];
602 a1 = pt1->v[MMG5_idir[i][1]];
603 a2 = pt1->v[MMG5_idir[i][2]];
604
605 b0 = pt2->v[MMG5_idir[voy][0]];
606 b1 = pt2->v[MMG5_idir[voy][1]];
607 b2 = pt2->v[MMG5_idir[voy][2]];
608
609 if(!(((a0 == b0)&&(a1 == b1)&&(a2 ==b2))||((a0 == b0)&&(a1 == b2)&&(a2 ==b1))\
610 || ((a0 == b1)&&(a1 == b0)&&(a2 ==b2)) || ((a0 == b1)&&(a1 == b2)&&(a2 ==b0)) \
611 || ((a0 == b2)&&(a1 == b0)&&(a2 ==b1)) || ((a0 == b2)&&(a1 == b1)&&(a2 ==b0)) )){
612 if ( !mmgErr3 ) {
613 fprintf(stderr,"\n ## Warning: %s: Inconsistent faces : tetra %" MMG5_PRId " face %d;"
614 " tetra %" MMG5_PRId " face %i \n",__func__,MMG3D_indElt(mesh,k),i,
615 MMG3D_indElt(mesh,adj),voy);
616 fprintf(stderr,"Tet 1 : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",MMG3D_indPt(mesh,a0),
618 fprintf(stderr,"Tet 2 : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",MMG3D_indPt(mesh,b0),
620 mmgErr3 = 1;
621 }
622 return 0;
623 }
624 }
625 }
626
627 /* This test may have to be disactivated : check wether boundary faces (i.e. no neighbour)
628 arise only when a BDY face is hit */
629 for(k=1;k<=mesh->ne;k++){
630 pt = &mesh->tetra[k];
631 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
632 adja = &mesh->adja[4*(k-1)+1];
633 for(i=0;i<4;i++){
634 if(!adja[i]){
635 if(!pt->xt){
636 if ( !mmgErr4 ) {
637 mmgErr4 = 1;
638 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId ": boundary face"
639 " not tagged: %d \n",__func__,MMG3D_indElt(mesh,k),i);
640 }
641 return 0;
642 }
643 else{
644 pxt = &mesh->xtetra[pt->xt];
645 if(!(pxt->ftag[i] & MG_BDY)){
646 if ( !mmgErr4 ) {
647 mmgErr4 = 1;
648 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId ": boundary face"
649 " not tagged : %d \n",__func__,MMG3D_indElt(mesh,k),i);
650 }
651 return 0;
652 }
653 }
654 }
655 }
656 }
657
658 /* Case of an implicit surface embedded in mesh : check whether a face separating two
659 different subdomains is tagged bdy */
660 for(k=1; k<=mesh->ne; k++){
661 pt = &mesh->tetra[k];
662 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
663
664 adja = &mesh->adja[4*(k-1)+1];
665 for(i=0; i<4; i++){
666 if(!adja[i]) continue;
667 iel = adja[i] / 4;
668 pt1 = &mesh->tetra[iel];
669
670 if(pt->ref != pt1->ref){
671 if(!pt->xt){
672 if ( !mmgErr5 ) {
673 mmgErr5 = 1;
674 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId " face %d: common"
675 " face is a limit of two subdomains"
676 " and has not xt : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",__func__,
677 MMG3D_indElt(mesh,k),i,
678 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][0]]),
679 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][1]]),
680 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][2]]));
681 }
682 return 0;
683 }
684 else{
685 pxt = &mesh->xtetra[pt->xt];
686 if(!(pxt->ftag[i] & MG_BDY)){
687 if ( !mmgErr5 ) {
688 mmgErr5 = 1;
689 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId " %d : common"
690 " face is a limit of two subdomains"
691 " and is not tagged %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " -->%d\n",__func__,
692 MMG3D_indElt(mesh,k),i,
693 MMG3D_indElt(mesh,pt->v[MMG5_idir[i][0]]),
694 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][1]]),
695 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][2]]), pxt->ftag[i]);
696 }
697 return 0;
698 }
699 }
700 }
701 }
702 }
703 return 1;
704}
705
714 MMG5_pTetra pt;
715 MMG5_pxTetra pxt;
716 MMG5_pPoint p0;
717 MMG5_int k;
718 int8_t i,j,ip;
719 static int8_t mmgWarn0=0,mmgWarn1=0;
720
721 for(k=1;k<=mesh->np;k++)
722 mesh->point[k].flag = 0;
723
724 /* Put flag = 1 at each point belonging to a boundary face */
725 for(k=1; k<=mesh->ne; k++){
726 pt = &mesh->tetra[k];
727 if(!MG_EOK(pt)) continue;
728 if(!pt->xt) continue;
729 pxt = &mesh->xtetra[pt->xt];
730 for(i=0; i<4; i++){
731 if(!(pxt->ftag[i] & MG_BDY)) continue;
732 for(j=0; j<3; j++){
733 ip = MMG5_idir[i][j];
734 if(pt->v[ip] == np) {
735 if ( !mmgWarn0 ) {
736 mmgWarn0 = 1;
737 fprintf(stderr,"\n ## Error: %s: point %" MMG5_PRId " on face %d of tetra %" MMG5_PRId " :"
738 " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",__func__, MMG3D_indPt(mesh,pt->v[ip]),i,
739 MMG3D_indElt(mesh,k), MMG3D_indPt(mesh,pt->v[0]),
740 MMG3D_indPt(mesh,pt->v[1]),
741 MMG3D_indPt(mesh,pt->v[2]), MMG3D_indPt(mesh,pt->v[3]));
742 }
743 }
744 p0 = &mesh->point[pt->v[ip]];
745 p0->flag = 1;
746 }
747 }
748 }
749
750
751 /* Make sure that all the remaining points are not tagged BDY */
752 for(k=1; k<=mesh->np; k++){
753 p0 = &mesh->point[k];
754 if(!MG_VOK(p0)) continue;
755 if(p0->flag) continue;
756 if(p0->tag & MG_BDY){
757 if ( !mmgWarn1 ) {
758 mmgWarn1 = 1;
759 fprintf(stderr,"\n ## Error: %s: point %" MMG5_PRId " tagged bdy while belonging to no BDY face\n",
760 __func__,MMG3D_indPt(mesh,k));
761 }
762 return 0;
763 }
764 }
765
766 return 1;
767}
768
775int MMG5_cntbdypt(MMG5_pMesh mesh, MMG5_int nump){
776 MMG5_pTetra pt;
777 MMG5_pxTetra pxt;
778 MMG5_int k,v0,v1,v2;
779 int nf;
780 int8_t i,j,ip;
781 static int8_t mmgWarn0 = 0;
782
783 nf = 0;
784
785 for(k=1; k<=mesh->ne;k++){
786 pt = &mesh->tetra[k];
787 if(!MG_EOK(pt)) continue;
788 if(!pt->xt) continue;
789 pxt = &mesh->xtetra[pt->xt];
790 for(i=0; i<4; i++){
791 if(!(pxt->ftag[i] & MG_BDY)) continue;
792 for(j=0; j<3; j++){
793 ip = MMG5_idir[i][j];
794 if(pt->v[ip] == nump){
795 if ( !mmgWarn0 ) {
796 mmgWarn0 = 1;
797 v0 = pt->v[MMG5_idir[i][0]];
798 v1 = pt->v[MMG5_idir[i][0]];
799 v2 = pt->v[MMG5_idir[i][0]];
800
801 fprintf(stderr,"\n ## Error: %s: face %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " in tetra : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",
802 __func__,MMG3D_indPt(mesh,v0),MMG3D_indPt(mesh,v1),
803 MMG3D_indPt(mesh,v2),
804 MMG3D_indPt(mesh,pt->v[0]),MMG3D_indPt(mesh,pt->v[1]),
805 MMG3D_indPt(mesh,pt->v[2]),MMG3D_indPt(mesh,pt->v[3]));
806 }
807 nf++;
808 }
809 }
810 }
811 }
812 return nf;
813}
814
825 MMG5_pTetra pt,pt1;
826 MMG5_pxTetra pxt;
827 MMG5_pPoint p0,p1;
828 MMG5_int k,ntet,ned,np,np1,ischk,npchk,iel;
829 int64_t list[MMG3D_LMAX+2];
830 int nf,ilist,l;
831 int8_t i0,j,i,i1,ia,ier;
832
833 ntet = ned = 0;
834 for(k=1; k<=mesh->np; k++)
835 mesh->point[k].flag = 0;
836
837 /* Count elements with at least two boundary faces */
838 for (k=1; k<=mesh->ne; k++) {
839 pt = &mesh->tetra[k];
840 if ( !MG_EOK(pt) ) continue;
841 else if ( !pt->xt ) continue;
842 pxt = &mesh->xtetra[pt->xt];
843
844 nf = 0;
845 for (i=0; i<4; i++) {
846 if ( pxt->ftag[i] & MG_BDY ) nf++;
847 }
848 if ( nf >= 2 ) ntet++;
849 }
850 if ( mesh->info.imprim > 0 && ntet )
851 printf(" *** %" MMG5_PRId " tetras with at least 2 boundary faces.\n",ntet);
852
853 /* Count internal edges connecting two points of the boundary */
854 for (k=1; k<=mesh->ne; k++) {
855 pt = &mesh->tetra[k];
856 if ( !MG_EOK(pt) ) continue;
857
858 for (i=0; i<4; i++) {
859 np = pt->v[i];
860 p0 = &mesh->point[np];
861 if ( !(p0->tag & MG_BDY) ) continue;
862
863 ischk = p0->flag % 2;
864 if ( ischk ) continue;
865 p0->flag += 1;
866
867 ilist = MMG5_boulevolp(mesh,k,i,list);
868 for (l=0; l<ilist; l++) {
869 iel = list[l] / 4;
870 i0 = list[l] % 4;
871 i1 = i0;
872
873 pt1 = &mesh->tetra[iel];
874 for (j=0; j<3; j++) {
875 i1 = MMG5_inxt3[i1];
876 np1 = pt1->v[i1];
877 if ( np1 < np ) continue;
878 p1 = &mesh->point[np1];
879 if ( !(p1->tag & MG_BDY) ) continue;
880
881 ischk = p1->flag % 2;
882 npchk = p1->flag / 2;
883 if ( npchk == np ) continue;
884
885 ia = IEDG(i0,i1);
886 p1->flag = 2*np + ischk;
887
888 ier = MMG5_srcbdy(mesh,iel,ia);
889 if ( ier<0 ) return 0;
890 else if ( !ier ) ned++;
891 }
892 }
893 }
894 }
895 if ( mesh->info.imprim > 0 && ned )
896 printf(" *** %" MMG5_PRId " internal edges connecting boundary points.\n",ned);
897 return 1;
898}
899
907int srcface(MMG5_pMesh mesh,MMG5_int n0,MMG5_int n1,MMG5_int n2) {
908 MMG5_pTetra pt;
909 MMG5_pxTetra pxt;
910 MMG5_int ref,minn,maxn,sn,k,ip0,ip1,ip2,mins,maxs,sum;
911 uint16_t tag;
912 int8_t i;
913 static int8_t mmgWarn0 = 0;
914
915 minn = MG_MIN(n0,MG_MIN(n1,n2));
916 maxn = MG_MAX(n0,MG_MAX(n1,n2));
917 sn = n0 + n1 + n2;
918 pxt = 0;
919
920 for(k=1; k<=mesh->ne; k++) {
921 pt = &mesh->tetra[k];
922 if( !MG_EOK(pt) ) continue;
923
924 if( pt->xt ) pxt = &mesh->xtetra[pt->xt];
925 for(i=0; i<4; i++) {
926 ip0 = pt->v[MMG5_idir[i][0]];
927 ip1 = pt->v[MMG5_idir[i][1]];
928 ip2 = pt->v[MMG5_idir[i][2]];
929
930 mins = MG_MIN(ip0,MG_MIN(ip1,ip2));
931 maxs = MG_MAX(ip0,MG_MAX(ip1,ip2));
932 sum = ip0 + ip1 + ip2;
933 tag = pt->xt ? pxt->ftag[i] : 0;
934 ref = pt->xt ? pxt->ref[i] : 0;
935
936 if( mins == minn && maxs == maxn && sum == sn ) {
937 if ( !mmgWarn0 ) {
938 mmgWarn0 = 1;
939 fprintf(stderr,"\n ## Error: %s: Face %d in tetra %" MMG5_PRId " with ref %" MMG5_PRId ":"
940 " corresponding ref %" MMG5_PRId " , tag: %d\n",__func__,i,
941 MMG3D_indElt(mesh,k),pt->ref,ref,tag);
942 }
943 }
944 }
945 }
946
947
948 return 1;
949}
int ier
MMG5_pMesh * mesh
int MMG5_boulevolp(MMG5_pMesh mesh, MMG5_int start, int ip, int64_t *list)
Given a vertex and a tetrahedron, find all tetrahedra in the ball of this vertex.
Definition: boulep_3d.c:57
int MMG3D_findEdge(MMG5_pMesh mesh, MMG5_pTetra pt, MMG5_int k, MMG5_int na, MMG5_int nb, int error, int8_t *mmgWarn, int8_t *ia)
Definition: boulep_3d.c:116
int MMG5_srcbdy(MMG5_pMesh mesh, MMG5_int start, int ia)
Definition: boulep_3d.c:1557
int MMG5_coquilface(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int ia, int64_t *list, MMG5_int *it1, MMG5_int *it2, int silent)
Definition: boulep_3d.c:1846
int MMG3D_chk_shellEdgeTag(MMG5_pMesh mesh, MMG5_int start, int8_t ia, uint16_t tag, MMG5_int ref)
Definition: chkmsh_3d.c:142
int srcface(MMG5_pMesh mesh, MMG5_int n0, MMG5_int n1, MMG5_int n2)
Definition: chkmsh_3d.c:907
void MMG3D_chkfacetags(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:323
static int MMG3D_chkcoquilface(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:466
static void MMG3D_consistency_error_message(MMG5_pMesh mesh, MMG5_pPoint ppt, MMG5_int k, int i, MMG5_int ip1, MMG5_int ip2)
Definition: chkmsh_3d.c:354
int MMG5_chkmshsurf(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:432
int MMG5_chkfemtopo(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:824
int MMG5_mmg3dChkmsh(MMG5_pMesh mesh, int severe, MMG5_int base)
Definition: chkmsh_3d.c:508
#define IEDG(a, b)
Definition: chkmsh_3d.c:40
void MMG3D_chkmeshedgestags(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:200
int MMG5_chkptonbdy(MMG5_pMesh mesh, MMG5_int np)
Definition: chkmsh_3d.c:713
static int MMG3D_chk_shellEdgeTag_oneDir(MMG5_pMesh mesh, MMG5_int start, MMG5_int na, MMG5_int nb, uint16_t tag, MMG5_int ref, MMG5_int piv, MMG5_int adj)
Definition: chkmsh_3d.c:92
void MMG3D_chkedgetag(MMG5_pMesh mesh, MMG5_int ip1, MMG5_int ip2, int tag)
Definition: chkmsh_3d.c:290
int MMG5_cntbdypt(MMG5_pMesh mesh, MMG5_int nump)
Definition: chkmsh_3d.c:775
int8_t ddb
Definition: mmg3d1_delone.c:42
void MMG5_chkvol(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:51
void MMG3D_chkpointtag(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:383
int MMG5_hEdge(MMG5_pMesh mesh, MMG5_HGeom *hash, MMG5_int a, MMG5_int b, MMG5_int ref, uint16_t tag)
Definition: hash_3d.c:1040
int MMG5_hGet(MMG5_HGeom *hash, MMG5_int a, MMG5_int b, MMG5_int *ref, uint16_t *tag)
Definition: hash_3d.c:1007
int MMG5_hNew(MMG5_pMesh mesh, MMG5_HGeom *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash_3d.c:1083
API headers and documentation for the mmg3d library, for volumetric meshes in 3D.
#define MMG3D_LMAX
Definition: libmmg3d.h:130
MMG5_int MMG3D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_3d.c:918
static const int8_t MMG5_iarf[4][3]
iarf[i]: edges of face opposite to vertex i
static const uint8_t MMG5_iare[6][2]
vertices of extremities of the edges of the tetra
static const uint8_t MMG5_ifar[6][2]
ifar[i][]: faces sharing the ith edge of the tetra
static const uint8_t MMG5_inxt3[7]
next vertex of tetra: {1,2,3,0,1,2,3}
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel)
Definition: tools_3d.c:862
#define MG_REQ
#define MG_GEO
#define MG_EOK(pt)
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MG_EDG(tag)
#define MG_OLDPARBDY
#define MG_EDG_OR_NOM(tag)
#define MG_SIN(tag)
#define MMG5_NULKAL
#define MG_VOK(ppt)
#define MG_CRN
double MMG5_orvol(MMG5_pPoint point, MMG5_int *v)
Definition: tools.c:951
#define MG_BDY
#define MG_NOM
#define MG_SIN_OR_NOM(tag)
#define MMG5_DEL_MEM(mesh, ptr)
Hash table to store geometric edges.
Definition: libmmgtypes.h:582
MMG5_hgeom * geom
Definition: libmmgtypes.h:583
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_int ne
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_pTetra tetra
Definition: libmmgtypes.h:651
MMG5_int nt
Definition: libmmgtypes.h:620
MMG5_pTria tria
Definition: libmmgtypes.h:655
MMG5_int np
Definition: libmmgtypes.h:620
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:652
MMG5_int * adjt
Definition: libmmgtypes.h:636
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
uint16_t tag
Definition: libmmgtypes.h:290
MMG5_int flag
Definition: libmmgtypes.h:288
Structure to store tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:407
MMG5_int v[4]
Definition: libmmgtypes.h:409
MMG5_int xt
Definition: libmmgtypes.h:413
MMG5_int ref
Definition: libmmgtypes.h:410
uint16_t tag
Definition: libmmgtypes.h:417
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
uint16_t tag[3]
Definition: libmmgtypes.h:348
Structure to store additional information for the surface tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:425
uint16_t tag[6]
Definition: libmmgtypes.h:432
MMG5_int edg[6]
Definition: libmmgtypes.h:428
MMG5_int ref[4]
Definition: libmmgtypes.h:426
uint16_t ftag[4]
Definition: libmmgtypes.h:430