Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
inlined_functions_private.h
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
34#include "mmgcommon_private.h"
35
36#ifndef _INLINED_FUNC_H
37#define _INLINED_FUNC_H
38
53static inline
54double MMG5_lenEdg(MMG5_pMesh mesh,MMG5_int np0,MMG5_int np1,
55 double *m0,double *m1,int8_t isedg) {
56 MMG5_pPoint p0,p1;
57 double gammaprim0[3],gammaprim1[3],t[3],*n1,*n2,ux,uy,uz,ps1,ps2,l0,l1;
58 static int8_t mmgWarn=0;
59
60 p0 = &mesh->point[np0];
61 p1 = &mesh->point[np1];
62
63 ux = p1->c[0] - p0->c[0];
64 uy = p1->c[1] - p0->c[1];
65 uz = p1->c[2] - p0->c[2];
66
67 /* computation of the two tangent vectors to the underlying curve of [i0i1] */
68 if ( MG_SIN(p0->tag) || (MG_NOM & p0->tag) ) {
69 gammaprim0[0] = ux;
70 gammaprim0[1] = uy;
71 gammaprim0[2] = uz;
72 }
73 else if ( isedg ) {
74 memcpy(t,p0->n,3*sizeof(double));
75 ps1 = ux*t[0] + uy*t[1] + uz*t[2];
76 gammaprim0[0] = ps1*t[0];
77 gammaprim0[1] = ps1*t[1];
78 gammaprim0[2] = ps1*t[2];
79 }
80 else {
81 if ( MG_GEO & p0->tag ) {
82 //assert(p0->xp);
83 n1 = &mesh->xpoint[p0->xp].n1[0];
84 n2 = &mesh->xpoint[p0->xp].n2[0];
85 ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
86 ps2 = ux*n2[0] + uy*n2[1] + uz*n2[2];
87 if ( fabs(ps2) < fabs(ps1) ) {
88 n1 = &mesh->xpoint[p0->xp].n2[0];
89 ps1 = ps2;
90 }
91 }
92 else if ( MG_REF & p0->tag || MG_BDY & p0->tag ) {
93 // ( MG_BDY & p0->tag ) => mmg3d
94 n1 = &mesh->xpoint[p0->xp].n1[0];
95 ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
96 }
97 else {
98 // we come from mmgs because in mmg3d the boundary points are tagged
99 // MG_BDY.
100 n1 = &(p0->n[0]);
101 ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
102 }
103 gammaprim0[0] = ux - ps1*n1[0];
104 gammaprim0[1] = uy - ps1*n1[1];
105 gammaprim0[2] = uz - ps1*n1[2];
106 }
107
108 if ( MG_SIN(p1->tag) || (MG_NOM & p1->tag) ) {
109 gammaprim1[0] = -ux;
110 gammaprim1[1] = -uy;
111 gammaprim1[2] = -uz;
112 }
113 else if ( isedg ) {
114 memcpy(t,p1->n,3*sizeof(double));
115 ps1 = -ux*t[0] - uy*t[1] - uz*t[2];
116 gammaprim1[0] = ps1*t[0];
117 gammaprim1[1] = ps1*t[1];
118 gammaprim1[2] = ps1*t[2];
119 }
120 else {
121 if ( MG_GEO & p1->tag ) {
122 n1 = &mesh->xpoint[p1->xp].n1[0];
123 n2 = &mesh->xpoint[p1->xp].n2[0];
124 ps1 = -ux*n1[0] - uy*n1[1] - uz*n1[2];
125 ps2 = -ux*n2[0] - uy*n2[1] - uz*n2[2];
126
127 if ( fabs(ps2) < fabs(ps1) ) {
128 n1 = &mesh->xpoint[p1->xp].n2[0];
129 ps1 = ps2;
130 }
131 }
132 else if ( MG_REF & p1->tag || MG_BDY & p1->tag ) {
133 // ( MG_BDY & p1->tag ) => mmg3d )
134 n1 = &mesh->xpoint[p1->xp].n1[0];
135 ps1 = - ux*n1[0] - uy*n1[1] - uz*n1[2];
136 }
137 else {
138 // we come from mmgs because in mmg3d the boundary points are tagged
139 // MG_BDY.
140 n1 = &(p1->n[0]);
141 ps1 = -ux*n1[0] - uy*n1[1] - uz*n1[2];
142 }
143 gammaprim1[0] = - ux - ps1*n1[0];
144 gammaprim1[1] = - uy - ps1*n1[1];
145 gammaprim1[2] = - uz - ps1*n1[2];
146 }
147
148 /* computation of the length of the two tangent vectors in their respective
149 * tangent plane */
150 /* l_ab = int_a^b sqrt(m_ij d_t x_i(t) d_t x_j(t) ) : evaluated by a 2-point
151 * quadrature method. */
152 l0 = m0[0]*gammaprim0[0]*gammaprim0[0] + m0[3]*gammaprim0[1]*gammaprim0[1] \
153 + m0[5]*gammaprim0[2]*gammaprim0[2] \
154 + 2.0*m0[1]*gammaprim0[0]*gammaprim0[1] + 2.0*m0[2]*gammaprim0[0]*gammaprim0[2] \
155 + 2.0*m0[4]*gammaprim0[1]*gammaprim0[2];
156
157 l1 = m1[0]*gammaprim1[0]*gammaprim1[0] + m1[3]*gammaprim1[1]*gammaprim1[1] \
158 + m1[5]*gammaprim1[2]*gammaprim1[2] \
159 +2.0*m1[1]*gammaprim1[0]*gammaprim1[1] + 2.0*m1[2]*gammaprim1[0]*gammaprim1[2] \
160 + 2.0*m1[4]*gammaprim1[1]*gammaprim1[2];
161
162 if( l0 < 0.) {
163 if ( !mmgWarn ) {
164 fprintf(stderr," ## Warning: %s: at least 1 negative edge length "
165 "(%e)\n",__func__,l0);
166 mmgWarn = 1;
167 }
168 return 0.;
169 }
170 if(l1 < 0.) {
171 if ( !mmgWarn ) {
172 fprintf(stderr," ## Warning: %s: at least 1 negative edge length "
173 "(%e)\n",__func__,l1);
174 mmgWarn = 1;
175 }
176 return 0.;
177 }
178 l0 = 0.5*(sqrt(l0) + sqrt(l1));
179
180 return l0;
181}
182
198static inline
199double MMG5_lenSurfEdg_ani(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int np0,MMG5_int np1,int8_t isedg) {
200 MMG5_pPoint p0,p1;
201 double *m0,*m1,met0[6],met1[6],ux,uy,uz,rbasis[3][3];
202 static int8_t mmgWarn = 0;
203
204 p0 = &mesh->point[np0];
205 p1 = &mesh->point[np1];
206
207 ux = p1->c[0] - p0->c[0];
208 uy = p1->c[1] - p0->c[1];
209 uz = p1->c[2] - p0->c[2];
210
211 /* Set metrics */
212 if ( MG_SIN(p0->tag) || (MG_NOM & p0->tag)) {
213 m0 = &met->m[6*np0];
214 }
215 else if ( MG_GEO & p0->tag ) {
216 /* Note that rbasis isn't used here */
217 if ( !MMG5_buildridmet(mesh,met,np0,ux,uy,uz,met0,rbasis) ) {
218 if ( !mmgWarn ) {
219 fprintf(stderr," ## Warning: %s: a- unable to compute at least 1 ridge"
220 " metric.\n",__func__);
221 mmgWarn = 1;
222 }
223 return 0.;
224 }
225 m0 = met0;
226 }
227 else {
228 m0 = &met->m[6*np0];
229 }
230
231 if ( MG_SIN(p1->tag) || (MG_NOM & p1->tag)) {
232 m1 = &met->m[6*np1];
233 }
234 else if ( MG_GEO & p1->tag ) {
235 /* Note that rbasis isn't used here */
236 if ( !MMG5_buildridmet(mesh,met,np1,ux,uy,uz,met1,rbasis) ) {
237 if ( !mmgWarn ) {
238 fprintf(stderr," ## Warning: %s: b- unable to compute at least 1 ridge"
239 " metric.\n",__func__);
240 mmgWarn = 1;
241 }
242 return 0.;
243 }
244 m1 = met1;
245 }
246 else {
247 m1 = &met->m[6*np1];
248 }
249
250 return MMG5_lenEdg(mesh,np0,np1,m0,m1,isedg);
251}
252
253
267static inline
269 MMG5_int np0,MMG5_int np1,int8_t isedg) {
270 double *m0,*m1;
271
272 /* Set metrics */
273 m0 = &met->m[6*np0];
274 m1 = &met->m[6*np1];
275
276 return MMG5_lenEdg(mesh,np0,np1,m0,m1,isedg);
277}
278
292static
293inline double MMG5_lenSurfEdg_iso(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int ip1,MMG5_int ip2, int8_t isedg) {
294 MMG5_pPoint p1,p2;
295 double h1,h2,l,r,len;
296
297 p1 = &mesh->point[ip1];
298 p2 = &mesh->point[ip2];
299 h1 = met->m[ip1];
300 h2 = met->m[ip2];
301 l = (p2->c[0]-p1->c[0])*(p2->c[0]-p1->c[0]) + (p2->c[1]-p1->c[1])*(p2->c[1]-p1->c[1]) \
302 + (p2->c[2]-p1->c[2])*(p2->c[2]-p1->c[2]);
303 l = sqrt(l);
304 r = h2 / h1 - 1.0;
305 len = fabs(r) < MMG5_EPS ? l / h1 : l / (h2-h1) * log1p(r);
306
307 return len;
308}
309
323static inline
324void MMG5_simredmat(int8_t dim,double *m,double *dm,double *iv) {
325 int8_t i,j,k,ij;
326
327 /* Storage of a matrix as a one-dimensional array: dim*(dim+1)/2 entries for
328 * a symmetric matrix. */
329 ij = 0;
330
331 /* Loop on matrix rows */
332 for( i = 0; i < dim; i++ ) {
333 /* Loop on the upper-triangular part of the matrix */
334 for( j = i; j < dim; j++ ) {
335 /* Initialize matrix entry */
336 m[ij] = 0.0;
337 /* Compute matrix entry as the recomposition of diagonal values after
338 * projection on the coreduction basis, using the inverse of the
339 * transformation:
340 *
341 * M_{ij} = \sum_{k,l} V^{-1}_{ki} Lambda_{kl} V^{-1}_{lj} =
342 * = \sum_{k} lambda_{k} V^{-1}_{ki} V^{-1}_{kj}
343 *
344 * Since the inverse of the transformation is the inverse of an
345 * eigenvectors matrix (which is stored in Mmg by columns, and not by
346 * rows), the storage of the inverse matrix is also transposed and the
347 * indices have to be exchanged when implementing the above formula. */
348 for( k = 0; k < dim; k++ ) {
349 m[ij] += dm[k]*iv[i*dim+k]*iv[j*dim+k];
350 }
351 /* Go to the next entry */
352 ++ij;
353 }
354 }
355 assert( ij == (dim+1)*dim/2 );
356}
357
358#endif
MMG5_pMesh * mesh
#define MMG5_EPS
static double MMG5_lenSurfEdg_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip1, MMG5_int ip2, int8_t isedg)
static double MMG5_lenSurfEdg33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int np0, MMG5_int np1, int8_t isedg)
static void MMG5_simredmat(int8_t dim, double *m, double *dm, double *iv)
static double MMG5_lenSurfEdg_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int np0, MMG5_int np1, int8_t isedg)
static double MMG5_lenEdg(MMG5_pMesh mesh, MMG5_int np0, MMG5_int np1, double *m0, double *m1, int8_t isedg)
inlined Functions
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 MG_SIN(tag)
#define MG_BDY
#define MG_NOM
#define MG_REF
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:650
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double n[3]
Definition: libmmgtypes.h:278
double c[3]
Definition: libmmgtypes.h:277
uint16_t tag
Definition: libmmgtypes.h:290
MMG5_int xp
Definition: libmmgtypes.h:285
double * m
Definition: libmmgtypes.h:680
double n2[3]
Definition: libmmgtypes.h:301
double n1[3]
Definition: libmmgtypes.h:301