ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/magic/lib/toxfem/src/toxfem.cpp
Revision: 258
Committed: Thu Aug 12 19:10:34 2010 UTC (15 years ago) by francois
File size: 27841 byte(s)
Log Message:
Mise a jour toxfem + parametrisation compilation toxfem + bug 
comparaison

File Contents

# Content
1 #include "gestionversion.h"
2 #include "toxfem.h"
3 #include "mg_file.h"
4 #include "ot_mathematique.h"
5 #include "tpl_map_entite.h"
6 #include "tpl_relation_entite.h"
7 #include "tpl_octree.h"
8 #include "toxfem_point.h"
9 #include "vct.h"
10 #include <math.h>
11 #include <fstream>
12 #include "IBrep.h"
13
14
15
16 TOXFEM::TOXFEM(class MG_GESTIONNAIRE *g,class MG_GEOMETRIE *ge,class FEM_MAILLAGE* femm,int nbpas):geo(ge),gest(g),mai(femm),NPAS(nbpas)
17 {
18 }
19
20
21 TOXFEM::~TOXFEM()
22 {
23 }
24
25
26
27 int TOXFEM::estdansletetra(FEM_TETRA *tet,double x,double y, double z)
28 {
29 double *xyz1,*xyz2,*xyz3,*xyz4;
30 if (tet->get_nb_fem_noeud()==4)
31 {
32 xyz1=tet->get_fem_noeud(0)->get_coord();
33 xyz2=tet->get_fem_noeud(1)->get_coord();
34 xyz3=tet->get_fem_noeud(2)->get_coord();
35 xyz4=tet->get_fem_noeud(3)->get_coord();
36 }
37 if (tet->get_nb_fem_noeud()==10)
38 {
39 xyz1=tet->get_fem_noeud(0)->get_coord();
40 xyz2=tet->get_fem_noeud(2)->get_coord();
41 xyz3=tet->get_fem_noeud(4)->get_coord();
42 xyz4=tet->get_fem_noeud(9)->get_coord();
43 }
44 OT_VECTEUR_3D v1(xyz2[0]-xyz1[0],xyz2[1]-xyz1[1],xyz2[2]-xyz1[2]);
45 OT_VECTEUR_3D v2(xyz3[0]-xyz1[0],xyz3[1]-xyz1[1],xyz3[2]-xyz1[2]);
46 OT_VECTEUR_3D v3(xyz4[0]-xyz1[0],xyz4[1]-xyz1[1],xyz4[2]-xyz1[2]);
47 OT_VECTEUR_3D v4(x-xyz1[0],y-xyz1[1],z-xyz1[2]);
48 OT_MATRICE_3D mat(v1,v2,v3);
49 OT_MATRICE_3D mat1(v4,v2,v3);
50 OT_MATRICE_3D mat2(v1,v4,v3);
51 OT_MATRICE_3D mat3(v1,v2,v4);
52 double det=mat.get_determinant();
53 double xsi=mat1.get_determinant()/det;
54 double eta=mat2.get_determinant()/det;
55 double dseta=mat3.get_determinant()/det;
56 int reponse=1;
57 if (xsi<-0.000001) reponse=0;
58 if (eta<-0.000001) reponse=0;
59 if (dseta<-0.000001) reponse=0;
60 if (xsi+eta+dseta>1.000001) reponse=0;
61 return reponse;
62
63 }
64
65 double TOXFEM::calculdist(double *n,double x,double y,double z,FEM_NOEUD* noeud)
66 {
67 double* xyz=noeud->get_coord();
68 double dist=sqrt((xyz[0]-x)*(xyz[0]-x)+(xyz[1]-y)*(xyz[1]-y)+(xyz[2]-z)*(xyz[2]-z));
69 OT_VECTEUR_3D vec1(n[0],n[1],n[2]);
70 OT_VECTEUR_3D vec2(xyz[0]-x,xyz[1]-y,xyz[2]-z);
71 double ps=vec1*vec2;
72 if (ps<0.) dist=-dist;
73 return dist;
74 }
75
76 //void TOXFEM::importer(std::string nomfichier,class MagXchange* data,std::string nomfichierout)
77 void TOXFEM::importer(std::string nomfichier,std::string nomfichieribrep,MG_GROUPE_TOPOLOGIQUE* mggt)
78 {
79 TPL_MAP_ENTITE<MG_ELEMENT_TOPOLOGIQUE*> lst;
80 int nbface=geo->get_nb_mg_face();
81 if (mggt!=NULL)
82 {
83 int nb=mggt->get_nb();
84 for (int i=0;i<nb;i++)
85 {
86 lst.ajouter(mggt->get(i));
87 mggt->get(i)->get_topologie_sousjacente(&lst);
88 }
89 }
90 else
91 {
92 int nbvol=geo->get_nb_mg_volume();
93 for (int i=0;i<nbvol;i++)
94 {
95 lst.ajouter(geo->get_mg_volume(i));
96 geo->get_mg_volume(i)->get_topologie_sousjacente(&lst);
97 }
98 }
99 int nbvraiface=0;
100 TPL_MAP_ENTITE<MG_ELEMENT_TOPOLOGIQUE*>::ITERATEUR it;
101 for (MG_ELEMENT_TOPOLOGIQUE* ele=lst.get_premier(it);ele!=NULL;ele=lst.get_suivant(it))
102 if (ele->get_dimension()==2) nbvraiface++;
103 int nb_noeud=mai->get_nb_fem_noeud();
104 std::string nomfichier2=nomfichier+".sol";
105 FEM_SOLUTION* solution=new FEM_SOLUTION(mai,nbvraiface+1,(char*)nomfichier2.c_str(),nb_noeud,"LS_",ENTITE_NOEUD);
106 solution->change_legende(0,"Peau");
107 int i=0;
108 for (MG_ELEMENT_TOPOLOGIQUE* ele=lst.get_premier(it);ele!=NULL;ele=lst.get_suivant(it))
109 {
110 if (ele->get_dimension()!=2) continue;
111 if (mggt!=NULL)
112 if (lst.existe(ele)==0) continue;
113 char mess[255];
114 sprintf(mess,"Face %lu",ele->get_id());
115 ++i;
116 solution->change_legende(i,mess);
117 }
118 gest->ajouter_fem_solution(solution);
119 double xmin=1e300,ymin=1e300,zmin=1e308;
120 double xmax=-1e300,ymax=-1e300,zmax=-1e308;
121 TPL_MAP_ENTITE<FEM_NOEUD*> lst_noeud;
122 LISTE_FEM_NOEUD::iterator it2;
123 i=0;
124 for (FEM_NOEUD* noeud=mai->get_premier_noeud(it2);noeud!=NULL;noeud=mai->get_suivant_noeud(it2))
125 {
126 double* xyz=noeud->get_coord();
127 if (xyz[0]<xmin) xmin=xyz[0];
128 if (xyz[1]<ymin) ymin=xyz[1];
129 if (xyz[2]<zmin) zmin=xyz[2];
130 if (xyz[0]>xmax) xmax=xyz[0];
131 if (xyz[1]>ymax) ymax=xyz[1];
132 if (xyz[2]>zmax) zmax=xyz[2];
133 for (int j=0;j<nbvraiface+1;j++)
134 solution->ecrire(i,j,1e300);
135 lst_noeud.ajouter(noeud);
136 i++;
137 }
138 octree.initialiser(&lst_noeud,1,xmin,ymin,zmin,xmax,ymax,zmax);
139 LISTE_FEM_TETRA::iterator it3;
140 for (FEM_TETRA* tet=mai->get_premier_tetra(it3);tet!=NULL;tet=mai->get_suivant_tetra(it3))
141 octree.inserer(tet);
142 //levelset0(solution,0);
143 for (int i=0;i<nbface;i++)
144 {
145 MG_FACE* face=geo->get_mg_face(i);
146 if (!lst.existe(face)) continue;
147 vector<MG_FACE*> lstface;
148 lstface.push_back(face);
149 /*TPL_LISTE_ENTITE<double> lst;
150 int type=face->get_surface()->get_type_geometrique(lst);
151 int idem=0;
152 for (int j=0;j<i;j++)
153 {
154 TPL_LISTE_ENTITE<double> lst2;
155 MG_FACE* face2=geo->get_mg_face(j);
156 int type2=face2->get_surface()->get_type_geometrique(lst2);
157 if (type==type2)
158 if (lst.get_nb()==lst2.get_nb())
159 {
160 int diff=0;
161 for (int i=0;i<lst.get_nb();i++)
162 if (fabs(lst.get(i)-lst2.get(i))>0.000001) diff=1;
163 if (diff==0) idem=1;
164 }
165 }
166 if (!idem) lstface.push_back(geo->get_mg_face(i));
167 for (int j=i+1;j<nbface;j++)
168 {
169 TPL_LISTE_ENTITE<double> lst2;
170 MG_FACE* face2=geo->get_mg_face(j);
171 int type2=face2->get_surface()->get_type_geometrique(lst2);
172 if (type==type2)
173 if (lst.get_nb()==lst2.get_nb())
174 {
175 int diff=0;
176 for (int i=0;i<lst.get_nb();i++)
177 if (fabs(lst.get(i)-lst2.get(i))>0.000001) diff=1;
178 if (diff==0) lstface.push_back(face2);
179 }
180 }*/
181 levelsetn(&lst,&lstface,solution,i+1);
182 }
183 exporter_IBrep(nomfichieribrep,solution,mggt);
184 }
185
186 void TOXFEM::levelset0(FEM_SOLUTION *solution,int numsol)
187 {
188 solution->active_solution(numsol);
189 int nbface=geo->get_nb_mg_face();
190 vector<TOXFEM_POINT*> lst;
191 for (int iface=0;iface<nbface;iface++)
192 {
193 MG_FACE* face=geo->get_mg_face(iface);
194 int nbpoint=lst.size();
195 TPL_SET<MG_ELEMENT_MAILLAGE*>::ITERATEUR it;
196 for (MG_ELEMENT_MAILLAGE* ele=face->get_lien_maillage()->get_premier(it);ele!=NULL;ele=face->get_lien_maillage()->get_suivant(it))
197 {
198 MG_TRIANGLE *tri=(MG_TRIANGLE*)ele;
199 TOXFEM_POINT *pt1=new TOXFEM_POINT(tri->get_noeud1()->get_x(),tri->get_noeud1()->get_y(),tri->get_noeud1()->get_z(),tri->get_noeud1()->get_lien_topologie());
200 TOXFEM_POINT *pt2=new TOXFEM_POINT(tri->get_noeud2()->get_x(),tri->get_noeud2()->get_y(),tri->get_noeud2()->get_z(),tri->get_noeud2()->get_lien_topologie());
201 TOXFEM_POINT *pt3=new TOXFEM_POINT(tri->get_noeud3()->get_x(),tri->get_noeud3()->get_y(),tri->get_noeud3()->get_z(),tri->get_noeud3()->get_lien_topologie());
202 lst.push_back(pt1);
203 lst.push_back(pt2);
204 lst.push_back(pt3);
205 }
206 calcullevelsetpremierepasse(solution,numsol,face,8,&lst,nbpoint,lst.size());
207 }
208 calcullevelsetdeuxiemepasse(solution,numsol,&lst);
209 }
210 void TOXFEM::calcullevelsetpremierepasse(FEM_SOLUTION *solution,int numsol,MG_FACE* face,int sens,vector<TOXFEM_POINT*> *lst,int n1,int n2)
211 {
212 for (int i=n1;i<n2;i++)
213 {
214 TOXFEM_POINT* pt=(*lst)[i];
215 double uv[2];
216 double xyz[3];
217 pt->get_coord3(xyz);
218 double normal[3];
219 face->inverser(uv,xyz);
220 face->calcul_normale_unitaire(uv,normal);
221 normal[0]=normal[0]*sens*(-1.);
222 normal[1]=normal[1]*sens*(-1.);
223 normal[2]=normal[2]*sens*(-1.);
224 TPL_MAP_ENTITE<FEM_TETRA*> liste;
225 octree.rechercher(xyz[0],xyz[1],xyz[2],0.,liste);
226 TPL_MAP_ENTITE<FEM_TETRA*>::ITERATEUR it;
227 for (FEM_TETRA* tet=liste.get_premier(it);tet!=NULL;tet=liste.get_suivant(it))
228 {
229 //if (estdansletetra(tet,xyz[0],xyz[1],xyz[2]))
230 {
231 for (int k=0;k<tet->get_nb_fem_noeud();k++)
232 {
233 double dist=calculdist(normal,xyz[0],xyz[1],xyz[2],tet->get_fem_noeud(k));
234 if (fabs(dist)<fabs(tet->get_fem_noeud(k)->get_solution()))
235 {
236 tet->get_fem_noeud(k)->change_solution(dist);
237 tet->get_fem_noeud(k)->change_numero(pt->get_id());
238 pt->change_coord2(uv);
239 }
240 }
241 }
242 }
243 }
244 }
245
246 void TOXFEM::calcullevelsetdeuxiemepasse(FEM_SOLUTION *solution,int numsol,vector<TOXFEM_POINT*> *lst)
247 {
248 LISTE_FEM_TETRA::iterator ittet;
249 for (FEM_TETRA* tet=mai->get_premier_tetra(ittet);tet!=NULL;tet=mai->get_suivant_tetra(ittet))
250 {
251 for (int i=0;i<tet->get_nb_fem_noeud();i++)
252 if (tet->get_fem_noeud(i)->get_solution()<1e250)
253 {
254 TOXFEM_POINT* pt=(*lst)[tet->get_fem_noeud(i)->get_numero()];
255 int dim=pt->get_mg_element_topologique()->get_dimension();
256 if (dim==2)
257 {
258 MG_FACE* face=(MG_FACE*)pt->get_mg_element_topologique();
259 double dist=calcul_distance(tet->get_fem_noeud(i),face,pt);
260 int signe=1;
261 if (tet->get_fem_noeud(i)->get_solution()<0) signe=-1;
262 tet->get_fem_noeud(i)->change_solution(signe*dist);
263 }
264 if (dim==1)
265 {
266 MG_ARETE* arete=(MG_ARETE*)pt->get_mg_element_topologique();
267 double dist=calcul_distance(tet->get_fem_noeud(i),arete,pt);
268 tet->get_fem_noeud(i)->change_solution(dist);
269 }
270 if (dim==0)
271 {
272 MG_SOMMET* sommet=(MG_SOMMET*)pt->get_mg_element_topologique();
273 MG_ARETE* arete=sommet->get_mg_cosommet(0)->get_arete();
274 double dist=calcul_distance(tet->get_fem_noeud(i),arete,pt);
275 tet->get_fem_noeud(i)->change_solution(dist);
276 }
277
278 }
279 }
280 int i=0;
281 LISTE_FEM_NOEUD::iterator itnoeud;
282 for (FEM_NOEUD* noeud=mai->get_premier_noeud(itnoeud);noeud!=NULL;noeud=mai->get_suivant_noeud(itnoeud))
283 {
284 solution->ecrire(i,numsol,noeud->get_solution());
285 ++i;
286 }
287 int nbpt=(*lst).size();
288 for (int i=0;i<nbpt;i++) delete (*lst)[i];
289 TOXFEM_POINT::remisecompteurid();
290
291 }
292
293 double TOXFEM::calcul_distance(FEM_NOEUD* noeud,MG_ARETE* are,TOXFEM_POINT* pt,double precision)
294 {
295 double tii,eps;
296 are->inverser(tii,noeud->get_coord());
297 int compteur=0;
298 OT_VECTEUR_3D Pt(noeud->get_x(),noeud->get_y(),noeud->get_z());
299 do
300 {
301 compteur++;
302 double ti=tii;
303 double xyz[3],dxyz[3],ddxyz[3];
304 are->deriver_seconde(ti,ddxyz,dxyz,xyz);
305 OT_VECTEUR_3D Ct(xyz[0],xyz[1],xyz[2]);
306 OT_VECTEUR_3D Ct_deriver(dxyz[0],dxyz[1],dxyz[2]);
307 OT_VECTEUR_3D Ct_deriver_seconde(ddxyz[0],ddxyz[1],ddxyz[2]);
308 OT_VECTEUR_3D Distance = Ct-Pt;
309 tii=ti-Ct_deriver*Distance/(Ct_deriver_seconde*Distance+Ct_deriver.get_longueur2());
310 eps=fabs(tii-ti);
311 if (compteur>500) return 1e300;
312 if (tii<are->get_tmin())
313 {
314 tii=are->get_tmin();
315 eps=0.;
316 }
317 if (tii>are->get_tmax())
318 {
319 tii=are->get_tmax();
320 eps=0.;
321 }
322 }
323 while (eps>precision);
324 double xyz[3],dxyz[3];
325 are->evaluer(tii,xyz);
326 OT_VECTEUR_3D Ct(xyz[0],xyz[1],xyz[2]);
327 double distance=(Ct-Pt).get_longueur();
328 MG_FACE* face1=are->get_mg_coarete(0)->get_boucle()->get_mg_face();
329 MG_FACE* face2=are->get_mg_coarete(1)->get_boucle()->get_mg_face();
330 are->deriver(tii,dxyz);
331 OT_VECTEUR_3D x1(dxyz[0],dxyz[1],dxyz[2]);
332 OT_VECTEUR_3D x2(dxyz[0],dxyz[1],dxyz[2]);
333 x1=are->get_mg_coarete(0)->get_orientation()*x1;
334 x2=are->get_mg_coarete(1)->get_orientation()*x2;
335 x1.norme();
336 x2.norme();
337 double uv1[2],uv2[2];
338 double normal1[3],normal2[3];
339 face1->inverser(uv1,xyz);
340 face2->inverser(uv2,xyz);
341 face1->calcul_normale_unitaire(uv1,normal1);
342 face2->calcul_normale_unitaire(uv2,normal2);
343 OT_VECTEUR_3D z1(normal1[0],normal1[1],normal1[2]);
344 OT_VECTEUR_3D z2(normal2[0],normal2[1],normal2[2]);
345 z1=face1->get_mg_coface(0)->get_orientation()*z1;
346 z2=face2->get_mg_coface(0)->get_orientation()*z2;
347 OT_VECTEUR_3D y1=z1&x1;
348 OT_VECTEUR_3D y2=z2&x2;
349 double test=(z1&z2)*x1;
350 int signe=-1;
351 OT_VECTEUR_3D dirpt=Pt-Ct;
352 if (test>0)
353 {if ((z1*dirpt>0.) || (z2*dirpt>0.)) signe=1;}
354 else
355 {if ((z1*dirpt>0.) && (z2*dirpt>0.)) signe=1;}
356 return signe*distance;
357 }
358
359 double TOXFEM::calcul_distance(FEM_NOEUD* noeud,MG_FACE* face,TOXFEM_POINT* pt,double precision)
360 {
361 double uvii[2],eps;
362 pt->get_coord2(uvii);
363 int compteur=0;
364 OT_VECTEUR_3D Pt(noeud->get_x(),noeud->get_y(),noeud->get_z());
365 double delta_u,delta_v;
366 do
367 {
368 compteur++;
369 double uvi[2];
370 uvi[0]=uvii[0];
371 uvi[1]=uvii[1];
372 double xyzduu[3],xyzdvv[3],xyzduv[3],xyzdu[3],xyzdv[3],xyz[3];
373 face->deriver_seconde(uvi,xyzduu,xyzduv,xyzdvv,xyz,xyzdu,xyzdv);
374 OT_VECTEUR_3D S(xyz[0],xyz[1],xyz[2]);
375 OT_VECTEUR_3D Su(xyzdu[0],xyzdu[1],xyzdu[2]);
376 OT_VECTEUR_3D Sv(xyzdv[0],xyzdv[1],xyzdv[2]);
377 OT_VECTEUR_3D Suu(xyzduu[0],xyzduu[1],xyzduu[2]);
378 OT_VECTEUR_3D Suv(xyzduv[0],xyzduv[1],xyzduv[2]);
379 OT_VECTEUR_3D Svv(xyzdvv[0],xyzdvv[1],xyzdvv[2]);
380 OT_VECTEUR_3D Distance = S-Pt;
381 double a[4],b[2];
382 a[0]=Su.get_longueur2()+Distance*Suu;
383 a[1]=Su*Sv+Distance*Suv;
384 a[2]=Su*Sv+Distance*Suv;
385 a[3]=Sv.get_longueur2()+Distance*Svv;
386 b[0]=Distance*Su;b[0]=-b[0];
387 b[1]=Distance*Sv;b[1]=-b[1];
388 double deltau,deltav;
389 double denominateur_delta=(a[0]*a[3]-a[2]*a[1]);
390 if (a[0]<1E-12)
391 deltau=0;
392 else delta_u=(b[0]*a[3]-b[1]*a[1])/denominateur_delta;
393 if (a[3]<1E-12)
394 deltav=0;
395 else delta_v=(a[0]*b[1]-a[2]*b[0])/denominateur_delta;
396 /*if (fabs(denominateur_delta) < ( (fabs(a[0])+fabs(a[1])+fabs(a[2])+fabs(a[3]))*1e-12 ) )
397 return 1e300;*/
398 uvii[0]=uvi[0]+delta_u;
399 uvii[1]=uvi[1]+delta_v;
400 if (face->get_surface()->est_periodique_u()==1)
401 {
402 if(uvii[0]<0.) uvii[0]=face->get_surface()->get_periode_u()-uvii[0];
403 if(uvii[0]>face->get_surface()->get_periode_u()) uvii[0]=uvii[0]-face->get_surface()->get_periode_u();
404 }
405 if (face->get_surface()->est_periodique_v()==1)
406 {
407 if(uvii[1]<0.) uvii[0]=face->get_surface()->get_periode_v()-uvii[1];
408 if(uvii[1]>face->get_surface()->get_periode_v()) uvii[1]=uvii[1]-face->get_surface()->get_periode_v();
409 }
410 delta_u=uvii[0]-uvi[0];
411 delta_v=uvii[1]-uvi[1];
412 if (compteur>500) return 1e300;
413 }
414
415 while ((fabs(delta_u)>precision)||(fabs(delta_v)>precision));
416 double xyz[3];
417 face->evaluer(uvii,xyz);
418 OT_VECTEUR_3D S(xyz[0],xyz[1],xyz[2]);
419 double distance=(S-Pt).get_longueur();
420 return distance;
421 }
422
423 void TOXFEM::levelsetn(TPL_MAP_ENTITE<MG_ELEMENT_TOPOLOGIQUE*> *lsttopo,vector<MG_FACE*> *lstface,class FEM_SOLUTION* solution,int numsol)
424 {
425 solution->active_solution(numsol);
426 int nbface=lstface->size();
427 if (nbface==0) return;
428 vector<TOXFEM_POINT*> lst;
429 BOITE_2D boite=ot.get_boite_2D((*lstface)[0]);
430 for (int iface=1;iface<nbface;iface++)
431 {
432 MG_FACE* face=(*lstface)[iface];
433 BOITE_2D boiteface=ot.get_boite_2D(face);
434 boite=boite+boiteface;
435 }
436 MG_FACE* face=(*lstface)[0];
437 int trouve=0;
438 int orientation;
439 int j=0;
440 do
441 {
442 MG_COFACE* coface=face->get_mg_coface(j);
443 MG_VOLUME* vol=coface->get_coquille()->get_mg_volume();
444 if (lsttopo->existe(vol))
445 {
446 orientation=coface->get_orientation();
447 trouve=1;
448 }
449 j++;
450 }
451 while (trouve==0);
452 double umin=boite.get_xmin();
453 double umax=boite.get_xmax();
454 double vmin=boite.get_ymin();
455 double vmax=boite.get_ymax();
456 if (face->get_surface()->est_periodique_u())
457 {
458 umin=0;
459 umax=face->get_surface()->get_periode_u();
460 }
461 if (face->get_surface()->est_periodique_v())
462 {
463 vmin=0;
464 vmax=face->get_surface()->get_periode_v();
465 }
466 for (int i=-5;i<NPAS+5;i++)
467 for (int j=-5;j<NPAS+5;j++)
468 {
469 double uv[2];
470 uv[0]=umin+i*1.0/NPAS*(umax-umin);
471 uv[1]=vmin+j*1.0/NPAS*(vmax-vmin);
472 double xyz[3];
473 if ((face->valide_parametre_u(uv[0])) && (face->valide_parametre_u(uv[1])))
474 {
475 face->evaluer(uv,xyz);
476 TOXFEM_POINT *pt=new TOXFEM_POINT(xyz[0],xyz[1],xyz[2],face);
477 lst.push_back(pt);
478 }
479 }
480 calcullevelsetpremierepasse(solution,numsol,face,orientation,&lst,0,lst.size());
481 calcullevelsetdeuxiemepasse(solution,numsol,&lst);
482 //etendrelevelset(solution,numsol);
483 }
484
485 void TOXFEM::etendrelevelset(FEM_SOLUTION* sol,int numsol)
486 {
487 sol->active_solution(numsol);
488
489
490 LISTE_FM know;
491 LISTE_FM trial;
492 LISTE_FM far;
493 LISTE_FM exterieur;
494 LISTE_FM_TRI trialtri;
495 LISTE_FM_TRI_ID trialtriid;
496
497
498 LISTE_FEM_TETRA::iterator ittet;
499 for (FEM_TETRA* tet=mai->get_premier_tetra(ittet);tet!=NULL;tet=mai->get_suivant_tetra(ittet))
500 {
501 tet->change_solution(0.);
502 int numsol=0;
503 if (tet->get_fem_noeud(0)->get_solution()<1e200) {numsol++;tet->get_fem_noeud(0)->change_numero(1);} else tet->get_fem_noeud(0)->change_numero(0);
504 if (tet->get_fem_noeud(1)->get_solution()<1e200) {numsol++;tet->get_fem_noeud(1)->change_numero(1);} else tet->get_fem_noeud(1)->change_numero(0);
505 if (tet->get_fem_noeud(2)->get_solution()<1e200) {numsol++;tet->get_fem_noeud(2)->change_numero(1);} else tet->get_fem_noeud(2)->change_numero(0);
506 if (tet->get_fem_noeud(3)->get_solution()<1e200) {numsol++;tet->get_fem_noeud(3)->change_numero(1);} else tet->get_fem_noeud(3)->change_numero(0);
507 if (numsol==4)
508 ajouter_liste(know,tet);
509
510 else if (numsol==3)
511 {
512 if (tet->get_fem_noeud(0)->get_numero()==0) tet->change_numero(0);
513 else if (tet->get_fem_noeud(1)->get_numero()==0) tet->change_numero(1);
514 else if (tet->get_fem_noeud(2)->get_numero()==0) tet->change_numero(2);
515 else tet->change_numero(3);
516 ajouter_liste(trial,tet);
517 }
518 else
519 ajouter_liste(far,tet);
520
521 }
522 for (LISTE_FM::iterator i=trial.begin();i!=trial.end();i++)
523 {
524 FEM_TETRA* tet=*i;
525 int signe;
526 double sol=resoudgradT(tet,&signe);
527 if (fabs(sol)>0.00000001)
528 {
529 if (fabs(sol)<fabs(tet->get_fem_noeud(tet->get_numero())->get_solution()))
530 {
531 tet->get_fem_noeud(tet->get_numero())->change_solution(sol);
532 ajouter_liste(trialtri,trialtriid,tet,fabs(tet->get_fem_noeud(tet->get_numero())->get_solution()));
533 }
534 }
535 else
536 {
537 ajouter_liste(exterieur,tet);
538 tet->change_solution(1e300);
539 }
540 }
541 int fin=0;
542 LISTE_FM_TRI::iterator itfin=trialtri.end();
543 itfin--;
544 double longref=(*itfin).first;
545 do
546 {
547 LISTE_FM_TRI::iterator it=trialtri.begin();
548 FEM_TETRA* tet=(*it).second;
549 double longcourant=(*it).first;
550 supprimer_liste(trialtri,trialtriid,tet);
551 ajouter_liste(know,tet);
552 FEM_NOEUD* noeud=tet->get_fem_noeud(tet->get_numero());
553 noeud->change_numero(1);
554 if (noeud->get_solution()>20000)
555 cout << "BUGGGGGGG" <<endl;
556 int nbtetra=noeud->get_lien_tetra()->get_nb();
557 for (int i=0;i<nbtetra;i++)
558 {
559 FEM_TETRA* tet2=noeud->get_lien_tetra()->get(i);
560 if (tet2==tet) continue;
561 LISTE_FM_TRI_ID::iterator it=trialtriid.find(tet2->get_id());
562 if (it!=trialtriid.end())
563 {
564 int signe;
565 double sol=resoudgradT(tet2,&signe);
566 double solution=tet2->get_fem_noeud(tet2->get_numero())->get_solution();
567 if (fabs(sol)>0.00000001)
568 if (!((solution<1e200)&&(sol*solution<0)))
569 if (fabs(sol)<fabs(solution))
570 {
571 supprimer_liste(trialtri,trialtriid,tet2);
572 ajouter_liste(trialtri,trialtriid,tet2,fabs(sol));
573 tet2->get_fem_noeud(tet2->get_numero())->change_solution(sol);
574 }
575 }
576 LISTE_FM::iterator it2=find(far.begin(),far.end(),tet2);
577 if (it2!=far.end())
578 {
579 int numsol=0;
580 if (tet2->get_fem_noeud(0)->get_numero()==1) numsol++;
581 if (tet2->get_fem_noeud(1)->get_numero()==1) numsol++;
582 if (tet2->get_fem_noeud(2)->get_numero()==1) numsol++;
583 if (tet2->get_fem_noeud(3)->get_numero()==1) numsol++;
584 //if (numsol==4)
585 //cout << " BUG " <<endl;
586 if (numsol==3)
587 {
588 if (tet2->get_fem_noeud(0)->get_numero()==0) tet2->change_numero(0);
589 else if (tet2->get_fem_noeud(1)->get_numero()==0) tet2->change_numero(1);
590 else if (tet2->get_fem_noeud(2)->get_numero()==0) tet2->change_numero(2);
591 else tet2->change_numero(3);
592 int signe;
593 double sol=resoudgradT(tet2,&signe);
594 double ancsol=tet2->get_fem_noeud(tet2->get_numero())->get_solution();
595 if (fabs(sol)>0.00000001)
596 {
597 if (!((ancsol<1e200) && (ancsol*sol<0.) ))
598 {
599 tet2->get_fem_noeud(tet2->get_numero())->change_solution(sol);
600 supprimer_liste(far,tet2);
601 ajouter_liste(trialtri,trialtriid,tet2,fabs(sol));
602 }
603 }
604 else
605 {
606 tet2->change_solution(1e300);
607 ajouter_liste(exterieur,tet2);
608 }
609 }
610 }
611 }
612 if (trialtri.size()==0) fin=1;
613 if (exterieur.size()>0)
614 if (fin==0)
615 if (longcourant>longref)
616 {
617 int nombre=exterieur.size();
618 for (int i=0;i<nombre;i++)
619 {
620 FEM_TETRA* tet2=(*(exterieur.begin()));
621 supprimer_liste(exterieur,tet2);
622 ajouter_liste(know,tet2);
623 for (int nd=0;nd<4;nd++)
624 {
625 FEM_NOEUD* noeud=tet2->get_fem_noeud(nd);
626 int nbtetra=noeud->get_lien_tetra()->get_nb();
627 for (int i=0;i<nbtetra;i++)
628 {
629 FEM_TETRA* tet3=noeud->get_lien_tetra()->get(i);
630 if (tet2==tet3) continue;
631 LISTE_FM::iterator it2=find(far.begin(),far.end(),tet3);
632 if (it2!=far.end())
633 {
634 supprimer_liste(far,tet3);
635 ajouter_liste(exterieur,tet3);
636 tet3->change_solution(1e300);
637 }
638 }
639 }
640 }
641 LISTE_FM_TRI::iterator itfin=trialtri.end();
642 itfin--;
643 longref=(*itfin).first;
644 }
645 }
646 while (fin==0);
647 LISTE_FEM_NOEUD::iterator itnoeud;
648 for (FEM_NOEUD* noeud=mai->get_premier_noeud(itnoeud);noeud!=NULL;noeud=mai->get_suivant_noeud(itnoeud))
649 noeud->change_numero(0);
650 for (FEM_TETRA* tet=mai->get_premier_tetra(ittet);tet!=NULL;tet=mai->get_suivant_tetra(ittet))
651 {
652 if (tet->get_solution()>1e200) continue;
653 tet->get_fem_noeud(0)->change_numero(1);
654 tet->get_fem_noeud(1)->change_numero(1);
655 tet->get_fem_noeud(2)->change_numero(1);
656 tet->get_fem_noeud(3)->change_numero(1);
657 }
658 int i=0;
659 for (FEM_NOEUD* noeud=mai->get_premier_noeud(itnoeud);noeud!=NULL;noeud=mai->get_suivant_noeud(itnoeud))
660 {
661 if (noeud->get_numero()==1) sol->ecrire(i,numsol,noeud->get_solution()); else sol->ecrire(i,numsol,1e300);
662 ++i;
663 }
664 }
665 void TOXFEM::exporter_IBrep(string chemin,FEM_SOLUTION* solution,MG_GROUPE_TOPOLOGIQUE* mggt)
666 {
667 TPL_MAP_ENTITE<MG_VOLUME*> lst;
668 if (mggt==NULL)
669 {
670 int nbvol=geo->get_nb_mg_volume();
671 for (int i=0;i<nbvol;i++)
672 lst.ajouter(geo->get_mg_volume(i));
673 }
674 else
675 {
676 int nbmggt=mggt->get_nb();
677 for (int i=0;i<nbmggt;i++)
678 if (mggt->get(i)->get_dimension()==3)
679 lst.ajouter((MG_VOLUME*)mggt->get(i));
680 }
681 IBrep brep(100);
682 int nbvolexp=lst.get_nb();
683 for (int i=0;i<nbvolexp;i++)
684 {
685 MG_VOLUME* vol=lst.get(i);
686 int nbcoq=vol->get_nb_mg_coquille();
687 IVolume ivoltmp(vol->get_id());
688 IVolume* ivol=brep.AddVolume(ivoltmp);
689 for (int j=0;j<nbcoq;j++)
690 {
691 MG_COQUILLE* coq=vol->get_mg_coquille(j);
692 int nbface=coq->get_nb_mg_coface();
693 IShell ishell(nbface);
694 for (int k=0;k<nbface;k++)
695 {
696 MG_COFACE* coface=coq->get_mg_coface(k);
697 ishell[k]=coface->get_id();
698 MG_FACE* face=coface->get_face();
699 int sens=coface->get_orientation();
700 ICoFaceN icoface(coface->get_id(),face->get_id(),sens);
701 brep.AddCoFace(icoface);
702 IFace* iface=brep.GetFace(face->get_id());
703 if (iface==NULL)
704 {
705 IFace ifacenew(face->get_id());
706 iface=brep.AddFace(ifacenew);
707 int nbbou=face->get_nb_mg_boucle();
708 for (int l=0;l<nbbou;l++)
709 {
710 MG_BOUCLE* bou=face->get_mg_boucle(l);
711 int nbare=bou->get_nb_mg_coarete();
712 ILoop iloop(nbare);
713 for (int m=0;m<nbare;m++)
714 {
715 MG_COARETE* coare=bou->get_mg_coarete(m);
716 iloop[m]=coare->get_id();
717 MG_ARETE* are=coare->get_arete();
718 int sens=coare->get_orientation();
719 ICoEdgeN icoedge(coare->get_id(),are->get_id(),sens,face->get_id());
720 brep.AddCoEdge(icoedge);
721 IEdge* iedge=brep.GetEdge(are->get_id());
722 IVertex *ivertex1,*ivertex2;
723 ICoVertex *icover1,*icover2;
724 if (iedge==NULL)
725 {
726 MG_COSOMMET* cover1=are->get_cosommet1();
727 MG_COSOMMET* cover2=are->get_cosommet2();
728 MG_SOMMET* ver1=cover1->get_sommet();
729 MG_SOMMET* ver2=cover2->get_sommet();
730 ICoVertexN icovertmp1(cover1->get_id(),are->get_id(),ver1->get_id(),cover1->get_t());
731 ICoVertexN icovertmp2(cover2->get_id(),are->get_id(),ver2->get_id(),cover2->get_t());
732 icover1=brep.AddCoVertex(icovertmp1);
733 icover2=brep.AddCoVertex(icovertmp2);
734 IEdgeN iedgetmp(are->get_id(),cover1->get_id(),cover2->get_id());
735 ivertex1=brep.GetVertex(ver1->get_id());
736 ivertex2=brep.GetVertex(ver2->get_id());
737 if (ivertex1==NULL)
738 {
739 MG_POINT* pt=ver1->get_point();
740 double xyz[3];
741 pt->evaluer(xyz);
742 IVertexN ivertex(ver1->get_id(),xyz);
743 ivertex1=brep.AddVertex(ivertex);
744 }
745 if (ivertex2==NULL)
746 {
747 MG_POINT* pt=ver2->get_point();
748 double xyz[3];
749 pt->evaluer(xyz);
750 IVertexN ivertex(ver2->get_id(),xyz);
751 ivertex2=brep.AddVertex(ivertex);
752 }
753 ivertex1->AddCoVertex(cover1->get_id());
754 ivertex2->AddCoVertex(cover2->get_id());
755 iedge=brep.AddEdge(iedgetmp);
756 }
757 iedge->AddCoEdge(coare->get_id(),brep);
758 if (sens==1)
759 {
760 icover1=brep.GetCoVertex(iedge->FromCoVertex());
761 ivertex1=brep.GetVertex(icover1->Vertex());
762 ivertex1->AddFace(face->get_id());
763 }
764 else
765 {
766 icover2=brep.GetCoVertex(iedge->ToCoVertex());
767 ivertex2=brep.GetVertex(icover2->Vertex());
768 ivertex2->AddFace(face->get_id());
769 }
770 }
771 iface->AddLoop(iloop);
772 }
773 }
774 iface->AddCoFace(coface->get_id());
775 }
776 ivol->AddShell(ishell);
777 }
778 }
779 int nbsol=solution->get_nb_champ();
780 LISTE_FEM_NOEUD::iterator itnoeud;
781 int i=0;
782 for (FEM_NOEUD* noeud=mai->get_premier_noeud(itnoeud);noeud!=NULL;noeud=mai->get_suivant_noeud(itnoeud))
783 {
784 int nbsolnoeud=0;
785 for (int j=0;j<nbsol;j++)
786 {
787 if (solution->lire(i,j)<1e200) nbsolnoeud++;
788 }
789 double *xyz=noeud->get_coord();
790 INodeN inoeudtmp(noeud->get_id(),xyz[0],xyz[1],xyz[2],nbsolnoeud);
791 INode* inoeud=brep.AddNode(inoeudtmp);
792 int num=0;
793 for (int j=0;j<nbsol;j++)
794 {
795 if (solution->lire(i,j)<1e200)
796 {
797 inoeud->Fields()[num]=j;
798 inoeud->Values()[num]=solution->lire(i,j);
799 num++;
800 }
801 }
802 i++;
803 }
804 LISTE_FEM_TETRA::iterator ittet;
805 int num=0;
806 for (FEM_TETRA* tet=mai->get_premier_tetra(ittet);tet!=NULL;tet=mai->get_suivant_tetra(ittet))
807 {
808 IElementN xfemele(IElement::TETRAHEDRON);
809 num++;
810 xfemele.num=num;
811 xfemele.GetNode(0)=tet->get_fem_noeud(0)->get_id();
812 xfemele.GetNode(1)=tet->get_fem_noeud(1)->get_id();
813 xfemele.GetNode(2)=tet->get_fem_noeud(2)->get_id();
814 xfemele.GetNode(3)=tet->get_fem_noeud(3)->get_id();
815 brep.AddElement(xfemele);
816 }
817
818
819
820
821 std::ofstream output(chemin.c_str());
822 output << brep << std::endl;
823 output.close();
824
825 }
826
827
828
829 void TOXFEM::ajouter_liste(LISTE_FM_TRI &lst,LISTE_FM_TRI_ID &lstid,FEM_TETRA* tet,double val)
830 {
831 pair<double,FEM_TETRA*> p(val,tet);
832 LISTE_FM_TRI::iterator it=lst.insert(p);
833 lstid[tet->get_id()]=it;
834 }
835
836 void TOXFEM::supprimer_liste(LISTE_FM_TRI &lst,LISTE_FM_TRI_ID &lstid,FEM_TETRA* tet)
837 {
838 LISTE_FM_TRI::iterator it2=lstid[tet->get_id()];
839 LISTE_FM_TRI_ID::iterator it3=lstid.find(tet->get_id());
840 lstid.erase(it3);
841 lst.erase(it2);
842 }
843
844 void TOXFEM::ajouter_liste(LISTE_FM& lst,FEM_TETRA* tet)
845 {
846 lst.push_back(tet);
847 }
848
849 void TOXFEM::supprimer_liste(LISTE_FM& lst,FEM_TETRA* tet)
850 {
851 LISTE_FM::iterator it=find(lst.begin(),lst.end(),tet);
852 if (it!=lst.end()) lst.erase(it);
853 }
854
855
856
857 double TOXFEM::resoudgradT(FEM_TETRA* tet,int *signe)
858 {
859 double j[9];
860 double N[12];
861 double jN[12]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
862 double T[4];
863 double uv[2]={0.25,0.25};
864
865
866 tet->get_inverse_jacob(j,uv);
867 for (int i=0;i<3;i++)
868 for (int k=0;k<4;k++)
869 N[i*4+k]=tet->get_fonction_derive_interpolation(k+1,i+1,uv);
870 int premier=0;
871 double tmin=1e300;
872 double tmax=-1e300;
873 for (int i=0;i<4;i++)
874 {
875 if (i==tet->get_numero()) continue;
876 T[i]=tet->get_fem_noeud(i)->get_solution();
877 if (fabs(T[i])>0.000001)
878 {
879 if (premier==0)
880 if (T[i]>0) (*signe)=1; else (*signe)=-1;
881 else if (T[i]*(*signe)<0) (*signe)=0;
882 }
883 T[i]=fabs(T[i]);
884 if (tet->get_numero()!=i)
885 {
886 if (T[i]<tmin) tmin=T[i];
887 if (T[i]>tmax) tmax=T[i];
888 }
889 premier=1;
890 }
891 for (int i=0;i<3;i++)
892 for (int k=0;k<4;k++)
893 for (int l=0;l<3;l++)
894 jN[i*4+k]=jN[i*4+k]+j[i*3+l]*N[l*4+k];
895 double a=0.,b=0.,c=-1.;
896 for (int i=0;i<3;i++)
897 {
898 double coef=0.;
899 double coefinc=0.;
900 for (int l=0;l<4;l++)
901 {
902 if (tet->get_numero()!=l) coef=coef+jN[i*4+l]*T[l];
903 else coefinc=coefinc+jN[i*4+l];
904 }
905 c=c+coef*coef;
906 a=a+coefinc*coefinc;
907 b=b+2*coef*coefinc;
908 }
909 /*if (*signe==0)
910 cout << "attention " <<endl;*/
911 double det=b*b-4.*a*c;
912 if (det<0.) det=0.; else det=sqrt(det);
913 double sol1=(-b-det)/2./a;
914 double sol2=(-b+det)/2./a;
915 double sol=sol1;
916 if (sol2>sol1) sol=sol2;
917 if (sol<tmin*0.99)
918 sol=0.;
919 sol=sol*(*signe);
920 return sol;
921 }