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 int16_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,int16_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
202 MMG5_pTetra pt;
203 MMG5_pxTetra pxt;
204 MMG5_Hash hash;
205 int i,tag;
206 MMG5_int k,nt,ip1,ip2;
207
208 /* Rough eval of the number of boundary triangles */
209 nt = 0;
210 for (k=1; k<=mesh->ne; k++) {
211 pt = &mesh->tetra[k];
212 if ( !MG_EOK(pt) ) continue;
213 if ( !pt->xt ) continue;
214
215 pxt = &mesh->xtetra[pt->xt];
216 for (i=0; i<4; i++) {
217 if ( pxt->ftag[i] & MG_BDY ) {
218 ++nt;
219 }
220 }
221 }
222 nt = nt/2 + 1;
223
224 /* Travel mesh edges and hash boundary ones */
225 MMG5_hashNew(mesh,&hash,nt,3*nt);
226
227 for (k=1; k<=mesh->ne; k++) {
228 pt = &mesh->tetra[k];
229 if ( !MG_EOK(pt) ) continue;
230 if ( !pt->xt ) continue;
231
232 pxt = &mesh->xtetra[pt->xt];
233 for (i=0; i<6; i++) {
234 if ( pxt->tag[i] & MG_BDY ) {
235 ip1 = pt->v[MMG5_iare[i][0]];
236 ip2 = pt->v[MMG5_iare[i][1]];
237 tag = MMG5_hashEdgeTag ( mesh,&hash,ip1,ip2,pxt->tag[i]);
238 if ( tag != pxt->tag[i] ) {
239 fprintf(stderr,"Error: %s: %d: Non consistency at tet %" MMG5_PRId " (%" MMG5_PRId "), edge %d:%" MMG5_PRId "--%" MMG5_PRId "\n ",
240 __func__,__LINE__,k,MMG3D_indElt(mesh,k),i,ip1,ip2);
241 assert( tag == pxt->tag[i] && "edge tag error" );
242 }
243 }
244 }
245 }
246 MMG5_DEL_MEM(mesh,hash.item);
247}
248
249
261void MMG3D_chkedgetag(MMG5_pMesh mesh, MMG5_int ip1, MMG5_int ip2, int tag) {
262 MMG5_pTetra pt;
263 MMG5_pxTetra pxt;
264 MMG5_int k,i1,i2;
265 int i;
266
267 for (k=1; k<=mesh->ne; k++) {
268 pt = &mesh->tetra[k];
269 if ( !MG_EOK(pt) ) continue;
270 if ( !pt->xt ) continue;
271
272 pxt = &mesh->xtetra[pt->xt];
273 for (i=0; i<6; i++) {
274 i1 = pt->v[MMG5_iare[i][0]];
275 i2 = pt->v[MMG5_iare[i][1]];
276
277 if ( ((i1==ip1) && (i2==ip2)) || ((i2==ip1) && (i1==ip2)) ) {
278 if ( pxt->tag[i] != tag ) {
279 fprintf(stderr,"Error: %s: %d: Non consistency at tet %" MMG5_PRId " (%" MMG5_PRId "), edge %d\n ",
280 __func__,__LINE__,k,MMG3D_indElt(mesh,k),i);
281 assert(0);
282 }
283 }
284 }
285 }
286}
287
299static inline
300void MMG3D_consistency_error_message(MMG5_pMesh mesh,MMG5_pPoint ppt,MMG5_int k,int i,MMG5_int ip1,MMG5_int ip2) {
301
302 assert ( mesh->tetra && "no tetra array");
303 MMG5_pTetra pt = &mesh->tetra[k];
304
305 assert ( pt->xt && "no xtetra");
306 MMG5_pxTetra pxt = &mesh->xtetra[pt->xt];
307
308 fprintf(stderr,"Error: %s: %d: Tag error at point %" MMG5_PRId " (%" MMG5_PRId "), "
309 "tetra %" MMG5_PRId " (%" MMG5_PRId "), edge %d:%" MMG5_PRId "--%" MMG5_PRId " (%" MMG5_PRId
310 "--%" MMG5_PRId ").\n",__func__,__LINE__,
311 ip1,MMG3D_indPt(mesh,ip1),k,MMG3D_indElt(mesh,k),i,ip1,ip2,
312 MMG3D_indPt(mesh,ip1),MMG3D_indPt(mesh,ip2));
313 fprintf(stderr," point tag: %d; edge tag: %d\n",ppt->tag,pxt->tag[i]);
314
317 MMG3D_chkedgetag(mesh,ip1,ip2,pxt->tag[i]);
318 assert(0);
319}
320
330 MMG5_pTetra pt;
331 MMG5_pxTetra pxt;
332 MMG5_pPoint p1,p2;
333 int i,i1,i2;
334 MMG5_int k,ip1,ip2;
335
337 for (k=1; k<=mesh->ne; k++) {
338 pt = &mesh->tetra[k];
339 if ( !MG_EOK(pt) ) continue;
340 if ( !pt->xt ) continue;
341
342 pxt = &mesh->xtetra[pt->xt];
343
344 for ( i=0; i<6; ++i ) {
345 i1 = MMG5_iare[i][0];
346 i2 = MMG5_iare[i][1];
347 ip1 = pt->v[i1];
348 ip2 = pt->v[i2];
349 p1 = &mesh->point[ip1];
350 p2 = &mesh->point[ip2];
351
352 if ( MG_EDG(pxt->tag[i]) ) {
353 if ( !(MG_EDG(p1->tag) || MG_SIN(p1->tag)) ) {
355 }
356 if ( !(MG_EDG(p2->tag) || MG_SIN(p2->tag)) ) {
358 }
359 }
360
361 if ( pxt->tag[i] & MG_NOM ) {
362 if ( !MG_SIN_OR_NOM(p1->tag) ) {
364 }
365 if ( !MG_SIN_OR_NOM(p2->tag) ) {
367 }
368 }
369 }
370 }
371}
372
379 MMG5_pTria pt;
380 MMG5_int k,k1;
381 MMG5_int *adja,*adja1;
382 int8_t i,voy;
383
384 for (k=1; k<=mesh->nt; k++) {
385 pt = &mesh->tria[k];
386 adja = &mesh->adjt[3*(k-1)+1];
387 for (i=0; i<3; i++) {
388 if ( pt->tag[i] & MG_NOM ) continue;
389 k1 = adja[i] / 3;
390 voy = adja[i] % 3;
391
392 if(!k1) continue;
393 adja1 = &mesh->adjt[3*(k1-1)+1];
394
395 if(adja1[voy] / 3 != k){
396 fprintf(stderr,"\n ## Warning: %s: wrong adjacency relation"
397 " for triangles : %" MMG5_PRId " %" MMG5_PRId " \n",__func__,k,k1);
398 return 0;
399 }
400 }
401 }
402 return 1;
403}
404
411static inline
413 MMG5_pTetra pt;
414 MMG5_pxTetra pxt;
415 MMG5_int k,it1,it2;
416 int64_t list[MMG3D_LMAX+2];
417 int i,j,ret;
418 int8_t ia;
419
420 for (k=1; k<=mesh->ne; k++) {
421 pt = &mesh->tetra[k];
422 if ( (!MG_EOK(pt)) || pt->ref < 0 || (pt->tag & MG_REQ) ) continue;
423 else if ( !pt->xt ) continue;
424 pxt = &mesh->xtetra[pt->xt];
425
426 for (i=0; i<4; i++) {
427 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
428 for (j=0; j<3; j++) {
429 ia = MMG5_iarf[i][j];
430
431 /* No check for geom edge (I am not sure that it can works) */
432 if ( MG_EDG_OR_NOM(pxt->tag[ia]) || (pxt->tag[ia] & MG_REQ) )
433 {
434 continue;
435 }
436
437 ret = MMG5_coquilface(mesh,k,i,ia,list,&it1,&it2,0);
438 if ( ret < 0 ) return 0;
439 }
440 }
441 }
442 return 1;
443}
444
454int MMG5_mmg3dChkmsh(MMG5_pMesh mesh,int severe,MMG5_int base) {
455 MMG5_pTetra pt,pt1,pt2;
456 MMG5_pxTetra pxt;
457 MMG5_int *adja,*adja1,adj,adj1,k,iadr,iel;
458 MMG5_int a0,a1,a2,b0,b1,b2;
459 int i;
460 uint8_t voy,voy1;
461 static int8_t mmgErr0=0,mmgErr1=0,mmgErr2=0,mmgErr3=0,mmgErr4=0,mmgErr5=0;
462
463 /* Check edge tag consistency (between xtetra) */
465
466 /* Check point tags consistency with edge tag */
468
469 if ( !mesh->adja ) return 1;
470
471 /* Check edge tag consistency with number of boundary faces in the edge shell */
473
474 for (k=1; k<=mesh->ne; k++) {
475 pt1 = &mesh->tetra[k];
476 if ( !MG_EOK(pt1) || pt1->ref < 0 ) continue;
477 iadr = 4*(k-1) + 1;
478 adja = &mesh->adja[iadr];
479
480 for (i=0; i<4; i++) {
481 adj = adja[i];
482
483 if ( !adj ) continue;
484 adj /= 4;
485 voy = adja[i] % 4;
486
487 if ( adj == k ) {
488 if ( !mmgErr0 ) {
489 fprintf(stderr,"\n ## Error: %s: 1. at least 1 wrong adjacency %" MMG5_PRId " %" MMG5_PRId "\n",
490 __func__,MMG3D_indElt(mesh,k),MMG3D_indElt(mesh,adj));
491 fprintf(stderr,"triangle %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
492 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
493 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
494 fprintf(stderr,"adj (%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
495 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
496 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
497 mmgErr0 = 1;
498 }
499 return 0;
500 }
501 pt2 = &mesh->tetra[adj];
502 if ( !MG_EOK(pt2) || pt2->ref < 0 ){
503 if ( !mmgErr1 ) {
504 fprintf(stderr,"\n ## Error: %s: 4. at least 1 invalid adjacent %" MMG5_PRId " %" MMG5_PRId "\n",
505 __func__,MMG3D_indElt(mesh,adj),MMG3D_indElt(mesh,k));
506 fprintf(stderr,"vertices of k %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
507 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
508 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
509 fprintf(stderr,"vertices of adj %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
510 MMG3D_indPt(mesh,pt2->v[0]),MMG3D_indPt(mesh,pt2->v[1]),
511 MMG3D_indPt(mesh,pt2->v[2]),MMG3D_indPt(mesh,pt2->v[3]));
512 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
513 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
514 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
515 mmgErr1 = 1;
516 }
517 return 0;
518 }
519 iadr = (adj-1)*4 + 1;
520 adja1 = &mesh->adja[iadr];
521 adj1 = adja1[voy] / 4;
522 voy1 = adja1[voy] % 4;
523 if ( adj1 != k || voy1 != i ) {
524 if ( !mmgErr2 ) {
525 fprintf(stderr,"\n ## Error: %s: 2. at least 1 wrong adjacency %" MMG5_PRId " %" MMG5_PRId "\n",
526 __func__,MMG3D_indElt(mesh,k),MMG3D_indElt(mesh,adj1));
527 fprintf(stderr,"vertices of %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
528 MMG3D_indPt(mesh,pt1->v[0]),MMG3D_indPt(mesh,pt1->v[1]),
529 MMG3D_indPt(mesh,pt1->v[2]),MMG3D_indPt(mesh,pt1->v[3]));
530 fprintf(stderr,"vertices of adj %" MMG5_PRId ": %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
531 MMG3D_indPt(mesh,pt2->v[0]),MMG3D_indPt(mesh,pt2->v[1]),
532 MMG3D_indPt(mesh,pt2->v[2]),MMG3D_indPt(mesh,pt2->v[3]));
533 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,k),
534 MMG3D_indElt(mesh,adja[0]/4),MMG3D_indElt(mesh,adja[1]/4),
535 MMG3D_indElt(mesh,adja[2]/4),MMG3D_indElt(mesh,adja[3]/4));
536 fprintf(stderr,"adj(%" MMG5_PRId "): %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",MMG3D_indElt(mesh,adj),
537 MMG3D_indElt(mesh,adja1[0]/4),MMG3D_indElt(mesh,adja1[1]/4),
538 MMG3D_indElt(mesh,adja1[2]/4),MMG3D_indElt(mesh,adja1[3]/4));
539 mmgErr2 = 1;
540 }
541 return 0;
542 }
543
544 a0 = pt1->v[MMG5_idir[i][0]];
545 a1 = pt1->v[MMG5_idir[i][1]];
546 a2 = pt1->v[MMG5_idir[i][2]];
547
548 b0 = pt2->v[MMG5_idir[voy][0]];
549 b1 = pt2->v[MMG5_idir[voy][1]];
550 b2 = pt2->v[MMG5_idir[voy][2]];
551
552 if(!(((a0 == b0)&&(a1 == b1)&&(a2 ==b2))||((a0 == b0)&&(a1 == b2)&&(a2 ==b1))\
553 || ((a0 == b1)&&(a1 == b0)&&(a2 ==b2)) || ((a0 == b1)&&(a1 == b2)&&(a2 ==b0)) \
554 || ((a0 == b2)&&(a1 == b0)&&(a2 ==b1)) || ((a0 == b2)&&(a1 == b1)&&(a2 ==b0)) )){
555 if ( !mmgErr3 ) {
556 fprintf(stderr,"\n ## Warning: %s: Inconsistent faces : tetra %" MMG5_PRId " face %d;"
557 " tetra %" MMG5_PRId " face %i \n",__func__,MMG3D_indElt(mesh,k),i,
558 MMG3D_indElt(mesh,adj),voy);
559 fprintf(stderr,"Tet 1 : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",MMG3D_indPt(mesh,a0),
561 fprintf(stderr,"Tet 2 : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",MMG3D_indPt(mesh,b0),
563 mmgErr3 = 1;
564 }
565 return 0;
566 }
567 }
568 }
569
570 /* This test may have to be disactivated : check wether boundary faces (i.e. no neighbour)
571 arise only when a BDY face is hit */
572 for(k=1;k<=mesh->ne;k++){
573 pt = &mesh->tetra[k];
574 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
575 adja = &mesh->adja[4*(k-1)+1];
576 for(i=0;i<4;i++){
577 if(!adja[i]){
578 if(!pt->xt){
579 if ( !mmgErr4 ) {
580 mmgErr4 = 1;
581 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId ": boundary face"
582 " not tagged: %d \n",__func__,MMG3D_indElt(mesh,k),i);
583 }
584 return 0;
585 }
586 else{
587 pxt = &mesh->xtetra[pt->xt];
588 if(!(pxt->ftag[i] & MG_BDY)){
589 if ( !mmgErr4 ) {
590 mmgErr4 = 1;
591 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId ": boundary face"
592 " not tagged : %d \n",__func__,MMG3D_indElt(mesh,k),i);
593 }
594 return 0;
595 }
596 }
597 }
598 }
599 }
600
601 /* Case of an implicit surface embedded in mesh : check whether a face separating two
602 different subdomains is tagged bdy */
603 for(k=1; k<=mesh->ne; k++){
604 pt = &mesh->tetra[k];
605 if ( !MG_EOK(pt) || pt->ref < 0 ) continue;
606
607 adja = &mesh->adja[4*(k-1)+1];
608 for(i=0; i<4; i++){
609 if(!adja[i]) continue;
610 iel = adja[i] / 4;
611 pt1 = &mesh->tetra[iel];
612
613 if(pt->ref != pt1->ref){
614 if(!pt->xt){
615 if ( !mmgErr5 ) {
616 mmgErr5 = 1;
617 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId " face %d: common"
618 " face is a limit of two subdomains"
619 " and has not xt : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",__func__,
620 MMG3D_indElt(mesh,k),i,
621 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][0]]),
622 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][1]]),
623 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][2]]));
624 }
625 return 0;
626 }
627 else{
628 pxt = &mesh->xtetra[pt->xt];
629 if(!(pxt->ftag[i] & MG_BDY)){
630 if ( !mmgErr5 ) {
631 mmgErr5 = 1;
632 fprintf(stderr,"\n ## Error: %s: Tetra %" MMG5_PRId " %d : common"
633 " face is a limit of two subdomains"
634 " and is not tagged %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " -->%d\n",__func__,
635 MMG3D_indElt(mesh,k),i,
636 MMG3D_indElt(mesh,pt->v[MMG5_idir[i][0]]),
637 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][1]]),
638 MMG3D_indPt(mesh,pt->v[MMG5_idir[i][2]]), pxt->ftag[i]);
639 }
640 return 0;
641 }
642 }
643 }
644 }
645 }
646 return 1;
647}
648
657 MMG5_pTetra pt;
658 MMG5_pxTetra pxt;
659 MMG5_pPoint p0;
660 MMG5_int k;
661 int8_t i,j,ip;
662 static int8_t mmgWarn0=0,mmgWarn1=0;
663
664 for(k=1;k<=mesh->np;k++)
665 mesh->point[k].flag = 0;
666
667 /* Put flag = 1 at each point belonging to a boundary face */
668 for(k=1; k<=mesh->ne; k++){
669 pt = &mesh->tetra[k];
670 if(!MG_EOK(pt)) continue;
671 if(!pt->xt) continue;
672 pxt = &mesh->xtetra[pt->xt];
673 for(i=0; i<4; i++){
674 if(!(pxt->ftag[i] & MG_BDY)) continue;
675 for(j=0; j<3; j++){
676 ip = MMG5_idir[i][j];
677 if(pt->v[ip] == np) {
678 if ( !mmgWarn0 ) {
679 mmgWarn0 = 1;
680 fprintf(stderr,"\n ## Error: %s: point %" MMG5_PRId " on face %d of tetra %" MMG5_PRId " :"
681 " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",__func__, MMG3D_indPt(mesh,pt->v[ip]),i,
682 MMG3D_indElt(mesh,k), MMG3D_indPt(mesh,pt->v[0]),
683 MMG3D_indPt(mesh,pt->v[1]),
684 MMG3D_indPt(mesh,pt->v[2]), MMG3D_indPt(mesh,pt->v[3]));
685 }
686 }
687 p0 = &mesh->point[pt->v[ip]];
688 p0->flag = 1;
689 }
690 }
691 }
692
693
694 /* Make sure that all the remaining points are not tagged BDY */
695 for(k=1; k<=mesh->np; k++){
696 p0 = &mesh->point[k];
697 if(!MG_VOK(p0)) continue;
698 if(p0->flag) continue;
699 if(p0->tag & MG_BDY){
700 if ( !mmgWarn1 ) {
701 mmgWarn1 = 1;
702 fprintf(stderr,"\n ## Error: %s: point %" MMG5_PRId " tagged bdy while belonging to no BDY face\n",
703 __func__,MMG3D_indPt(mesh,k));
704 }
705 return 0;
706 }
707 }
708
709 return 1;
710}
711
718int MMG5_cntbdypt(MMG5_pMesh mesh, MMG5_int nump){
719 MMG5_pTetra pt;
720 MMG5_pxTetra pxt;
721 MMG5_int k,v0,v1,v2;
722 int nf;
723 int8_t i,j,ip;
724 static int8_t mmgWarn0 = 0;
725
726 nf = 0;
727
728 for(k=1; k<=mesh->ne;k++){
729 pt = &mesh->tetra[k];
730 if(!MG_EOK(pt)) continue;
731 if(!pt->xt) continue;
732 pxt = &mesh->xtetra[pt->xt];
733 for(i=0; i<4; i++){
734 if(!(pxt->ftag[i] & MG_BDY)) continue;
735 for(j=0; j<3; j++){
736 ip = MMG5_idir[i][j];
737 if(pt->v[ip] == nump){
738 if ( !mmgWarn0 ) {
739 mmgWarn0 = 1;
740 v0 = pt->v[MMG5_idir[i][0]];
741 v1 = pt->v[MMG5_idir[i][0]];
742 v2 = pt->v[MMG5_idir[i][0]];
743
744 fprintf(stderr,"\n ## Error: %s: face %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " in tetra : %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " \n",
745 __func__,MMG3D_indPt(mesh,v0),MMG3D_indPt(mesh,v1),
746 MMG3D_indPt(mesh,v2),
747 MMG3D_indPt(mesh,pt->v[0]),MMG3D_indPt(mesh,pt->v[1]),
748 MMG3D_indPt(mesh,pt->v[2]),MMG3D_indPt(mesh,pt->v[3]));
749 }
750 nf++;
751 }
752 }
753 }
754 }
755 return nf;
756}
757
768 MMG5_pTetra pt,pt1;
769 MMG5_pxTetra pxt;
770 MMG5_pPoint p0,p1;
771 MMG5_int k,ntet,ned,np,np1,ischk,npchk,iel;
772 int64_t list[MMG3D_LMAX+2];
773 int nf,ilist,l;
774 int8_t i0,j,i,i1,ia,ier;
775
776 ntet = ned = 0;
777 for(k=1; k<=mesh->np; k++)
778 mesh->point[k].flag = 0;
779
780 /* Count elements with at least two boundary faces */
781 for (k=1; k<=mesh->ne; k++) {
782 pt = &mesh->tetra[k];
783 if ( !MG_EOK(pt) ) continue;
784 else if ( !pt->xt ) continue;
785 pxt = &mesh->xtetra[pt->xt];
786
787 nf = 0;
788 for (i=0; i<4; i++) {
789 if ( pxt->ftag[i] & MG_BDY ) nf++;
790 }
791 if ( nf >= 2 ) ntet++;
792 }
793 if ( mesh->info.imprim > 0 && ntet )
794 printf(" *** %" MMG5_PRId " tetras with at least 2 boundary faces.\n",ntet);
795
796 /* Count internal edges connecting two points of the boundary */
797 for (k=1; k<=mesh->ne; k++) {
798 pt = &mesh->tetra[k];
799 if ( !MG_EOK(pt) ) continue;
800
801 for (i=0; i<4; i++) {
802 np = pt->v[i];
803 p0 = &mesh->point[np];
804 if ( !(p0->tag & MG_BDY) ) continue;
805
806 ischk = p0->flag % 2;
807 if ( ischk ) continue;
808 p0->flag += 1;
809
810 ilist = MMG5_boulevolp(mesh,k,i,list);
811 for (l=0; l<ilist; l++) {
812 iel = list[l] / 4;
813 i0 = list[l] % 4;
814 i1 = i0;
815
816 pt1 = &mesh->tetra[iel];
817 for (j=0; j<3; j++) {
818 i1 = MMG5_inxt3[i1];
819 np1 = pt1->v[i1];
820 if ( np1 < np ) continue;
821 p1 = &mesh->point[np1];
822 if ( !(p1->tag & MG_BDY) ) continue;
823
824 ischk = p1->flag % 2;
825 npchk = p1->flag / 2;
826 if ( npchk == np ) continue;
827
828 ia = IEDG(i0,i1);
829 p1->flag = 2*np + ischk;
830
831 ier = MMG5_srcbdy(mesh,iel,ia);
832 if ( ier<0 ) return 0;
833 else if ( !ier ) ned++;
834 }
835 }
836 }
837 }
838 if ( mesh->info.imprim > 0 && ned )
839 printf(" *** %" MMG5_PRId " internal edges connecting boundary points.\n",ned);
840 return 1;
841}
842
850int srcface(MMG5_pMesh mesh,MMG5_int n0,MMG5_int n1,MMG5_int n2) {
851 MMG5_pTetra pt;
852 MMG5_pxTetra pxt;
853 MMG5_int ref,minn,maxn,sn,k,ip0,ip1,ip2,mins,maxs,sum;
854 int16_t tag;
855 int8_t i;
856 static int8_t mmgWarn0 = 0;
857
858 minn = MG_MIN(n0,MG_MIN(n1,n2));
859 maxn = MG_MAX(n0,MG_MAX(n1,n2));
860 sn = n0 + n1 + n2;
861 pxt = 0;
862
863 for(k=1; k<=mesh->ne; k++) {
864 pt = &mesh->tetra[k];
865 if( !MG_EOK(pt) ) continue;
866
867 if( pt->xt ) pxt = &mesh->xtetra[pt->xt];
868 for(i=0; i<4; i++) {
869 ip0 = pt->v[MMG5_idir[i][0]];
870 ip1 = pt->v[MMG5_idir[i][1]];
871 ip2 = pt->v[MMG5_idir[i][2]];
872
873 mins = MG_MIN(ip0,MG_MIN(ip1,ip2));
874 maxs = MG_MAX(ip0,MG_MAX(ip1,ip2));
875 sum = ip0 + ip1 + ip2;
876 tag = pt->xt ? pxt->ftag[i] : 0;
877 ref = pt->xt ? pxt->ref[i] : 0;
878
879 if( mins == minn && maxs == maxn && sum == sn ) {
880 if ( !mmgWarn0 ) {
881 mmgWarn0 = 1;
882 fprintf(stderr,"\n ## Error: %s: Face %d in tetra %" MMG5_PRId " with ref %" MMG5_PRId ":"
883 " corresponding ref %" MMG5_PRId " , tag: %d\n",__func__,i,
884 MMG3D_indElt(mesh,k),pt->ref,ref,tag);
885 }
886 }
887 }
888 }
889
890
891 return 1;
892}
int ier
MMG5_pMesh * mesh
int MMG5_boulevolp(MMG5_pMesh mesh, MMG5_int start, int ip, int64_t *list)
Definition: boulep_3d.c:54
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:113
int MMG5_srcbdy(MMG5_pMesh mesh, MMG5_int start, int ia)
Definition: boulep_3d.c:1554
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:1843
static int MMG3D_chk_shellEdgeTag_oneDir(MMG5_pMesh mesh, MMG5_int start, MMG5_int na, MMG5_int nb, int16_t tag, MMG5_int ref, MMG5_int piv, MMG5_int adj)
Definition: chkmsh_3d.c:92
int srcface(MMG5_pMesh mesh, MMG5_int n0, MMG5_int n1, MMG5_int n2)
Definition: chkmsh_3d.c:850
static int MMG3D_chkcoquilface(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:412
int MMG3D_chk_shellEdgeTag(MMG5_pMesh mesh, MMG5_int start, int8_t ia, int16_t tag, MMG5_int ref)
Definition: chkmsh_3d.c:142
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:300
int MMG5_chkmshsurf(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:378
int MMG5_chkfemtopo(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:767
int MMG5_mmg3dChkmsh(MMG5_pMesh mesh, int severe, MMG5_int base)
Definition: chkmsh_3d.c:454
#define IEDG(a, b)
Definition: chkmsh_3d.c:40
void MMG3D_chkmeshedgestags(MMG5_pMesh mesh)
Definition: chkmsh_3d.c:201
int MMG5_chkptonbdy(MMG5_pMesh mesh, MMG5_int np)
Definition: chkmsh_3d.c:656
void MMG3D_chkedgetag(MMG5_pMesh mesh, MMG5_int ip1, MMG5_int ip2, int tag)
Definition: chkmsh_3d.c:261
int MMG5_cntbdypt(MMG5_pMesh mesh, MMG5_int nump)
Definition: chkmsh_3d.c:718
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:329
int MMG5_hashEdgeTag(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, int16_t tag)
Definition: hash.c:437
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:526
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
MMG5_int MMG3D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_3d.c:916
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:860
#define MG_REQ
#define MG_EOK(pt)
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MG_EDG(tag)
#define MG_EDG_OR_NOM(tag)
#define MG_SIN(tag)
#define MMG5_NULKAL
#define MG_VOK(ppt)
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)
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
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
MMG5_int * adjt
Definition: libmmgtypes.h:628
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
MMG5_int flag
Definition: libmmgtypes.h:282
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int ref
Definition: libmmgtypes.h:404
int16_t tag
Definition: libmmgtypes.h:410
int16_t tag[3]
Definition: libmmgtypes.h:342
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
MMG5_int edg[6]
Definition: libmmgtypes.h:421
MMG5_int ref[4]
Definition: libmmgtypes.h:419