Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
velextls_3d.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#ifdef USE_ELAS
36
37#include "libmmg3d_private.h"
38#include "ls_calls.h"
39
40#define MMG5_DEGTOL 0.75
41#define _LS_LAMBDA 10.0e5
42#define _LS_MU 8.2e5
43
59MMG5_int* MMG5_packLS(MMG5_pMesh mesh,MMG5_pSol disp,LSst *lsst,MMG5_int *npfin) {
60 MMG5_pTetra pt,pt1;
61 MMG5_pxTetra pxt;
62 MMG5_pPoint p0;
63 double u[3];
64 int n,nlay,ilist,ilisto,ilistck;
65 MMG5_int k,ip,npf,ntf,iel,jel,*perm,*invperm,*adja,*list,vper[4];
66 int refdirh,refdirnh;
67 int8_t i,j,jface;
68
69 nlay = 20;
70 refdirh = 0;
71 refdirnh = 1;
72 npf = 0;
73 ntf = 0;
74 u[0] = u[1] = u[2] = 0.0;
75 *npfin = 0;
76
77 MMG5_ADD_MEM(mesh,(mesh->ne+1)*sizeof(MMG5_int),"element list",return NULL);
78 MMG5_SAFE_CALLOC(list,mesh->ne+1,MMG5_int,return NULL);
79
80 MMG5_ADD_MEM(mesh,(mesh->np+1)*sizeof(MMG5_int),"point permutation",return NULL);
81 MMG5_SAFE_CALLOC(perm,mesh->np+1,MMG5_int,return NULL);
82
83 ilist = ilisto = ilistck = 0;
84
85 for (k=1; k<=mesh->ne; k++)
86 mesh->tetra[k].mark = 0; // A faire fusionner avec celui de mmg3d3.c
87
88 /* Step 1: pile all the tetras containing a triangle with ref DISPREF */
89 for(k=1; k<=mesh->ne; k++) {
90 pt = &mesh->tetra[k];
91 if ( !MG_EOK(pt) || !pt->xt ) continue;
92 pxt = &mesh->xtetra[pt->xt];
93
94 for(i=0; i<4; i++) {
95 if ( (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
96 ilist++;
97 list[ilist] = k;
98 MG_SET(pt->mark,0);
99
100 for(j=0; j<4; j++) {
101 ip = pt->v[j];
102 if ( !perm[ip] ) {
103 npf++;
104 perm[ip] = npf;
105 }
106 }
107 break;
108 }
109 }
110 }
111 if ( !npf ) {
112 fprintf(stderr,
113 "\n ## Error: %s: no triangle with reference %d in the mesh.\n"
114 " Nothing to move.\n",__func__,MMG5_DISPREF);
115 MMG5_DEL_MEM ( mesh,list );
116 MMG5_DEL_MEM ( mesh,perm );
117 return NULL;
118 }
119
120 /* Step 2: create a layer around these tetras */
121 for(n=0; n<nlay; n++) {
122 ilistck = ilisto;
123 ilisto = ilist;
124
125 for(k=ilistck+1; k<=ilisto; k++) {
126 iel = list[k];
127 adja = &mesh->adja[4*(iel-1)+1];
128
129 for(i=0; i<4; i++) {
130 jel = adja[i] / 4;
131 if ( !jel ) continue;
132 pt1 = &mesh->tetra[jel];
133 if ( MG_EOK(pt1) && (!MG_GET(pt1->mark,0) ) ) {
134 ilist++;
135 assert( ilist <= mesh->ne );
136 MG_SET(pt1->mark,0);
137 list[ilist] = jel;
138
139 for(j=0; j<4; j++) {
140 ip = pt1->v[j];
141 if ( !perm[ip] ) {
142 npf++;
143 perm[ip] = npf;
144 }
145 }
146 }
147 }
148 }
149 }
150
151 /* Creation of the inverse permutation table */
152 MMG5_ADD_MEM ( mesh,(npf+1)*sizeof(MMG5_int),"permutation table",
153 MMG5_DEL_MEM ( mesh,list );
154 MMG5_DEL_MEM ( mesh,perm );
155 return NULL );
156 MMG5_SAFE_CALLOC ( invperm,(npf+1),MMG5_int,
157 MMG5_DEL_MEM ( mesh,list );
158 MMG5_DEL_MEM ( mesh,perm );
159 return NULL );
160
161 /* Step 3: count of the surface triangles in the new mesh
162 Code for pt->mark : if MG_GET(pt->mark,0) = in the list
163 if !MG_GET(pt->mark,0) = not in the list
164 if MG_GET(pt->mark, i+1) : face i has a boundary triangle which has already been counted */
165 for(k=1; k<=ilist; k++) {
166 iel = list[k];
167 pt = &mesh->tetra[iel];
168 adja = &mesh->adja[4*(iel-1)+1];
169 if (pt->xt) pxt = &mesh->xtetra[pt->xt];
170
171 for(i=0; i<4; i++) {
172 jel = adja[i] / 4;
173 jface = adja[i] % 4;
174
175 /* Face i carries a non homogeneous Dirichlet BC */
176 if ( pt->xt && (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
177 /* If this triangle has not been taken into account */
178 if ( MG_GET(pt->mark,i+1) ) continue;
179
180 ntf++;
181 if ( !jel ) continue;
182 pt1 = &mesh->tetra[jel];
183 MG_SET(pt1->mark,jface+1);
184 }
185 /* iel has no neighbour through face i within the list */
186 else if ( !jel || ( !mesh->tetra[jel].mark ) ) ntf++;
187 }
188 }
189
190 /* Step 4: creation of the mesh for elasticity */
191 if ( !LS_mesh(lsst,npf,0,ntf,ilist) ) {
192 fprintf(stderr,"\n ## Error: %s: problem in fn LS_mesh. Exiting.\n",
193 __func__);
194 MMG5_DEL_MEM ( mesh,list );
195 MMG5_DEL_MEM ( mesh,perm );
196 MMG5_DEL_MEM ( mesh,invperm );
197 return NULL;
198 }
199
200 /* Set verbosity and debug info */
201 LS_setPar(lsst, (mesh->info.imprim > 0), 0);
202
203 /* Step 5: fill the LS mesh */
204 /* Add vertices */
205 for(k=1; k<=mesh->np; k++) {
206 ip = perm[k];
207 if ( !ip ) continue;
208
209 p0 = &mesh->point[k];
210 invperm[ip] = k;
211 if ( !LS_addVer(lsst,ip,p0->c,p0->ref) ) {
212 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addVer. Exiting.\n",
213 __func__);
214 MMG5_DEL_MEM ( mesh,list );
215 MMG5_DEL_MEM ( mesh,perm );
216 MMG5_DEL_MEM ( mesh,invperm );
217 return NULL;
218 }
219 }
220
221 /* Add tetrahedra */
222 for(k=1; k<=ilist; k++) {
223 iel = list[k];
224 pt = &mesh->tetra[iel];
225
226 for(i=0; i<4; i++)
227 vper[i] = perm[pt->v[i]];
228
229 if (!LS_addTet(lsst,(int)k,(int*)vper,0) ) {
230 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTet. Exiting.\n",
231 __func__);
232 MMG5_DEL_MEM ( mesh,list );
233 MMG5_DEL_MEM ( mesh,perm );
234 MMG5_DEL_MEM ( mesh,invperm );
235 return NULL;
236 }
237 }
238
239 /* Add surface triangles */
240 ntf = 0;
241 for(k=1; k<=ilist; k++) {
242 iel = list[k];
243 pt = &mesh->tetra[iel];
244 adja = &mesh->adja[4*(iel-1)+1];
245 if (pt->xt) pxt = &mesh->xtetra[pt->xt];
246
247 for(i=0; i<4; i++) {
248 jel = adja[i] / 4;
249
250 /* Face i carries a non homogeneous Dirichlet BC */
251 if ( pt->xt && (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
252 /* If this triangle has not been taken into account */
253 if ( MG_GET(pt->mark,i+1) ) continue;
254 ntf++;
255 for (j=0; j<3; j++)
256 vper[j] = perm[pt->v[MMG5_idir[i][j]]];
257
258 if ( !LS_addTri(lsst,(int)ntf,(int*)vper,refdirnh) ) {
259 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTri. Exiting.\n",
260 __func__);
261 MMG5_DEL_MEM ( mesh,list );
262 MMG5_DEL_MEM ( mesh,perm );
263 MMG5_DEL_MEM ( mesh,invperm );
264 return NULL;
265 }
266 }
267 /* iel has no neighbour through face i within list */
268 else if ( !jel || (!mesh->tetra[jel].mark) ) {
269 ntf++;
270 for (j=0; j<3; j++)
271 vper[j] = perm[pt->v[MMG5_idir[i][j]]];
272
273 if ( !LS_addTri(lsst,(int)ntf,(int*)vper,refdirh) ) {
274 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTri. Exiting.\n",
275 __func__);
276 MMG5_DEL_MEM ( mesh,list );
277 MMG5_DEL_MEM ( mesh,perm );
278 MMG5_DEL_MEM ( mesh,invperm );
279 return NULL;
280 }
281 }
282 }
283 }
284
285 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && (ilist+npf+ntf > 0) )
286 printf("Number of packed tetra %d, points %" MMG5_PRId
287 ", triangles %" MMG5_PRId "\n",ilist,npf,ntf);
288
289 /* Add boundary conditions */
290 if ( !LS_setBC(lsst,Dirichlet,refdirnh,'f',LS_tri,NULL) ) {
291 fprintf(stderr,"\n ## Error: %s: problem in fn LS_set BC. Exiting.\n",
292 __func__);
293 MMG5_DEL_MEM ( mesh,list );
294 MMG5_DEL_MEM ( mesh,perm );
295 MMG5_DEL_MEM ( mesh,invperm );
296 return NULL;
297 }
298
299 if ( !LS_setBC(lsst,Dirichlet,refdirh,'v',LS_tri,u) ) {
300 fprintf(stderr,"\n ## Error: %s: problem in fn LS_set BC. Exiting.\n",
301 __func__);
302 MMG5_DEL_MEM ( mesh,list );
303 MMG5_DEL_MEM ( mesh,perm );
304 MMG5_DEL_MEM ( mesh,invperm );
305 return NULL;
306 }
307
308 /* Add materials */
309 if ( !LS_setLame(lsst,0,_LS_LAMBDA,_LS_MU) ) {
310 fprintf(stderr,"\n ## Error: %s: problem in fn LS_setLame. Exiting.\n",
311 __func__);
312 MMG5_DEL_MEM ( mesh,list );
313 MMG5_DEL_MEM ( mesh,perm );
314 MMG5_DEL_MEM ( mesh,invperm );
315 return NULL;
316 }
317
318 /* Transfer displacement */
319 if ( !LS_newSol(lsst) ) {
320 fprintf(stderr,"\n ## Error: %s: problem in fn LS_newSol. Exiting.\n",
321 __func__);
322 MMG5_DEL_MEM ( mesh,list );
323 MMG5_DEL_MEM ( mesh,perm );
324 MMG5_DEL_MEM ( mesh,invperm );
325 return NULL;
326 }
327
328 for(k=1; k<=mesh->np; k++) {
329 ip = perm[k];
330 if ( !ip ) continue;
331
332 if ( !LS_addSol(lsst,ip,&disp->m[3*k]) ) {
333 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addSol. Exiting.\n",
334 __func__);
335 MMG5_DEL_MEM ( mesh,list );
336 MMG5_DEL_MEM ( mesh,perm );
337 MMG5_DEL_MEM ( mesh,invperm );
338 return NULL;
339 }
340 }
341
342 *npfin = npf;
343 MMG5_DEL_MEM ( mesh,list );
344 MMG5_DEL_MEM ( mesh,perm );
345
346 return invperm;
347}
348
362int MMG5_unpackLS(MMG5_pMesh mesh,MMG5_pSol disp,LSst *lsst,MMG5_int npf,MMG5_int *invperm) {
363 double *u;
364 MMG5_int ip,k;
365 int8_t i;
366
367 u = LS_getSol(lsst);
368
369 for(k=1; k<=mesh->np; k++) {
370 for(i=0; i<3; i++)
371 disp->m[3*k+i] = 0.0;
372 }
373
374 for(k=1; k<=npf; k++) {
375 ip = invperm[k];
376
377 for(i=0; i<3; i++)
378 disp->m[3*ip+i] = u[3*(k-1)+i];
379 }
380
381 return 1;
382}
383
394 LSst *lsst;
395 MMG5_int npf,*invperm;
396
397 /* LibElas is not compatible with int64: Check for int32 overflow */
398 if ( mesh->np > INT_MAX || mesh->ne > INT_MAX || sizeof(MMG5_int) == 8 ) {
399 fprintf(stderr,"\n ## Error: %s: impossible to call elasticity library"
400 " with int64 integers.\n",__func__);
401 return 0;
402 }
403
404 /* Creation of the data structure for the submesh */
405 lsst = LS_init(mesh->dim,mesh->ver,P1,1);
406 invperm = MMG5_packLS(mesh,disp,lsst,&npf);
407
408 if ( !npf ) {
409 fprintf(stderr,"\n ## Error: %s: problem in fn MMG5_packLS. Exiting.\n",
410 __func__);
411 return 0;
412 }
413
414 /* Resolution of the elasticity system on the submesh */
415 if ( !LS_elastic(lsst) ) {
416 fprintf(stderr,"\n ## Error: %s: Problem in fn elasti1. Exiting.\n",
417 __func__);
418 return 0;
419 }
420
421 /* Update of the displacement */
422 if ( !MMG5_unpackLS(mesh,disp,lsst,npf,invperm) ) {
423 fprintf(stderr,"\n ## Error: %s: problem in fn MMG5_unpackLS. Exiting.\n",
424 __func__);
425 return 0;
426 }
427
428 /* Free memory */
429 MMG5_DEL_MEM ( mesh, invperm );
430
431 if ( !LS_stop(lsst) ) {
432 fprintf(stderr,"\n ## Error: %s: problem in fn LS_stop. Exiting.\n",
433 __func__);
434 return 0;
435 }
436
437 return 1;
438}
439#else
445#ifdef _WIN32
446void MMG3D_unused_function(void) {
447 return;
448}
449#else
450void __attribute__((unused)) MMG3D_unused_function(void) {
451 return;
452}
453#endif
454
455#endif
if(!ier) exit(EXIT_FAILURE)
MMG5_pMesh * mesh
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MMG5_DISPREF
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MG_GET(flag, bit)
#define MG_BDY
#define MMG5_DEL_MEM(mesh, ptr)
#define MG_SET(flag, bit)
int8_t ddebug
Definition: libmmgtypes.h:539
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_int ne
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_pTetra tetra
Definition: libmmgtypes.h:651
MMG5_int np
Definition: libmmgtypes.h:620
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:652
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double c[3]
Definition: libmmgtypes.h:277
MMG5_int ref
Definition: libmmgtypes.h:284
double * m
Definition: libmmgtypes.h:680
Structure to store tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:407
MMG5_int v[4]
Definition: libmmgtypes.h:409
MMG5_int xt
Definition: libmmgtypes.h:413
MMG5_int mark
Definition: libmmgtypes.h:412
Structure to store additional information for the surface tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:425
MMG5_int ref[4]
Definition: libmmgtypes.h:426
uint16_t ftag[4]
Definition: libmmgtypes.h:430
MMG5_int * MMG5_packLS(MMG5_pMesh mesh, MMG5_pSol disp, LSst *lsst, MMG5_int *npfin)
Definition: velextls_3d.c:59
int MMG5_unpackLS(MMG5_pMesh mesh, MMG5_pSol disp, LSst *lsst, MMG5_int npf, MMG5_int *invperm)
Definition: velextls_3d.c:362
#define _LS_MU
Definition: velextls_3d.c:42
int MMG5_velextLS(MMG5_pMesh mesh, MMG5_pSol disp)
Definition: velextls_3d.c:393
#define _LS_LAMBDA
Definition: velextls_3d.c:41