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