Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
quality.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
35#include "mmgcommon_private.h"
36
48 double anisurf,dd,abx,aby,abz,acx,acy,acz,bcx,bcy,bcz;
49 double *a,*b,*c,*ma,*mb,*mc,m[6],l0,l1,l2,rap;
50 MMG5_int ia,ib,ic;
51 int8_t i;
52
53 ia = pt->v[0];
54 ib = pt->v[1];
55 ic = pt->v[2];
56
57 ma = &met->m[6*ia];
58 mb = &met->m[6*ib];
59 mc = &met->m[6*ic];
60
61 /* 2*area */
62 anisurf = MMG5_surftri33_ani(mesh,pt,ma,mb,mc);
63 if ( anisurf <= MMG5_EPSD2 ) return 0.0;
64
65 dd = 1.0 / 3.0;
66 for (i=0; i<6; i++)
67 m[i] = dd * (ma[i] + mb[i] + mc[i]);
68
69 a = &mesh->point[ia].c[0];
70 b = &mesh->point[ib].c[0];
71 c = &mesh->point[ic].c[0];
72
73 abx = b[0] - a[0];
74 aby = b[1] - a[1];
75 abz = b[2] - a[2];
76 acx = c[0] - a[0];
77 acy = c[1] - a[1];
78 acz = c[2] - a[2];
79 bcx = c[0] - b[0];
80 bcy = c[1] - b[1];
81 bcz = c[2] - b[2];
82
83 /* length */
84 l0 = m[0]*abx*abx + m[3]*aby*aby + m[5]*abz*abz
85 + 2.0*(m[1]*abx*aby + m[2]*abx*abz + m[4]*aby*abz);
86
87 l1 = m[0]*acx*acx + m[3]*acy*acy + m[5]*acz*acz
88 + 2.0*(m[1]*acx*acy + m[2]*acx*acz + m[4]*acy*acz);
89
90 l2 = m[0]*bcx*bcx + m[3]*bcy*bcy + m[5]*bcz*bcz
91 + 2.0*(m[1]*bcx*bcy + m[2]*bcx*bcz + m[4]*bcy*bcz);
92
93 rap = l0 + l1 + l2;
94
95 /* quality = 2*area/length */
96 if ( rap > MMG5_EPSD2 ) {
97 return anisurf / rap;
98 }
99 else
100 return 0.0;
101}
102
116 MMG5_pPoint p[3];
117 double rap,anisurf,l0,l1,l2,m[6],mm[6],rbasis[3][3];
118 double abx,aby,abz,acx,acy,acz,bcy,bcx,bcz;
119 int i,j;
120 MMG5_int np[3];
121 int8_t i1,i2;
122
123 for (i=0; i<3; i++) {
124 np[i] = ptt->v[i];
125 p[i] = &mesh->point[np[i]];
126 }
127
128 /* Set metric tensors at vertices of tria iel */
129 for ( j=0; j<6; ++j) {
130 mm[j] = 0;
131 }
132
133 for(i=0; i<3; i++) {
134
135 if ( MG_SIN(p[i]->tag) || (MG_NOM & p[i]->tag) ) {
136 memcpy(&m[0],&met->m[6*np[i]],6*sizeof(double));
137 }
138 else if ( p[i]->tag & MG_GEO ) {
139 i1 = MMG5_inxt2[i];
140 i2 = MMG5_iprv2[i];
141 abx = 0.5*(p[i1]->c[0]+p[i2]->c[0]) - p[i]->c[0];
142 aby = 0.5*(p[i1]->c[1]+p[i2]->c[1]) - p[i]->c[1];
143 abz = 0.5*(p[i1]->c[2]+p[i2]->c[2]) - p[i]->c[2];
144 /* Note that rbasis is unused here */
145 if ( !MMG5_buildridmet(mesh,met,np[i],abx,aby,abz,&m[0],rbasis) ) {
146 return 0.0;
147 }
148 }
149 else {
150 memcpy(&m[0],&met->m[6*np[i]],6*sizeof(double));
151 }
152
153 for ( j=0; j<6; ++j) {
154 mm[j] += MMG5_ATHIRD*m[j];
155 }
156 }
157
158 anisurf = MMG5_surftri33_ani(mesh,ptt,mm,mm,mm);
159
160 /* length */
161 abx = p[1]->c[0] - p[0]->c[0];
162 aby = p[1]->c[1] - p[0]->c[1];
163 abz = p[1]->c[2] - p[0]->c[2];
164 acx = p[2]->c[0] - p[0]->c[0];
165 acy = p[2]->c[1] - p[0]->c[1];
166 acz = p[2]->c[2] - p[0]->c[2];
167 bcx = p[2]->c[0] - p[1]->c[0];
168 bcy = p[2]->c[1] - p[1]->c[1];
169 bcz = p[2]->c[2] - p[1]->c[2];
170
171
172 l0 = mm[0]*abx*abx + mm[3]*aby*aby + mm[5]*abz*abz
173 + 2.0*(mm[1]*abx*aby + mm[2]*abx*abz + mm[4]*aby*abz);
174
175 l1 = mm[0]*acx*acx + mm[3]*acy*acy + mm[5]*acz*acz
176 + 2.0*(mm[1]*acx*acy + mm[2]*acx*acz + mm[4]*acy*acz);
177
178 l2 = mm[0]*bcx*bcx + mm[3]*bcy*bcy + mm[5]*bcz*bcz
179 + 2.0*(mm[1]*bcx*bcy + mm[2]*bcx*bcz + mm[4]*bcy*bcz);
180
181 rap = l0 + l1 + l2;
182
183 if ( rap < MMG5_EPSD2 ) return 0.0;
184
185 /* quality = 2*area/length */
186 return (anisurf / rap);
187}
188
200 double *a,*b,*c,cal,abx,aby,abz,acx,acy,acz,bcx,bcy,bcz,rap;
201
202 a = &mesh->point[ptt->v[0]].c[0];
203 b = &mesh->point[ptt->v[1]].c[0];
204 c = &mesh->point[ptt->v[2]].c[0];
205
206 /* area */
207 abx = b[0] - a[0];
208 aby = b[1] - a[1];
209 abz = b[2] - a[2];
210 acx = c[0] - a[0];
211 acy = c[1] - a[1];
212 acz = c[2] - a[2];
213 bcx = c[0] - b[0];
214 bcy = c[1] - b[1];
215 bcz = c[2] - b[2];
216
217 cal = (aby*acz - abz*acy) * (aby*acz - abz*acy);
218 cal += (abz*acx - abx*acz) * (abz*acx - abx*acz);
219 cal += (abx*acy - aby*acx) * (abx*acy - aby*acx);
220
221 if ( cal < MMG5_EPSD2 ) return 0.0;
222
223 /* qual = 2.*surf / length */
224 rap = abx*abx + aby*aby + abz*abz;
225 rap += acx*acx + acy*acy + acz*acz;
226 rap += bcx*bcx + bcy*bcy + bcz*bcz;
227
228 if ( rap < MMG5_EPSD2 ) return 0.0;
229
230 return sqrt(cal) / rap;
231}
232
252void MMG5_displayLengthHisto(MMG5_pMesh mesh, MMG5_int ned, double *avlen,
253 MMG5_int amin, MMG5_int bmin, double lmin,
254 MMG5_int amax, MMG5_int bmax, double lmax,
255 int nullEdge,double *bd, MMG5_int *hl,int8_t shift)
256{
257 double dned;
258
259 dned = (double)ned;
260 (*avlen) = (*avlen) / dned;
261
262 fprintf(stdout,"\n -- RESULTING EDGE LENGTHS %" MMG5_PRId "\n",ned);
263 fprintf(stdout," AVERAGE LENGTH %12.4f\n",(*avlen));
264 fprintf(stdout," SMALLEST EDGE LENGTH %12.4f %6" MMG5_PRId " %6" MMG5_PRId "\n",
265 lmin,amin,bmin);
266 fprintf(stdout," LARGEST EDGE LENGTH %12.4f %6" MMG5_PRId " %6" MMG5_PRId " \n",
267 lmax,amax,bmax);
268
269 MMG5_displayLengthHisto_internal( ned,amin,bmin,lmin,amax,bmax,
270 lmax,nullEdge,bd,hl,shift,
271 mesh->info.imprim);
272
273 return;
274}
275
294void MMG5_displayLengthHisto_internal( MMG5_int ned,MMG5_int amin,
295 MMG5_int bmin, double lmin,MMG5_int amax, MMG5_int bmax,
296 double lmax,MMG5_int nullEdge,double *bd,
297 MMG5_int *hl,int8_t shift,int imprim)
298{
299 int k;
300
301 if ( abs(imprim) < 3 ) return;
302
303 if ( hl[2+shift]+hl[3+shift]+hl[4+shift] )
304 fprintf(stdout," %6.2f < L <%5.2f %8"MMG5_PRId" %5.2f %% \n",
305 bd[2+shift],bd[5+shift],hl[2+shift]+hl[3+shift]+hl[4+shift],
306 100.*(hl[2+shift]+hl[3+shift]+hl[4+shift])/(double)ned);
307
308 if ( abs(imprim) < 4 ) return;
309
310 if ( abs(imprim) > 3 ) {
311 fprintf(stdout,"\n HISTOGRAMM:\n");
312 if ( hl[0] )
313 fprintf(stdout," 0.00 < L < 0.30 %8"MMG5_PRId" %5.2f %% \n",
314 hl[0],100.*(hl[0]/(float)ned));
315 if ( lmax > 0.2 ) {
316 for (k=2; k<9; k++) {
317 if ( hl[k-1] > 0 )
318 fprintf(stdout," %6.2f < L <%5.2f %8"MMG5_PRId" %5.2f %% \n",
319 bd[k-1],bd[k],hl[k-1],100.*(hl[k-1]/(float)ned));
320 }
321 if ( hl[8] )
322 fprintf(stdout," 5. < L %8"MMG5_PRId" %5.2f %% \n",
323 hl[8],100.*(hl[8]/(float)ned));
324 }
325 if ( nullEdge )
326 fprintf(stdout,"\n WARNING: unable to compute the length of %"MMG5_PRId
327 " edges\n",nullEdge);
328 }
329}
330
331
343int MMG5_minQualCheck ( MMG5_int iel, double minqual, double alpha )
344{
345 double minqualAlpha;
346
347 minqualAlpha = minqual*alpha;
348
349 if ( minqualAlpha < MMG5_NULKAL ) {
350 fprintf(stderr,"\n ## Error: %s: too bad quality for the worst element: "
351 "(elt %" MMG5_PRId " -> %15e)\n",__func__,iel,minqual);
352 return 0;
353 }
354 else if ( minqualAlpha < MMG5_EPSOK ) {
355 fprintf(stderr,"\n ## Warning: %s: very bad quality for the worst element: "
356 "(elt %" MMG5_PRId " -> %15e)\n",__func__,iel,minqual);
357 }
358
359 return 1;
360}
MMG5_pMesh * mesh
double MMG5_surftri33_ani(MMG5_pMesh mesh, MMG5_pTria ptt, double ma[6], double mb[6], double mc[6])
Definition: anisosiz.c:171
int MMG5_buildridmet(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int np0, double ux, double uy, double uz, double mr[6], double r[3][3])
Definition: mettools.c:676
#define MG_GEO
#define MMG5_EPSOK
static const uint8_t MMG5_iprv2[3]
#define MMG5_ATHIRD
#define MG_SIN(tag)
#define MMG5_NULKAL
static const uint8_t MMG5_inxt2[6]
#define MG_NOM
#define MMG5_EPSD2
int MMG5_minQualCheck(MMG5_int iel, double minqual, double alpha)
Definition: quality.c:343
double MMG5_caltri_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria ptt)
Definition: quality.c:115
void MMG5_displayLengthHisto_internal(MMG5_int ned, MMG5_int amin, MMG5_int bmin, double lmin, MMG5_int amax, MMG5_int bmax, double lmax, MMG5_int nullEdge, double *bd, MMG5_int *hl, int8_t shift, int imprim)
Definition: quality.c:294
void MMG5_displayLengthHisto(MMG5_pMesh mesh, MMG5_int ned, double *avlen, MMG5_int amin, MMG5_int bmin, double lmin, MMG5_int amax, MMG5_int bmax, double lmax, int nullEdge, double *bd, MMG5_int *hl, int8_t shift)
Definition: quality.c:252
double MMG5_caltri_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria ptt)
Definition: quality.c:199
double MMG5_caltri33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria pt)
Definition: quality.c:47
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_pPoint point
Definition: libmmgtypes.h:641
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