Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
optlap_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
34#include "libmmg3d.h"
37
47 MMG5_pTetra pt,pt1;
48 MMG5_pPoint ppt,pptb,ppta;
49
50 int it,lon,l;
51 int64_t list[MMG3D_LMAX+2];
52 MMG5_int k,i,iel,ipt,ipta,iptb;
53 int maxiter;
54 MMG5_int ipt0,ipt1,ipt2,ipt3,*compt;
55 double vol,ax,ay,az,bx,by,bz;
56 double *nv,*pos,res,dd,ox,oy,oz,declic;
57 double LLAMBDA = 0.33;
58 double LMU = 0.331;
59
60 maxiter = 3;
61 MMG5_ADD_MEM(mesh,(3*mesh->np+1)*sizeof(double),"nv",
62 return 0);
63 MMG5_ADD_MEM(mesh,(3*mesh->np+1)*sizeof(double),"pos",
64 return 0);
65 MMG5_ADD_MEM(mesh,(mesh->np+1)*sizeof(double),"compt",
66 return 0);
67 MMG5_SAFE_CALLOC(nv, 3*mesh->np+1, double,return 0);
68 MMG5_SAFE_CALLOC(pos, 3*mesh->np+1, double,return 0);
69 MMG5_SAFE_CALLOC(compt, mesh->np+1, MMG5_int,return 0);
70
71 it = 1;
72 declic = 3./MMG3D_ALPHAD;
73 do {
74
75 /*initialisation*/
76 for(i = 1 ; i<=mesh->np ; i++) {
77 compt[i] = 0;
78 pos[3*(i-1) + 1 + 0] = 0.;
79 pos[3*(i-1) + 1 + 1] = 0.;
80 pos[3*(i-1) + 1 + 2] = 0.;
81 }
82
83 /*1st stage : laplacian*/
84 for(k = 1 ; k<=mesh->ne ; k++) {
85 pt = &mesh->tetra[k];
86 if ( (!MG_EOK(pt)) || MG_REQ & pt->tag || pt->qual > declic ) continue;
87
88 for(i=0 ; i<6 ; i++) {
89 ipta = pt->v[MMG5_iare[i][0]];
90 ppta = &mesh->point[ipta];
91
92 iptb = pt->v[MMG5_iare[i][1]];
93 pptb = &mesh->point[iptb];
94
95 if ( !( (ppta->tag & MG_BDY) || (ppta->tag & MG_REQ) ) ) {
96 pos[3*(ipta-1) + 1 + 0] += pptb->c[0];
97 pos[3*(ipta-1) + 1 + 1] += pptb->c[1];
98 pos[3*(ipta-1) + 1 + 2] += pptb->c[2];
99 compt[ipta]++;
100 }
101 if ( !( (pptb->tag & MG_BDY) || (pptb->tag & MG_REQ) ) ) {
102 pos[3*(iptb-1) + 1 + 0] += ppta->c[0];
103 pos[3*(iptb-1) + 1 + 1] += ppta->c[1];
104 pos[3*(iptb-1) + 1 + 2] += ppta->c[2];
105 compt[iptb]++;
106 }
107 }
108 }
109
110 for ( i=1 ; i<=mesh->np ; i++) {
111
112 ppt = &mesh->point[i];
113 if ( !MG_VOK(ppt) ) {
114 assert ( !compt[i] );
115 continue;
116 }
117
118 if ( compt[i]) {
119 dd = 1./(double) compt[i];
120 pos[3*(i-1) + 1 + 0] *= dd;
121 pos[3*(i-1) + 1 + 1] *= dd;
122 pos[3*(i-1) + 1 + 2] *= dd;
123 nv[3*(i-1) + 1] = ppt->c[0] + LLAMBDA * (ppt->c[0] - pos[3*(i-1) + 1 + 0]);
124 nv[3*(i-1) + 2] = ppt->c[1] + LLAMBDA * (ppt->c[1] - pos[3*(i-1) + 1 + 1]);
125 nv[3*(i-1) + 3] = ppt->c[2] + LLAMBDA * (ppt->c[2] - pos[3*(i-1) + 1 + 2]);
126 } else {
127 nv[3*(i-1) + 1] = ppt->c[0];
128 nv[3*(i-1) + 2] = ppt->c[1];
129 nv[3*(i-1) + 3] = ppt->c[2];
130
131 }
132 compt[i] = 0;
133 pos[3*(i-1) + 1 + 0] = 0.;
134 pos[3*(i-1) + 1 + 1] = 0.;
135 pos[3*(i-1) + 1 + 2] = 0.;
136
137 }
138
139 /* 2nd stage : anti-laplacian */
140 for(k = 1 ; k<=mesh->ne ; k++) {
141 pt = &mesh->tetra[k];
142 if ( (!MG_EOK(pt)) || MG_REQ & pt->tag || pt->qual > declic ) continue;
143
144 for(i=0 ; i<6 ; i++) {
145 ipta = pt->v[MMG5_iare[i][0]];
146 ppta = &mesh->point[ipta];
147
148 iptb = pt->v[MMG5_iare[i][1]];
149 pptb = &mesh->point[iptb];
150
151 if ( !( (ppta->tag & MG_BDY) || (ppta->tag & MG_REQ) ) ) {
152 pos[3*(ipta-1) + 1 + 0] += nv[3*(iptb-1) + 1];
153 pos[3*(ipta-1) + 1 + 1] += nv[3*(iptb-1) + 2];
154 pos[3*(ipta-1) + 1 + 2] += nv[3*(iptb-1) + 3];
155 compt[ipta]++;
156 }
157 if ( !( (pptb->tag & MG_BDY) || (pptb->tag & MG_REQ) ) ) {
158 pos[3*(iptb-1) + 1 + 0] += nv[3*(ipta-1) + 1];
159 pos[3*(iptb-1) + 1 + 1] += nv[3*(ipta-1) + 2];
160 pos[3*(iptb-1) + 1 + 2] += nv[3*(ipta-1) + 3];
161 compt[iptb]++;
162 }
163 }
164 }
165
166 res= 0.;
167 for(i=1 ; i<=mesh->np ; i++) {
168 if ( compt[i] ) {
169 dd = 1./(double) compt[i];
170 pos[3*(i-1) + 1 + 0] *= dd;
171 pos[3*(i-1) + 1 + 1] *= dd;
172 pos[3*(i-1) + 1 + 2] *= dd;
173 ox = nv[3*(i-1) + 1];
174 oy = nv[3*(i-1) + 2];
175 oz = nv[3*(i-1) + 3];
176 nv[3*(i-1) + 1] = nv[3*(i-1) + 1] - LMU * (nv[3*(i-1) + 1] - pos[3*(i-1) + 1 + 0]);
177 nv[3*(i-1) + 2] = nv[3*(i-1) + 2] - LMU * (nv[3*(i-1) + 2] - pos[3*(i-1) + 1 + 1]);
178 nv[3*(i-1) + 3] = nv[3*(i-1) + 3] - LMU * (nv[3*(i-1) + 3] - pos[3*(i-1) + 1 + 2]);
179
180 dd = (nv[3*(i-1) + 1]-ox)*(nv[3*(i-1) + 1]-ox)
181 + (nv[3*(i-1) + 2]-oy)*(nv[3*(i-1) + 2]-oy)
182 + (nv[3*(i-1) + 3]-oz)*(nv[3*(i-1) + 3]-oz);
183 res +=dd;
184
185 }
186
187 compt[i] = 0;
188 pos[3*(i-1) + 1 + 0] = 0.;
189 pos[3*(i-1) + 1 + 1] = 0.;
190 pos[3*(i-1) + 1 + 2] = 0.;
191 }
192
193 /* check new coor */
194 for(k = 1 ; k<=mesh->ne ; k++) {
195 pt = &mesh->tetra[k];
196
197 if ( !MG_EOK(pt) ) continue;
198
199 for(i=0 ; i<4 ; i++) {
200 ipt = pt->v[i];
201 ppt = &mesh->point[ipt];
202
203 if ( (ppt->tag & MG_BDY) || (ppt->tag & MG_REQ) ) continue;
204
205 //if(ppt->tmp) continue;
206 //ppt->tmp = 1;
207 lon = MMG5_boulevolp(mesh,k,i,&list[0]);
208
209 for ( l=0; l<lon; l++ ) {
210 iel = list[l] /4;
211 pt1 = &mesh->tetra[iel];
212 ipt0 = 3*(pt1->v[0] - 1);
213 ipt1 = 3*(pt1->v[1] - 1);
214 ipt2 = 3*(pt1->v[2] - 1);
215 ipt3 = 3*(pt1->v[3] - 1);
216
217 ax = nv[ipt2 + 1] - nv[ipt0 + 1];
218 ay = nv[ipt2 + 2] - nv[ipt0 + 2];
219 az = nv[ipt2 + 3] - nv[ipt0 + 3];
220
221 bx = nv[ipt3 + 1] - nv[ipt0 + 1];
222 by = nv[ipt3 + 2] - nv[ipt0 + 2];
223 bz = nv[ipt3 + 3] - nv[ipt0 + 3];
224
225 vol = (nv[ipt1 + 1] - nv[ipt0 + 1]) * (ay*bz - az*by) \
226 + (nv[ipt1 + 2] - nv[ipt0 + 2]) * (az*bx - ax*bz) \
227 + (nv[ipt1 + 3] - nv[ipt0 + 3]) * (ax*by - ay*bx);
228
229 if ( vol < 0 ) {
230 break;
231 }
232 }
233 if ( l<=lon ) {
234 memcpy(&pos[3*(ipt-1) + 1],ppt->c,3*sizeof(double));
235 for ( l=0; l<lon; l++ ) {
236 iel = list[l] / 4;
237 pt1 = &mesh->tetra[iel];
238 ipt0 = 3*(pt1->v[0] - 1);
239 ipt1 = 3*(pt1->v[1] - 1);
240 ipt2 = 3*(pt1->v[2] - 1);
241 ipt3 = 3*(pt1->v[3] - 1);
242
243 ax = nv[ipt2 + 1] - nv[ipt0 + 1];
244 ay = nv[ipt2 + 2] - nv[ipt0 + 2];
245 az = nv[ipt2 + 3] - nv[ipt0 + 3];
246
247 bx = nv[ipt3 + 1] - nv[ipt0 + 1];
248 by = nv[ipt3 + 2] - nv[ipt0 + 2];
249 bz = nv[ipt3 + 3] - nv[ipt0 + 3];
250
251 vol = (nv[ipt1 + 1] - nv[ipt0 + 1]) * (ay*bz - az*by) \
252 + (nv[ipt1 + 2] - nv[ipt0 + 2]) * (az*bx - ax*bz) \
253 + (nv[ipt1 + 3] - nv[ipt0 + 3]) * (ax*by - ay*bx);
254
255 if ( vol < 0 ) {
256 break;
257 }
258 }
259
260 if ( l<lon ) break;
261 }
262 }
263 if ( i<4 ) break;
264 }
265
266
267 if(k > mesh->ne) {
268 /*update coor*/
269 for(i=1 ; i<=mesh->np ; i++) {
270 ppt = &mesh->point[i];
271 ppt->c[0] = nv[3*(i-1) + 1];
272 ppt->c[1] = nv[3*(i-1) + 2];
273 ppt->c[2] = nv[3*(i-1) + 3];
274 }
275 for(k=1 ; k<=mesh->ne ; k++) {
276 pt = &mesh->tetra[k];
277 if ( !MG_EOK(pt) ) continue;
278
279 pt->qual = MMG5_caltet(mesh,sol,pt);
280 }
281 if( mesh->info.imprim > 5) fprintf(stdout," LAPLACIAN : %8f\n",res);
282 } else {
283 if( mesh->info.imprim > 5) fprintf(stdout," NO LAPLACIAN\n");
284 break;
285 }
286 if(res<1e-5) break;
287
288 } while(it++ < maxiter);
289
290 MMG5_DEL_MEM(mesh,nv);
291 MMG5_DEL_MEM(mesh,pos);
292 MMG5_DEL_MEM(mesh,compt);
293
294 return 1;
295}
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMG5_boulevolp(MMG5_pMesh mesh, MMG5_int start, int ip, int64_t *list)
Definition: boulep_3d.c:54
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
#define MMG3D_ALPHAD
static const uint8_t MMG5_iare[6][2]
vertices of extremities of the edges of the tetra
#define MG_REQ
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MG_VOK(ppt)
#define MG_BDY
#define MMG5_DEL_MEM(mesh, ptr)
int MMG3D_optlap(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: optlap_3d.c:46
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_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
MMG5_int v[4]
Definition: libmmgtypes.h:403
double qual
Definition: libmmgtypes.h:402
int16_t tag
Definition: libmmgtypes.h:410