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 /* LibElas is not compatible with int64: Check for int32 overflow */
70 if ( mesh->np > INT_MAX || mesh->ne > INT_MAX ) {
71 fprintf(stderr,"\n ## Error: %s: impossible to call elasticity library"
72 " with int64 integers.\n",__func__);
73 return NULL;
74 }
75
76 nlay = 20;
77 refdirh = 0;
78 refdirnh = 1;
79 npf = 0;
80 ntf = 0;
81 u[0] = u[1] = u[2] = 0.0;
82 *npfin = 0;
83
84 MMG5_ADD_MEM(mesh,(mesh->ne+1)*sizeof(MMG5_int),"element list",return NULL);
85 MMG5_SAFE_CALLOC(list,mesh->ne+1,MMG5_int,return NULL);
86
87 MMG5_ADD_MEM(mesh,(mesh->np+1)*sizeof(MMG5_int),"point permutation",return NULL);
88 MMG5_SAFE_CALLOC(perm,mesh->np+1,MMG5_int,return NULL);
89
90 ilist = ilisto = ilistck = 0;
91
92 for (k=1; k<=mesh->ne; k++)
93 mesh->tetra[k].mark = 0; // A faire fusionner avec celui de mmg3d3.c
94
95 /* Step 1: pile all the tetras containing a triangle with ref DISPREF */
96 for(k=1; k<=mesh->ne; k++) {
97 pt = &mesh->tetra[k];
98 if ( !MG_EOK(pt) || !pt->xt ) continue;
99 pxt = &mesh->xtetra[pt->xt];
100
101 for(i=0; i<4; i++) {
102 if ( (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
103 ilist++;
104 list[ilist] = k;
105 MG_SET(pt->mark,0);
106
107 for(j=0; j<4; j++) {
108 ip = pt->v[j];
109 if ( !perm[ip] ) {
110 npf++;
111 perm[ip] = npf;
112 }
113 }
114 break;
115 }
116 }
117 }
118 if ( !npf ) {
119 fprintf(stderr,
120 "\n ## Error: %s: no triangle with reference %d in the mesh.\n"
121 " Nothing to move.\n",__func__,MMG5_DISPREF);
122 MMG5_DEL_MEM ( mesh,list );
123 MMG5_DEL_MEM ( mesh,perm );
124 return NULL;
125 }
126
127 /* Step 2: create a layer around these tetras */
128 for(n=0; n<nlay; n++) {
129 ilistck = ilisto;
130 ilisto = ilist;
131
132 for(k=ilistck+1; k<=ilisto; k++) {
133 iel = list[k];
134 adja = &mesh->adja[4*(iel-1)+1];
135
136 for(i=0; i<4; i++) {
137 jel = adja[i] / 4;
138 if ( !jel ) continue;
139 pt1 = &mesh->tetra[jel];
140 if ( MG_EOK(pt1) && (!MG_GET(pt1->mark,0) ) ) {
141 ilist++;
142 assert( ilist <= mesh->ne );
143 MG_SET(pt1->mark,0);
144 list[ilist] = jel;
145
146 for(j=0; j<4; j++) {
147 ip = pt1->v[j];
148 if ( !perm[ip] ) {
149 npf++;
150 perm[ip] = npf;
151 }
152 }
153 }
154 }
155 }
156 }
157
158 /* Creation of the inverse permutation table */
159 MMG5_ADD_MEM ( mesh,(npf+1)*sizeof(MMG5_int),"permutation table",
160 MMG5_DEL_MEM ( mesh,list );
161 MMG5_DEL_MEM ( mesh,perm );
162 return NULL );
163 MMG5_SAFE_CALLOC ( invperm,(npf+1),MMG5_int,
164 MMG5_DEL_MEM ( mesh,list );
165 MMG5_DEL_MEM ( mesh,perm );
166 return NULL );
167
168 /* Step 3: count of the surface triangles in the new mesh
169 Code for pt->mark : if MG_GET(pt->mark,0) = in the list
170 if !MG_GET(pt->mark,0) = not in the list
171 if MG_GET(pt->mark, i+1) : face i has a boundary triangle which has already been counted */
172 for(k=1; k<=ilist; k++) {
173 iel = list[k];
174 pt = &mesh->tetra[iel];
175 adja = &mesh->adja[4*(iel-1)+1];
176 if (pt->xt) pxt = &mesh->xtetra[pt->xt];
177
178 for(i=0; i<4; i++) {
179 jel = adja[i] / 4;
180 jface = adja[i] % 4;
181
182 /* Face i carries a non homogeneous Dirichlet BC */
183 if ( pt->xt && (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
184 /* If this triangle has not been taken into account */
185 if ( MG_GET(pt->mark,i+1) ) continue;
186
187 ntf++;
188 if ( !jel ) continue;
189 pt1 = &mesh->tetra[jel];
190 MG_SET(pt1->mark,jface+1);
191 }
192 /* iel has no neighbour through face i within the list */
193 else if ( !jel || ( !mesh->tetra[jel].mark ) ) ntf++;
194 }
195 }
196
197 /* Step 4: creation of the mesh for elasticity */
198 if ( !LS_mesh(lsst,npf,0,ntf,ilist) ) {
199 fprintf(stderr,"\n ## Error: %s: problem in fn LS_mesh. Exiting.\n",
200 __func__);
201 MMG5_DEL_MEM ( mesh,list );
202 MMG5_DEL_MEM ( mesh,perm );
203 MMG5_DEL_MEM ( mesh,invperm );
204 return NULL;
205 }
206
207 /* Set verbosity and debug info */
208 LS_setPar(lsst, (mesh->info.imprim > 0), 0);
209
210 /* Step 5: fill the LS mesh */
211 /* Add vertices */
212 for(k=1; k<=mesh->np; k++) {
213 ip = perm[k];
214 if ( !ip ) continue;
215
216 p0 = &mesh->point[k];
217 invperm[ip] = k;
218 if ( !LS_addVer(lsst,ip,p0->c,p0->ref) ) {
219 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addVer. Exiting.\n",
220 __func__);
221 MMG5_DEL_MEM ( mesh,list );
222 MMG5_DEL_MEM ( mesh,perm );
223 MMG5_DEL_MEM ( mesh,invperm );
224 return NULL;
225 }
226 }
227
228 /* Add tetrahedra */
229 for(k=1; k<=ilist; k++) {
230 iel = list[k];
231 pt = &mesh->tetra[iel];
232
233 for(i=0; i<4; i++)
234 vper[i] = perm[pt->v[i]];
235
236 if (!LS_addTet(lsst,(int)k,(int*)vper,0) ) {
237 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTet. Exiting.\n",
238 __func__);
239 MMG5_DEL_MEM ( mesh,list );
240 MMG5_DEL_MEM ( mesh,perm );
241 MMG5_DEL_MEM ( mesh,invperm );
242 return NULL;
243 }
244 }
245
246 /* Add surface triangles */
247 ntf = 0;
248 for(k=1; k<=ilist; k++) {
249 iel = list[k];
250 pt = &mesh->tetra[iel];
251 adja = &mesh->adja[4*(iel-1)+1];
252 if (pt->xt) pxt = &mesh->xtetra[pt->xt];
253
254 for(i=0; i<4; i++) {
255 jel = adja[i] / 4;
256
257 /* Face i carries a non homogeneous Dirichlet BC */
258 if ( pt->xt && (pxt->ftag[i] & MG_BDY) && (pxt->ref[i] == MMG5_DISPREF) ) {
259 /* If this triangle has not been taken into account */
260 if ( MG_GET(pt->mark,i+1) ) continue;
261 ntf++;
262 for (j=0; j<3; j++)
263 vper[j] = perm[pt->v[MMG5_idir[i][j]]];
264
265 if ( !LS_addTri(lsst,(int)ntf,(int*)vper,refdirnh) ) {
266 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTri. Exiting.\n",
267 __func__);
268 MMG5_DEL_MEM ( mesh,list );
269 MMG5_DEL_MEM ( mesh,perm );
270 MMG5_DEL_MEM ( mesh,invperm );
271 return NULL;
272 }
273 }
274 /* iel has no neighbour through face i within list */
275 else if ( !jel || (!mesh->tetra[jel].mark) ) {
276 ntf++;
277 for (j=0; j<3; j++)
278 vper[j] = perm[pt->v[MMG5_idir[i][j]]];
279
280 if ( !LS_addTri(lsst,(int)ntf,(int*)vper,refdirh) ) {
281 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addTri. Exiting.\n",
282 __func__);
283 MMG5_DEL_MEM ( mesh,list );
284 MMG5_DEL_MEM ( mesh,perm );
285 MMG5_DEL_MEM ( mesh,invperm );
286 return NULL;
287 }
288 }
289 }
290 }
291
292 if ( (abs(mesh->info.imprim) > 4 || mesh->info.ddebug) && (ilist+npf+ntf > 0) )
293 printf("Number of packed tetra %d, points %" MMG5_PRId
294 ", triangles %" MMG5_PRId "\n",ilist,npf,ntf);
295
296 /* Add boundary conditions */
297 if ( !LS_setBC(lsst,Dirichlet,refdirnh,'f',LS_tri,NULL) ) {
298 fprintf(stderr,"\n ## Error: %s: problem in fn LS_set BC. Exiting.\n",
299 __func__);
300 MMG5_DEL_MEM ( mesh,list );
301 MMG5_DEL_MEM ( mesh,perm );
302 MMG5_DEL_MEM ( mesh,invperm );
303 return NULL;
304 }
305
306 if ( !LS_setBC(lsst,Dirichlet,refdirh,'v',LS_tri,u) ) {
307 fprintf(stderr,"\n ## Error: %s: problem in fn LS_set BC. Exiting.\n",
308 __func__);
309 MMG5_DEL_MEM ( mesh,list );
310 MMG5_DEL_MEM ( mesh,perm );
311 MMG5_DEL_MEM ( mesh,invperm );
312 return NULL;
313 }
314
315 /* Add materials */
316 if ( !LS_setLame(lsst,0,_LS_LAMBDA,_LS_MU) ) {
317 fprintf(stderr,"\n ## Error: %s: problem in fn LS_setLame. Exiting.\n",
318 __func__);
319 MMG5_DEL_MEM ( mesh,list );
320 MMG5_DEL_MEM ( mesh,perm );
321 MMG5_DEL_MEM ( mesh,invperm );
322 return NULL;
323 }
324
325 /* Transfer displacement */
326 if ( !LS_newSol(lsst) ) {
327 fprintf(stderr,"\n ## Error: %s: problem in fn LS_newSol. Exiting.\n",
328 __func__);
329 MMG5_DEL_MEM ( mesh,list );
330 MMG5_DEL_MEM ( mesh,perm );
331 MMG5_DEL_MEM ( mesh,invperm );
332 return NULL;
333 }
334
335 for(k=1; k<=mesh->np; k++) {
336 ip = perm[k];
337 if ( !ip ) continue;
338
339 if ( !LS_addSol(lsst,ip,&disp->m[3*k]) ) {
340 fprintf(stderr,"\n ## Error: %s: problem in fn LS_addSol. Exiting.\n",
341 __func__);
342 MMG5_DEL_MEM ( mesh,list );
343 MMG5_DEL_MEM ( mesh,perm );
344 MMG5_DEL_MEM ( mesh,invperm );
345 return NULL;
346 }
347 }
348
349 *npfin = npf;
350 MMG5_DEL_MEM ( mesh,list );
351 MMG5_DEL_MEM ( mesh,perm );
352
353 return invperm;
354}
355
369int MMG5_unpackLS(MMG5_pMesh mesh,MMG5_pSol disp,LSst *lsst,MMG5_int npf,MMG5_int *invperm) {
370 double *u;
371 MMG5_int ip,k;
372 int8_t i;
373
374 u = LS_getSol(lsst);
375
376 for(k=1; k<=mesh->np; k++) {
377 for(i=0; i<3; i++)
378 disp->m[3*k+i] = 0.0;
379 }
380
381 for(k=1; k<=npf; k++) {
382 ip = invperm[k];
383
384 for(i=0; i<3; i++)
385 disp->m[3*ip+i] = u[3*(k-1)+i];
386 }
387
388 return 1;
389}
390
401 LSst *lsst;
402 MMG5_int npf,*invperm;
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:532
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
MMG5_int ref
Definition: libmmgtypes.h:278
double * m
Definition: libmmgtypes.h:671
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int mark
Definition: libmmgtypes.h:406
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
MMG5_int ref[4]
Definition: libmmgtypes.h:419
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:369
#define _LS_MU
Definition: velextls_3d.c:42
int MMG5_velextLS(MMG5_pMesh mesh, MMG5_pSol disp)
Definition: velextls_3d.c:400
#define _LS_LAMBDA
Definition: velextls_3d.c:41