Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
anisomovpt_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*/
34#include "libmmg2d_private.h"
36
37/* Relocate internal vertex whose ball is passed */
38int MMG2D_movintpt_ani(MMG5_pMesh mesh,MMG5_pSol met,int ilist,MMG5_int *list,int8_t improve) {
39 MMG5_pTria pt,pt0;
40 MMG5_pPoint ppt0,p0,p1,p2;
41 double calold,calnew,area,det,alpha,ps,ps1,ps2,step,sqdetm1,sqdetm2;
42 double gr[2],grp[2],*m0,*m1,*m2;
43 MMG5_int k,iel,ip0,ip1,ip2;
44 int8_t i,i1,i2;
45 static int8_t mmgWarn0=0;
46
47 pt0 = &mesh->tria[0];
48 ppt0 = &mesh->point[0];
49 gr[0] = gr[1] = 0.0;
50 calold = calnew = DBL_MAX;
51 step = 0.1;
52
53 /* Step 1: Calculation of the gradient of the variance function; store the quality of the previous
54 configuration */
55 p0 = p1 = p2 = NULL;
56 m0 = NULL;
57 assert ( ilist );
58 for (k=0; k<ilist; k++) {
59 iel = list[k] / 3;
60 pt = &mesh->tria[iel];
61
62 /* Quality of pt */
63 calold = MG_MIN(MMG2D_caltri(mesh,met,pt),calold);
64
65 i = list[k] % 3;
66 i1 = MMG5_inxt2[i];
67 i2 = MMG5_iprv2[i];
68
69 ip0 = pt->v[i];
70 ip1 = pt->v[i1];
71 ip2 = pt->v[i2];
72
73 p0 = &mesh->point[ip0];
74 p1 = &mesh->point[ip1];
75 p2 = &mesh->point[ip2];
76
77 area = (p1->c[0]-p0->c[0])*(p2->c[1]-p0->c[1]) - (p1->c[1]-p0->c[1])*(p2->c[0]-p0->c[0]);
78 area = 0.5*fabs(area);
79
80 m0 = &met->m[3*ip0];
81 m1 = &met->m[3*ip1];
82 m2 = &met->m[3*ip2];
83
84 sqdetm1 = sqrt(m1[0]*m1[2]-m1[1]*m1[1]);
85 sqdetm2 = sqrt(m2[0]*m2[2]-m2[1]*m2[1]);
86
87 gr[0] += MMG5_ATHIRD*area*((p1->c[0]-p0->c[0])*sqdetm1 + (p2->c[0]-p0->c[0])*sqdetm2);
88 gr[1] += MMG5_ATHIRD*area*((p1->c[1]-p0->c[1])*sqdetm1 + (p2->c[1]-p0->c[1])*sqdetm2);
89 }
90
91 /* Preconditionning of the gradient gr = M^{-1}gr */
92 assert(m0 && (m0+1) && (m0+2));
93 det = m0[0]*m0[2]-m0[1]*m0[1];
94
95 if ( det < MMG5_EPSD ) return 0;
96 det = 1.0 / det;
97
98 grp[0] = det*(m0[2]*gr[0]-m0[1]*gr[1]);
99 grp[1] = det*(-m0[1]*gr[0]+m0[0]*gr[1]);
100
101 /* Step 2: Identification of the triangle such that gr is comprised in the associated angular sector */
102 ps1 = ps2 = 0.;
103 for (k=0; k<ilist; k++) {
104 iel = list[k] / 3;
105 pt = &mesh->tria[iel];
106
107 i = list[k] % 3;
108 i1 = MMG5_inxt2[i];
109 i2 = MMG5_iprv2[i];
110
111 ip0 = pt->v[i];
112 ip1 = pt->v[i1];
113 ip2 = pt->v[i2];
114
115 p0 = &mesh->point[ip0];
116 p1 = &mesh->point[ip1];
117 p2 = &mesh->point[ip2];
118
119 ps1 = (p1->c[0]-p0->c[0])*grp[1] - (p1->c[1]-p0->c[1])*grp[0];
120 ps2 = grp[0]*(p2->c[1]-p0->c[1]) - grp[1]*(p2->c[0]-p0->c[0]);
121
122 if ( ps1 >= 0.0 && ps2 >= 0.0 ) break;
123 }
124
125 if ( k == ilist ) {
126 if ( !mmgWarn0 ) {
127 mmgWarn0=1;
128 fprintf(stderr,"\n ## Error: %s: impossible to locate at least"
129 " 1 gradient - abort.\n",__func__);
130 }
131 return 0;
132 }
133
134 /* coordinates of the proposed position for relocation p = p0 + alpha*set*grp, so that
135 the new point is inside the triangle */
136 det = (p1->c[0]-p0->c[0])*(p2->c[1]-p0->c[1]) - (p1->c[1]-p0->c[1])*(p2->c[0]-p0->c[0]);
137 ps = ps1+ps2;
138 if ( ps < MMG5_EPSD ) return 0;
139 alpha = det / ps;
140
141 ppt0->c[0] = p0->c[0] + alpha*step*grp[0];
142 ppt0->c[1] = p0->c[1] + alpha*step*grp[1];
143
144 /* Step 3: Vertex relocation and checks */
145 i = 0;
146 pt = NULL;
147 for (k=0; k<ilist; k++) {
148 iel = list[k] / 3;
149 i = list[k] % 3;
150 pt = &mesh->tria[iel];
151 memcpy(pt0,pt,sizeof(MMG5_Tria));
152 pt0->v[i] = 0;
153
154 calnew = MG_MIN(MMG2D_caltri(mesh,met,pt0),calnew);
155 }
156
157 if (calold < MMG2D_NULKAL && calnew <= calold) return 0;
158 else if (calnew < MMG2D_NULKAL) return 0;
159 else if ( improve && calnew < 1.02 * calold ) return 0;
160 else if ( calnew < 0.3 * calold ) return 0;
161
162 /* Update of the coordinates of the point */
163 p0 = &mesh->point[pt->v[i]];
164 p0->c[0] = ppt0->c[0];
165 p0->c[1] = ppt0->c[1];
166
167 return 1;
168}
MMG5_pMesh * mesh
int MMG2D_movintpt_ani(MMG5_pMesh mesh, MMG5_pSol met, int ilist, MMG5_int *list, int8_t improve)
Definition: anisomovpt_2d.c:38
#define MMG5_EPSD
#define MMG2D_NULKAL
#define MG_MIN(a, b)
static const uint8_t MMG5_iprv2[3]
#define MMG5_ATHIRD
static const uint8_t MMG5_inxt2[6]
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_pTria tria
Definition: libmmgtypes.h:647
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
double * m
Definition: libmmgtypes.h:671
MMG5_int v[3]
Definition: libmmgtypes.h:334