Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
hash_2d.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#include "libmmg2d_private.h"
24
25#define KTA 7
26#define KTB 11
27
36 MMG5_pTria pt,pt1;
37 MMG5_int k,kk,pp,l,ll,mins,mins1,maxs,maxs1;
38 MMG5_int *hcode,*link,inival,hsize,iadr;
39 uint8_t i,ii,i1,i2;
40 unsigned int key;
41
42 if ( mesh->adja ) return 1;
43 if ( !mesh->nt ) return 1;
44
45 /* memory alloc */
46 MMG5_SAFE_CALLOC(hcode,mesh->nt+1,MMG5_int,return 0);
47
48 /* memory alloc */
49 MMG5_ADD_MEM(mesh,(3*mesh->ntmax+5)*sizeof(MMG5_int),"adjacency table",
50 printf(" Exit program.\n");
51 return 0;);
52 MMG5_SAFE_CALLOC(mesh->adja,3*mesh->ntmax+5,MMG5_int,return 0);
53
54 link = mesh->adja;
55 hsize = mesh->nt;
56
57 /* init */
58 inival = MMG5_INTMAX;
59
60 for (k=0; k<=mesh->nt; k++)
61 hcode[k] = -inival;
62
63 /* build hash table */
64 for (k=1; k<=mesh->nt; k++) {
65 pt = &mesh->tria[k];
66
67 if ( !pt->v[0] ) continue;
68 for (i=0; i<3; i++) {
69 i1 = MMG2D_idir[i+1];
70 i2 = MMG2D_idir[i+2];
71 if ( pt->v[i1] < pt->v[i2] ) {
72 mins = pt->v[i1];
73 maxs = pt->v[i2];
74 }
75 else {
76 mins = pt->v[i2];
77 maxs = pt->v[i1];
78 }
79
80 /* compute key */
81 key = (KTA*(int64_t)mins + KTB*(int64_t)maxs)%hsize+1;
82
83 /* insert */
84 iadr = 3*(k-1) + i+1;
85 link[iadr] = hcode[key];
86 hcode[key] = -iadr;
87 }
88 }
89
90 /* set adjacency */
91 for (l=3*mesh->nt; l>0; l--) {
92 if ( link[l] >= 0 ) continue;
93 k = (l-1) / 3 + 1;
94 i = (l-1) % 3;
95 i1 = MMG2D_idir[i+1];
96 i2 = MMG2D_idir[i+2];
97 pt = &mesh->tria[k];
98
99 mins = M_MIN(pt->v[i1],pt->v[i2]);
100 maxs = M_MAX(pt->v[i1],pt->v[i2]);
101
102 /* accross link */
103 ll = -link[l];
104 pp = 0;
105 link[l] = 0;
106
107 while ( ll != inival ) {
108 kk = (ll-1) / 3 + 1;
109 ii = (ll-1) % 3;
110 i1 = MMG2D_idir[ii+1];
111 i2 = MMG2D_idir[ii+2];
112 pt1 = &mesh->tria[kk];
113 if ( pt1->v[i1] < pt1->v[i2] ) {
114 mins1 = pt1->v[i1];
115 maxs1 = pt1->v[i2];
116 }
117 else {
118 mins1 = pt1->v[i2];
119 maxs1 = pt1->v[i1];
120 }
121
122 if ( mins1 == mins && maxs1 == maxs ) {
123 /* adjacent found */
124 if ( pp != 0 ) link[pp] = link[ll];
125 link[l] = 3*kk + ii;
126 link[ll]= 3*k + i;
127 break;
128 }
129 pp = ll;
130 ll = -link[ll];
131 }
132 }
133 MMG5_SAFE_FREE(hcode);
134
135 return 1;
136}
137
152 MMG5_pQuad pq,pq1;
153 MMG5_pTria pt;
154 MMG5_Hash hash;
155 MMG5_int k,kk,pp,l,ll,mins,mins1,maxs,maxs1,iadr;
156 MMG5_int *hcode,*link,hsize,inival;
157 uint8_t i,ii,i1,i2;
158 unsigned int key;
159
161 if ( !mesh->nquad ) {
162 return 1;
163 }
164
165 /* default */
166 if ( mesh->adjq ) {
167 if ( abs(mesh->info.imprim) > 3 || mesh->info.ddebug ) {
168 fprintf(stderr,"\n ## Warning: %s: no re-build of adjacencies of quadrangles. "
169 "mesh->adjq must be freed to enforce analysis.\n",__func__);
170 }
171 return 1;
172 }
173
174 if ( abs(mesh->info.imprim) > 5 || mesh->info.ddebug )
175 fprintf(stdout," ** SETTING QUAD ADJACENCY\n");
176
177 /* memory alloc */
178 MMG5_ADD_MEM(mesh,(4*mesh->nquad+5)*sizeof(MMG5_int),"quad adjacency table",
179 fprintf(stderr," Exit program.\n");
180 return 0);
181 MMG5_SAFE_CALLOC(mesh->adjq,4*mesh->nquad+5,MMG5_int,return 0);
182 MMG5_SAFE_CALLOC(hcode,mesh->nquad+5,MMG5_int,return 0);
183
184 link = mesh->adjq;
185 hsize = mesh->nquad;
186
187 /* init */
188 if ( mesh->info.ddebug ) fprintf(stdout," h- stage 1: init\n");
189
190 inival = MMG5_INTMAX;
191
192 iadr = 0;
193 for (k=0; k<=mesh->nquad; k++)
194 hcode[k] = -inival;
195
196 /* hash quads */
197 for (k=1; k<=mesh->nquad; k++) {
198 pq = &mesh->quadra[k];
199 if ( !MG_EOK(pq) ) continue;
200 for (i=0; i<4; i++) {
201 i1 = MMG2D_idir_q[i][0];
202 i2 = MMG2D_idir_q[i][1];
203 if ( pq->v[i1] < pq->v[i2] ) {
204 mins = pq->v[i1];
205 maxs = pq->v[i2];
206 }
207 else {
208 mins = pq->v[i2];
209 maxs = pq->v[i1];
210 }
211
212 /* compute key */
213 key = (KTA*(int64_t)mins + KTB*(int64_t)maxs)%hsize+1;
214
215 /* insert */
216 iadr++;
217 link[iadr] = hcode[key];
218 hcode[key] = -iadr;
219 }
220 }
221
222 /* set adjacency */
223 if ( mesh->info.ddebug ) fprintf(stdout," h- stage 2: adjacencies\n");
224
225 for (l=iadr; l>0; l--) {
226 if ( link[l] >= 0 ) continue;
227
228 /* current element */
229 k = (l-1) / 4 + 1;
230 i = (l-1) % 4;
231 i1 = MMG2D_idir_q[i][0];
232 i2 = MMG2D_idir_q[i][1];
233
234 pq = &mesh->quadra[k];
235 if ( pq->v[i1] < pq->v[i2] ) {
236 mins = pq->v[i1];
237 maxs = pq->v[i2];
238 }
239 else {
240 mins = pq->v[i2];
241 maxs = pq->v[i1];
242 }
243
244 /* accross link */
245 ll = -link[l];
246 pp = 0;
247 link[l] = 0;
248 while ( ll != inival ) {
249 kk = (ll-1) / 4 + 1;
250 ii = (ll-1) % 4;
251 i1 = MMG2D_idir_q[ii][0];
252 i2 = MMG2D_idir_q[ii][1];
253 pq1 = &mesh->quadra[kk];
254
255 if ( pq1->v[i1] < pq1->v[i2] ) {
256 mins1 = pq1->v[i1];
257 maxs1 = pq1->v[i2];
258 }
259 else {
260 mins1 = pq1->v[i2];
261 maxs1 = pq1->v[i1];
262 }
263
264 if ( mins1 == mins && maxs1 == maxs ) {
265 /* adjacent found */
266 if ( pp != 0 ) link[pp] = link[ll];
267 link[l] = 4*kk + ii;
268 link[ll] = 4*k + i;
269 break;
270 }
271 pp = ll;
272 ll = -link[ll];
273 }
274 }
275 MMG5_SAFE_FREE(hcode);
276
278 /* Temporarily allocate a hash structure for storing edges */
279 if ( !MMG5_hashNew( mesh,&hash,0.51*mesh->nt, 1.51*mesh->nt) ) return 0;
280
281 /* Hash edge belonging to only one triangle (hcode==0) */
282 for (k=1; k<=mesh->nt; k++) {
283 pt = &mesh->tria[k];
284 if ( !MG_EOK(pt) ) continue;
285
286 hcode = &mesh->adja[3*(k-1)+1];
287 for (i=0; i<3; i++) {
288 if ( hcode[i] ) {
289 continue;
290 }
291 /* The edge belongs to one tria only */
292 MMG5_hashEdge(mesh,&hash,pt->v[MMG5_iprv2[i]],pt->v[MMG5_inxt2[i]],3*k+i);
293 }
294 }
295
296 /* Search edges that belong to one quad only and update adjacency array if the
297 * edge is founded in the hash table */
298 for (k=1; k<=mesh->nquad; k++) {
299 pq = &mesh->quadra[k];
300 if ( !MG_EOK(pq) ) continue;
301
302 hcode = &mesh->adjq[4*(k-1)+1];
303 for (i=0; i<4; i++) {
304 assert ( hcode[i] >= 0 );
305
306 if ( hcode[i] ) {
307 continue;
308 }
309
310 /* The edge belongs to one quad only */
311 i1 = MMG2D_idir_q[i][0];
312 i2 = MMG2D_idir_q[i][1];
313
314 kk = MMG5_hashGet(&hash,pq->v[i1],pq->v[i2]);
315 if ( kk ) {
316 /* The edge is at the interface between a quad and a triangle */
317 hcode[i] = -kk;
318 }
319 }
320 }
321 MMG5_DEL_MEM(mesh,hash.item);
322
323 return 1;
324}
325
335 MMG5_Hash hash;
336 MMG5_pTria pt;
337 MMG5_pQuad pq;
338 MMG5_pEdge pa;
339 MMG5_int ia;
340 MMG5_int k;
341 int8_t ier;
342 uint8_t i,i1,i2;
343
355 if ( !mesh->info.metRidTyp ) {
356 /* Try to clean triangle structure (in case where mmg2dlib is called after
357 * mmg2dmesh) */
358 for (k=1; k<=mesh->nt; k++) {
359 pt = &mesh->tria[k];
360 if ( !MG_EOK(pt) ) continue;
361
362 /* If all edges are required, the triangle is maybe required by the user */
363 if ( (pt->tag[0] & MG_REQ) && (pt->tag[1] & MG_REQ) && (pt->tag[2] & MG_REQ) ) {
364 continue;
365 }
366
367 /* Otherwise there is no reason to have required tags on edges */
368 for ( ia = 0; ia < 3; ++ia ) {
369 pt->tag[ia] &= ~MG_REQ;
370 }
371 }
372 mesh->info.metRidTyp = 1;
373 }
374
375 if ( !mesh->na ) return 1;
376
377 /* Temporarily allocate a hash structure for storing edges */
378 ier = MMG5_hashNew ( mesh,&hash, mesh->na,3*mesh->na );
379 if ( !ier ) {
380 printf(" ## Error: %s: Unable to allocate edge hash table\n.",__func__);
381 return 0;
382 }
383
384 /* hash mesh edges */
385 for (k=1; k<=mesh->na; k++) {
386 ier = MMG5_hashEdge(mesh,&hash,mesh->edge[k].a,mesh->edge[k].b,k);
387 if ( !ier ) {
388 fprintf(stderr,"\n ## Error: %s: unable to hash edge %" MMG5_PRId " %" MMG5_PRId ".\n",__func__,
390 return 0;
391 }
392 }
393
394 /* set references to triangles */
395 for (k=1; k<=mesh->nt; k++) {
396 pt = &mesh->tria[k];
397 if ( !MG_EOK(pt) ) continue;
398
399 for (i=0; i<3; i++) {
400 i1 = MMG5_inxt2[i];
401 ia = MMG5_hashGet(&hash,pt->v[i],pt->v[i1]);
402 if ( ia ) {
403 i2 = MMG5_inxt2[i1];
404 pa = &mesh->edge[ia];
405 pt->edg[i2] = pa->ref;
406 pt->tag[i2] |= pa->tag;
407
408 }
409 }
410 }
411
412 /* set references to quadrangles */
413 for (k=1; k<=mesh->nquad; k++) {
414 pq = &mesh->quadra[k];
415 if ( !MG_EOK(pq) ) continue;
416
417 for (i=0; i<4; i++) {
418 i1 = MMG2D_idir_q[i][0];
419 i2 = MMG2D_idir_q[i][1];
420 ia = MMG5_hashGet(&hash,pq->v[i1],pq->v[i2]);
421 if ( ia ) {
422 pa = &mesh->edge[ia];
423 pq->edg[i] = pa->ref;
424 pq->tag[i] |= pa->tag;
425 }
426 }
427 }
428
429 /* Delete the hash for edges */
430 MMG5_DEL_MEM(mesh,hash.item);
432 mesh->na = 0;
433
434 return 1;
435}
436
450 MMG5_pTria pt,pt1;
451 MMG5_pEdge pa;
452 MMG5_pPoint p0;
453 MMG5_int k,*adja,natmp,iel;
454 int8_t i,i1,i2;
455
456 natmp = 0;
457 mesh->na = 0;
458
459 /* First step: Count number of boundary edges */
460 for (k=1; k<=mesh->nt; k++) {
461 pt = &mesh->tria[k];
462 if ( !MG_EOK(pt) ) continue;
463
464 adja = &mesh->adja[3*(k-1)+1];
465
466 for (i=0; i<3; i++) {
467 iel = adja[i] / 3;
468 pt1 = &mesh->tria[iel];
469
470 if ( iel && pt->ref <= pt1->ref ) continue;
471 natmp++;
472 }
473 }
474
475 /* Second step: Create edge mesh and store the corresponding edges */
476 MMG5_ADD_MEM(mesh,(natmp+1)*sizeof(MMG5_Edge),"edges",return 0);
477 MMG5_SAFE_CALLOC(mesh->edge,natmp+1,MMG5_Edge,return 0);
478
479 for (k=1; k<=mesh->nt; k++) {
480 pt = &mesh->tria[k];
481 if ( !MG_EOK(pt) ) continue;
482
483 adja = &mesh->adja[3*(k-1)+1];
484
485 for (i=0; i<3; i++) {
486 iel = adja[i] / 3;
487 pt1 = &mesh->tria[iel];
488
489 if ( iel && pt->ref <= pt1->ref ) continue;
490
491 i1 = MMG5_inxt2[i];
492 i2 = MMG5_inxt2[i1];
493
494 mesh->na++;
495 pa = &mesh->edge[mesh->na];
496 pa->a = pt->v[i1];
497 pa->b = pt->v[i2];
498
499 pa->tag = pt->tag[i];
500 pa->ref = pt->edg[i];
501
502 }
503 }
504
505 /* Set point tags */
506 for (k=1; k<=mesh->na; k++) {
507 pa = &mesh->edge[k];
508 p0 = &mesh->point[pa->a];
509 p0->tag |= MG_BDY;
510
511 p0 = &mesh->point[pa->b];
512 p0->tag |= MG_BDY;
513 }
514
515 return 1;
516}
517
518
531 MMG5_pTria pt,ptnew,pt1;
532 MMG5_pQuad pq,pq1;
533 MMG5_pEdge ped;
534 MMG5_pPoint ppt,pptnew;
535 MMG5_int np,ned,nt,k,iel,nbl,isol,isolnew,memWarn,nc;
536 MMG5_int iadr,iadrnew,iadrv,*adjav,*adja,*adjanew,voy;
537 int8_t i,i1,i2;
538
539 /* Keep only one domain if asked */
541
543 if ( !MMG2D_hashTria(mesh) ) {
544 fprintf(stderr,"\n ## Warning: %s: hashing problem. Exit program.\n",
545 __func__);
546 return 0;
547 }
548
550 np = nc = 0;
551 for (k=1; k<=mesh->np; k++) {
552 ppt = &mesh->point[k];
553 if ( !MG_VOK(ppt) ) continue;
554 ppt->tmp = ++np;
555
556 if ( ppt->tag & MG_CRN ) nc++;
557
558 if ( ppt->tag & MG_NOSURF ) {
559 ppt->tag &= ~MG_NOSURF;
560 ppt->tag &= ~MG_REQ;
561 }
562 }
563
565 memWarn = 0;
566 ned = 0;
567
568 if ( mesh->edge ) {
569 fprintf(stderr,"\n ## Warning: %s: unexpected edge table..."
570 " Ignored data.\n",__func__);
572 mesh->na = 0;
573 }
574
575 if ( mesh->nquad && mesh->quadra ) {
576 if ( !MMG2D_hashQuad(mesh) ) {
577 fprintf(stderr,"\n ## Warning: %s: unable to build quad adjacencies."
578 " Quad edges will be ignored.\n",__func__);
579 }
580 }
581
582 mesh->na = 0;
584 for (k=1; k<=mesh->nt; k++) {
585 pt = &mesh->tria[k];
586 if ( !MG_EOK(pt) ) continue;
587 adja = &mesh->adja[3*(k-1)+1];
588
589 for (i=0; i<3; i++) {
590 iel = adja[i] / 3;
591
592 if ( pt->tag[i] & MG_NOSURF ) {
593 pt->tag[i] &= ~MG_REQ;
594 pt->tag[i] &= ~MG_NOSURF;
595 }
596
597 pt1 = &mesh->tria[iel];
598 if ( (!iel) || (pt->ref > pt1->ref) ) {
599 ++mesh->na;
600 }
601 else if ( (pt->ref==pt1->ref) && MG_SIN(pt->tag[i]) ) {
602 ++mesh->na;
603 }
604 else if ( mesh->info.opnbdy ) {
605 if ( (pt->tag[i] & MG_REF) || pt->tag[i] & MG_BDY ) {
606 assert ( pt->tag[i] & (MG_REF+MG_BDY) );
607 ++mesh->na;
608 }
609 }
610 }
611 }
613 for (k=1; k<=mesh->nquad; k++) {
614 pq = &mesh->quadra[k];
615 if ( !MG_EOK(pq) ) continue;
616 adja = &mesh->adjq[4*(k-1)+1];
617
618 for (i=0; i<4; i++) {
619 iel = adja[i] / 4;
620
621 if ( iel < 0) {
622 /* Edge at the interface between a quad and a tria: treated from the tria */
623 continue;
624 }
625
626 pq1 = &mesh->quadra[iel];
627 if ( (!iel) || (pq->ref > pq1->ref) ) {
628 ++mesh->na;
629 }
630 else if ( (pq->ref==pq1->ref) && MG_SIN(pq->tag[i]) ) {
631 ++mesh->na;
632 }
633 else if ( mesh->info.opnbdy ) {
634 if ( (pq->tag[i] & MG_REF) || pq->tag[i] & MG_BDY ) {
635 assert ( pq->tag[i] & (MG_REF+MG_BDY) );
636 ++mesh->na;
637 }
638 }
639 }
640 }
641
643 mesh->namax = mesh->na;
644 if ( mesh->na ) {
645
646 MMG5_ADD_MEM(mesh,(mesh->namax+1)*sizeof(MMG5_Edge),"final edges", memWarn=1);
647
648 if ( memWarn ) {
649 if ( mesh->info.ddebug )
650 printf(" -- Attempt to allocate a smallest edge table...\n");
651 mesh->namax = mesh->na;
652 memWarn = 0;
653 MMG5_ADD_MEM(mesh,(mesh->namax+1)*sizeof(MMG5_Edge),"final edges",
654 fprintf(stderr,"\n ## Warning: %s: uncomplete mesh.\n",
655 __func__);
656 memWarn=1);
657 }
658
659 if ( memWarn )
660 mesh->na = 0;
661 else {
662 /* We have enough memory to allocate the edge table */
663 MMG5_SAFE_CALLOC(mesh->edge,(mesh->namax+1),MMG5_Edge, return 0);
664
665 nt = 0;
666 /* Edges stored in triangles */
667 for (k=1; k<=mesh->nt; k++) {
668 pt = &mesh->tria[k];
669 if ( !MG_EOK(pt) ) continue;
670 ++nt;
671 adja = &mesh->adja[3*(k-1)+1];
672
673 for (i=0; i<3; i++) {
674 i1 = MMG5_inxt2[i];
675 i2 = MMG5_iprv2[i];
676 iel = adja[i] / 3;
677 pt1 = &mesh->tria[iel];
678 if ( !iel || (pt->ref > pt1->ref) ||
679 ((pt->ref==pt1->ref) && MG_SIN(pt->tag[i])) ||
680 (mesh->info.opnbdy && ((pt->tag[i] & MG_REF) || (pt->tag[i] & MG_BDY)))) {
681 ++ned;
682 ped = &mesh->edge[ned];
683 ped->a = pt->v[i1];
684 ped->b = pt->v[i2];
685 /* the base field is used to be able to recover the tria (and its face)
686 * from which comes a boundary edge */
687 ped->base = 3*nt+i;
688 ped->ref = pt->edg[i];
689 ped->tag = pt->tag[i];
690 }
691 }
692 }
693
694 /* Edges stored in quadrangles */
695 nt = 0;
696 for (k=1; k<=mesh->nquad; k++) {
697 pq = &mesh->quadra[k];
698 if ( !MG_EOK(pq) ) continue;
699 ++nt;
700 adja = &mesh->adjq[4*(k-1)+1];
701
702 for (i=0; i<4; i++) {
703 i1 = MMG2D_idir_q[i][0];
704 i2 = MMG2D_idir_q[i][1];
705
706 iel = adja[i] / 4;
707
708 if ( iel < 0) {
709 /* Edge at the interface between a quad and a tria: treated from the tria */
710 continue;
711 }
712
713 pq1 = &mesh->quadra[iel];
714 if ( !iel || (pq->ref > pq1->ref) ||
715 ((pq->ref==pq1->ref) && MG_SIN(pq->tag[i])) ||
716 (mesh->info.opnbdy && ((pq->tag[i] & MG_REF) || (pq->tag[i] & MG_BDY)))) {
717 ++ned;
718 ped = &mesh->edge[ned];
719 ped->a = pq->v[i1];
720 ped->b = pq->v[i2];
721 /* the base field is used to be able to recover the quad (and its face)
722 * from which comes a boundary edge */
723 ped->base = 4*nt+i;
724 ped->ref = pq->edg[i];
725 ped->tag = pq->tag[i];
726 }
727 }
728 }
729 }
730 }
731
732 for (k=1; k<=mesh->na; k++) {
733 ped = &mesh->edge[k];
734 if ( !ped->a ) continue;
735 ped->a = mesh->point[ped->a].tmp;
736 ped->b = mesh->point[ped->b].tmp;
737 }
738
740 nt = 0;
741 nbl = 1;
742 for (k=1; k<=mesh->nt; k++) {
743 pt = &mesh->tria[k];
744 if ( !MG_EOK(pt) ) continue;
745
746 pt->v[0] = mesh->point[pt->v[0]].tmp;
747 pt->v[1] = mesh->point[pt->v[1]].tmp;
748 pt->v[2] = mesh->point[pt->v[2]].tmp;
749 nt++;
750
751 if ( k != nbl ) {
752 ptnew = &mesh->tria[nbl];
753 memcpy(ptnew,pt,sizeof(MMG5_Tria));
754
755 /* Update the adjacency */
756 iadr = 3*(k-1) + 1;
757 adja = &mesh->adja[iadr];
758 iadrnew = 3*(nbl-1) + 1;
759 adjanew = &mesh->adja[iadrnew];
760
761 for(i=0; i<3; i++) {
762 adjanew[i] = adja[i];
763 if ( !adja[i] ) continue;
764 iadrv = 3*(adja[i]/3-1)+1;
765 adjav = &mesh->adja[iadrv];
766 voy = i;
767 adjav[adja[i]%3] = 3*nbl + voy;
768 adja[i] = 0;
769 }
770 memset(pt,0,sizeof(MMG5_Tria));
771 }
772 nbl++;
773 }
774 mesh->nt = nt;
775
777 if ( mesh->quadra ) {
778 k = 1;
779 do {
780 pq = &mesh->quadra[k];
781 if ( !MG_EOK(pq) ) {
782 pq1 = &mesh->quadra[mesh->nquad];
783 assert( pq && pq1 && MG_EOK(pq1) );
784 memcpy(pq,pq1,sizeof(MMG5_Quad));
785 --mesh->nquad;
786 }
787 }
788 while ( ++k < mesh->nquad );
789 }
790
791 if ( mesh->quadra ) {
792 for (k=1; k<=mesh->nquad; k++) {
793 pq = &mesh->quadra[k];
794 if ( !MG_EOK(pq) ) continue;
795 pq->v[0] = mesh->point[pq->v[0]].tmp;
796 pq->v[1] = mesh->point[pq->v[1]].tmp;
797 pq->v[2] = mesh->point[pq->v[2]].tmp;
798 pq->v[3] = mesh->point[pq->v[3]].tmp;
799 }
800 }
801
803 if ( sol && sol->m ) {
804 nbl = 1;
805 for (k=1; k<=mesh->np; k++) {
806 ppt = &mesh->point[k];
807 if ( !MG_VOK(ppt) ) continue;
808 isol = k * sol->size;
809 isolnew = nbl * sol->size;
810
811 for (i=0; i<sol->size; i++)
812 sol->m[isolnew + i] = sol->m[isol + i];
813 ++nbl;
814 }
815 }
816
817 if ( met && met->m ) {
818 nbl = 1;
819 for (k=1; k<=mesh->np; k++) {
820 ppt = &mesh->point[k];
821 if ( !MG_VOK(ppt) ) continue;
822 isol = k * met->size;
823 isolnew = nbl * met->size;
824
825 for (i=0; i<met->size; i++)
826 met->m[isolnew + i] = met->m[isol + i];
827 ++nbl;
828 }
829 }
830
832 np = 0;
833 nbl = 1;
834 for (k=1; k<=mesh->np; k++) {
835 ppt = &mesh->point[k];
836 if ( !MG_VOK(ppt) ) continue;
837
838 if ( k != nbl ) {
839 pptnew = &mesh->point[nbl];
840 memcpy(pptnew,ppt,sizeof(MMG5_Point));
841 ppt->tag = 0;
842 assert ( ppt->tmp == nbl );
843 }
844 np++;
845 if ( k != nbl ) {
846 ppt = &mesh->point[k];
847 memset(ppt,0,sizeof(MMG5_Point));
848 ppt->tag = 0;
849 }
850 nbl++;
851 }
852 mesh->np = np;
853 if ( sol && sol->m ) sol->np = np;
854
856 for(k=1 ; k<=mesh->np ; k++)
857 mesh->point[k].tmp = 0;
858
859 if(mesh->np < mesh->npmax - 3) {
860 mesh->npnil = mesh->np + 1;
861 for (k=mesh->npnil; k<mesh->npmax-1; k++)
862 mesh->point[k].tmp = k+1;
863 }
864 else {
865 mesh->npnil = 0;
866 }
867
869 if ( mesh->nt < mesh->ntmax - 3 ) {
870 mesh->nenil = mesh->nt + 1;
871 for (k=mesh->nenil; k<mesh->ntmax-1; k++)
872 mesh->tria[k].v[2] = k+1;
873 }
874 else {
875 mesh->nenil = 0;
876 }
877
878 if ( mesh->info.imprim > 0 ) {
879 fprintf(stdout," NUMBER OF VERTICES %8" MMG5_PRId " CORNERS %8" MMG5_PRId "\n",mesh->np,nc);
880 fprintf(stdout," NUMBER OF TRIANGLES %8" MMG5_PRId "\n",mesh->nt);
881 if ( mesh->nquad ) {
882 fprintf(stdout," NUMBER OF QUADRILATERALS %8" MMG5_PRId "\n",mesh->nquad);
883 }
884 if ( mesh->na )
885 fprintf(stdout," NUMBER OF EDGES %8" MMG5_PRId "\n",mesh->na);
886 }
887
888 if ( memWarn ) return 0;
889
890 return 1;
891}
int ier
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:532
MMG5_int MMG5_hashGet(MMG5_Hash *hash, MMG5_int a, MMG5_int b)
Definition: hash.c:501
int MMG5_hashEdge(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:346
int MMG2D_bdryEdge(MMG5_pMesh mesh)
Definition: hash_2d.c:449
int MMG2D_hashQuad(MMG5_pMesh mesh)
Definition: hash_2d.c:151
int MMG2D_assignEdge(MMG5_pMesh mesh)
Definition: hash_2d.c:334
#define KTA
Definition: hash_2d.c:25
int MMG2D_hashTria(MMG5_pMesh mesh)
Definition: hash_2d.c:35
#define KTB
Definition: hash_2d.c:26
int MMG2D_pack(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: hash_2d.c:530
MMG5_int MMG2D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_2d.c:70
#define M_MIN(a, b)
static const unsigned int MMG2D_idir[5]
#define M_MAX(a, b)
static const uint8_t MMG2D_idir_q[4][2]
idir[i]: vertices of edge i for a quad
void MMG2D_keep_only1Subdomain(MMG5_pMesh mesh, int nsd)
Definition: tools_2d.c:92
#define MG_REQ
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MMG5_ADD_MEM(mesh, size, message, law)
static const uint8_t MMG5_iprv2[3]
#define MG_SIN(tag)
static const uint8_t MMG5_inxt2[6]
#define MG_VOK(ppt)
#define MG_CRN
#define MG_BDY
#define MG_NOSURF
#define MG_REF
#define MMG5_SAFE_FREE(ptr)
#define MMG5_DEL_MEM(mesh, ptr)
Structure to store edges of am MMG mesh.
Definition: libmmgtypes.h:311
MMG5_int b
Definition: libmmgtypes.h:312
MMG5_int base
Definition: libmmgtypes.h:314
uint16_t tag
Definition: libmmgtypes.h:316
MMG5_int ref
Definition: libmmgtypes.h:313
MMG5_int a
Definition: libmmgtypes.h:312
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:603
MMG5_hedge * item
Definition: libmmgtypes.h:605
int8_t ddebug
Definition: libmmgtypes.h:539
uint8_t metRidTyp
Definition: libmmgtypes.h:554
MMG5_int nsd
Definition: libmmgtypes.h:529
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_int ntmax
Definition: libmmgtypes.h:620
MMG5_pQuad quadra
Definition: libmmgtypes.h:656
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_int nquad
Definition: libmmgtypes.h:621
MMG5_int npmax
Definition: libmmgtypes.h:620
MMG5_int nenil
Definition: libmmgtypes.h:630
MMG5_int * adjq
Definition: libmmgtypes.h:644
MMG5_int namax
Definition: libmmgtypes.h:620
MMG5_int nt
Definition: libmmgtypes.h:620
MMG5_pTria tria
Definition: libmmgtypes.h:655
MMG5_int np
Definition: libmmgtypes.h:620
MMG5_pEdge edge
Definition: libmmgtypes.h:657
MMG5_int na
Definition: libmmgtypes.h:620
MMG5_int npnil
Definition: libmmgtypes.h:629
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
MMG5_int tmp
Definition: libmmgtypes.h:286
uint16_t tag
Definition: libmmgtypes.h:290
Structure to store quadrangles of an MMG mesh.
Definition: libmmgtypes.h:372
MMG5_int ref
Definition: libmmgtypes.h:374
MMG5_int v[4]
Definition: libmmgtypes.h:373
uint16_t tag[4]
Definition: libmmgtypes.h:378
MMG5_int edg[4]
Definition: libmmgtypes.h:376
double * m
Definition: libmmgtypes.h:680
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
MMG5_int edg[3]
Definition: libmmgtypes.h:345
MMG5_int ref
Definition: libmmgtypes.h:341
uint16_t tag[3]
Definition: libmmgtypes.h:348
MMG5_int v[3]
Definition: libmmgtypes.h:340