TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Diff_VEFP1NCP1B_Face.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Op_Diff_VEFP1NCP1B_Face.h>
17#include <Champ_P1NC.h>
18#include <Dirichlet.h>
19#include <Dirichlet_homogene.h>
20#include <Periodique.h>
21#include <Neumann_paroi.h>
22#include <Neumann_homogene.h>
23#include <Neumann_sortie_libre.h>
24#include <Echange_externe_impose.h>
25#include <Symetrie.h>
26#include <Champ_Uniforme.h>
27#include <Domaine.h>
28#include <Debog.h>
29#include <TRUSTLists.h>
30#include <Champ_front_txyz.h>
31#include <Champ_Don_lu.h>
32#include <Champ_Don_Fonc_xyz.h>
33#include <Champ_Uniforme_Morceaux.h>
34#include <Porosites_champ.h>
35#include <Check_espace_virtuel.h>
36#include <Conduction.h>
37#include <fstream>
38using std::ofstream;
39using std::endl;
40
41Implemente_instanciable_sans_constructeur(Op_Diff_VEFP1NCP1B_Face,"Op_Diff_VEFP1NCP1B_P1NC",Op_Diff_VEF_Face);
42
43
44static inline double maximum(const double x,
45 const double y)
46{
47 if(x<y)
48 return y;
49 return x;
50}
51/*
52static inline double maximum(const double& x,
53 const double& y,
54 const double& z)
55{
56 return maximum(maximum(x,y),z);
57}
58*/
63
65{
66 return s << que_suis_je() ;
67}
68
69//// readOn
70//
71
73{
74 //Les mots a reconnaitre
75 Motcle motlu, accouverte = "{" , accfermee = "}" ;
76 Motcles les_mots(6);
77 {
78 les_mots[0] = "alphaE";
79 les_mots[1] = "alphaS";
80 les_mots[2] = "alphaA";
81 les_mots[3] = "test";
82 les_mots[4] = "decentrage";
83 les_mots[5] = "epsilon";
84 }
85
86 //Verification de la syntaxe
87 s >> motlu;
88 if (motlu!=accouverte)
89 {
90 Cerr << "Erreur Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
91 Cerr << "Depuis la 1.5.5, la syntaxe du mot cle P1NCP1B a change." << finl;
92 Cerr << "Il faut commencer par une accolade ouvrante {" << finl;
93 Cerr << "et les options eventuelles sont entre les accolades :" << finl;
94 Cerr << "Diffusion { P1NCP1B } -> Diffusion { P1NCB { } }" << finl;
95 exit();
96 }
97
98
99 //Lecture des parametres
100 s >> motlu;
101 while(motlu!=accfermee)
102 {
103 int rang = les_mots.search(motlu);
104
105 switch(rang)
106 {
107 case 0 :
108
109 s >> alphaE;
110 break;
111
112 case 1 :
113
114 s >> alphaS;
115 break;
116
117 case 2 :
118
119 if (Objet_U::dimension==3)
120 s >> alphaA;
121 else
122 {
123 Cerr << "Erreur Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
124 Cerr << "L'option alphaA ne peut etre activee qu'en " << "dimension 3" << finl;
125 Cerr << "Sortie du programme" << finl;
126 exit();
127 }
128 break;
129
130 case 3 :
131
132 test_=1;
133 break;
134
135 case 4 :
136
137 s >> decentrage_;
138 break;
139
140 case 5 :
141
142 s >> convexite_;
143 break;
144
145 default :
146
147 Cerr << "Erreur Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
148 Cerr << "Mot clef " << motlu << " non reconnu" << finl;
149 Cerr << "Les mots clef reconnus sont : " << les_mots << finl;
150 Cerr << "Sortie du programme" << finl;
151 exit();
152 break;
153 }//fin du switch
154
155 //Suite de la lecture
156 s >> motlu;
157 }//fin du while
158
159 if (alphaE && !alphaS) convexite_=1.;
160 else if (alphaS && !alphaE) convexite_=0.;
161
162 coeff_=1.;//alphaE+alphaS;
163
164 return s;
165}
166
167//// associer
168//
169
170
171
172
173
175 const Domaine_Cl_dis_base& domaine_cl_dis,
176 const Champ_Inc_base& ch_diffuse)
177{
178 const Domaine_VEF& zvef = ref_cast(Domaine_VEF,domaine_dis);
179 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
180
181 // On bloque la symetrie dans l operateur de diffusion P1NC sur vitesse (OK pour scalaire)
182 for (int i = 0; i<zclvef.nb_cond_lim(); i++)
183 {
184 Cond_lim la_cl = zclvef.les_conditions_limites(i);
185 if ( sub_type(Symetrie,la_cl.valeur()) && (ch_diffuse.nature_du_champ()==vectoriel) )
186 {
187 Cerr << "\nBoundary conditions of 'Symetrie' type with P1NCP1B diffusion operator are only allowed for Conduction equation!" << finl;
188 Cerr << "Here you use a P1NCP1B diffusion operator in a '" << equation().que_suis_je() << "' equation where" << finl;
189 Cerr << "boundary condition number " << i << ", on boundary '" << la_cl->frontiere_dis().le_nom() << "' has been assigned to: '" << la_cl->que_suis_je() << "'." << finl;
191 }
192 }
193
194 if (sub_type(Champ_P1NC,ch_diffuse))
195 {
196 const Champ_P1NC& inco = ref_cast(Champ_P1NC,ch_diffuse);
197 inconnue_ = inco;
198 }
199
200 le_dom_vef = zvef;
201 la_zcl_vef = zclvef;
202}
203
210
211//ATTENTION : NE TIENT PAS COMPTE DE LA POROSITE 09/04/2009
213{
214 const Domaine_VEF& domaine_VEF=domaine_vef();
215 const Domaine& domaine=domaine_VEF.domaine();
216 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
217 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
218
219 const int nb_faces=domaine_VEF.nb_faces();
220 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
221
222 const DoubleVect& volumes_entrelaces=domaine_VEF.volumes_entrelaces();
223 const DoubleVect& porosite_elem = equation().milieu().porosite_elem();
224
225 DoubleTab coeffOperateur(nb_faces_tot);
226 coeffOperateur=0.;
227
228 DoubleTab nu;
229
230 const int nb_bords=les_cl.size();
231 const int marq = phi_psi_diffuse(equation());
232
233 int face=0;
234 int ind_face=0;
235 int num1=0,num2=0;
236 int n_bord=0;
237
238 double dt_stab=DMAXFLOAT;
239
240 //Calcul de la porosite
242 modif_par_porosite_si_flag(nu_,nu,!marq,porosite_elem);
243
244 //Calcul : contribution des parties P0, P1 et Pa au dt_stab
245 if (alphaE) calculer_dt_stab_elem(nu,coeffOperateur);
246 if (alphaS)
247 {
248 DoubleTab nu_p1;
249 domaine.creer_tableau_sommets(nu_p1);
250 remplir_nu_p1(nu,nu_p1);
251 calculer_dt_stab_som(nu_p1,coeffOperateur);
252 }
253 if (alphaA)
254 {
255 DoubleTab nu_pA;
256 domaine_VEF.creer_tableau_aretes(nu_pA);
257 remplir_nu_pA(nu,nu_pA);
258 calculer_dt_stab_aretes(nu_pA,coeffOperateur);
259 }
260 //Calcul : modification pour tenir compte de la matrice de masse
261 for (face=0; face<nb_faces; face++)
262 {
263 coeffOperateur(face)/=volumes_entrelaces(face);
264 assert(coeffOperateur(face)>=0.);
265 coeffOperateur(face)=1./(coeffOperateur(face)+DMINFLOAT);
266 }
267
268 //Calcul : modification pour les faces de Dirichlet
269 for (n_bord=0; n_bord<nb_bords; n_bord++)
270 {
271 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
272 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
273
274 num1=0;
275 num2=le_bord.nb_faces();
276
277 if (sub_type(Dirichlet_homogene,la_cl.valeur()) ||
278 sub_type(Dirichlet,la_cl.valeur())
279 )
280 for (ind_face=num1; ind_face<num2; ind_face++)
281 {
282 face=le_bord.num_face(ind_face);
283 coeffOperateur(face)=1.e20;
284 }
285 }
286
287 //Calcul du pas de temps de stabilite
288 //: on en a besoin que sur les faces reelles
289 for (face=0; face<nb_faces; face++)
290 if (coeffOperateur(face)<dt_stab)
291 dt_stab=coeffOperateur(face);
292
293 dt_stab=Process::mp_min(dt_stab);
294 return dt_stab;
295}
296
298calculer_dt_stab_elem(const DoubleTab& nu, DoubleTab& coeffOperateur) const
299{
300 const Domaine_VEF& domaine_VEF=domaine_vef();
301 const Domaine& domaine=domaine_VEF.domaine();
302 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
303 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
304
305 const DoubleTab& face_normales=domaine_VEF.face_normales();
306 const DoubleVect& volumes=domaine_VEF.volumes();
307
308 const IntTab& elem_faces=domaine_VEF.elem_faces();
309
310 const int nb_elem_tot=domaine.nb_elem_tot();
311 const int nb_faces_elem=domaine.nb_faces_elem();
312 const int nb_bords=les_cl.size();
313
314 int elem=0;
315 int face=0,face_loc=0;
316 int faceAss=0,faceAss_loc=0;
317 int dim=0;
318 int ind_face=0;
319 int num1=0,num2=0;
320 int n_bord=0;
321
322 double psc=0.;
323 double volume=0.;
324 double nu_elem=0.;
325 double coeff=0.;
326
327 for (elem=0; elem<nb_elem_tot; elem++)
328 {
329 volume=volumes(elem);
330 nu_elem=nu_(elem);
331
332 for (face_loc=0; face_loc<nb_faces_elem; face_loc++)
333 {
334 face=elem_faces(elem,face_loc);
335
336 psc=0.;
337 for (dim=0; dim<dimension; dim++)
338 psc+=face_normales(face,dim)*face_normales(face,dim);
339
340 coeff=nu_elem;
341 coeff/=volume;
342 coeff*=psc;
343 coeff*=convexite_;
344 coeffOperateur(face)+=coeff;
345 }
346 }
347
348 for (n_bord=0; n_bord<nb_bords; n_bord++)
349 {
350 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
351 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
352
353 num1=0;
354 num2=le_bord.nb_faces();
355
356 if (sub_type(Periodique,la_cl.valeur()))
357 {
358 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
359
360 for (ind_face=num1; ind_face<num2; ind_face++)
361 {
362 face=le_bord.num_face(ind_face);
363 faceAss_loc=la_cl_perio.face_associee(ind_face);
364 faceAss=le_bord.num_face(faceAss_loc);
365
366 if (face<faceAss)
367 {
368 coeffOperateur(faceAss)+=coeffOperateur(face);
369 coeffOperateur(face)=coeffOperateur(faceAss);
370 }
371 }
372 }
373 }
374}
375
377calculer_dt_stab_som(const DoubleTab& nu_som, DoubleTab& coeffOperateur) const
378{
379 const Domaine_VEF& domaine_VEF=domaine_vef();
380
381 const int nb_faces=domaine_VEF.nb_faces();
382
383 int face=0;
384 int face_C=0;
385
386 if (laplacien_p1_.nb_lignes()<2) dimensionner(laplacien_p1_);
388
389 //REMARQUE : on multiplie par -1 car laplacien_p1_=+Delta
390 for (face=0; face<nb_faces; face++)
391 {
392 face_C=face*dim_ch_;//pour le cas vectoriel
393 coeffOperateur(face)+=-1.*laplacien_p1_(face_C,face_C);
394 }
395}
396
398calculer_dt_stab_aretes(const DoubleTab& nu, DoubleTab& coeffOperateur) const
399{
400 Cerr<<"Error in Op_Diff_VEFP1NCP1B_Face::calculer_dt_stab_aretes()"<<finl;
401 Cerr<<"Function not coded"<<finl;
402 Cerr<<"Exit"<<finl;
403 exit();
404}
405
406
408calculer_gradient_elem(const DoubleVect& inconnue) const
409{
410 const Domaine_VEF& domaine_VEF = domaine_vef();
411
412 const Domaine& domaine = domaine_VEF.domaine();
413 const DoubleTab& face_normales = domaine_VEF.face_normales();
414 const DoubleVect& volumes = domaine_VEF.volumes();
415 const IntTab& elem_faces=domaine_VEF.elem_faces();
416 const IntTab& face_voisins=domaine_VEF.face_voisins();
417
418 const int nb_faces_elem=domaine.nb_faces_elem();
419 const int nb_elem_tot=domaine.nb_elem_tot();
420 int elem=0,face_loc=0,face=0,compi=0,compj=0;
421
422 double signe=0.;
423 double volume=0.;
424
425 //Valeurs INTEGRALES du gradient_p0_
426 for(elem=0; elem<nb_elem_tot; elem++)
427 for(face_loc=0; face_loc<nb_faces_elem; face_loc++)
428 {
429 face=elem_faces(elem,face_loc);
430
431 signe=1;
432 if(elem!=face_voisins(face,0)) signe=-1;
433
434 for(compi=0; compi<dim_ch_; compi++)
435 for(compj=0; compj<dimension; compj++)
436 gradient_p0_(elem,compi,compj)+=signe*
437 inconnue[face*dim_ch_+compi]*
438 face_normales(face,compj);
439 }
440
441 //Valeurs NODALES du gradient_p0_
442 for (elem=0; elem<nb_elem_tot; elem++)
443 {
444 volume = volumes(elem);
445
446 for (compi=0; compi<dim_ch_; compi++)
447 for (compj=0; compj<dimension; compj++)
448 gradient_p0_(elem,compi,compj)/=(coeff_*volume);
449 }
450
451 //REMARQUE : cet echange_espace_virtuel() est NECESSAIRE
452 //dans le cas ou alphaS==1 et/ou alphaA=1
454 gradient_p0_.echange_espace_virtuel();
455 Debog::verifier("OpDifP1NCP1B Gradient P0 : ",gradient_p0_);
456
457 return gradient_p0_;
458}
459
461calculer_gradient_som(const DoubleVect& inconnue) const
462{
463 const Domaine_VEF& domaine_VEF = domaine_vef();
464 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
465 const Domaine& domaine = domaine_VEF.domaine();
466 const Domaine& dom=domaine;
467
468 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
469
470 const int nb_faces_elem=domaine.nb_faces_elem();
471 const int nb_som_face=domaine_VEF.nb_som_face();
472 const int nb_elem_tot=domaine_VEF.nb_elem_tot();
473 const int nb_som=domaine_VEF.nb_som();
474 const int nb_som_tot=domaine_VEF.nb_som_tot();
475 const int nb_bords =les_cl.size();
476 int elem=0,face_loc=0,som_loc=0,face=0;
477 int compi=0,compj=0,som=0,num1=0,num2=0;
478 int i=0,ind_face=0;
479 int n_bord=0;
480
481 const double coeff_som=1./(dimension)/(dimension+1);
482 double signe=0.;
483
484 const DoubleTab& face_normales = domaine_VEF.face_normales();
485 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
486
487 DoubleTab secmem(gradient_p1_);
488 ArrOfDouble sigma(dimension);
489
490 DoubleVect secmemij;
491 DoubleVect gradij;
492 dom.creer_tableau_sommets(secmemij);
493 dom.creer_tableau_sommets(gradij);
494
495 const IntTab& som_elem=domaine.les_elems();
496 const IntTab& elem_faces=domaine_VEF.elem_faces();
497 const IntTab& face_voisins=domaine_VEF.face_voisins();
498 const IntTab& face_sommets=domaine_VEF.face_sommets();
499
500 //Le second membre du systeme a inverser
501 secmem=0.;
502 for(elem=0; elem<nb_elem_tot; elem++)
503 {
504 sigma = 0;
505 for(face_loc=0; face_loc<nb_faces_elem; face_loc++)
506 {
507 face = elem_faces(elem,face_loc);
508
509 for(compi=0; compi<dim_ch_; compi++)
510 sigma[compi]+=inconnue[face*dim_ch_+compi];
511 }
512
513 for(face_loc=0; face_loc<nb_faces_elem; face_loc++)
514 {
515 som = dom.get_renum_som_perio(som_elem(elem,face_loc));
516 face = elem_faces(elem,face_loc);
517
518 signe=1;
519 if(elem!=face_voisins(face,0)) signe=-1;
520
521 for(compi=0; compi<dim_ch_; compi++)
522 for(compj=0; compj<dimension; compj++)
523 secmem(som,compi,compj)+=coeff_som*signe*
524 sigma[compi]*face_normales(face,compj);
525 }
526 }
527
528 secmem.echange_espace_virtuel();
529 Debog::verifier("OpDifP1NCP1B secmem, avant CL : ", secmem);
530
531 //Les conditions aux limites pour le second membre
532 for (n_bord=0; n_bord<nb_bords; n_bord++)
533 {
534 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
535 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
536
537 num1=0;
538 num2=le_bord.nb_faces_tot();
539
540 if (sub_type(Dirichlet_homogene,la_cl.valeur()))
541 {
542 //On ne fait rien et c'est normal
543 }
544 else if (sub_type(Dirichlet,la_cl.valeur()))
545 {
546 const Dirichlet& dirichlet =
547 ref_cast(Dirichlet,la_cl.valeur());
548
549 double x=0.,y=0.,z=0.;
550 double inconnue_pt=0.;
551 double temps = equation().schema_temps().temps_courant();
552
553 const DoubleTab& coord_sommets = dom.coord_sommets();
554
555 if (sub_type(Champ_front_txyz,dirichlet.champ_front()))
556 {
557 const Champ_front_txyz& champ_front =
558 ref_cast(Champ_front_txyz,dirichlet.champ_front());
559
560 for (ind_face=num1; ind_face<num2; ind_face++)
561 {
562 face=le_bord.num_face(ind_face);
563
564 for(som_loc=0; som_loc<nb_som_face; som_loc++)
565 {
566 som=dom.get_renum_som_perio(face_sommets(face,som_loc));
567
568 //Formule d'integration numerique exacte pour les polynomes de degre 2
569 if (dimension==2) //formule de Simpson
570 {
571 //Coordonnees du sommet "som"
572 x=coord_sommets(som,0);
573 y=coord_sommets(som,1);
574
575 //Valeur de l'inconnue au point d'integration
576 for (compi=0; compi<dim_ch_; compi++)
577 {
578 inconnue_pt=
579 champ_front.valeur_au_temps_et_au_point(temps,som,x,y,z,compi);
580
581 for (compj=0; compj<dimension; compj++)
582 secmem(som,compi,compj) +=
583 1./6*(2*inconnue[face*dim_ch_+compi]+inconnue_pt)
584 *face_normales(face,compj) ;
585 }
586 }//fin du if sur dimension==2
587
588 else //formule exacte pour les polynomes de degre 2
589 {
590 //On suppose que l'element considere est un TETRAEDRE
591 for (i=1; i<3; i++)
592 {
593 int som2=face_sommets(face,(som_loc+i)%nb_som_face);
594 som2=dom.get_renum_som_perio(som2);
595
596 //Coordonnees des points d'integration
597 x=(coord_sommets(som,0)+coord_sommets(som2,0))/2.;
598 y=(coord_sommets(som,1)+coord_sommets(som2,1))/2.;
599 z=(coord_sommets(som,2)+coord_sommets(som2,2))/2.;
600
601 //Vitesse au point d'integration
602 for (compi=0; compi<dim_ch_; compi++)
603 {
604 inconnue_pt=
605 champ_front.valeur_au_temps_et_au_point(temps,som,x,y,z,compi);
606
607 for (compj=0; compj<dimension; compj++)
608 secmem(som, compi, compj) += 1./dimension*
609 1/2.*inconnue_pt*face_normales(face,compj) ;
610 }
611 }
612 }//fin du else sur la dimension
613
614 }//fin du for sur "som_loc"
615
616 }//fin du for sur "ind_face"
617
618 }//fin du if sur "Champ_front_txyz"
619 else
620 {
621 for (ind_face=num1; ind_face<num2; ind_face++)
622 {
623 face = le_bord.num_face(ind_face);
624
625 for(som_loc=0; som_loc<nb_som_face; som_loc++)
626 {
627 som=dom.get_renum_som_perio(face_sommets(face,som_loc));
628
629 for (compi=0; compi<dim_ch_; compi++)
630 for (compj=0; compj<dimension; compj++)
631 secmem(som,compi,compj) += 1./dimension*
632 inconnue[face*dim_ch_+compi]*face_normales(face,compj) ;
633
634 }//fin du for sur "som_loc"
635
636 }//fin du for sur "ind_face"
637 }
638
639 }//fin du if sur "Dirichlet"
640
641 else if (!sub_type(Periodique,la_cl.valeur()))
642 {
643 for (ind_face=num1; ind_face<num2; ind_face++)
644 {
645 face = le_bord.num_face(ind_face);
646
647 for(som_loc=0; som_loc<nb_som_face; som_loc++)
648 {
649 som=dom.get_renum_som_perio(face_sommets(face,som_loc));
650
651 for (compi=0; compi<dim_ch_; compi++)
652 for (compj=0; compj<dimension; compj++)
653 secmem(som,compi,compj) += 1./dimension*
654 inconnue[face*dim_ch_+compi]*face_normales(face,compj) ;
655
656 }//fin du for sur "som_loc"
657
658 }//fin du for sur "ind_face"
659
660 }//fin du if sur "!Periodique"
661
662 }//fin du for sur "n_bord"
663
664 secmem.echange_espace_virtuel();
665 Debog::verifier("OpDifP1NCP1B secmem, apres CL : ", secmem);
666
667 //Calcul de la solution du systeme a inverser
668 for (compi=0; compi<dim_ch_; compi++)
669 for (compj=0; compj<dimension; compj++)
670 {
671 for(i=0; i<nb_som_tot; i++)
672 {
673 som=dom.get_renum_som_perio(i);
674 secmemij(som)=secmem(som,compi,compj);
675 }
676
677 //Resolution du systeme
678 for(i=0; i<nb_som; i++)
679 {
680 som=dom.get_renum_som_perio(i);
681 gradij(som)=secmemij(som)/(coeff_*volume_aux_sommets(som));
682 }
683
684 for(i=0; i<nb_som_tot; i++)
685 {
686 som=dom.get_renum_som_perio(i);
687 gradient_p1_(som,compi,compj)
688 =gradij(som);
689 }
690 }
691
692 gradient_p1_.echange_espace_virtuel();
693 Debog::verifier("OpDifP1NCP1B Gradient P1 : ",gradient_p1_);
694
695 return gradient_p1_;
696}
697
699calculer_gradient_aretes(const DoubleVect& inconnue) const
700{
701 return gradient_pa_;
702}
703
704
706corriger_div_pour_Cl(const DoubleVect& inconnue,const DoubleTab& nu,
707 DoubleVect& div) const
708{
709 const Domaine_VEF& domaine_VEF = domaine_vef();
710 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
711 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
712#ifndef NDEBUG
713 const IntTab& face_voisins=domaine_VEF.face_voisins();
714#endif
715 const int nb_bords =les_cl.size();
716 int n_bord=0, num1=0, num2=0;
717 int face=0, face_asso_loc=0, face_associee=0;
718 int ind_face=0, comp=0;
719
720 double flux=0.;
721
722 for (n_bord=0; n_bord<nb_bords; n_bord++)
723 {
724 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
725 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
726
727 //Reinitialisation de num1 et num2
728 num1 = 0;
729 num2 = le_bord.nb_faces();
730
731 if (sub_type(Periodique,la_cl.valeur()))
732 {
733 //periodicite
734 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
735
736 for (ind_face=num1; ind_face<num2; ind_face++)
737 {
738 face = le_bord.num_face(ind_face);
739 face_asso_loc=la_cl_perio.face_associee(ind_face);
740 face_associee=le_bord.num_face(face_asso_loc);
741
742 if (face<face_associee)
743 for (comp=0; comp<dim_ch_; comp++)
744 {
745 div[face*dim_ch_+comp]+=div[face_associee*dim_ch_+comp];
746 div[face_associee*dim_ch_+comp]=div[face*dim_ch_+comp];
747 }
748
749 }//fin du if sur for "ind_face"
750
751 }//fin de la periodicite
752
753 else if (sub_type(Neumann_paroi,la_cl.valeur()))
754 {
755 const Neumann_paroi& la_cl_paroi =
756 ref_cast(Neumann_paroi, la_cl.valeur());
757
758 for (ind_face=num1; ind_face<num2; ind_face++)
759 {
760 face = le_bord.num_face(ind_face);
761
762 assert(face_voisins(face,0)!=-1);
763
764 for (comp=0; comp<dim_ch_; comp++)
765 {
766 flux=la_cl_paroi.flux_impose(ind_face,comp)
767 *domaine_VEF.surface(face);
768
769 div[face*dim_ch_+comp]+=flux;
770 }
771 }
772
773 }//fin if sur "Neumann"
774 else if (sub_type(Echange_externe_impose,la_cl.valeur()))
775 {
776 const Echange_externe_impose& la_cl_paroi=
777 ref_cast(Echange_externe_impose, la_cl.valeur());
778
779 for (ind_face=num1; ind_face<num2; ind_face++)
780 {
781 face = le_bord.num_face(ind_face);
782
783 for (comp=0; comp<dim_ch_; comp++)
784 {
785 flux=la_cl_paroi.h_imp(ind_face,comp)
786 *domaine_VEF.surface(face);
787 flux*=(la_cl_paroi.T_ext(ind_face,comp)-inconnue[face*dim_ch_+comp]);
788
789 div[face*dim_ch_+comp]+=flux;
790 }
791 }
792 }
793 }//fin du for sur "n_bords"
794
796 Debog::verifier("OpDifP1NCP1B divergence apres CL : ", div);
797 return div;
798}
799
801calculer_divergence_elem(DoubleVect& div) const
802{
803 const Domaine_VEF& domaine_VEF = domaine_vef();
804
805 const DoubleTab& face_normales = domaine_VEF.face_normales();
806
807 const IntTab& elem_faces=domaine_VEF.elem_faces();
808 const IntTab& face_voisins=domaine_VEF.face_voisins();
809
810 const int nb_faces_elem=domaine_VEF.domaine().nb_faces_elem();
811 const int nb_elem_tot=domaine_VEF.nb_elem_tot();
812 int elem=0,face_loc=0,face=0,compi=0,compj=0;
813
814 double signe=0.;
815
816 for(elem=0; elem<nb_elem_tot; elem++)
817 for(face_loc=0; face_loc<nb_faces_elem; face_loc++)
818 {
819 face=elem_faces(elem,face_loc);
820
821 signe=1.;
822 if(elem!=face_voisins(face,0)) signe=-1.;
823
824 for(compi=0; compi<dim_ch_; compi++)
825 for(compj=0; compj<dimension; compj++)
826 div[face*dim_ch_+compi]-=
827 gradient_p0_(elem,compi,compj)
828 *signe*face_normales(face,compj);
829 }
830
832 Debog::verifier("OpDifP1NCP1B divergence P0 : ", div);
833 return div;
834}
835
837calculer_divergence_som(DoubleVect& div) const
838{
839 const Domaine_VEF& domaine_VEF = domaine_vef();
840 const Domaine& domaine = domaine_VEF.domaine();
841 const Domaine& dom=domaine;
842
843 const DoubleTab& face_normales = domaine_VEF.face_normales();
844 ArrOfDouble sigma(dimension);
845
846 const IntTab& som_elem=domaine.les_elems();
847 const IntTab& elem_faces=domaine_VEF.elem_faces();
848 const IntTab& face_voisins=domaine_VEF.face_voisins();
849
850 const int nb_faces_elem=domaine.nb_faces_elem();
851 const int nb_som_face=domaine_VEF.nb_som_face();
852 const int nb_elem_tot=domaine_VEF.nb_elem_tot();
853 int elem=0,face_loc=0,face_loc2=0,face=0;
854 int compi=0,compj=0,som=0,ind_face=0;
855 int num1=0, num2=0,som_loc=0;
856
857 static double coeff_som=1./(dimension)/(dimension+1);
858 double signe=0.;
859
860 //Algorithme sans tenir compte des CL
861 for(elem=0; elem<nb_elem_tot; elem++)
862 for(face_loc=0; face_loc<nb_faces_elem; face_loc++)
863 {
864 som=dom.get_renum_som_perio(som_elem(elem,face_loc));
865 face=elem_faces(elem,face_loc);
866
867 signe=1;
868 if(elem!=face_voisins(face,0)) signe=-1;
869
870 for(compj=0; compj<dimension; compj++)
871 sigma[compj]=signe*face_normales(face,compj);
872
873 for(face_loc2=0; face_loc2<nb_faces_elem; face_loc2++)
874 for(compi=0; compi<dim_ch_; compi++)
875 for(compj=0; compj<dimension; compj++)
876 div[elem_faces(elem,face_loc2)*dim_ch_+compi]-=
877 coeff_som*gradient_p1_(som,compi,compj)*sigma[compj];
878 }
879
880 //Les conditions aux limites
881 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
882 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
883 const IntTab& face_sommets = domaine_VEF.face_sommets();
884 const int nb_bords =les_cl.size();
885
886 DoubleTab gradient_bord(dim_ch_,dimension);
887
888 for (int n_bord=0; n_bord<nb_bords; n_bord++)
889 {
890 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
891 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
892 num1 = 0;
893 num2 = le_bord.nb_faces();
894
895 if (sub_type(Neumann,la_cl.valeur()) ||
896 sub_type(Neumann_val_ext,la_cl.valeur()) ||
897 sub_type(Neumann_homogene,la_cl.valeur()) ||
898 sub_type(Symetrie,la_cl.valeur())
899 )
900 {
901 for (ind_face=num1; ind_face<num2; ind_face++)
902 {
903 //Le numero de la face (qui peut etre virtuelle)
904 face=le_bord.num_face(ind_face);
905
906 //Le numero de l'element voisin
907 elem=face_voisins(face,0);
908 assert(elem!=-1);
909
910 //Calcul du gradient au milieu de la face de bord
911 //On prend une integration numerique approchee
912 gradient_bord=0.;
913 for (som_loc=0; som_loc<nb_som_face; som_loc++)
914 {
915 som=dom.get_renum_som_perio(face_sommets(face,som_loc));
916
917 for(compi=0; compi<dim_ch_; compi++)
918 for(compj=0; compj<dimension; compj++)
919 gradient_bord(compi,compj)+=
920 gradient_p1_(som,compi,compj);
921 }
922 gradient_bord/=dimension;
923
924 //Calcul divergence au bord : formule d'integration numerique
925 //exacte pour polynome d'ordre 1
926 for(compi=0; compi<dim_ch_; compi++)
927 for(compj=0; compj<dimension; compj++)
928 div[face*dim_ch_+compi]-=
929 gradient_bord(compi,compj)
930 *face_normales(face,compj);
931
932 }//fin du for sur "ind_face"
933
934 }//fin du if sur "Neumann_paroi", "Neumann", "Symetrie"
935
936 }//fin du for sur "n_bords"
937
939 Debog::verifier("OpDifP1NCP1B divergence P1 : ", div);
940 return div;
941}
942
944calculer_divergence_aretes(DoubleVect& div) const
945{
946 return div;
947}
948
950calculer_laplacien_som(const DoubleTab& nu_som) const
951{
952 const Champ_base& diffu=diffusivite();
953
954 bool testl=false;
955 testl|=sub_type(Champ_Don_Fonc_xyz,diffu);
956 testl|=sub_type(Champ_Don_lu,diffu);
957 testl|=sub_type(Champ_Uniforme,diffu);
958 testl|=sub_type(Champ_Uniforme_Morceaux,diffu);
959 testl|=sub_type(Champ_Fonc_base,diffu);
961
962 auto& coeff = laplacien_p1_.get_set_coeff();
963
964 const DoubleTab& inconnue1=equation().inconnue().valeurs();
965 const DoubleVect& porosite_face=equation().milieu().porosite_face();
966
967 assert(laplacien_p1_.nb_lignes()>2);
968
969 coeff=0.;
970 ajouter_contribution_som(inconnue1,porosite_face,nu_som,laplacien_p1_);
971 coeff*=-1;//pour l'explicite
972}
973
975ajouter(const DoubleTab& inconnue, DoubleTab& resu) const
976{
977 const Domaine_VEF& domaine_VEF = domaine_vef();
978 const Domaine& domaine=domaine_VEF.domaine();
979
980 const int nb_aretes_tot=domaine.nb_aretes_tot();
981
982 //Recuperation de la diffusivite
984
985 //Pour tenir compte de la porosite
986 const int marq = phi_psi_diffuse(equation());
987 const DoubleVect& porosite_face = equation().milieu().porosite_face();
988 const DoubleVect& porosite_elem = equation().milieu().porosite_elem();
989
990 DoubleTab nu,nu_p1,nu_pA;
991 modif_par_porosite_si_flag(nu_,nu,!marq,porosite_elem);
992
993 DoubleTab inconnue1;
994 modif_par_porosite_si_flag(inconnue,inconnue1,marq,porosite_face);
995
996 const DoubleVect& inconnue2 = inconnue1;
997 DoubleVect& resu2 = resu;
998 DoubleVect resu3(resu2);
999 resu3=0.;
1000
1001 if (alphaE)
1002 {
1003 gradient_p0_=0.;
1004 calculer_gradient_elem(inconnue2);
1005
1008
1010 calculer_flux_bords_elem(inconnue2);
1011 }
1012 if (alphaA)
1013 {
1014 gradient_pa_=0.;
1015 nu_pA.resize(nb_aretes_tot);
1016 remplir_nu_pA(nu,nu_pA);
1017
1018 calculer_gradient_aretes(inconnue2);
1019
1021
1023 calculer_flux_bords_aretes(inconnue2);
1024 }
1025 corriger_div_pour_Cl(inconnue2,nu,resu3);
1026
1027 //Le corriger_div_pour_Cl() doit etre fait AVANT le calcul
1028 //de la partie p1 car la matrice est deja codee pour tenir
1029 //compte des coefficients periodiques
1030 //REMARQUE IMPORTANTE : pour des raisons techniques inherentes
1031 //a TrioU, le calcul du dt_stab a lieu AVANT l'application
1032 //de la fonction ajouter(). Or le dt_stab a besoin de la matrice
1033 //pour etre correctement calcule par consequent, la matrice
1034 //laplacien_p1_ est construite dans la fonction calculer_dt_stab()
1035 //et est seulement reutilisee ici.
1036 if (alphaS)
1037 {
1038 domaine.creer_tableau_sommets(nu_p1);
1039 remplir_nu_p1(nu,nu_p1);
1040 laplacien_p1_.ajouter_multvect(inconnue2,resu3);
1041
1042 gradient_p1_=0.;
1043 calculer_gradient_som(inconnue2);
1046 calculer_flux_bords_som(inconnue2);
1047 }
1048
1049 if (test_) test();
1050
1051 resu2+=resu3;
1053 modifier_flux(*this);
1054 return resu;
1055}
1056
1058calculer(const DoubleTab& inconnue, DoubleTab& resu) const
1059{
1060 resu = 0;
1061 return ajouter(inconnue,resu);
1062}
1063
1065corriger_pour_diffusivite(const DoubleTab& nu,DoubleTab& grad) const
1066{
1067 tab_multiply_any_shape(grad, nu);
1068 return grad;
1069}
1070
1071
1073{
1074 const Domaine_VEF& domaine_VEF = domaine_vef();
1075
1076 const DoubleTab& unknown = equation().inconnue().valeurs();
1077 const int size = unknown.line_size();
1078
1079 //Definition des gradients
1080 gradient_p0_.resize(0, size, Objet_U::dimension);
1082
1083 gradient_p1_.resize(0, size, Objet_U::dimension);
1085
1086 if (alphaA)
1087 {
1088 gradient_pa_.resize(0, size, Objet_U::dimension);
1090 }
1091
1092 //Initialisation de l'attribut dim_ch_
1093 dim_ch_=size;
1094
1095 //Dimensionnemt du tableau flux_bords
1096 flux_bords_.resize(domaine_VEF.nb_faces_bord(),size);
1097 flux_bords_=0.;
1098}
1099
1100//Fonction qui calcule le flux aux bords du domaine
1101void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_elem(const DoubleVect& inconnue) const
1102{
1103 const Domaine_VEF& domaine_VEF = domaine_vef();
1104 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1105
1106 const IntTab& face_voisins=domaine_VEF.face_voisins();
1107
1108 const DoubleTab& face_normales=domaine_VEF.face_normales();
1109
1110 const int nb_bords=domaine_VEF.nb_front_Cl();
1111
1112 int face=0;
1113 int elem=0;
1114 int n_bord=0,ind_face=0;
1115 int num1=0,num2=0;
1116 int compi=0,compj=0;
1117
1118 double surface=0.;
1119 double Text=0.;
1120
1121 double coeff_conv=1.;
1122 if (alphaS) coeff_conv=convexite_;
1123
1124 for (n_bord=0; n_bord<nb_bords; n_bord++)
1125 {
1126 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1127 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1128
1129 num1=0;
1130 num2=le_bord.nb_faces();
1131
1132 if (sub_type(Neumann_paroi,la_cl.valeur()))
1133 {
1134 const Neumann_paroi& la_cl_paroi=
1135 ref_cast(Neumann_paroi,la_cl.valeur());
1136
1137 for (ind_face=num1; ind_face<num2; ind_face++)
1138 {
1139 face=le_bord.num_face(ind_face);
1140 surface=domaine_VEF.face_surfaces(face);
1141
1142 for (compi=0; compi<dim_ch_; compi++)
1143 flux_bords_(face,compi)=coeff_conv*
1144 la_cl_paroi.flux_impose(ind_face,compi)*
1145 surface;
1146 }
1147 }
1148 else if (sub_type(Echange_externe_impose,la_cl.valeur()))
1149 {
1150 const Echange_externe_impose& la_cl_paroi=
1151 ref_cast(Echange_externe_impose,la_cl.valeur());
1152
1153 for (ind_face=num1; ind_face<num2; ind_face++)
1154 {
1155 face=le_bord.num_face(ind_face);
1156 surface=domaine_VEF.face_surfaces(face);
1157
1158 for (compi=0; compi<dim_ch_; compi++)
1159 {
1160 Text=la_cl_paroi.T_ext(ind_face,compi);
1161
1162 flux_bords_(face,compi)=coeff_conv*la_cl_paroi.h_imp(ind_face,compi)*surface;
1163 flux_bords_(face,compi)*=(Text-inconnue[face*dim_ch_+compi]);
1164 }
1165 }
1166 }
1167 else if ( sub_type(Neumann_homogene,la_cl.valeur()) ||
1168 sub_type(Neumann_sortie_libre,la_cl.valeur()) ||
1169 sub_type(Symetrie,la_cl.valeur())
1170 )
1171 {
1172 for (ind_face=num1; ind_face<num2; ind_face++)
1173 {
1174 face=le_bord.num_face(ind_face);
1175
1176 for (compi=0; compi<dim_ch_; compi++)
1177 flux_bords_(face,compi)=0.;
1178 }
1179 }
1180 else
1181 {
1182 for (ind_face=num1; ind_face<num2; ind_face++)
1183 {
1184 face=le_bord.num_face(ind_face);
1185 elem=face_voisins(face,0);
1186 assert(elem!=-1);
1187
1188 //le coefficient de convexite est deja dans gradient_p0_
1189 for (compi=0; compi<dim_ch_; compi++)
1190 for (compj=0; compj<dimension; compj++)
1191 flux_bords_(face,compi)=gradient_p0_(elem,compi,compj)
1192 *face_normales(face,compj);
1193 }
1194 }
1195 }//fin du for sur n_bord
1196}
1197
1198//Fonction qui calcule le flux aux bords du domaine
1199void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_som(const DoubleVect& inconnue) const
1200{
1201 const Domaine_VEF& domaine_VEF = domaine_vef();
1202 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1203 const Domaine& domaine = domaine_VEF.domaine();
1204 const Domaine& dom=domaine;
1205
1206 const IntTab& face_sommets=domaine_VEF.face_sommets();
1207
1208 const DoubleTab& face_normales=domaine_VEF.face_normales();
1209
1210 const int nb_som_face=domaine_VEF.nb_som_face();
1211 const int nb_bords=domaine_VEF.nb_front_Cl();
1212
1213 int face=0;
1214 int som=0,som_loc=0;
1215 int n_bord=0,ind_face=0;
1216 int num1=0,num2=0;
1217 int compi=0,compj=0;
1218
1219 double surface=0.;
1220 double Text=0.;
1221 double coeff_conv=1.;
1222 if (alphaE) coeff_conv=1.-convexite_;
1223
1224 for (n_bord=0; n_bord<nb_bords; n_bord++)
1225 {
1226 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1227 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1228
1229 num1=0;
1230 num2=le_bord.nb_faces();
1231
1232 if (sub_type(Neumann_paroi,la_cl.valeur()))
1233 {
1234 const Neumann_paroi& la_cl_paroi=
1235 ref_cast(Neumann_paroi,la_cl.valeur());
1236
1237 for (ind_face=num1; ind_face<num2; ind_face++)
1238 {
1239 face=le_bord.num_face(ind_face);
1240 surface=domaine_VEF.face_surfaces(face);
1241
1242 for (compi=0; compi<dim_ch_; compi++)
1243 flux_bords_(face,compi)=coeff_conv*
1244 la_cl_paroi.flux_impose(ind_face,compi)*
1245 surface;
1246 }
1247 }
1248 else if (sub_type(Echange_externe_impose,la_cl.valeur()))
1249 {
1250 const Echange_externe_impose& la_cl_paroi=
1251 ref_cast(Echange_externe_impose,la_cl.valeur());
1252
1253 for (ind_face=num1; ind_face<num2; ind_face++)
1254 {
1255 face=le_bord.num_face(ind_face);
1256 surface=domaine_VEF.face_surfaces(face);
1257
1258 for (compi=0; compi<dim_ch_; compi++)
1259 {
1260 Text=la_cl_paroi.T_ext(ind_face,compi);
1261
1262 flux_bords_(face,compi)=coeff_conv*la_cl_paroi.h_imp(ind_face,compi)*surface;
1263 flux_bords_(face,compi)*=(Text-inconnue[face*dim_ch_+compi]);
1264 }
1265 }
1266 }
1267 else if ( sub_type(Neumann_homogene,la_cl.valeur()) ||
1268 sub_type(Neumann_sortie_libre,la_cl.valeur()) ||
1269 sub_type(Symetrie,la_cl.valeur())
1270 )
1271 {
1272 for (ind_face=num1; ind_face<num2; ind_face++)
1273 {
1274 face=le_bord.num_face(ind_face);
1275
1276 for (compi=0; compi<dim_ch_; compi++)
1277 flux_bords_(face,compi)=0.;
1278 }
1279 }
1280 else
1281 {
1282 for (ind_face=num1; ind_face<num2; ind_face++)
1283 {
1284 face=le_bord.num_face(ind_face);
1285
1286 //le coefficient de convexite est deja dans gradient_p1_
1287 for (som_loc=0; som_loc<nb_som_face; som_loc++)
1288 {
1289 som=face_sommets(face,som_loc);
1290 som=dom.get_renum_som_perio(som);
1291
1292 for (compi=0; compi<dim_ch_; compi++)
1293 for (compj=0; compj<dimension; compj++)
1294 flux_bords_(face,compi)+=gradient_p1_(som,compi,compj)*
1295 face_normales(face,compj);
1296 }
1297
1298 for (compi=0; compi<dim_ch_; compi++)
1299 flux_bords_(face,compi)/=nb_som_face;
1300 }
1301 }
1302 }//fin du for sur n_bord
1303}
1304
1305//Fonction qui calcule le flux aux bords du domaine
1306void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_aretes(const DoubleVect& inconnue) const
1307{
1308 Cerr<<"Op_Dift_VEF_P1NCP1B_Face::calculer_flux_bords_aretes() not coded"<<finl;
1309 Cerr<<"Exit"<<finl;
1310 exit();
1311}
1312
1313
1314///////////////////////////////////////////////////////////////
1315//Fonctions pour l'implicite
1316//////////////////////////////////////////////////////////////
1318ajouter_contribution_elem(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1319 const DoubleTab& nu,Matrice_Morse& matrice) const
1320{
1321 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1322 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
1323 const IntTab& elem_faces = domaine_VEF.elem_faces();
1324 const IntTab& face_voisins = domaine_VEF.face_voisins();
1325
1326 // int nb_faces_tot = domaine_VEF.nb_faces_tot();
1327 int nb_faces=domaine_VEF.nb_faces();
1328 int nb_faces_elem = domaine_VEF.domaine().nb_faces_elem();
1329 int nb_comp = inconnue.line_size();
1330
1331 int i,j,num_face;
1332 int elem1,elem2;
1333
1334 double val;
1335 double coeff=1./coeff_;
1336 if (alphaS) coeff*=convexite_;
1337
1338 int nb_bords=domaine_VEF.nb_front_Cl();
1339 for (int n_bord=0; n_bord<nb_bords; n_bord++)
1340 {
1341 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1342 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1343 int num1 = le_bord.num_premiere_face();
1344 int num2 = num1 + le_bord.nb_faces();
1345
1346 if (sub_type(Periodique,la_cl.valeur()))
1347 {
1348 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1349 int fac_asso;
1350 for (num_face=num1; num_face<num2; num_face++)
1351 {
1352 elem1 = face_voisins(num_face,0);
1353 fac_asso = la_cl_perio.face_associee(num_face-num1)+num1;
1354
1355 //A la fin de la boucle :
1356 //si ok=1, alors num_face appartient bien a elem1
1357 //si ok=0, alors num_face n'appartient pas a elem1 et
1358 // fac_asso appartient a elem1
1359 int ok=1;
1360 int fac_loc=0;
1361 while ((fac_loc<nb_faces_elem) && (elem_faces(elem1,fac_loc)!=num_face)) fac_loc++;
1362 if (fac_loc==nb_faces_elem) ok=0;
1363
1364 for (i=0; i<nb_faces_elem; i++)
1365 if ( ( (j= elem_faces(elem1,i)) > num_face ) && (j != fac_asso ) )
1366 {
1367 val = viscA(num_face,j,elem1,nu(elem1));
1368
1369 // int fac_loc=0;
1370 // while ((fac_loc<nb_faces_elem) && (elem_faces(elem1,fac_loc)!=num_face)) fac_loc++;
1371 // if (fac_loc==nb_faces_elem) ok=0;
1372
1373 for (int nc=0; nc<nb_comp; nc++)
1374 {
1375 int n0=num_face*nb_comp+nc;
1376 int j0=j*nb_comp+nc;
1377
1378 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1379 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1380
1381 if (!ok) n0=fac_asso*nb_comp+nc;
1382 if (j<nb_faces)
1383 {
1384 matrice(j0,n0)-=val*porosite_face((n0-nc)/nb_comp)*coeff;
1385 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1386 }
1387
1388 }
1389 }
1390
1391 //Deuxieme element
1392 elem2 = face_voisins(num_face,1);
1393
1394 for (i=0; i<nb_faces_elem; i++)
1395 if ( ( (j= elem_faces(elem2,i)) > num_face ) && (j != fac_asso ) )
1396 {
1397 val = viscA(num_face,j,elem2,nu(elem2));
1398
1399 for (int nc=0; nc<nb_comp; nc++)
1400 {
1401 int n0=num_face*nb_comp+nc;
1402 int j0=j*nb_comp+nc;
1403
1404 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1405 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1406 }
1407 }
1408
1409 }//fin du for sur "num_face"
1410 }
1411 else
1412 {
1413 for (num_face=num1; num_face<num2; num_face++)
1414 {
1415 elem1 = face_voisins(num_face,0);
1416
1417 for (i=0; i<nb_faces_elem; i++)
1418 if ( (j= elem_faces(elem1,i)) > num_face )
1419 {
1420 val = viscA(num_face,j,elem1,nu(elem1));
1421 for (int nc=0; nc<nb_comp; nc++)
1422 {
1423 int n0=num_face*nb_comp+nc;
1424 int j0=j*nb_comp+nc;
1425
1426 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1427 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1428 if (j<nb_faces) //necessaire ????
1429 {
1430 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1431 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1432 }
1433
1434 }
1435 }
1436 }
1437 }
1438 }
1439
1440 //On ne remplit que les lignes reelles
1441 for (num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
1442 {
1443 elem1 = face_voisins(num_face,0);
1444 elem2 = face_voisins(num_face,1);
1445
1446 for (i=0; i<nb_faces_elem; i++)
1447 {
1448 if ( (j=elem_faces(elem1,i)) > num_face )
1449 {
1450 val = viscA(num_face,j,elem1,nu(elem1));
1451 for (int nc=0; nc<nb_comp; nc++)
1452 {
1453 int n0=num_face*nb_comp+nc;
1454 int j0=j*nb_comp+nc;
1455
1456 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1457 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1458 if (j<nb_faces)
1459 {
1460 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1461 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1462 }
1463 }
1464 }
1465
1466 // if (elem2!=-1) //test non necessaire car la face est reelle
1467 if ( (j=elem_faces(elem2,i)) > num_face )
1468 {
1469 val= viscA(num_face,j,elem2,nu(elem2));
1470 for (int nc=0; nc<nb_comp; nc++)
1471 {
1472 int n0=num_face*nb_comp+nc;
1473 int j0=j*nb_comp+nc;
1474
1475 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1476 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1477 if (j<nb_faces)
1478 {
1479 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1480 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1481 }
1482
1483 }
1484 }
1485 }
1486 }
1487}
1488
1490ajouter_contribution_som(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1491 const DoubleTab& nu_som,Matrice_Morse& matrice) const
1492{
1493 const Domaine_VEF& domaine_VEF=domaine_vef();
1494 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1495
1496 IntVect liste_som(dimension+2);//pour triangles et tetraedres
1497
1498 DoubleTab gradient0(dimension,dimension+2);
1499 DoubleTab gradient1(dimension);
1500
1501 const int premiere_face_int=domaine_VEF.premiere_face_int();
1502 const int nb_faces=domaine_VEF.nb_faces();
1503 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
1504 const int nb_bords=domaine_VEF.nb_front_Cl();
1505
1506 int face=0;
1507 int ind_face=0;
1508 int n_bord=0;
1509 int num1=0,num2=0;
1510
1511 DoubleTab coeff_perio(nb_faces_tot);
1512 coeff_perio=1.;
1513 for (n_bord=0; n_bord<nb_bords; n_bord++)
1514 {
1515 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1516 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1517 num1=0;
1518 num2=le_bord.nb_faces_tot();
1519
1520 if (sub_type(Periodique,la_cl.valeur()))
1521 for (ind_face=num1; ind_face<num2; ind_face++)
1522 {
1523 face=le_bord.num_face(ind_face);
1524 coeff_perio(face)=0.5;
1525 }
1526 }
1527
1528 //
1529 //Partie P1 du laplacien discret :
1530 //on tourne sur les lignes donc nous n'avons
1531 //besoin que de remplir les lignes reelles.
1532 //ATTENTION : le remplissage des lignes reelles
1533 //peut induire le calcul d'un coefficient
1534 //lie a une colonne virtuelle
1535 //
1536
1537 /* Faces internes */
1538 for (face=premiere_face_int; face<nb_faces; face++)
1539 {
1540 coeff_matrice_som(face,liste_som,
1541 gradient0,gradient1,
1542 porosite_face,nu_som,
1543 coeff_perio,matrice);
1544 }
1545
1546 for (n_bord=0; n_bord<nb_bords; n_bord++)
1547 {
1548 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1549 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1550 num1=0;
1551 num2=le_bord.nb_faces();
1552
1553 if (sub_type(Periodique,la_cl.valeur()))
1554 {
1555 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1556 int faceAss=0;
1557
1558 for (ind_face=num1; ind_face<num2; ind_face++)
1559 {
1560 face=le_bord.num_face(ind_face);
1561 faceAss=le_bord.num_face(la_cl_perio.face_associee(ind_face));
1562
1563 //On prend la plus petite des faces pour etre sur de n'oublier
1564 //aucune face de bord
1565 coeff_matrice_som_perio(face,faceAss,liste_som,
1566 gradient0,gradient1,
1567 porosite_face,nu_som,
1568 coeff_perio,matrice);
1569
1570 }
1571 }
1572 else if (sub_type(Symetrie,la_cl.valeur()))
1573 for (ind_face=num1; ind_face<num2; ind_face++)
1574 {
1575 face=le_bord.num_face(ind_face);
1576
1577 coeff_matrice_som_symetrie(face,liste_som,
1578 gradient0,gradient1,
1579 porosite_face,nu_som,
1580 coeff_perio,matrice);
1581 }
1582
1583 else
1584 for (ind_face=num1; ind_face<num2; ind_face++)
1585 {
1586 face=le_bord.num_face(ind_face);
1587
1588 coeff_matrice_som_CL(face,liste_som,
1589 gradient0,gradient1,
1590 porosite_face,nu_som,
1591 coeff_perio,matrice);
1592 }
1593 }
1594}
1595
1597ajouter_contribution_aretes(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1598 const DoubleTab& nu,Matrice_Morse& matrice) const
1599{
1600}
1601
1602//Fonction qui calcule les coefficients de la matrice pour une face
1603//INTERNE.
1605coeff_matrice_som(const int face,IntVect& liste_som,
1606 DoubleTab& gradient0, DoubleTab& gradient1,
1607 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1608 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1609{
1610 const Domaine_VEF& domaine_VEF=domaine_vef();
1611
1612 const auto& tab1=matrice.get_tab1();
1613 const auto& tab2=matrice.get_tab2();
1614
1615 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1616
1617 const int nb_faces=domaine_VEF.nb_faces();
1618
1619 int face_C=0;
1620 int face2=0,face2_C=0;
1621 int som_loc=0,som=0;
1622 int som_loc0=0,som_loc1=0;
1623 int compi=0,compj=0;
1624 int elem0=0,elem1=0;
1625 int i=0;
1626 int nnz=0;
1627
1628 double coeff_som=0.,coeff_mat=0.;
1629 double coeff_diff=0.;
1630 double psc=0.;
1631 double delta=decentrage_;
1632
1633 double coeff_conv=1.;
1634 if (alphaE) coeff_conv=(1.-convexite_);
1635
1636 //Quelques verifications
1637 assert(gradient0.nb_dim()==2);
1638 assert(gradient0.dimension(0)==dimension);
1639 assert(gradient0.dimension(1)==dimension+2);
1640 assert(gradient1.nb_dim()==1);
1641 assert(gradient1.dimension(0)==dimension);
1642 assert(liste_som.size()==dimension+2);
1643
1644 //
1645 //Partie P1 du laplacien discret
1646 //
1647 liste_som=-1;
1648 gradient0=0.;
1649 gradient_som(face,nnz,liste_som,gradient0);
1650
1651
1652 /* gradient associe a "face" : calcul du coefficient */
1653 /* diagonal de la matrice associee a l'inconnue */
1654 coeff_mat=0.;
1655 for (som_loc=0; som_loc<nnz; som_loc++)
1656 {
1657 som=liste_som(som_loc);
1658 coeff_som=volume_aux_sommets(som)*coeff_;
1659
1660 psc=0.;
1661 for (compj=0; compj<dimension; compj++)
1662 psc+=gradient0(compj,som_loc)
1663 *gradient0(compj,som_loc);
1664
1665 psc*=coeff_som;
1666 psc*=nu_som(som);
1667
1668 coeff_mat+=psc;
1669 }
1670 coeff_mat*=coeff_conv;
1671
1672 for (compi=0; compi<dim_ch_; compi++)
1673 {
1674 face_C=face*dim_ch_+compi;
1675 matrice(face_C,face_C)+=coeff_mat;
1676 }
1677
1678
1679 /* calcul des coefficients extra-diagonaux de la matrice laplacien */
1680 /* la matrice etant diagonale par bloc, on effectue le calcul du */
1681 /* produit scalaire une seule fois avant de l'affecter aux differentes */
1682 /* composantes de la matrice */
1683 face_C=face*dim_ch_;
1684 auto debut=tab1[face_C]-1;
1685 auto size=tab1[face_C+1]-tab1[face_C];
1686
1687 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> deja rempli
1688 {
1689 face2_C=tab2[debut+i]-1;
1690 face2=face2_C/dim_ch_;//division euclidienne
1691
1692 if (face2>face)//pour la symetrie de l'operateur
1693 {
1694 coeff_mat=0.;
1695 for (som_loc=0; som_loc<nnz; som_loc++)
1696 {
1697 som=liste_som(som_loc);
1698 coeff_som=volume_aux_sommets(som)*coeff_;
1699 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1700
1701 if (elem0!=-1)//les deux faces se "voient"
1702 {
1703 assert(som_loc0!=-1);
1704 gradient1=0.;
1705 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1706
1707 psc=0.;
1708 for (compj=0; compj<dimension; compj++)
1709 psc+=gradient0(compj,som_loc)
1710 *gradient1(compj);
1711
1712 psc*=coeff_som;
1713 psc*=nu_som(som);
1714 coeff_mat+=psc;
1715 }
1716 }
1717 coeff_mat*=coeff_conv;
1718 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1719 coeff_mat+=coeff_diff;
1720
1721 for (compi=0; compi<dim_ch_; compi++)
1722 {
1723 face_C=face*dim_ch_+compi;
1724 face2_C=face2*dim_ch_+compi;
1725
1726 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
1727 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
1728 if (face2<nb_faces)
1729 {
1730 matrice(face2_C,face_C)+=coeff_mat;
1731 matrice(face2_C,face2_C)-=coeff_diff;
1732 }
1733 }
1734 }
1735 }
1736}
1737
1738//Fonction qui calcule les coefficients de la matrice pour une face
1739//de BORD qui n'est ni periodique ni symetrique.
1741coeff_matrice_som_CL(const int face,IntVect& liste_som,
1742 DoubleTab& gradient0, DoubleTab& gradient1,
1743 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1744 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1745{
1746 const Domaine_VEF& domaine_VEF=domaine_vef();
1747
1748 const auto& tab1=matrice.get_tab1();
1749 const auto& tab2=matrice.get_tab2();
1750
1751 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1752
1753 const int nb_faces=domaine_VEF.nb_faces();
1754
1755 int face_C=0;
1756 int face2=0,face2_C=0;
1757 int som_loc=0,som=0;
1758 int som_loc0=0,som_loc1=0;
1759 int compi=0,compj=0;
1760 int elem0=0,elem1=0;
1761 int i=0;
1762 int nnz=0;
1763
1764 double coeff_som=0.,coeff_mat=0.;
1765 double coeff_diff=0.;
1766 double psc=0.;
1767 double delta=decentrage_;
1768
1769 double coeff_conv=1.;
1770 if (alphaE) coeff_conv=(1.-convexite_);
1771
1772 //Quelques verifications
1773 assert(gradient0.nb_dim()==2);
1774 assert(gradient0.dimension(0)==dimension);
1775 assert(gradient0.dimension(1)==dimension+2);
1776 assert(gradient1.nb_dim()==1);
1777 assert(gradient1.dimension(0)==dimension);
1778 assert(liste_som.size()==dimension+2);
1779
1780 //
1781 //Partie P1 du laplacien discret
1782 //
1783 liste_som=-1;
1784 gradient0=0.;
1785 gradient_som_CL(face,nnz,liste_som,gradient0);
1786
1787
1788 /* gradient associe a "face" : calcul du coefficient */
1789 /* diagonal de la matrice associee a l'inconnue */
1790 coeff_mat=0.;
1791 for (som_loc=0; som_loc<nnz; som_loc++)
1792 {
1793 som=liste_som(som_loc);
1794 coeff_som=volume_aux_sommets(som)*coeff_;
1795
1796 psc=0.;
1797 for (compj=0; compj<dimension; compj++)
1798 psc+=gradient0(compj,som_loc)
1799 *gradient0(compj,som_loc);
1800
1801 psc*=coeff_som;
1802 psc*=nu_som(som);
1803
1804 coeff_mat+=psc;
1805 }
1806 coeff_mat*=coeff_conv;
1807
1808 for (compi=0; compi<dim_ch_; compi++)
1809 {
1810 face_C=face*dim_ch_+compi;
1811 matrice(face_C,face_C)+=coeff_mat;
1812 }
1813
1814
1815 /* calcul des coefficients extra-diagonaux de la matrice laplacien */
1816 /* la matrice etant diagonale par bloc, on effectue le calcul du */
1817 /* produit scalaire une seule fois avant de l'affecter aux differentes */
1818 /* composantes de la matrice */
1819 face_C=face*dim_ch_;
1820 auto debut=tab1[face_C]-1;
1821 auto size=tab1[face_C+1]-tab1[face_C];
1822
1823 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> deja rempli
1824 {
1825 face2_C=tab2[debut+i]-1;
1826 face2=face2_C/dim_ch_;//division euclidienne
1827
1828 if (face2>face)//pour la symetrie de l'operateur
1829 {
1830 coeff_mat=0.;
1831 for (som_loc=0; som_loc<nnz; som_loc++)
1832 {
1833 som=liste_som(som_loc);
1834 coeff_som=volume_aux_sommets(som)*coeff_;
1835 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1836
1837 if (elem0!=-1)//les deux faces se "voient"
1838 {
1839 assert(som_loc0!=-1);
1840 gradient1=0.;
1841 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1842
1843 psc=0.;
1844 for (compj=0; compj<dimension; compj++)
1845 psc+=gradient0(compj,som_loc)
1846 *gradient1(compj);
1847
1848 psc*=coeff_som;
1849 psc*=nu_som(som);
1850 coeff_mat+=psc;
1851 }
1852 }
1853 coeff_mat*=coeff_conv;
1854 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1855 coeff_mat+=coeff_diff;
1856
1857 for (compi=0; compi<dim_ch_; compi++)
1858 {
1859 face_C=face*dim_ch_+compi;
1860 face2_C=face2*dim_ch_+compi;
1861
1862 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
1863 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
1864 if (face2<nb_faces)
1865 {
1866 matrice(face2_C,face_C)+=coeff_mat;
1867 matrice(face2_C,face2_C)-=coeff_diff;
1868 }
1869 }
1870 }
1871 }
1872}
1873
1874//Fonction qui calcule les coefficients de la matrice pour une face
1875//de BORD qui est une face de SYMETRIE.
1877coeff_matrice_som_symetrie(const int face,IntVect& liste_som,
1878 DoubleTab& gradient0, DoubleTab& gradient1,
1879 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1880 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1881{
1882 const Domaine_VEF& domaine_VEF=domaine_vef();
1883
1884 const auto& tab1=matrice.get_tab1();
1885 const auto& tab2=matrice.get_tab2();
1886
1887 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1888
1889 const int nb_faces=domaine_VEF.nb_faces();
1890
1891 int face_C=0;
1892 int face2=0,face2_C=0;
1893 int som_loc=0,som=0;
1894 int som_loc0=0,som_loc1=0;
1895 int compi=0,compj=0;
1896 int elem0=0,elem1=0;
1897 int i=0;
1898 int nnz=0;
1899
1900 double coeff_som=0.,coeff_mat=0.;
1901 double coeff_diff=0.;
1902 double psc=0.;
1903 double delta=decentrage_;
1904
1905 double coeff_conv=1.;
1906 if (alphaE) coeff_conv=(1.-convexite_);
1907
1908 //Quelques verifications
1909 assert(gradient0.nb_dim()==2);
1910 assert(gradient0.dimension(0)==dimension);
1911 assert(gradient0.dimension(1)==dimension+2);
1912 assert(gradient1.nb_dim()==1);
1913 assert(gradient1.dimension(0)==dimension);
1914 assert(liste_som.size()==dimension+2);
1915
1916 //
1917 //Partie P1 du laplacien discret
1918 //
1919 liste_som=-1;
1920 gradient0=0.;
1921 gradient_som_CL(face,nnz,liste_som,gradient0);
1922
1923
1924 /* gradient associe a "face" : calcul du coefficient */
1925 /* diagonal de la matrice associee a l'inconnue */
1926 coeff_mat=0.;
1927 for (som_loc=0; som_loc<nnz; som_loc++)
1928 {
1929 som=liste_som(som_loc);
1930 coeff_som=volume_aux_sommets(som)*coeff_;
1931
1932 psc=0.;
1933 for (compj=0; compj<dimension; compj++)
1934 psc+=gradient0(compj,som_loc)
1935 *gradient0(compj,som_loc);
1936
1937 psc*=coeff_som;
1938 psc*=nu_som(som);
1939
1940 coeff_mat+=psc;
1941 }
1942 coeff_mat*=coeff_conv;
1943
1944 for (compi=0; compi<dim_ch_; compi++)
1945 {
1946 face_C=face*dim_ch_+compi;
1947 matrice(face_C,face_C)+=coeff_mat;
1948 }
1949
1950
1951 /* calcul des coefficients extra-diagonaux de la matrice laplacien */
1952 /* la matrice etant diagonale par bloc, on effectue le calcul du */
1953 /* produit scalaire une seule fois avant de l'affecter aux differentes */
1954 /* composantes de la matrice */
1955 /* REMARQUE : la matrice est modifiee pour tenir compte des CL de */
1956 /* symetrie, mais on ne calcule pas les modifications associees -> */
1957 /* c'est la fonction Op_VEF_Face::modifier_pour_Cl() qui le fera */
1958 face_C=face*dim_ch_;
1959 auto debut=tab1[face_C]-1;
1960 auto size=tab1[face_C+1]-tab1[face_C];
1961 size-=(dim_ch_-1);//-> pour ne pas calculer les coefficients inutiles
1962
1963 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> deja rempli
1964 {
1965 face2_C=tab2[debut+i]-1;
1966 face2=face2_C/dim_ch_;//division euclidienne
1967
1968 if (face2>face)//pour la symetrie de l'operateur
1969 {
1970 coeff_mat=0.;
1971 for (som_loc=0; som_loc<nnz; som_loc++)
1972 {
1973 som=liste_som(som_loc);
1974 coeff_som=volume_aux_sommets(som)*coeff_;
1975 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1976
1977 if (elem0!=-1)//les deux faces se "voient"
1978 {
1979 assert(som_loc0!=-1);
1980 gradient1=0.;
1981 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1982
1983 psc=0.;
1984 for (compj=0; compj<dimension; compj++)
1985 psc+=gradient0(compj,som_loc)
1986 *gradient1(compj);
1987
1988 psc*=coeff_som;
1989 psc*=nu_som(som);
1990 coeff_mat+=psc;
1991 }
1992 }
1993 coeff_mat*=coeff_conv;
1994 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1995 coeff_mat+=coeff_diff;
1996
1997 for (compi=0; compi<dim_ch_; compi++)
1998 {
1999 face_C=face*dim_ch_+compi;
2000 face2_C=face2*dim_ch_+compi;
2001
2002 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
2003 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
2004 if (face2<nb_faces)
2005 {
2006 matrice(face2_C,face_C)+=coeff_mat;
2007 matrice(face2_C,face2_C)-=coeff_diff;
2008 }
2009 }
2010 }
2011 }
2012}
2013
2014//Fonction qui calcule les coefficients de la matrice pour une face
2015//PERIODIQUE.
2017coeff_matrice_som_perio(const int face,const int faceAss, IntVect& liste_som,
2018 DoubleTab& gradient0, DoubleTab& gradient1,
2019 const DoubleVect& porosite_face,const DoubleTab& nu_som,
2020 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
2021{
2022 const Domaine_VEF& domaine_VEF=domaine_vef();
2023
2024 const auto& tab1=matrice.get_tab1();
2025 const auto& tab2=matrice.get_tab2();
2026
2027 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2028
2029 const int nb_faces=domaine_VEF.nb_faces();
2030
2031 int face_C=0;
2032 int face2=0,face2_C=0;
2033 int som_loc=0,som=0;
2034 int som_loc0=0,som_loc1=0;
2035 int compi=0,compj=0;
2036 int elem0=0,elem1=0;
2037 int i=0;
2038 int nnz=0;
2039
2040 double coeff_som=0.,coeff_mat=0.;
2041 double coeff_diff=0.;
2042 double psc=0.;
2043 double delta=decentrage_;
2044
2045 double coeff_conv=1.;
2046 if (alphaE) coeff_conv=(1.-convexite_);
2047
2048 //Quelques verifications
2049 assert(gradient0.nb_dim()==2);
2050 assert(gradient0.dimension(0)==dimension);
2051 assert(gradient0.dimension(1)==dimension+2);
2052 assert(gradient1.nb_dim()==1);
2053 assert(gradient1.dimension(0)==dimension);
2054 assert(liste_som.size()==dimension+2);
2055
2056 //
2057 //Partie P1 du laplacien discret
2058 //
2059 liste_som=-1;
2060 gradient0=0.;
2061 gradient_som(face,nnz,liste_som,gradient0);
2062
2063
2064 /* gradient associe a "face" : calcul du coefficient */
2065 /* diagonal de la matrice associee a l'inconnue */
2066 coeff_mat=0.;
2067 for (som_loc=0; som_loc<nnz; som_loc++)
2068 {
2069 som=liste_som(som_loc);
2070 coeff_som=volume_aux_sommets(som)*coeff_;
2071
2072 psc=0.;
2073 for (compj=0; compj<dimension; compj++)
2074 psc+=gradient0(compj,som_loc)
2075 *gradient0(compj,som_loc);
2076
2077 psc*=coeff_som;
2078 psc*=nu_som(som);
2079
2080 coeff_mat+=psc;
2081 }
2082 coeff_mat*=coeff_conv;
2083
2084 for (compi=0; compi<dim_ch_; compi++)
2085 {
2086 face_C=face*dim_ch_+compi;
2087 matrice(face_C,face_C)+=coeff_mat;
2088 }
2089
2090
2091 /* calcul des coefficients extra-diagonaux de la matrice laplacien */
2092 /* la matrice etant diagonale par bloc, on effectue le calcul du */
2093 /* produit scalaire une seule fois avant de l'affecter aux differentes */
2094 /* composantes de la matrice */
2095 face_C=face*dim_ch_;
2096 auto debut=tab1[face_C]-1;
2097 auto size=tab1[face_C+1]-tab1[face_C];
2098
2099 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> deja rempli
2100 {
2101 face2_C=tab2[debut+i]-1;
2102 face2=face2_C/dim_ch_;//division euclidienne
2103
2104 if (face2>face)//pour la symetrie de l'operateur
2105 {
2106 coeff_mat=0.;
2107 for (som_loc=0; som_loc<nnz; som_loc++)
2108 {
2109 som=liste_som(som_loc);
2110 coeff_som=volume_aux_sommets(som)*coeff_;
2111 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
2112
2113 if (elem0!=-1)//les deux faces se "voient"
2114 {
2115 assert(som_loc0!=-1);
2116 gradient1=0.;
2117 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
2118
2119 psc=0.;
2120 for (compj=0; compj<dimension; compj++)
2121 psc+=gradient0(compj,som_loc)
2122 *gradient1(compj);
2123
2124 psc*=coeff_som;
2125 psc*=nu_som(som);
2126 coeff_mat+=psc;
2127 }
2128 }
2129 coeff_mat*=coeff_conv;
2130 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
2131 coeff_mat+=coeff_diff;
2132
2133 for (compi=0; compi<dim_ch_; compi++)
2134 {
2135 face_C=face*dim_ch_+compi;
2136 face2_C=face2*dim_ch_+compi;
2137
2138 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
2139 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
2140 if (face2<nb_faces)
2141 {
2142 matrice(face2_C,face_C)+=coeff_mat*coeff_perio(face);
2143 matrice(face2_C,face2_C)-=coeff_diff*coeff_perio(face);
2144 }
2145 }
2146 }
2147 }
2148}
2149
2151ajouter_contribution(const DoubleTab& inconnue,Matrice_Morse& matrice) const
2152{
2153 const Domaine_VEF& domaine_VEF=domaine_vef();
2154 const Domaine& domaine=domaine_VEF.domaine();
2155
2156 //Marqueur pour tenir compte de la porosite
2157 const int marq=phi_psi_diffuse(equation());
2158
2159 //Lignes pour tenir compte de la porosite
2160 const DoubleVect& porosite_elem=equation().milieu().porosite_elem();
2161 DoubleVect porosite_face(equation().milieu().porosite_face());
2162 if (!marq) porosite_face=1.;
2163
2164 //Lignes pour tenir compte de la diffusivite
2165 DoubleTab nu,nu_p1,nu_pA;
2166 remplir_nu(nu_);
2167 modif_par_porosite_si_flag(nu_,nu,!marq,porosite_elem);
2168
2169 //RESTE juste a gerer la porosite a la face
2170 if (alphaE)
2171 ajouter_contribution_elem(inconnue,porosite_face,nu,matrice);
2172 if (alphaS)
2173 {
2174 domaine.creer_tableau_sommets(nu_p1);
2175 remplir_nu_p1(nu,nu_p1);
2176 ajouter_contribution_som(inconnue,porosite_face,nu_p1,matrice);
2177 }
2178 if (alphaA)
2179 {
2180 domaine_VEF.creer_tableau_aretes(nu_pA);
2181 remplir_nu_pA(nu,nu_pA);
2182 ajouter_contribution_aretes(inconnue,porosite_face,nu_pA,matrice);
2183 }
2184
2185 if (test_) test();
2186}
2187
2188/*! @brief Calcule la diffusivite "nu_p1" aux sommets du maillage en fonction de la diffusivite "nu_elem" aux elements.
2189 *
2190 * On suppose que nu_elem a son espace virtuel a jour,
2191 * que nu_p1 est dimensionne nb_dim==1 avec la structure domaine.md_vector_sommets()
2192 * En sortie l'espace virtuel de nu_p1 est mis a jour
2193 *
2194 * L'interpolateur calculs pour un sommet la moyenne (non ponderee) des
2195 * diffusivites sur les elements adjacents a ce sommet.
2196 *
2197 */
2199remplir_nu_p1(const DoubleTab& nu_elem,DoubleTab& nu_p1) const
2200{
2201 const Domaine_VEF& domaine_VEF=domaine_vef();
2202 const Domaine& domaine=domaine_VEF.domaine();
2203 const Domaine& dom=domaine;
2204
2205 const int nb_som = dom.nb_som();
2206 const int nb_elem_tot=domaine.nb_elem_tot();
2207 const int nb_som_elem=domaine.nb_som_elem();
2208
2209 int elem=0;
2210 int som_loc=0,som=0;
2211
2212 const IntTab& elem_som=domaine.les_elems();
2213
2214 ArrOfInt nb_elem_per_som(nb_som); // Intialise a zero par defaut
2215
2216 assert(nu_elem.get_md_vector() == domaine.md_vector_elements());
2217 assert(nu_p1.get_md_vector() == dom.md_vector_sommets());
2218 // On a besoin que l'espace virtuel de nu_elem soit a jour.
2219 assert_espace_virtuel_vect(nu_elem);
2220
2221 //Calcul effectif de "nu_som"
2222
2223 nu_p1=0.;
2224
2225 for (elem=0; elem<nb_elem_tot; elem++)
2226 {
2227 const double nu = nu_elem[elem];
2228 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2229 {
2230 som=elem_som(elem,som_loc);
2231 // Ne pas calculer les valeurs pour les sommets virtuels
2232 // note BM: l'algo precedent ne calculait pas correctement les valeurs non plus
2233 if (som < nb_som)
2234 {
2235 som=dom.get_renum_som_perio(som);
2236 nu_p1(som) += nu;
2237 nb_elem_per_som[som]++;
2238 }
2239 }
2240 }
2241
2242 for (som = 0; som < nb_som; som++)
2243 {
2244 const int som_perio = dom.get_renum_som_perio(som);
2245 int nvoisins = nb_elem_per_som[som_perio];
2246 if (nvoisins > 0)
2247 {
2248 // La premiere fois qu'on tombe sur ce sommet on fait la division.
2249 // On traite du meme coup le cas ou le sommet n'a pas d'elements voisins.
2250 nu_p1(som_perio) /= nvoisins;
2251 nb_elem_per_som[som_perio] = 0;
2252 }
2253 if (som != som_perio)
2254 nu_p1(som) = nu_p1(som_perio);
2255 }
2256 // Le codage precedent n'avait apparemment pas besoin d'echange espace virtuel.
2257 // A mon avis (BM) c'est un miracle du au fait qu'on fait les calculs avec epaisseur2
2258 // (calcul sur nb_som_tot, donc les sommets des elements d'epaisseur 1 sont ok mais
2259 // pas ceux d'epaisseur 2)
2260 // Je prefere ce codage: (si on enleve, ca fait des ecarts en parallele)
2261 nu_p1.echange_espace_virtuel();
2262}
2263
2264//Fonction qui calcule la diffusivite aux aretes du maillage
2265//a partir de la diffusivite aux elements
2266//CONTRAINTE : la diffusivite aux elements "nu_elem" doit
2267// deja avoir ete calculee et est consideree
2268// comme un parametre d'entree
2269//CONTRAINTE : la diffusivite aux sommets "nu_som" doit
2270// deja avoir ete DIMENSIONNEE a la bonne
2271// taille et est consideree comme un parametre
2272// de sortie
2273//CONTRAINTE : l'interpolateur choisi pour le calcul de
2274// "nu_som" est tel que pour un sommet s
2275// donne nous avons
2276// * une liste L des elements possedant le sommet s
2277// * la diffusivite en s est la moyenne geometrique
2278// des "nu_elem" de L
2280remplir_nu_pA(const DoubleTab& nu_elem,DoubleTab& nu_pA) const
2281{
2282 Cerr << "Op_Diff_VEFP1NCP1B_Face::remplir_nu_pA() not coded" << finl;
2283 Cerr << "Exit" << finl;
2284 exit();
2285}
2286
2287
2288//Creation d'une liste qui a une face donnee associe les faces
2289//voisines au sens du support de l'operateur de diffusion P1B
2290//On passe par une liste intermediaire qui donne pour un sommet
2291//donnee, la liste des faces "voyant" le sommet au sens de l'operateur
2292//de diffusion P1B
2293void Op_Diff_VEFP1NCP1B_Face::liste_face(IntLists& liste,int& nnz) const
2294{
2295 const Domaine_VEF& domaine_VEF = domaine_vef();
2296 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
2297 const Domaine& domaine = domaine_VEF.domaine();
2298 const Domaine& dom=domaine;
2299
2300
2301 const IntTab& som_elem=domaine.les_elems();
2302 const IntTab& elem_faces=domaine_VEF.elem_faces();
2303 const IntTab& face_voisins=domaine_VEF.face_voisins();
2304
2305 const int firstFaceInt=domaine_VEF.premiere_face_int();
2306 const int nb_som_tot=dom.nb_som_tot();
2307 const int nb_elem_tot=domaine_VEF.nb_elem_tot();
2308 const int nb_som_elem=domaine.nb_som_elem();
2309 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
2310 const int nb_faces_elem=domaine.nb_faces_elem();
2311 const int nb_bords=domaine_VEF.nb_front_Cl();
2312
2313 int face=0,face2=0;
2314 int face_loc=0;
2315 int elem=0,elem_loc=0;
2316 int som=0,som_loc=0;
2317 int i=0,size=0;
2318 int n_bord=0,ind_face=0;
2319 int num1=0,num2=0;
2320 int tmp=0;
2321
2322 IntTab faces_perio(nb_faces_tot);
2323 ArrOfBit fait(nb_faces_tot);
2324 IntLists sommets_faces(nb_som_tot);
2325
2326 //Il faut creer un second tableau travaillant sur les faces periodiques
2327 //sinon la matrice pourrait ne pas etre homogene a l'operateur explicite
2328 for (face=0; face<nb_faces_tot; face++)
2329 faces_perio(face)=face;
2330
2331 for (n_bord=0; n_bord<nb_bords; n_bord++)
2332 {
2333 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2334 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2335
2336 num1=0;
2337 num2=le_bord.nb_faces_tot();
2338
2339 if (sub_type(Periodique,la_cl.valeur()))
2340 {
2341 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
2342 int faceAss=0;
2343
2344 for (ind_face=num1; ind_face<num2; ind_face++)
2345 {
2346 face=le_bord.num_face(ind_face);
2347 faceAss=la_cl_perio.face_associee(ind_face);
2348 faceAss=le_bord.num_face(faceAss);
2349
2350 //Test afin de ne parcourir que la moitie des faces periodiques
2351 //sachant que l'algorithme qui suit tient compte de ce choix
2352 //REMARQUE : ce test marche aussi en parallele ou les faces
2353 //virtuelles ne sont pas classees
2354 if (face<faceAss)
2355 {
2356 faces_perio(face)=faceAss;
2357 faces_perio(faceAss)=face;
2358 }
2359 }
2360 }
2361 }
2362
2363 //Connectivite liee aux sommets
2364 for (elem=0; elem<nb_elem_tot; elem++)
2365 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2366 {
2367 som=som_elem(elem,som_loc);
2368 som=dom.get_renum_som_perio(som);
2369
2370 for (face_loc=0; face_loc<nb_faces_elem; face_loc++)
2371 {
2372 face=elem_faces(elem,face_loc);
2373
2374 sommets_faces[som].add(face);
2375 if (faces_perio(face)!=face)
2376 sommets_faces[som].add(faces_perio(face));
2377 }
2378 }
2379
2380 nnz=0;
2381 liste.dimensionner(nb_faces_tot);
2382 //REMARQUE IMPORTANTE : IL FAUT ABSOLUMENT COMMENCER
2383 //PAR REMPLIR LES FACES PERIODIQUES SINON :
2384 //-LA MATRICE NE POURRA PAS ETRE PERIODIQUE
2385 //-ET DES COEFFICIENTS POURRAIENT ETRE OUBLIES
2386 for (n_bord=0; n_bord<nb_bords; n_bord++)
2387 {
2388 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2389 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2390
2391 num1=0;
2392 num2=le_bord.nb_faces_tot();
2393
2394 if (sub_type(Periodique,la_cl.valeur()))
2395 {
2396 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
2397 int faceAss=0;
2398
2399 for (ind_face=num1; ind_face<num2; ind_face++)
2400 {
2401 face=le_bord.num_face(ind_face);
2402 faceAss=la_cl_perio.face_associee(ind_face);
2403 faceAss=le_bord.num_face(faceAss);
2404
2405 //Test afin de ne parcourir que la moitie des faces periodiques
2406 //sachant que l'algorithme qui suit tient compte de ce choix
2407 //REMARQUE : ce test marche aussi en parallele ou les faces
2408 //virtuelles ne sont pas classees
2409 if (face<faceAss)
2410 {
2411 //RAZ du tableau fait
2412 fait=0;
2413
2414 //pour la periodicite
2415 size=liste[face].size();
2416 for (i=0; i<size; i++)
2417 fait.setbit(liste[face][i]);
2418
2419 //Pour que le premier element de la liste soit "face"
2420 //Tient compte de la periodicite
2421 if (size!=0)
2422 {
2423 tmp=liste[face][0];
2424 liste[face][0]=face;
2425 liste[face].add(tmp);
2426 tmp=liste[faceAss][0];
2427 liste[faceAss][0]=faceAss;
2428 liste[faceAss].add(tmp);
2429 }
2430 else
2431 {
2432 liste[face].add(face);
2433 liste[faceAss].add(faceAss);
2434 }
2435
2436 fait.setbit(face);
2437 fait.setbit(faceAss);
2438 nnz+=2;//car on ajoute 2 coefficients
2439
2440 for (elem_loc=0; elem_loc<2; elem_loc++)
2441 {
2442 elem=face_voisins(face,elem_loc);
2443 assert(elem!=-1);
2444
2445 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2446 {
2447 som=som_elem(elem,som_loc);
2448 som=dom.get_renum_som_perio(som);
2449
2450 size=sommets_faces[som].size();
2451 for (i=0; i<size; i++)
2452 {
2453 face2=sommets_faces[som][i];
2454
2455 if (!fait[face2])
2456 {
2457 fait.setbit(face2);
2458 liste[face].add(face2);
2459 liste[faceAss].add(face2);
2460 liste[face2].add(face);
2461 liste[face2].add(faceAss);
2462 nnz+=4;//car on ajoute 4 coefficients
2463 }
2464
2465 }//fin du for sur "i"
2466 }//fin du for sur "som_loc"
2467 }//fin du for sur "elem_loc"
2468 }//fin du if sur "face<faceAss"
2469 }//fin du for sur "ind_face"
2470 }//fin Periodique
2471 }//fin n_bord
2472
2473 //Autres conditions aux limites
2474 for (n_bord=0; n_bord<nb_bords; n_bord++)
2475 {
2476 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2477 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2478
2479 num1=0;
2480 num2=le_bord.nb_faces_tot();
2481
2482 if (!sub_type(Periodique,la_cl.valeur()))
2483 for (ind_face=num1; ind_face<num2; ind_face++)
2484 {
2485 face=le_bord.num_face(ind_face);
2486
2487 //RAZ du tableau fait
2488 fait=0;
2489
2490 //pour la periodicite
2491 size=liste[face].size();
2492 for (i=0; i<size; i++)
2493 fait.setbit(liste[face][i]);
2494
2495 //Pour que le premier element de la liste soit "face"
2496 //Tient compte de la periodicite
2497 if (size!=0)
2498 {
2499 tmp=liste[face][0];
2500 liste[face][0]=face;
2501 liste[face].add(tmp);
2502 }
2503 else
2504 liste[face].add(face);
2505
2506 fait.setbit(face);
2507 nnz++;
2508
2509 elem=face_voisins(face,0);
2510 assert(elem!=-1);
2511
2512 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2513 {
2514 som=som_elem(elem,som_loc);
2515 som=dom.get_renum_som_perio(som);
2516
2517 size=sommets_faces[som].size();
2518 for (i=0; i<size; i++)
2519 {
2520 face2=sommets_faces[som][i];
2521
2522 if (!fait[face2])
2523 {
2524 fait.setbit(face2);
2525 liste[face].add(face2);
2526 nnz++;
2527 }
2528
2529 }//fin du for sur "i"
2530 }//fin du for sur "som_loc"
2531 }//fin du else sur !Periodique
2532 }//fin du for sur n_bord
2533
2534 for (face=firstFaceInt; face<nb_faces_tot; face++)
2535 if (!domaine_VEF.est_une_face_virt_bord(face))
2536 {
2537 //RAZ du tableau fait
2538 fait=0;
2539
2540 //pour la periodicite
2541 size=liste[face].size();
2542 for (i=0; i<size; i++)
2543 fait.setbit(liste[face][i]);
2544
2545 //Pour que le premier element de la liste soit "face"
2546 //Tient compte de la periodicite
2547 if (size!=0)
2548 {
2549 tmp=liste[face][0];
2550 liste[face][0]=face;
2551 liste[face].add(tmp);
2552 }
2553 else
2554 liste[face].add(face);
2555
2556 fait.setbit(face);
2557 nnz++;
2558
2559 for (elem_loc=0; elem_loc<2; elem_loc++)
2560 {
2561 elem=face_voisins(face,elem_loc);
2562
2563 if (elem!=-1) //pour face interne de joint
2564 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2565 {
2566 som=som_elem(elem,som_loc);
2567 som=dom.get_renum_som_perio(som);
2568
2569 size=sommets_faces[som].size();
2570 for (i=0; i<size; i++)
2571 {
2572 face2=sommets_faces[som][i];
2573
2574 if (!fait[face2])
2575 {
2576 fait.setbit(face2);
2577 liste[face].add(face2);
2578 nnz++;
2579 }
2580
2581 }//fin du for sur "i"
2582 }//fin du for sur "som_loc"
2583 }//fin du for sur "elem_loc"
2584 }//fin du for sur "face"
2585}
2586
2587//Fonction qui calcule pour une face "face" donnee et un sommet "som"
2588//du stencil de "face", le gradient associe a "face" pour le sommet "som"
2589//ATTENTION : cette fonction ne doit etre utilisee que pour le calcul
2590// des gradients pour remplir une COLONNE de la matrice
2591//CONTRAINTE : "face" est le numero de la face sur laquelle on veut
2592// calculer le gradient. La face "face" est une face
2593// INTERNE ou PERIODIQUE.
2594//CONTRAINTE : le sommet "som" en parametre est suppose etre le
2595// numero d'un sommet APRES renumerotation periodique
2596//CONTRAINTE : le sommet "som" DOIT appartenir au stencil de "face"
2597//CONTRAINTE : "elem0" et "elem1" sont les numeros des elements
2598// qui contiennent "face" ET "som". Si l'un des elements
2599// est a -1, c'est que "face" et "som" n'appartiennent
2600// pas a un meme element. REMARQUE : l'element elem0
2601// est toujours suppose different de -1.
2602//CONTRAINTE : "som_loc0" et "som_loc1" sont les numeros locaux
2603// de "sim_glob" dans repectivement "elem0" et "elem1".
2604// Si l'un des elements est a -1, alors le numero local
2605// de sommet correspondant est a -1
2606//CONTRAINTE : le parametre de sortie "grad" contenant l'evaluation
2607// du gradient associe a "face" au sommet "som" est
2608// sense etre CORRECTEMENT dimensionne AVANT l'appel
2609// de cette fonction
2611gradient_som(const int face,const int som_glob,
2612 const int elem0, const int som_loc0,
2613 const int elem1, const int som_loc1,
2614 DoubleTab& grad) const
2615{
2616 const Domaine_VEF& domaine_VEF = domaine_vef();
2617
2618 const DoubleTab& face_normales=domaine_VEF.face_normales();
2619 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2620
2621 const IntTab& elem_faces=domaine_VEF.elem_faces();
2622 const IntTab& face_voisins=domaine_VEF.face_voisins();
2623
2624 const double coeff=1./dimension;
2625 const double coeff_som=coeff/(dimension+1);
2626
2627 int face_opp=0,compj=0;
2628 int elem=0;
2629 double signe=0.;
2630
2631 assert(grad.nb_dim()==1);
2632
2633 //
2634 //Calcul du gradient
2635 //
2636
2637 /* On regarde le premier element voisin */
2638 assert(elem0!=-1);
2639 assert(som_loc0!=-1);
2640
2641 //Calcul du gradient local
2642 face_opp = elem_faces(elem0,som_loc0);
2643 signe=1.;
2644 if(elem0!=face_voisins(face_opp,0)) signe=-1.;
2645
2646 for(compj=0; compj<dimension; compj++)
2647 grad(compj)=coeff_som*signe*
2648 face_normales(face_opp,compj);
2649
2650 /* On regarde le deuxieme element voisin */
2651 if (elem1==-1)
2652 {
2653 /* Plusieurs possibilite :
2654 - "face" est interne reel
2655 - "face" est interne virtuel
2656 - "face" est de bord reel
2657 - "face" est de bord virtuel
2658 - "face" une face de joint */
2659 assert(som_loc1==-1);
2660 elem=face_voisins(face,1);
2661 assert(face_voisins(face,0)!=-1);
2662
2663 /* "face" est de bord */
2664 if (elem==-1 && face_opp!=face)
2665 for (compj=0; compj<dimension; compj++)
2666 grad(compj)+=coeff*face_normales(face,compj) ;
2667 }
2668 else
2669 {
2670 assert(som_loc1!=-1);
2671 face_opp=elem_faces(elem1,som_loc1);
2672 signe=1.;
2673 if(elem1!=face_voisins(face_opp,0)) signe=-1.;
2674
2675 //Calcul du gradient local
2676 for(compj=0; compj<dimension; compj++)
2677 grad(compj)+=coeff_som*signe*
2678 face_normales(face_opp,compj);
2679 }
2680
2681 grad/=(coeff_*volume_aux_sommets(som_glob));
2682}
2683
2684//Pour une face donnee, calcule le gradient associee a cette face
2685//pour chacun des sommets ou le gradient est non nul
2686//ATTENTION : cette fonction ne doit etre utilisee que pour le calcul
2687// des gradients pour remplir une LIGNE de la matrice
2688//CONTRAINTE : le tableau "grad" est sense etre correctement
2689// dimensionne AVANT l'appel de cette fonction
2690//ENTREE : "face" est le numero global de la face INTERNE
2691// ou PERIODIQUE dont on veut calculer le gradient
2692//SORTIE : "som_glob" est une liste qui contient tous les sommets
2693// inclus dans le stencil de "face"
2694//SORTIE : "nnz" est le nombre de sommets inclus dans le stencil
2695// de face
2697gradient_som(const int face,int& nnz, IntVect& som_glob,DoubleTab& grad) const
2698{
2699 const Domaine_VEF& domaine_VEF=domaine_vef();
2700 const Domaine& domaine=domaine_VEF.domaine();
2701 const Domaine& dom=domaine;
2702
2703 const DoubleTab& face_normales=domaine_VEF.face_normales();
2704 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2705
2706 const IntTab& elem_faces=domaine_VEF.elem_faces();
2707 const IntTab& face_voisins=domaine_VEF.face_voisins();
2708 const IntTab& elem_som=domaine.les_elems();
2709
2710 const double coeff=1./dimension;
2711 const double coeff_som=coeff/(dimension+1);
2712
2713 const int nb_som_elem=domaine.nb_som_elem();
2714
2715 int face_opp=0,compj=0;
2716 int som_loc=0,som=0;
2717 int loc=0;
2718 int elem=0;
2719
2720 double signe=0.;
2721 double volume=0.;
2722
2723 assert(som_glob.size()==dimension+2);
2724 assert(grad.nb_dim()==2);
2725 assert(grad.dimension(1)==dimension+2);
2726
2727 //
2728 //Calcul du gradient
2729 //
2730
2731 nnz=0;
2732 /* On regarde le premier element voisin */
2733 elem=face_voisins(face,0);
2734 assert(elem!=-1);
2735
2736 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2737 {
2738 som=elem_som(elem,som_loc);
2739 som=dom.get_renum_som_perio(som);
2740
2741 face_opp=elem_faces(elem,som_loc);
2742 signe=1.;
2743 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2744
2745 //ajout a la liste et incrementation du repere
2746 som_glob(som_loc)=som;
2747 nnz++;
2748
2749 //Calcul du gradient local
2750 for(compj=0; compj<dimension; compj++)
2751 grad(compj,som_loc)=coeff_som*signe*
2752 face_normales(face_opp,compj);
2753 }
2754 assert(nnz==nb_som_elem);
2755
2756 /* On regarde le deuxieme element voisin */
2757 elem=face_voisins(face,1);
2758 assert(elem!=-1);
2759
2760 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2761 {
2762 som=elem_som(elem,som_loc);
2763 som=dom.get_renum_som_perio(som);
2764
2765 face_opp=elem_faces(elem,som_loc);
2766 signe=1.;
2767 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2768
2769 //Localisation dans la liste deja construite
2770 for (loc=0; loc<nnz; loc++)
2771 if (som_glob[loc]==som)
2772 break;
2773
2774 //ajout a la liste et incrementation du repere
2775 if (loc==nnz)
2776 {
2777 som_glob(nnz)=som;
2778 nnz++;
2779 }
2780
2781 //Calcul du gradient local
2782 for(compj=0; compj<dimension; compj++)
2783 grad(compj,loc)+=coeff_som*signe*
2784 face_normales(face_opp,compj);
2785 }
2786 assert(nnz<=(dimension+2));
2787
2788 for (som_loc=0; som_loc<nnz; som_loc++)
2789 {
2790 som=som_glob(som_loc);
2791 volume=coeff_*volume_aux_sommets(som);
2792
2793 //On divise par la matrice de masse lumpee
2794 for(compj=0; compj<dimension; compj++)
2795 grad(compj,som_loc)/=volume;
2796 }
2797}
2798
2799//Pour une face donnee, calcule le gradient associee a cette face
2800//pour chacun des sommets ou le gradient est non nul
2801//ATTENTION : cette fonction ne doit etre utilisee que pour le calcul
2802// des gradients pour remplir une LIGNE de la matrice
2803//CONTRAINTE : le tableau "grad" est sense etre correctement
2804// dimensionne AVANT l'appel de cette fonction
2805//ENTREE : "face" est le numero global de la face de BORD
2806// NON PERIODIQUE dont on veut calculer le gradient
2807//SORTIE : "som_glob" est une liste qui contient tous les sommets
2808// inclus dans le stencil de "face"
2809//SORTIE : "nnz" est le nombre de sommets inclus dans le stencil
2810// de face
2812gradient_som_CL(const int face,int& nnz, IntVect& som_glob,DoubleTab& grad) const
2813{
2814 const Domaine_VEF& domaine_VEF=domaine_vef();
2815 const Domaine& domaine=domaine_VEF.domaine();
2816 const Domaine& dom=domaine;
2817
2818 const DoubleTab& face_normales=domaine_VEF.face_normales();
2819 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2820
2821 const IntTab& elem_faces=domaine_VEF.elem_faces();
2822 const IntTab& face_voisins=domaine_VEF.face_voisins();
2823 const IntTab& elem_som=domaine.les_elems();
2824 const IntTab& face_sommets=domaine_VEF.face_sommets();
2825
2826 const double coeff=1./dimension;
2827 const double coeff_som=coeff/(dimension+1);
2828
2829 const int nb_som_elem=domaine.nb_som_elem();
2830 const int nb_som_face=domaine_VEF.nb_som_face();
2831
2832 int face_opp=0,compj=0;
2833 int som_loc=0,som=0;
2834 int loc=0;
2835 int elem=0;
2836
2837 double signe=0.;
2838 double volume=0.;
2839
2840 assert(som_glob.size()==dimension+2);
2841 assert(grad.nb_dim()==2);
2842 assert(grad.dimension(1)==dimension+2);
2843
2844 //
2845 //Calcul du gradient
2846 //
2847
2848 nnz=0;
2849 /* On regarde le premier element voisin */
2850 elem=face_voisins(face,0);
2851 assert(elem!=-1);
2852
2853 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2854 {
2855 som=elem_som(elem,som_loc);
2856 som=dom.get_renum_som_perio(som);
2857
2858 face_opp=elem_faces(elem,som_loc);
2859 signe=1.;
2860 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2861
2862 //ajout a la liste et incrementation du repere
2863 som_glob(som_loc)=som;
2864 nnz++;
2865
2866 //Calcul du gradient local
2867 for(compj=0; compj<dimension; compj++)
2868 grad(compj,som_loc)=coeff_som*signe*
2869 face_normales(face_opp,compj);
2870 }
2871 assert(nnz==nb_som_elem);
2872
2873 /* On regarde le deuxieme element voisin */
2874 assert(face_voisins(face,1)==-1);
2875
2876 for (som_loc=0; som_loc<nb_som_face; som_loc++) //sommets de "face"
2877 {
2878 som=face_sommets(face,som_loc);
2879 som=dom.get_renum_som_perio(som);
2880
2881 for (loc=0; loc<nnz; loc++)
2882 if (som_glob(loc)==som)
2883 break;
2884 assert(som_loc<nnz);
2885
2886 for (compj=0; compj<dimension; compj++)
2887 grad(compj,loc)+=coeff*face_normales(face,compj) ;
2888 }
2889 assert(nnz<=(dimension+2));
2890
2891 for (som_loc=0; som_loc<nnz; som_loc++)
2892 {
2893 som=som_glob(som_loc);
2894 volume=coeff_*volume_aux_sommets(som);
2895
2896 //On divise par la matrice de masse lumpee
2897 for(compj=0; compj<dimension; compj++)
2898 grad(compj,som_loc)/=volume;
2899 }
2900}
2901
2902
2903//Fonction verifiant si "som_glob" est dans le stencil de "face"
2904//CONTRAINTE : "som_glob" DOIT etre un numero PERIODIQUE de sommet
2905//SORTIE : le numero des elements du stencil de "face" qui contiennent
2906// le sommet "som_glob". Si le sommet n'est pas contenu
2907// dans un des elements du stencil de "face" alors le numero
2908// de l'element considere est mis a -1
2909//SORTIE : som_loc0 et som_loc1 sont les numeros locaux de som_glob
2910// dans respectivement elem0 et elem1.
2911// Si les sommet n'est pas contenu dans un des elements du
2912// stencil de "face" alors le numero local du sommet
2913// correspondant est mis a -1
2914void Op_Diff_VEFP1NCP1B_Face::isInStencil(int face,int som_glob,
2915 int& elem0, int& som_loc0,
2916 int& elem1, int& som_loc1) const
2917{
2918 const Domaine_VEF& domaine_VEF=domaine_vef();
2919 const Domaine& domaine=domaine_VEF.domaine();
2920 const Domaine& dom=domaine;
2921
2922 const IntTab& face_voisins=domaine_VEF.face_voisins();
2923 const IntTab& elem_som=domaine.les_elems();
2924
2925 const int nb_som_elem=domaine.nb_som_elem();
2926
2927 int elem00=0,elem11=0;
2928 int som_loc=0,som=0;
2929
2930 elem00=face_voisins(face,0);
2931 assert(elem00!=-1);
2932
2933 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2934 {
2935 som=elem_som(elem00,som_loc);
2936 som=dom.get_renum_som_perio(som);
2937
2938 if (som_glob==som)
2939 {
2940 som_loc0=som_loc;
2941 elem0=elem00;
2942 break;
2943 }
2944 }
2945 if (som_loc==nb_som_elem)
2946 {
2947 elem0=-1;
2948 som_loc0=-1;
2949 }
2950
2951 elem11=face_voisins(face,1);
2952 if (elem11==-1)
2953 {
2954 elem1=-1;
2955 som_loc1=-1;
2956 }
2957 else
2958 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2959 {
2960 som=elem_som(elem11,som_loc);
2961 som=dom.get_renum_som_perio(som);
2962
2963 if (som_glob==som)
2964 {
2965 som_loc1=som_loc;
2966 elem1=elem11;
2967 break;
2968 }
2969 }
2970 if (som_loc==nb_som_elem)
2971 {
2972 elem1=-1;
2973 som_loc1=-1;
2974 }
2975
2976 //On ordonne
2977 if (elem0==-1 && elem1!=-1)
2978 {
2979 elem0=elem1;
2980 elem1=-1;
2981 som_loc0=som_loc1;
2982 som_loc1=-1;
2983 }
2984}
2985
2987{
2988 const Domaine_VEF& domaine_VEF = domaine_vef();
2989
2990 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
2991 const int nb_comp = inconnue_->valeurs().line_size();
2992
2993 int face=0;
2994 int i=0,size=0;
2995 int comp=0,nnz=0,face_f77=0,face_C=0;
2996 int nb_faces_of_symetry=0;
2997 int next=0;
2998
2999 ArrOfBit is_symetry(nb_faces_tot);
3000
3001 auto& tab1 = matrice.get_set_tab1();
3002 auto& tab2 = matrice.get_set_tab2();
3003
3004 IntLists faces_faces;
3005
3006 if (alphaE && !alphaS && !alphaA)
3007 Op_VEF_Face::dimensionner(le_dom_vef.valeur(), la_zcl_vef.valeur(), matrice);
3008
3009 if (alphaS)
3010 {
3011 //Calcul de la liste des faces
3012 liste_face(faces_faces,nnz);
3013 isFaceOfSymetry(is_symetry,nb_faces_of_symetry);
3014
3015 //Dimensionnement des tableaux de la matrice
3016 //REMARQUE : par essence, ce dimensionnement sera toujours plus GRAND
3017 //que le dimensionnement par defaut issu de OP_VEF_FACE
3018 //REMARQUE : pour tenir compte des contraintes dues aux faces de
3019 //symetrie, le dimensionnement de la matrice doit etre legerement
3020 //elargie
3021 size=nnz*nb_comp;//dimensionnement sans face de symetrie
3022 // size+=nb_faces_of_symetry*(nb_comp-1)*nb_comp;//dimensionnement avec faces de symetrie
3023 // pour chaque face de symetrie pour chaque composante on ajoute nb_comp coeffs pour chaque face liee
3024 for (face=0; face<nb_faces_tot; face++)
3025 if (is_symetry[face])
3026 {
3027 int nb_v=faces_faces[face].size();
3028 size+=nb_v*(nb_comp-1)*nb_comp;
3029 }
3030
3031 matrice.dimensionner(nb_faces_tot*nb_comp,size);
3032
3033 //Initialisation des grandeurs connues pour tab1
3034 tab1[nb_faces_tot*nb_comp]=size+1;
3035 tab1[0]=1;
3036
3037 //Remplissage de tab1
3038
3039 /* pour les autres composantes de la face 0 */
3040 size=faces_faces[0].size();
3041 if (is_symetry[0]) size*=(nb_comp);
3042 for (comp=1; comp<nb_comp; comp++)
3043 {
3044 face_C=comp;
3045 tab1[face_C]=tab1[face_C-1]+size;
3046 }
3047
3048 /* pour les autres faces */
3049 for (face=1; face<nb_faces_tot; face++)
3050 {
3051 size=faces_faces[face-1].size();
3052 if (is_symetry[face-1]) size*=(nb_comp);
3053 for (comp=0; comp<nb_comp; comp++)
3054 {
3055 face_C=face*nb_comp+comp;
3056 tab1[face_C]=tab1[face_C-1]+size;
3057 size=faces_faces[face].size();
3058 if (is_symetry[face]) size*=(nb_comp);
3059 }
3060 }
3061
3062 //Remplissage de tab2
3063 for (face=0; face<nb_faces_tot; face++)
3064 {
3065 size=faces_faces[face].size();
3066
3067 for (comp=0; comp<nb_comp; comp++)
3068 {
3069 auto debut=tab1[face*nb_comp+comp]-1;
3070
3071 for (i=0; i<size; i++)
3072 {
3073 face_C=faces_faces[face][i]*nb_comp+comp;
3074 face_f77=face_C+1;
3075 tab2[debut+i]=face_f77;
3076 }//fin du for sur "i"
3077
3078 }//fin du for sur "comp"
3079
3080 }//fin du for sur "face"
3081
3082 for (face=0; face<nb_faces_tot; face++)
3083 if (is_symetry[face])
3084 {
3085 size=faces_faces[face].size();
3086
3087 for (comp=0; comp<nb_comp; comp++)
3088 {
3089 auto debut=tab1[face*nb_comp+comp]-1;
3090 debut+=size;
3091 for (int voi=0; voi<size; voi++)
3092 {
3093 int face2=faces_faces[face][voi];
3094 for (i=0; i<nb_comp-1; i++)
3095 {
3096 //reste de la division euclidienne
3097 next=(comp+i+1)%nb_comp;
3098 face_C=face2*nb_comp+next;
3099 face_f77=face_C+1;
3100 tab2[debut+i]=face_f77;
3101 // Cerr <<face*nb_comp+comp<<" face "<<face << " comp "<< comp<< " face2 "<< face2 << " comp "<<next <<" jface2 "<< face_C<<finl;
3102 assert(debut+i<tab1[face*nb_comp+comp+1]-1);
3103 }
3104 debut+=nb_comp-1;
3105 }
3106
3107 }//fin du for sur "comp"
3108
3109 }//fin du for sur "face"
3110
3111 }//fin du if sur "alphaS"
3112
3113 if (alphaA)
3114 {
3115 Cerr << "Erreur Op_Dift_VEFP1NCP1B_Face::dimensionner(Matrice_Morse&)" << finl;
3116 Cerr << "Le dimensionnement de la matrice implicite avec l'option alphaA"
3117 << " n'est pas encore codee" << finl;
3118 Cerr << "Sortie du programme" << finl;
3119 exit();
3120 }
3121}
3122
3123//Fonction qui initialise le tableau is_symetry passe en argument :
3124//-si une face "f" est une face de symetrie alors is_symetry(f)=1
3125//-si une face "f" n'est pas une face de symetrie alors is_symetry(f)=0
3126//La fonction renvoie egalement le nombre total de faces de symetrie (argument nnz)
3127//REMARQUE : le tableau "is_symetry" doit etre dimensionne a nb_faces_tot
3128//AVANT d'utiliser cette fonction
3129void Op_Diff_VEFP1NCP1B_Face::isFaceOfSymetry(ArrOfBit& is_symetry,int& nnz) const
3130{
3131 const Domaine_VEF& domaine_VEF=domaine_vef();
3132 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
3133
3134 const int nb_bords=domaine_VEF.nb_front_Cl();
3135
3136 int n_bord=0;
3137 int num1=0,num2=0;
3138 int ind_face=0;
3139
3140 assert(is_symetry.size_array()==domaine_VEF.nb_faces_tot());
3141
3142 //Preinitialisation
3143 nnz=0;
3144 is_symetry=0;
3145
3146 //Modification pour les faces de symetrie
3147 for (n_bord=0; n_bord<nb_bords; n_bord++)
3148 {
3149 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3150 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3151
3152 num1=0;
3153 num2=le_bord.nb_faces_tot();
3154
3155 if (sub_type(Symetrie,la_cl.valeur()))
3156 {
3157 nnz+=num2;
3158
3159 for (ind_face=num1; ind_face<num2; ind_face++)
3160 is_symetry.setbit(le_bord.num_face(ind_face));
3161 }
3162 }
3163}
3164
3165
3166
3167//////////////////////////////////////////////////////////
3168//Fonctions de test
3169/////////////////////////////////////////////////////////
3170
3172{
3173 const Domaine_VEF& domaine_VEF=domaine_vef();
3174 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
3175 const Domaine& domaine = domaine_VEF.domaine();
3176 const Domaine& dom=domaine;
3177
3178 const Solveur_Masse_base& solveur_masse=equation().solv_masse();
3179
3180 const int nb_bords=domaine_VEF.nb_front_Cl();
3181 const int firstFaceInt=domaine_VEF.premiere_face_int();
3182 const int nb_som_tot=dom.nb_som_tot();
3183
3184 const DoubleTab& unknown = equation().inconnue().valeurs();
3185 const DoubleTab& xv=domaine_VEF.xv();
3186 const DoubleTab& xs=dom.les_sommets();
3187
3188 DoubleTab inco(unknown);
3189 DoubleVect& incoV = inco;
3190 incoV=0.;
3191
3192 //DoubleTab tmp(inco);
3193
3194 DoubleTab resu(unknown);
3195 DoubleVect& resuV = resu;
3196 DoubleTab resuMat(unknown);
3197 const DoubleVect& resuMatV = resuMat;
3198 DoubleTab gradientMat(dimension,dimension+2);
3199
3200
3201 IntVect som_glob(dimension+2);
3202
3203 //Marqueur pour tenir compte de la porosite
3204 const int marq=phi_psi_diffuse(equation());
3205
3206 //Lignes pour tenir compte de la porosite
3207 const DoubleVect& poroE=equation().milieu().porosite_elem();
3208 DoubleVect poroF(equation().milieu().porosite_face());
3209 if (!marq) poroF=1.;
3210
3211 //Lignes pour tenir compte de la diffusivite
3212 DoubleTab nu;
3213 remplir_nu(nu_);
3214 modif_par_porosite_si_flag(nu_,nu,!marq,poroE);
3215
3216 DoubleTab nu_p1;
3217 dom.creer_tableau_sommets(nu_p1);
3218 remplir_nu_p1(nu,nu_p1);
3219
3220 //Diverses variables utiles
3221 int face=0;
3222 int faceAss=0;
3223 int comp=0;
3224 int size0=domaine_VEF.nb_faces();
3225 int i=0,j=0;
3226 int nnz=0;
3227 int compi=0,compj=0;
3228 int som=0;
3229 int n_bord=0;
3230 int num1=0,num2=0,ind_face=0;
3231 int ii=0;
3232
3233 int size1 = unknown.line_size();
3234
3235 Matrice_Morse matrice;
3236 dimensionner(matrice);
3237 if (alphaS) ajouter_contribution_som(inco,poroF,nu_p1,matrice);
3238 else if (alphaE) ajouter_contribution_elem(inco,poroF,nu,matrice);
3239
3240 bool test1=false;
3241 double max=0.;
3242
3243 DoubleTab gradient1(dimension);
3244
3245 Motcle type;
3247 type="_PAR";
3248 else
3249 type="_SEQ";
3250
3251 Motcles les_mots(8);
3252 {
3253 les_mots[0] = "matrice";
3254 les_mots[1] = "result";
3255 les_mots[2] = "res";
3256 les_mots[3] = "resMat";
3257 les_mots[4] = "grad";
3258 les_mots[5] = "gradMat";
3259 les_mots[6] = "div";
3260 les_mots[7] = "ligne_mat";
3261 }
3262 Motcle proc(Process::me());
3263 proc+=".txt";
3264
3265 for (i=0; i<les_mots.size(); i++)
3266 {
3267 les_mots[i]+=type;
3268 les_mots[i]+=proc;
3269 }
3270
3271 ofstream mat(les_mots[0].getChar());
3272 const Matrice_Morse& matConst=matrice;
3273 for (i=0; i<domaine_VEF.nb_faces(); i++)
3274 {
3275 for (j=0; j<matConst.nb_colonnes(); j++)
3276 mat<<matConst(i,j)<<",";
3277 mat<<endl;
3278 }
3279
3280 double coeff_diag=0.;
3281 double sum_coeff_extra_diag=0.;
3282 ofstream ligneMat(les_mots[7].getChar());
3283 for (i=0; i<matConst.nb_lignes(); i++)
3284 {
3285 coeff_diag=matConst(i,i);
3286 ligneMat<<"Ligne : "<<i<<endl;
3287 ligneMat<<"Coeff diag : "<<coeff_diag<<endl;
3288
3289 ligneMat<<"Coeff extra diag : ";
3290 sum_coeff_extra_diag=0.;
3291 for (j=0; j<matConst.nb_colonnes(); j++)
3292 if (j!=i) sum_coeff_extra_diag+=matConst(i,j);
3293 ligneMat<<sum_coeff_extra_diag<<endl;
3294
3295 ligneMat<<"Coeff extra diag par colonne : ";
3296 sum_coeff_extra_diag=0.;
3297 for (j=0; j<matConst.nb_colonnes(); j++)
3298 if (j!=i) sum_coeff_extra_diag+=matConst(j,i);
3299 ligneMat<<sum_coeff_extra_diag<<endl;
3300 }
3301
3302
3303 Motcle gradi("grad1");
3304 gradi+=type;
3305 gradi+=proc;
3306 int elem=0;
3307 int elem0=0,elem1=0;
3308 int som_loc0=1,som_loc1=1;
3309 int som_loc=0;
3310 const int nb_som_elem=domaine.nb_som_elem();
3311 const IntTab& face_voisins=domaine_VEF.face_voisins();
3312 const IntTab& elem_som=domaine.les_elems();
3313 ofstream grad1(gradi.getChar());
3314 for (face=0; face<size0; face++)
3315 {
3316 grad1<<"Face : "<<face<<endl;
3317 grad1<<"(";
3318 for (i=0; i<dimension; i++)
3319 grad1<<xv(face,i)<<",";
3320 grad1<<")"<<endl;
3321
3322 for (ii=0; ii<2; ii++)
3323 {
3324 elem=face_voisins(face,ii);
3325 if (elem!=-1)
3326 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
3327 {
3328 som=elem_som(elem,som_loc);
3329 som=dom.get_renum_som_perio(som);
3330 isInStencil(face,som,elem0,som_loc0,elem1,som_loc1);
3331
3332 gradient1=0.;
3333 gradient_som(face,som,elem0,som_loc0,
3334 elem1,som_loc1,gradient1);
3335
3336 grad1<<som<<"(";
3337 for (i=0; i<dimension; i++)
3338 grad1<<xs(som,i)<<",";
3339 grad1<<"):(";
3340 for (compj=0; compj<dimension; compj++)
3341 grad1<<gradient1(compj)<<",";
3342 grad1<<")"<<endl;
3343 }
3344 }
3345 }
3346
3347 ofstream result(les_mots[1].getChar());
3348 ofstream res(les_mots[2].getChar());
3349 ofstream resMat(les_mots[3].getChar());
3350 ofstream grad(les_mots[4].getChar());
3351 ofstream gradMat(les_mots[5].getChar());
3352 ofstream div(les_mots[6].getChar());
3353
3354 for (face=firstFaceInt; face<size0; face++)
3355 {
3356 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3358
3359 //Version explicite
3360 gradient_p1_=0.;
3362
3363 //Controle des gradients
3364 grad<<"Face interne : "<<face*size1+comp<<endl;
3365 grad<<"(";
3366 for (i=0; i<dimension; i++)
3367 grad<<xv(face,i)<<",";
3368 grad<<")"<<endl;
3369 for (som=0; som<nb_som_tot; som++)
3370 {
3371 grad <<som<<"(";
3372 for (i=0; i<dimension; i++)
3373 grad<<xs(som,i)<<",";
3374 grad<<"):(";
3375 for (compi=0; compi<dim_ch_; compi++)
3376 for (compj=0; compj<dimension; compj++)
3377 grad<<gradient_p1_(som,compi,compj)<<",";
3378 grad<<")"<<endl;
3379 }
3380
3381 gradientMat=0.;
3382 som_glob=-1;
3383 gradient_som(face,nnz,som_glob,gradientMat);
3384
3385 gradMat<<"Face interne : "<<face*size1+comp<<endl;
3386 gradMat<<"(";
3387 for (i=0; i<dimension; i++)
3388 gradMat<<xv(face,i)<<",";
3389 gradMat<<")"<<endl;
3390 for (i=0; i<nnz; i++)
3391 {
3392 gradMat<<som_glob[i]<<"(";
3393 for (ii=0; ii<dimension; ii++)
3394 gradMat<<xs(som_glob[i],ii)<<",";
3395 gradMat<<"):(";
3396 for (compj=0; compj<dimension; compj++)
3397 gradMat<<gradientMat(compj,i)<<",";
3398 gradMat<<")"<<endl;
3399 }
3400
3401 resu=0.;
3403 corriger_Cl_test(resu);
3404 solveur_masse.appliquer(resu);
3405 div<<"Face interne : "<<face*size1+comp<<endl;
3406 div<<"(";
3407 for (i=0; i<dimension; i++)
3408 div<<xv(face,i)<<",";
3409 div<<")"<<endl;
3410 for (i=0; i<size0; i++)
3411 {
3412 div<<i<<"(";
3413 for (ii=0; ii<dimension; ii++)
3414 div<<xv(i,ii)<<",";
3415 div<<"):=(";
3416 for (j=0; j<size1; j++)
3417 div<<resu[i*size1+j]<<",";
3418 div<<")"<<endl;
3419 }
3420
3421 resu*=-1.;
3422 res<<"Face interne : "<<face*size1+comp<<endl;
3423 res<<"(";
3424 for (i=0; i<dimension; i++)
3425 res<<xv(face,i)<<",";
3426 res<<")"<<endl;
3427 for (i=0; i<size0; i++)
3428 {
3429 res<<i<<"(";
3430 for (ii=0; ii<dimension; ii++)
3431 res<<xv(i,ii)<<",";
3432 res<<"):=(";
3433 for (j=0; j<size1; j++)
3434 res<<resu[i*size1+j]<<",";
3435 res<<")"<<endl;
3436 }
3437
3438 //Version matricielle
3439 resuMat=0.;
3440 matrice.ajouter_multTab_(inco,resuMat);
3441 solveur_masse.appliquer(resuMat);
3442 resuMat.echange_espace_virtuel();
3443 resMat<<"Face interne :"<<face*size1+comp<<endl;
3444 resMat<<"(";
3445 for (i=0; i<dimension; i++)
3446 resMat<<xv(face,i)<<",";
3447 resMat<<")"<<endl;
3448 for (i=0; i<size0; i++)
3449 {
3450 resMat<<i<<"(";
3451 for (ii=0; ii<dimension; ii++)
3452 resMat<<xv(i,ii)<<",";
3453 resMat<<"):=(";
3454 for (j=0; j<size1; j++)
3455 resMat<<resuMatV[i*size1+j]<<",";
3456 resMat<<")"<<endl;
3457 }
3458
3459 //Difference entre les resultat
3460 resu-=resuMat;
3461
3462 //Affichage des differences
3463 max=resu.local_max_abs_vect();
3464 if (max>1.e-14)
3465 {
3466 result<<"Diff pour face interne : "<<face*size1+comp<<endl;
3467 result<<"(";
3468 for (i=0; i<dimension; i++)
3469 result<<xv(face,i)<<",";
3470 result<<")"<<endl;
3471 for (i=0; i<size0; i++)
3472 {
3473 test1=false;
3474 for (j=0; j<size1; j++)
3475 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3476
3477 if (test1)
3478 {
3479 result<<i<<"(";
3480 for (ii=0; ii<dimension; ii++)
3481 result<<xv(i,ii)<<",";
3482 result<<"):=(";
3483 for (j=0; j<size1; j++)
3484 result <<resuV[i*size1+j]<<",";
3485 result <<")"<<endl;
3486 }
3487 }
3488 }
3489 else
3490 {
3491 result<<"Diff pour face interne : "<<face*size1+comp<<endl;
3492 result<<"Maximum : "<<max<<endl;
3493 }
3494
3495 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3497 }
3498
3499
3500 for (n_bord=0; n_bord<nb_bords; n_bord++)
3501 {
3502 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3503 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3504
3505 num1=0;
3506 num2=le_bord.nb_faces_tot();
3507
3508 //Modif pour tenir compte des conditions de Dirichlet
3509 //-> la matrice de masse doit tout annuler
3510 if (sub_type(Dirichlet_homogene,la_cl.valeur()))
3511 {
3512 //Il ne sert a rien de faire un test dans ce cas
3513 }
3514
3515 else if (sub_type(Dirichlet,la_cl.valeur()))
3516 for (ind_face=num1; ind_face<num2; ind_face++)
3517 {
3518 face=le_bord.num_face(ind_face);
3519
3520 //Version explicite
3521 gradient_p1_=0.;
3523
3524 //Controle des gradients
3525 grad<<"Face Dirichlet : "<<face*size1+comp<<endl;
3526 grad<<"(";
3527 for (i=0; i<dimension; i++)
3528 grad<<xv(face,i)<<",";
3529 grad<<")"<<endl;
3530 for (som=0; som<nb_som_tot; som++)
3531 {
3532 grad <<som<<"(";
3533 for (i=0; i<dimension; i++)
3534 grad<<xs(som,i)<<",";
3535 grad<<"):(";
3536 for (compi=0; compi<dim_ch_; compi++)
3537 for (compj=0; compj<dimension; compj++)
3538 grad<<gradient_p1_(som,compi,compj)<<",";
3539 grad<<")"<<endl;
3540 }
3541
3542 gradientMat=0.;
3543 som_glob=-1;
3544 gradient_som_CL(face,nnz,som_glob,gradientMat);
3545
3546 gradMat<<"Face Dirichlet : "<<face*size1+comp<<endl;
3547 gradMat<<"(";
3548 for (i=0; i<dimension; i++)
3549 gradMat<<xv(face,i)<<",";
3550 gradMat<<")"<<endl;
3551 for (i=0; i<nnz; i++)
3552 {
3553 gradMat<<som_glob[i]<<"(";
3554 for (ii=0; ii<dimension; ii++)
3555 gradMat<<xs(som_glob[i],ii)<<",";
3556 gradMat<<"):(";
3557 for (compj=0; compj<dimension; compj++)
3558 gradMat<<gradientMat(compj,i)<<",";
3559 gradMat<<")"<<endl;
3560 }
3561
3562 for (i=0; i<size0; i++)
3563 for (j=0; j<size1; j++)
3564 resuV[i*size1+j]=0.;
3565 }
3566
3567 else if (sub_type(Periodique,la_cl.valeur()))
3568 {
3569 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
3570
3571 assert(num2%2==0);
3572 for (ind_face=num1; ind_face<num2; ind_face++)
3573 {
3574 face=le_bord.num_face(ind_face);
3575 faceAss=le_bord.num_face(la_cl_perio.face_associee(ind_face));
3576
3577 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3578 if (Process::je_suis_maitre()) incoV[faceAss*size1+comp]=1.;
3580
3581 //Version explicite
3582 gradient_p1_=0.;
3584
3585 //Controle des gradients
3586 grad <<"Face perio : "<<face*size1+comp<<endl;
3587 grad<<"(";
3588 for (i=0; i<dimension; i++)
3589 grad<<xv(face,i)<<",";
3590 grad<<")"<<endl;
3591 for (som=0; som<nb_som_tot; som++)
3592 {
3593 grad <<som<<"(";
3594 for (i=0; i<dimension; i++)
3595 grad<<xs(som,i)<<",";
3596 grad<<"):(";
3597 for (compi=0; compi<dim_ch_; compi++)
3598 for (compj=0; compj<dimension; compj++)
3599 grad<<gradient_p1_(som,compi,compj)<<",";
3600 grad<<")"<<endl;
3601 }
3602
3603 gradientMat=0.;
3604 som_glob=-1;
3605 gradient_som(face,nnz,som_glob,gradientMat);
3606
3607 gradMat<<"Face perio : "<<face*size1+comp<<endl;
3608 gradMat<<"(";
3609 for (i=0; i<dimension; i++)
3610 gradMat<<xv(face,i)<<",";
3611 gradMat<<")"<<endl;
3612 for (i=0; i<nnz; i++)
3613 {
3614 gradMat<<som_glob[i]<<"(";
3615 for (ii=0; ii<dimension; ii++)
3616 gradMat<<xs(som_glob[i],ii)<<",";
3617 gradMat<<"):(";
3618 for (compj=0; compj<dimension; compj++)
3619 gradMat<<gradientMat(compj,i)<<",";
3620 gradMat<<")"<<endl;
3621 }
3622
3623 resu=0.;
3625 corriger_Cl_test(resu);
3626 solveur_masse.appliquer(resu);
3627 div<<"Face perio : "<<face*size1+comp<<endl;
3628 div<<"(";
3629 for (i=0; i<dimension; i++)
3630 div<<xv(face,i)<<",";
3631 div<<")"<<endl;
3632 for (i=0; i<size0; i++)
3633 {
3634 div<<i<<"(";
3635 for (ii=0; ii<dimension; ii++)
3636 div<<xv(i,ii)<<",";
3637 div<<"):=(";
3638 for (j=0; j<size1; j++)
3639 div<<resu[i*size1+j]<<",";
3640 div<<")"<<endl;
3641 }
3642
3643 resu*=-1.;
3644 res<<"Face perio : "<<face*size1+comp<<endl;
3645 res<<"(";
3646 for (i=0; i<dimension; i++)
3647 res<<xv(face,i)<<",";
3648 res<<")"<<endl;
3649 for (i=0; i<size0; i++)
3650 {
3651 res<<i<<"(";
3652 for (ii=0; ii<dimension; ii++)
3653 res<<xv(i,ii)<<",";
3654 res<<"):=(";
3655 for (j=0; j<size1; j++)
3656 res<<resu[i*size1+j]<<",";
3657 res<<")"<<endl;
3658 }
3659
3660 //Version matricielle
3661 resuMat=0.;
3662 matrice.ajouter_multTab_(inco,resuMat);
3663 solveur_masse.appliquer(resuMat);
3664 resuMat.echange_espace_virtuel();
3665 resMat<<"Face perio :"<<face*size1+comp<<endl;
3666 resMat<<"(";
3667 for (i=0; i<dimension; i++)
3668 resMat<<xv(face,i)<<",";
3669 resMat<<")"<<endl;
3670 for (i=0; i<size0; i++)
3671 {
3672 resMat<<i<<"(";
3673 for (ii=0; ii<dimension; ii++)
3674 resMat<<xv(i,ii)<<",";
3675 resMat<<"):=(";
3676 for (j=0; j<size1; j++)
3677 resMat<<resuMatV[i*size1+j]<<",";
3678 resMat<<")"<<endl;
3679 }
3680
3681 //Difference entre les resultat
3682 resu-=resuMat;
3683
3684 //Affichage des differences
3685 max=resu.local_max_abs_vect();
3686 if (max>1.e-14)
3687 {
3688 result<<"Diff pour face perio : "<<face*size1+comp<<endl;
3689 result<<"(";
3690 for (i=0; i<dimension; i++)
3691 result<<xv(face,i)<<",";
3692 result<<")"<<endl;
3693 for (i=0; i<size0; i++)
3694 {
3695 test1=false;
3696 for (j=0; j<size1; j++)
3697 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3698
3699 if (test1)
3700 {
3701 result<<i<<"(";
3702 for (ii=0; ii<dimension; ii++)
3703 result<<xv(i,ii)<<",";
3704 result<<"):=(";
3705 for (j=0; j<size1; j++)
3706 result <<resuV[i*size1+j]<<",";
3707 result <<")"<<endl;
3708 }
3709 }
3710 }
3711 else
3712 {
3713 result<<"Diff pour face perio : "<<face*size1+comp<<endl;
3714 result<<"Maximum : "<<max<<endl;
3715 }
3716
3717 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3718 if (Process::je_suis_maitre()) incoV[faceAss*size1+comp]=0.;
3720 }
3721 }//fin Perio
3722 else
3723 for (ind_face=num1; ind_face<num2; ind_face++)
3724 {
3725 face=le_bord.num_face(ind_face);
3726 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3728
3729 //Version explicite
3730 gradient_p1_=0.;
3732
3733 //Controle des gradients
3734 grad <<"Face CL : "<<face*size1+comp<<endl;
3735 grad<<"(";
3736 for (i=0; i<dimension; i++)
3737 grad<<xv(face,i)<<",";
3738 grad<<")"<<endl;
3739 for (som=0; som<nb_som_tot; som++)
3740 {
3741 grad <<som<<"(";
3742 for (i=0; i<dimension; i++)
3743 grad<<xs(som,i)<<",";
3744 grad<<"):(";
3745 for (compi=0; compi<dim_ch_; compi++)
3746 for (compj=0; compj<dimension; compj++)
3747 grad<<gradient_p1_(som,compi,compj)<<",";
3748 grad<<")"<<endl;
3749 }
3750
3751 gradientMat=0.;
3752 som_glob=-1;
3753 gradient_som_CL(face,nnz,som_glob,gradientMat);
3754
3755 gradMat<<"Face CL : "<<face*size1+comp<<endl;
3756 gradMat<<"(";
3757 for (i=0; i<dimension; i++)
3758 gradMat<<xv(face,i)<<",";
3759 gradMat<<")"<<endl;
3760 for (i=0; i<nnz; i++)
3761 {
3762 gradMat<<som_glob[i]<<"(";
3763 for (ii=0; ii<dimension; ii++)
3764 gradMat<<xs(som_glob[i],ii)<<",";
3765 gradMat<<"):(";
3766 for (compj=0; compj<dimension; compj++)
3767 gradMat<<gradientMat(compj,i)<<",";
3768 gradMat<<")"<<endl;
3769 }
3770
3771 resu=0.;
3773 corriger_Cl_test(resu);
3774 solveur_masse.appliquer(resu);
3775 div<<"Face CL : "<<face*size1+comp<<endl;
3776 div<<"(";
3777 for (i=0; i<dimension; i++)
3778 div<<xv(face,i)<<",";
3779 div<<")"<<endl;
3780 for (i=0; i<size0; i++)
3781 {
3782 div<<i<<"(";
3783 for (ii=0; ii<dimension; ii++)
3784 div<<xv(i,ii)<<",";
3785 div<<"):=(";
3786 for (j=0; j<size1; j++)
3787 div<<resu[i*size1+j]<<",";
3788 div<<")"<<endl;
3789 }
3790
3791 resu*=-1.;
3792 res<<"Face CL : "<<face*size1+comp<<endl;
3793 res<<"(";
3794 for (i=0; i<dimension; i++)
3795 res<<xv(face,i)<<",";
3796 res<<")"<<endl;
3797 for (i=0; i<size0; i++)
3798 {
3799 test1=false;
3800 for (j=0; j<size1; j++)
3801 test1|=(std::fabs(resuV[i*size1+j])>max);
3802
3803 if (test1)
3804 {
3805 res<<i<<"(";
3806 for (ii=0; ii<dimension; ii++)
3807 res<<xv(i,ii)<<",";
3808 res<<"):=(";
3809 for (j=0; j<size1; j++)
3810 res<<resu[i*size1+j]<<",";
3811 res<<")"<<endl;
3812 }
3813 }
3814
3815 //Version matricielle
3816 resuMat=0.;
3817 matrice.ajouter_multTab_(inco,resuMat);
3818 solveur_masse.appliquer(resuMat);
3819 resuMat.echange_espace_virtuel();
3820 resMat<<"Face CL :"<<face*size1+comp<<endl;
3821 resMat<<"(";
3822 for (i=0; i<dimension; i++)
3823 resMat<<xv(face,i)<<",";
3824 resMat<<")"<<endl;
3825 for (i=0; i<size0; i++)
3826 {
3827 resMat<<i<<"(";
3828 for (ii=0; ii<dimension; ii++)
3829 resMat<<xv(i,ii)<<",";
3830 resMat<<"):=(";
3831 for (j=0; j<size1; j++)
3832 resMat<<resuMatV[i*size1+j]<<",";
3833 resMat<<")"<<endl;
3834 }
3835
3836 //Difference entre les resultat
3837 resu-=resuMat;
3838
3839 //Affichage des differences
3840 max=resu.local_max_abs_vect();
3841 if (max>1.e-14)
3842 {
3843 result<<"Diff pour face CL : "<<face*size1+comp<<endl;
3844 result<<"(";
3845 for (i=0; i<dimension; i++)
3846 result<<xv(face,i)<<",";
3847 result<<")"<<endl;
3848 for (i=0; i<size0; i++)
3849 {
3850 test1=false;
3851 for (j=0; j<size1; j++)
3852 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3853
3854 if (test1)
3855 {
3856 result<<i<<"(";
3857 for (ii=0; ii<dimension; ii++)
3858 result<<xv(i,ii)<<",";
3859 result<<"):=(";
3860 for (j=0; j<size1; j++)
3861 result <<resuV[i*size1+j]<<",";
3862 result <<")"<<endl;
3863 }
3864 }
3865 }
3866 else
3867 {
3868 result<<"Diff pour face CL : "<<face*size1+comp<<endl;
3869 result<<"Maximum : "<<max<<endl;
3870 }
3871
3872 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3874 }//fin autres CL
3875 }//fin du for sur n_bord
3876 exit();
3877}
3878
3880{
3881 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
3882 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
3883
3884 const int nb_bords =les_cl.size();
3885 int n_bord=0, num1=0, num2=0;
3886 int face=0, face_associee=0;
3887 int ind_face=0, comp=0;
3888
3889 for (n_bord=0; n_bord<nb_bords; n_bord++)
3890 {
3891 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3892 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3893
3894 num1=0;
3895 num2=le_bord.nb_faces();
3896
3897 if (sub_type(Periodique,la_cl.valeur()))
3898 {
3899 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
3900
3901 for (ind_face=num1; ind_face<num2; ind_face++)
3902 {
3903 face = le_bord.num_face(ind_face);
3904 face_associee=
3905 le_bord.num_face(la_cl_perio.face_associee(ind_face));
3906
3907 if (face<face_associee)
3908 for (comp=0; comp<dim_ch_; comp++)
3909 {
3910 resu[face*dim_ch_+comp]+=resu[face_associee*dim_ch_+comp];
3911 resu[face_associee*dim_ch_+comp]=resu[face*dim_ch_+comp];
3912 }
3913 }
3914 }
3915 }
3917}
int_t size_array() const
Renvoie la taille du tableau en bits.
Definition ArrOfBit.h:45
void setbit(int_t i) const
Met le bit e a 1.
Definition ArrOfBit.h:73
class Champ_Don_Fonc_xyz Cette classe represente un champ de donnees fonction
: class Champ_Don_lu Cette classe represente un champ de donnees que l'on lit dans un fichier avec le...
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Champ_Uniforme_Morceaux Cette classe represente champ constant par morceaux dans l'espace
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Champ_front_txyz Classe derivee de Champ_front_var qui represente les
double valeur_au_temps_et_au_point(double temps, int som, double x, double y, double z, int comp) const override
Champ_front_base & champ_front()
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
int_t nb_aretes_tot() const
renvoie le nombre d'aretes total (reelles+virtuelles).
Definition Domaine.h:145
virtual const MD_Vector & md_vector_sommets() const
Definition Domaine.h:369
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
DoubleTab_t & les_sommets()
Definition Domaine.h:113
int_t get_renum_som_perio(int_t i) const
Definition Domaine.h:281
IntTab_t & les_elems()
Definition Domaine.h:129
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
int_t nb_som_tot() const
Renvoie le nombre total de sommets du domaine i.e. le nombre de sommets reels et virtuels sur le proc...
Definition Domaine.h:123
int_t nb_som() const
Renvoie le nombre de sommets du domaine.
Definition Domaine.h:121
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
const DoubleVect & volume_aux_sommets() const
Definition Domaine_VEF.h:90
void creer_tableau_aretes(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
double volumes(int i) const
Definition Domaine_VF.h:113
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
virtual double surface(int i) const
Definition Domaine_VF.h:53
int est_une_face_virt_bord(int) const
renvoie 1 si face est une face virtuelle de bord, 0 sinon
Definition Domaine_VF.h:681
int nb_som_face() const
renvoie le nombre de sommets par face.
Definition Domaine_VF.h:494
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
int nb_som_tot() const
Classe Echange_externe_impose: Cette classe represente le cas particulier de la classe.
virtual double h_imp(int num) const
Renvoie la valeur du coefficient d'echange de chaleur impose sur la i-eme composante.
virtual double T_ext(int num) const
Renvoie la valeur de la temperature imposee sur la i-eme composante du champ de frontiere.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual const Champ_Inc_base & inconnue() const =0
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
virtual Nature_du_champ nature_du_champ() const
Definition Field_base.h:77
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
int nb_faces_tot() const
Definition Front_VF.h:58
int num_face(const int) const
Definition Front_VF.h:68
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
auto & get_set_tab2()
const auto & get_tab2() const
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
const auto & get_tab1() const
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
auto & get_set_tab1()
int nb_lignes() const override
Return local number of lines (=size on the current proc).
DoubleTab & ajouter_multTab_(const DoubleTab &, DoubleTab &) const override
Operation de multiplication-accumulation (saxpy) matrice matrice (matrice X representee par un tablea...
DoubleVect & porosite_elem()
Definition Milieu_base.h:58
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
Classe Neumann_homogene Cette classe est la classe de base de la hierarchie des conditions aux limite...
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
Classe Neumann_val_ext Cette classe est la classe de base de la hierarchie des conditions.
Classe Neumann Cette classe est la classe de base de la hierarchie des conditions aux limites de type...
Definition Neumann.h:31
virtual double flux_impose(int i) const
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
Definition Neumann.cpp:35
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
class Op_Diff_VEF_Face Cette classe represente l'operateur de diffusion
void coeff_matrice_som(const int, IntVect &, DoubleTab &, DoubleTab &, const DoubleVect &, const DoubleTab &, const DoubleTab &, Matrice_Morse &) const
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
DoubleTab & corriger_pour_diffusivite(const DoubleTab &, DoubleTab &) const
void liste_face(IntLists &, int &) const
void coeff_matrice_som_symetrie(const int, IntVect &, DoubleTab &, DoubleTab &, const DoubleVect &, const DoubleTab &, const DoubleTab &, Matrice_Morse &) const
void ajouter_contribution_elem(const DoubleTab &, const DoubleVect &, const DoubleTab &, Matrice_Morse &) const
void coeff_matrice_som_CL(const int, IntVect &, DoubleTab &, DoubleTab &, const DoubleVect &, const DoubleTab &, const DoubleTab &, Matrice_Morse &) const
void calculer_dt_stab_som(const DoubleTab &, DoubleTab &) const
DoubleVect & calculer_divergence_aretes(DoubleVect &) const
void calculer_laplacien_som(const DoubleTab &) const
void gradient_som_CL(const int, int &, IntVect &, DoubleTab &) const
void remplir_nu_pA(const DoubleTab &, DoubleTab &) const
void dimensionner(Matrice_Morse &) const override
on dimensionne notre matrice.
void calculer_flux_bords_elem(const DoubleVect &) const
void isInStencil(int, int, int &, int &, int &, int &) const
DoubleVect & calculer_divergence_som(DoubleVect &) const
const Domaine_VEF & domaine_vef() const
void ajouter_contribution_som(const DoubleTab &, const DoubleVect &, const DoubleTab &, Matrice_Morse &) const
DoubleVect & calculer_gradient_elem(const DoubleVect &) const
void calculer_dt_stab_aretes(const DoubleTab &, DoubleTab &) const
double calculer_dt_stab() const override
Calcul dt_stab.
void ajouter_contribution(const DoubleTab &, Matrice_Morse &) const
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void remplir_nu_p1(const DoubleTab &, DoubleTab &) const
Calcule la diffusivite "nu_p1" aux sommets du maillage en fonction de la diffusivite "nu_elem" aux el...
void calculer_flux_bords_som(const DoubleVect &) const
DoubleVect & calculer_gradient_som(const DoubleVect &) const
void ajouter_contribution_aretes(const DoubleTab &, const DoubleVect &, const DoubleTab &, Matrice_Morse &) const
void coeff_matrice_som_perio(const int, const int, IntVect &, DoubleTab &, DoubleTab &, const DoubleVect &, const DoubleTab &, const DoubleTab &, Matrice_Morse &) const
void corriger_Cl_test(DoubleTab &) const
DoubleVect & calculer_gradient_aretes(const DoubleVect &) const
void calculer_dt_stab_elem(const DoubleTab &, DoubleTab &) const
DoubleVect & corriger_div_pour_Cl(const DoubleVect &, const DoubleTab &, DoubleVect &) const
void gradient_som(const int face, const int, const int, const int, const int, const int, DoubleTab &) const
void calculer_flux_bords_aretes(const DoubleVect &) const
DoubleVect & calculer_divergence_elem(DoubleVect &) const
void isFaceOfSymetry(ArrOfBit &, int &) const
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
class Op_Diff_VEF_Face Cette classe represente l'operateur de diffusion
const Champ_base & diffusivite() const override
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
int phi_psi_diffuse(const Equation_base &eq) const
definit si on calcule div(phi nu grad Psi) ou div(nu grap Phi psi)
virtual void remplir_nu(DoubleTab &) const
double viscA(int face_i, int face_j, int num_elem, const _TYPE_ &diffu) const
void dimensionner(const Domaine_VEF &, const Domaine_Cl_VEF &, Matrice_Morse &) const
Dimensionnement de la matrice qui devra recevoir les coefficients provenant de la convection,...
void modifier_flux(const Operateur_base &) const
DoubleTab flux_bords_
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:386
static bool is_parallel()
Definition Process.cpp:110
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
double temps_courant() const
Renvoie le temps courant.
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual void declare_support_masse_volumique(int ok)
Le constructeur d'une classe derivee qui se sert de la masse volumique doit appeler cette fonction av...
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37
int size() const
Definition TRUSTLists.h:86
void dimensionner(int)
Redimensionne un tableau de listes.
Definition TRUSTLists.h:156
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
_TYPE_ local_max_abs_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:156
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")