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
52static inline
53double MMG5_lenEdg(MMG5_pMesh mesh,MMG5_int np0,MMG5_int np1,
54 double *m0,double *m1,int8_t isedg) {
55 MMG5_pPoint p0,p1;
56 double gammaprim0[3],gammaprim1[3],t[3],*n1,*n2,ux,uy,uz,ps1,ps2,l0,l1;
57 static int8_t mmgWarn=0;
58
59 p0 = &mesh->point[np0];
60 p1 = &mesh->point[np1];
61
62 ux = p1->c[0] - p0->c[0];
63 uy = p1->c[1] - p0->c[1];
64 uz = p1->c[2] - p0->c[2];
65
66 /* computation of the two tangent vectors to the underlying curve of [i0i1] */
67 if ( MG_SIN(p0->tag) || (MG_NOM & p0->tag) ) {
68 gammaprim0[0] = ux;
69 gammaprim0[1] = uy;
70 gammaprim0[2] = uz;
71 }
72 else if ( isedg ) {
73 memcpy(t,p0->n,3*sizeof(double));
74 ps1 = ux*t[0] + uy*t[1] + uz*t[2];
75 gammaprim0[0] = ps1*t[0];
76 gammaprim0[1] = ps1*t[1];
77 gammaprim0[2] = ps1*t[2];
78 }
79 else {
80 if ( MG_GEO & p0->tag ) {
81 //assert(p0->xp);
82 n1 = &mesh->xpoint[p0->xp].n1[0];
83 n2 = &mesh->xpoint[p0->xp].n2[0];
84 ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
85 ps2 = ux*n2[0] + uy*n2[1] + uz*n2[2];
86
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
196static inline
197double MMG5_lenSurfEdg_ani(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int np0,MMG5_int np1,int8_t isedg) {
198 MMG5_pPoint p0,p1;
199 double *m0,*m1,met0[6],met1[6],ux,uy,uz,rbasis[3][3];
200 static int8_t mmgWarn = 0;
201
202 p0 = &mesh->point[np0];
203 p1 = &mesh->point[np1];
204
205 ux = p1->c[0] - p0->c[0];
206 uy = p1->c[1] - p0->c[1];
207 uz = p1->c[2] - p0->c[2];
208
209 /* Set metrics */
210 if ( MG_SIN(p0->tag) || (MG_NOM & p0->tag)) {
211 m0 = &met->m[6*np0];
212 }
213 else if ( MG_GEO & p0->tag ) {
214 /* Note that rbasis isn't used here */
215 if ( !MMG5_buildridmet(mesh,met,np0,ux,uy,uz,met0,rbasis) ) {
216 if ( !mmgWarn ) {
217 fprintf(stderr," ## Warning: %s: a- unable to compute at least 1 ridge"
218 " metric.\n",__func__);
219 mmgWarn = 1;
220 }
221 return 0.;
222 }
223 m0 = met0;
224 }
225 else {
226 m0 = &met->m[6*np0];
227 }
228
229 if ( MG_SIN(p1->tag) || (MG_NOM & p1->tag)) {
230 m1 = &met->m[6*np1];
231 }
232 else if ( MG_GEO & p1->tag ) {
233 /* Note that rbasis isn't used here */
234 if ( !MMG5_buildridmet(mesh,met,np1,ux,uy,uz,met1,rbasis) ) {
235 if ( !mmgWarn ) {
236 fprintf(stderr," ## Warning: %s: b- unable to compute at least 1 ridge"
237 " metric.\n",__func__);
238 mmgWarn = 1;
239 }
240 return 0.;
241 }
242 m1 = met1;
243 }
244 else {
245 m1 = &met->m[6*np1];
246 }
247
248 return MMG5_lenEdg(mesh,np0,np1,m0,m1,isedg);
249}
250
251
264static inline
266 MMG5_int np0,MMG5_int np1,int8_t isedg) {
267 double *m0,*m1;
268
269 /* Set metrics */
270 m0 = &met->m[6*np0];
271 m1 = &met->m[6*np1];
272
273 return MMG5_lenEdg(mesh,np0,np1,m0,m1,isedg);
274}
275
289static
290inline double MMG5_lenSurfEdg_iso(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int ip1,MMG5_int ip2, int8_t isedg) {
291 MMG5_pPoint p1,p2;
292 double h1,h2,l,r,len;
293
294 p1 = &mesh->point[ip1];
295 p2 = &mesh->point[ip2];
296 h1 = met->m[ip1];
297 h2 = met->m[ip2];
298 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]) \
299 + (p2->c[2]-p1->c[2])*(p2->c[2]-p1->c[2]);
300 l = sqrt(l);
301 r = h2 / h1 - 1.0;
302 len = fabs(r) < MMG5_EPS ? l / h1 : l / (h2-h1) * log1p(r);
303
304 return len;
305}
306
320static inline
321void MMG5_simredmat(int8_t dim,double *m,double *dm,double *iv) {
322 int8_t i,j,k,ij;
323
324 /* Storage of a matrix as a one-dimensional array: dim*(dim+1)/2 entries for
325 * a symmetric matrix. */
326 ij = 0;
327
328 /* Loop on matrix rows */
329 for( i = 0; i < dim; i++ ) {
330 /* Loop on the upper-triangular part of the matrix */
331 for( j = i; j < dim; j++ ) {
332 /* Initialize matrix entry */
333 m[ij] = 0.0;
334 /* Compute matrix entry as the recomposition of diagonal values after
335 * projection on the coreduction basis, using the inverse of the
336 * transformation:
337 *
338 * M_{ij} = \sum_{k,l} V^{-1}_{ki} Lambda_{kl} V^{-1}_{lj} =
339 * = \sum_{k} lambda_{k} V^{-1}_{ki} V^{-1}_{kj}
340 *
341 * Since the inverse of the transformation is the inverse of an
342 * eigenvectors matrix (which is stored in Mmg by columns, and not by
343 * rows), the storage of the inverse matrix is also transposed and the
344 * indices have to be exchanged when implementing the above formula. */
345 for( k = 0; k < dim; k++ ) {
346 m[ij] += dm[k]*iv[i*dim+k]*iv[j*dim+k];
347 }
348 /* Go to the next entry */
349 ++ij;
350 }
351 }
352 assert( ij == (dim+1)*dim/2 );
353}
354
355#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:605
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double n[3]
Definition: libmmgtypes.h:272
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
MMG5_int xp
Definition: libmmgtypes.h:279
double * m
Definition: libmmgtypes.h:671
double n2[3]
Definition: libmmgtypes.h:295
double n1[3]
Definition: libmmgtypes.h:295