TrioCFD 1.9.9_beta
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 //Keywords to recognise
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 //Syntax check
87 s >> motlu;
88 if (motlu!=accouverte)
89 {
90 Cerr << "Error in Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
91 Cerr << "Since version 1.5.5, the syntax of keyword P1NCP1B has changed." << finl;
92 Cerr << "An opening brace { is required first." << finl;
93 Cerr << "Optional settings go between the braces:" << finl;
94 Cerr << "Diffusion { P1NCP1B } -> Diffusion { P1NCB { } }" << finl;
95 exit();
96 }
97
98
99 //Read parameters
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 << "Error in Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
124 Cerr << "The alphaA option can only be enabled in dimension 3" << finl;
125 Cerr << "Exiting program" << 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 << "Error in Op_Diff_VEFP1NCP1B_Face::readOn()" << finl;
148 Cerr << "Keyword " << motlu << " not recognised" << finl;
149 Cerr << "Recognised keywords are: " << les_mots << finl;
150 Cerr << "Exiting program" << finl;
151 exit();
152 break;
153 }//end switch
154
155 //Continue reading
156 s >> motlu;
157 }//end 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//// associate
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 // Block symmetry in the P1NC diffusion operator on velocity (OK for scalar)
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//WARNING: DOES NOT ACCOUNT FOR POROSITY 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 //Compute porosity
242 modif_par_porosite_si_flag(nu_,nu,!marq,porosite_elem);
243
244 //Compute: contribution of the P0, P1 and Pa parts to 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 //Compute: modification to account for the mass matrix
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 //Compute: modification for Dirichlet faces
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 //Compute stability time step
288 //: only needed on real faces
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 //NOTE: multiply by -1 because laplacien_p1_=+Delta
390 for (face=0; face<nb_faces; face++)
391 {
392 face_C=face*dim_ch_;//for the vector case
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 //INTEGRAL values of 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 //NODAL values of 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 //NOTE: this echange_espace_virtuel() is REQUIRED
452 //when alphaS==1 and/or 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 //Right-hand side of the system to invert
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 //Boundary conditions for the right-hand side
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 //Nothing to do, this is expected
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 //Exact numerical integration formula for degree-2 polynomials
569 if (dimension==2) //Simpson's rule
570 {
571 //Coordinates of vertex "som"
572 x=coord_sommets(som,0);
573 y=coord_sommets(som,1);
574
575 //Value of the unknown at the integration point
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 }//end if on dimension==2
587
588 else //exact formula for degree-2 polynomials
589 {
590 //Assume the element is a TETRAHEDRON
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 //Coordinates of the integration points
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 //Velocity at the integration point
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 }//end else on dimension
613
614 }//end loop over "som_loc"
615
616 }//end loop over "ind_face"
617
618 }//end if on "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 }//end loop over "som_loc"
635
636 }//end loop over "ind_face"
637 }
638
639 }//end if on "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 }//end loop over "som_loc"
657
658 }//end loop over "ind_face"
659
660 }//end if on "!Periodique"
661
662 }//end loop over "n_bord"
663
664 secmem.echange_espace_virtuel();
665 Debog::verifier("OpDifP1NCP1B secmem, apres CL : ", secmem);
666
667 //Compute the solution of the system to invert
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 //Solve the system
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 //Re-initialise num1 and num2
728 num1 = 0;
729 num2 = le_bord.nb_faces();
730
731 if (sub_type(Periodique,la_cl.valeur()))
732 {
733 //periodicity
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 }//end loop over "ind_face"
750
751 }//end of periodicity
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 }//end if on "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 }//end loop over "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 //Algorithm without accounting for boundary conditions
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 //Boundary conditions
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 //The face index (which may be virtual)
904 face=le_bord.num_face(ind_face);
905
906 //The index of the neighbouring element
907 elem=face_voisins(face,0);
908 assert(elem!=-1);
909
910 //Compute the gradient at the midpoint of the boundary face
911 //using an approximate numerical integration
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 //Compute boundary divergence: exact numerical integration formula
925 //for degree-1 polynomials
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 }//end loop over "ind_face"
933
934 }//end if on "Neumann_paroi", "Neumann", "Symetrie"
935
936 }//end loop over "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;//for the explicit scheme
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 //Retrieve the diffusivity
984
985 //To account for porosity
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 //corriger_div_pour_Cl() must be called BEFORE computing
1028 //the p1 part because the matrix is already coded to account
1029 //for periodic coefficients
1030 //IMPORTANT NOTE: for technical reasons inherent to TrioU, the dt_stab
1031 //computation takes place BEFORE the ajouter() function is applied.
1032 //Since dt_stab needs the matrix to be correctly computed, the matrix
1033 //laplacien_p1_ is built in calculer_dt_stab() and is only reused here.
1034 if (alphaS)
1035 {
1036 domaine.creer_tableau_sommets(nu_p1);
1037 remplir_nu_p1(nu,nu_p1);
1038 laplacien_p1_.ajouter_multvect(inconnue2,resu3);
1039
1040 gradient_p1_=0.;
1041 calculer_gradient_som(inconnue2);
1044 calculer_flux_bords_som(inconnue2);
1045 }
1046
1047 if (test_) test();
1048
1049 resu2+=resu3;
1051 modifier_flux(*this);
1052 return resu;
1053}
1054
1056calculer(const DoubleTab& inconnue, DoubleTab& resu) const
1057{
1058 resu = 0;
1059 return ajouter(inconnue,resu);
1060}
1061
1063corriger_pour_diffusivite(const DoubleTab& nu,DoubleTab& grad) const
1064{
1065 tab_multiply_any_shape(grad, nu);
1066 return grad;
1067}
1068
1069
1071{
1072 const Domaine_VEF& domaine_VEF = domaine_vef();
1073
1074 const DoubleTab& unknown = equation().inconnue().valeurs();
1075 const int size = unknown.line_size();
1076
1077 //Define the gradients
1078 gradient_p0_.resize(0, size, Objet_U::dimension);
1080
1081 gradient_p1_.resize(0, size, Objet_U::dimension);
1083
1084 if (alphaA)
1085 {
1086 gradient_pa_.resize(0, size, Objet_U::dimension);
1088 }
1089
1090 //Initialise the dim_ch_ attribute
1091 dim_ch_=size;
1092
1093 //Size the flux_bords array
1094 flux_bords_.resize(domaine_VEF.nb_faces_bord(),size);
1095 flux_bords_=0.;
1096}
1097
1098//Function that computes the flux at the domain boundaries
1099void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_elem(const DoubleVect& inconnue) const
1100{
1101 const Domaine_VEF& domaine_VEF = domaine_vef();
1102 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1103
1104 const IntTab& face_voisins=domaine_VEF.face_voisins();
1105
1106 const DoubleTab& face_normales=domaine_VEF.face_normales();
1107
1108 const int nb_bords=domaine_VEF.nb_front_Cl();
1109
1110 int face=0;
1111 int elem=0;
1112 int n_bord=0,ind_face=0;
1113 int num1=0,num2=0;
1114 int compi=0,compj=0;
1115
1116 double surface=0.;
1117 double Text=0.;
1118
1119 double coeff_conv=1.;
1120 if (alphaS) coeff_conv=convexite_;
1121
1122 for (n_bord=0; n_bord<nb_bords; n_bord++)
1123 {
1124 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1125 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1126
1127 num1=0;
1128 num2=le_bord.nb_faces();
1129
1130 if (sub_type(Neumann_paroi,la_cl.valeur()))
1131 {
1132 const Neumann_paroi& la_cl_paroi=
1133 ref_cast(Neumann_paroi,la_cl.valeur());
1134
1135 for (ind_face=num1; ind_face<num2; ind_face++)
1136 {
1137 face=le_bord.num_face(ind_face);
1138 surface=domaine_VEF.face_surfaces(face);
1139
1140 for (compi=0; compi<dim_ch_; compi++)
1141 flux_bords_(face,compi)=coeff_conv*
1142 la_cl_paroi.flux_impose(ind_face,compi)*
1143 surface;
1144 }
1145 }
1146 else if (sub_type(Echange_externe_impose,la_cl.valeur()))
1147 {
1148 const Echange_externe_impose& la_cl_paroi=
1149 ref_cast(Echange_externe_impose,la_cl.valeur());
1150
1151 for (ind_face=num1; ind_face<num2; ind_face++)
1152 {
1153 face=le_bord.num_face(ind_face);
1154 surface=domaine_VEF.face_surfaces(face);
1155
1156 for (compi=0; compi<dim_ch_; compi++)
1157 {
1158 Text=la_cl_paroi.T_ext(ind_face,compi);
1159
1160 flux_bords_(face,compi)=coeff_conv*la_cl_paroi.h_imp(ind_face,compi)*surface;
1161 flux_bords_(face,compi)*=(Text-inconnue[face*dim_ch_+compi]);
1162 }
1163 }
1164 }
1165 else if ( sub_type(Neumann_homogene,la_cl.valeur()) ||
1166 sub_type(Neumann_sortie_libre,la_cl.valeur()) ||
1167 sub_type(Symetrie,la_cl.valeur())
1168 )
1169 {
1170 for (ind_face=num1; ind_face<num2; ind_face++)
1171 {
1172 face=le_bord.num_face(ind_face);
1173
1174 for (compi=0; compi<dim_ch_; compi++)
1175 flux_bords_(face,compi)=0.;
1176 }
1177 }
1178 else
1179 {
1180 for (ind_face=num1; ind_face<num2; ind_face++)
1181 {
1182 face=le_bord.num_face(ind_face);
1183 elem=face_voisins(face,0);
1184 assert(elem!=-1);
1185
1186 //the convexity coefficient is already included in gradient_p0_
1187 for (compi=0; compi<dim_ch_; compi++)
1188 for (compj=0; compj<dimension; compj++)
1189 flux_bords_(face,compi)=gradient_p0_(elem,compi,compj)
1190 *face_normales(face,compj);
1191 }
1192 }
1193 }//end loop over n_bord
1194}
1195
1196//Function that computes the flux at the domain boundaries
1197void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_som(const DoubleVect& inconnue) const
1198{
1199 const Domaine_VEF& domaine_VEF = domaine_vef();
1200 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1201 const Domaine& domaine = domaine_VEF.domaine();
1202 const Domaine& dom=domaine;
1203
1204 const IntTab& face_sommets=domaine_VEF.face_sommets();
1205
1206 const DoubleTab& face_normales=domaine_VEF.face_normales();
1207
1208 const int nb_som_face=domaine_VEF.nb_som_face();
1209 const int nb_bords=domaine_VEF.nb_front_Cl();
1210
1211 int face=0;
1212 int som=0,som_loc=0;
1213 int n_bord=0,ind_face=0;
1214 int num1=0,num2=0;
1215 int compi=0,compj=0;
1216
1217 double surface=0.;
1218 double Text=0.;
1219 double coeff_conv=1.;
1220 if (alphaE) coeff_conv=1.-convexite_;
1221
1222 for (n_bord=0; n_bord<nb_bords; n_bord++)
1223 {
1224 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1225 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1226
1227 num1=0;
1228 num2=le_bord.nb_faces();
1229
1230 if (sub_type(Neumann_paroi,la_cl.valeur()))
1231 {
1232 const Neumann_paroi& la_cl_paroi=
1233 ref_cast(Neumann_paroi,la_cl.valeur());
1234
1235 for (ind_face=num1; ind_face<num2; ind_face++)
1236 {
1237 face=le_bord.num_face(ind_face);
1238 surface=domaine_VEF.face_surfaces(face);
1239
1240 for (compi=0; compi<dim_ch_; compi++)
1241 flux_bords_(face,compi)=coeff_conv*
1242 la_cl_paroi.flux_impose(ind_face,compi)*
1243 surface;
1244 }
1245 }
1246 else if (sub_type(Echange_externe_impose,la_cl.valeur()))
1247 {
1248 const Echange_externe_impose& la_cl_paroi=
1249 ref_cast(Echange_externe_impose,la_cl.valeur());
1250
1251 for (ind_face=num1; ind_face<num2; ind_face++)
1252 {
1253 face=le_bord.num_face(ind_face);
1254 surface=domaine_VEF.face_surfaces(face);
1255
1256 for (compi=0; compi<dim_ch_; compi++)
1257 {
1258 Text=la_cl_paroi.T_ext(ind_face,compi);
1259
1260 flux_bords_(face,compi)=coeff_conv*la_cl_paroi.h_imp(ind_face,compi)*surface;
1261 flux_bords_(face,compi)*=(Text-inconnue[face*dim_ch_+compi]);
1262 }
1263 }
1264 }
1265 else if ( sub_type(Neumann_homogene,la_cl.valeur()) ||
1266 sub_type(Neumann_sortie_libre,la_cl.valeur()) ||
1267 sub_type(Symetrie,la_cl.valeur())
1268 )
1269 {
1270 for (ind_face=num1; ind_face<num2; ind_face++)
1271 {
1272 face=le_bord.num_face(ind_face);
1273
1274 for (compi=0; compi<dim_ch_; compi++)
1275 flux_bords_(face,compi)=0.;
1276 }
1277 }
1278 else
1279 {
1280 for (ind_face=num1; ind_face<num2; ind_face++)
1281 {
1282 face=le_bord.num_face(ind_face);
1283
1284 //the convexity coefficient is already included in gradient_p1_
1285 for (som_loc=0; som_loc<nb_som_face; som_loc++)
1286 {
1287 som=face_sommets(face,som_loc);
1288 som=dom.get_renum_som_perio(som);
1289
1290 for (compi=0; compi<dim_ch_; compi++)
1291 for (compj=0; compj<dimension; compj++)
1292 flux_bords_(face,compi)+=gradient_p1_(som,compi,compj)*
1293 face_normales(face,compj);
1294 }
1295
1296 for (compi=0; compi<dim_ch_; compi++)
1297 flux_bords_(face,compi)/=nb_som_face;
1298 }
1299 }
1300 }//end loop over n_bord
1301}
1302
1303//Function that computes the flux at the domain boundaries
1304void Op_Diff_VEFP1NCP1B_Face::calculer_flux_bords_aretes(const DoubleVect& inconnue) const
1305{
1306 Cerr<<"Op_Dift_VEF_P1NCP1B_Face::calculer_flux_bords_aretes() not coded"<<finl;
1307 Cerr<<"Exit"<<finl;
1308 exit();
1309}
1310
1311
1312///////////////////////////////////////////////////////////////
1313//Functions for the implicit scheme
1314//////////////////////////////////////////////////////////////
1316ajouter_contribution_elem(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1317 const DoubleTab& nu,Matrice_Morse& matrice) const
1318{
1319 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1320 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
1321 const IntTab& elem_faces = domaine_VEF.elem_faces();
1322 const IntTab& face_voisins = domaine_VEF.face_voisins();
1323
1324 // int nb_faces_tot = domaine_VEF.nb_faces_tot();
1325 int nb_faces=domaine_VEF.nb_faces();
1326 int nb_faces_elem = domaine_VEF.domaine().nb_faces_elem();
1327 int nb_comp = inconnue.line_size();
1328
1329 int i,j,num_face;
1330 int elem1,elem2;
1331
1332 double val;
1333 double coeff=1./coeff_;
1334 if (alphaS) coeff*=convexite_;
1335
1336 int nb_bords=domaine_VEF.nb_front_Cl();
1337 for (int n_bord=0; n_bord<nb_bords; n_bord++)
1338 {
1339 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1340 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1341 int num1 = le_bord.num_premiere_face();
1342 int num2 = num1 + le_bord.nb_faces();
1343
1344 if (sub_type(Periodique,la_cl.valeur()))
1345 {
1346 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1347 int fac_asso;
1348 for (num_face=num1; num_face<num2; num_face++)
1349 {
1350 elem1 = face_voisins(num_face,0);
1351 fac_asso = la_cl_perio.face_associee(num_face-num1)+num1;
1352
1353 // At the end of the loop:
1354 // if ok=1, then num_face belongs to elem1
1355 // if ok=0, then num_face does not belong to elem1 and
1356 // fac_asso belongs to elem1
1357 int ok=1;
1358 int fac_loc=0;
1359 while ((fac_loc<nb_faces_elem) && (elem_faces(elem1,fac_loc)!=num_face)) fac_loc++;
1360 if (fac_loc==nb_faces_elem) ok=0;
1361
1362 for (i=0; i<nb_faces_elem; i++)
1363 if ( ( (j= elem_faces(elem1,i)) > num_face ) && (j != fac_asso ) )
1364 {
1365 val = viscA(num_face,j,elem1,nu(elem1));
1366
1367 // int fac_loc=0;
1368 // while ((fac_loc<nb_faces_elem) && (elem_faces(elem1,fac_loc)!=num_face)) fac_loc++;
1369 // if (fac_loc==nb_faces_elem) ok=0;
1370
1371 for (int nc=0; nc<nb_comp; nc++)
1372 {
1373 int n0=num_face*nb_comp+nc;
1374 int j0=j*nb_comp+nc;
1375
1376 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1377 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1378
1379 if (!ok) n0=fac_asso*nb_comp+nc;
1380 if (j<nb_faces)
1381 {
1382 matrice(j0,n0)-=val*porosite_face((n0-nc)/nb_comp)*coeff;
1383 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1384 }
1385
1386 }
1387 }
1388
1389 //Second element
1390 elem2 = face_voisins(num_face,1);
1391
1392 for (i=0; i<nb_faces_elem; i++)
1393 if ( ( (j= elem_faces(elem2,i)) > num_face ) && (j != fac_asso ) )
1394 {
1395 val = viscA(num_face,j,elem2,nu(elem2));
1396
1397 for (int nc=0; nc<nb_comp; nc++)
1398 {
1399 int n0=num_face*nb_comp+nc;
1400 int j0=j*nb_comp+nc;
1401
1402 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1403 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1404 }
1405 }
1406
1407 }//end loop over "num_face"
1408 }
1409 else
1410 {
1411 for (num_face=num1; num_face<num2; num_face++)
1412 {
1413 elem1 = face_voisins(num_face,0);
1414
1415 for (i=0; i<nb_faces_elem; i++)
1416 if ( (j= elem_faces(elem1,i)) > num_face )
1417 {
1418 val = viscA(num_face,j,elem1,nu(elem1));
1419 for (int nc=0; nc<nb_comp; nc++)
1420 {
1421 int n0=num_face*nb_comp+nc;
1422 int j0=j*nb_comp+nc;
1423
1424 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1425 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1426 if (j<nb_faces) //needed ????
1427 {
1428 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1429 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1430 }
1431
1432 }
1433 }
1434 }
1435 }
1436 }
1437
1438 //Fill only real rows
1439 for (num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
1440 {
1441 elem1 = face_voisins(num_face,0);
1442 elem2 = face_voisins(num_face,1);
1443
1444 for (i=0; i<nb_faces_elem; i++)
1445 {
1446 if ( (j=elem_faces(elem1,i)) > num_face )
1447 {
1448 val = viscA(num_face,j,elem1,nu(elem1));
1449 for (int nc=0; nc<nb_comp; nc++)
1450 {
1451 int n0=num_face*nb_comp+nc;
1452 int j0=j*nb_comp+nc;
1453
1454 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1455 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1456 if (j<nb_faces)
1457 {
1458 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1459 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1460 }
1461 }
1462 }
1463
1464 // if (elem2!=-1) //test not needed as the face is real
1465 if ( (j=elem_faces(elem2,i)) > num_face )
1466 {
1467 val= viscA(num_face,j,elem2,nu(elem2));
1468 for (int nc=0; nc<nb_comp; nc++)
1469 {
1470 int n0=num_face*nb_comp+nc;
1471 int j0=j*nb_comp+nc;
1472
1473 matrice(n0,n0)+=val*porosite_face(num_face)*coeff;
1474 matrice(n0,j0)-=val*porosite_face(j)*coeff;
1475 if (j<nb_faces)
1476 {
1477 matrice(j0,n0)-=val*porosite_face(num_face)*coeff;
1478 matrice(j0,j0)+=val*porosite_face(j)*coeff;
1479 }
1480
1481 }
1482 }
1483 }
1484 }
1485}
1486
1488ajouter_contribution_som(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1489 const DoubleTab& nu_som,Matrice_Morse& matrice) const
1490{
1491 const Domaine_VEF& domaine_VEF=domaine_vef();
1492 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
1493
1494 IntVect liste_som(dimension+2);//for triangles and tetrahedra
1495
1496 DoubleTab gradient0(dimension,dimension+2);
1497 DoubleTab gradient1(dimension);
1498
1499 const int premiere_face_int=domaine_VEF.premiere_face_int();
1500 const int nb_faces=domaine_VEF.nb_faces();
1501 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
1502 const int nb_bords=domaine_VEF.nb_front_Cl();
1503
1504 int face=0;
1505 int ind_face=0;
1506 int n_bord=0;
1507 int num1=0,num2=0;
1508
1509 DoubleTab coeff_perio(nb_faces_tot);
1510 coeff_perio=1.;
1511 for (n_bord=0; n_bord<nb_bords; n_bord++)
1512 {
1513 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1514 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1515 num1=0;
1516 num2=le_bord.nb_faces_tot();
1517
1518 if (sub_type(Periodique,la_cl.valeur()))
1519 for (ind_face=num1; ind_face<num2; ind_face++)
1520 {
1521 face=le_bord.num_face(ind_face);
1522 coeff_perio(face)=0.5;
1523 }
1524 }
1525
1526 //
1527 //P1 part of the discrete Laplacian:
1528 //iterating over rows, so we only need
1529 //to fill the real rows.
1530 //WARNING: filling the real rows
1531 //may involve computing a coefficient
1532 //linked to a virtual column
1533 //
1534
1535 /* Internal faces */
1536 for (face=premiere_face_int; face<nb_faces; face++)
1537 {
1538 coeff_matrice_som(face,liste_som,
1539 gradient0,gradient1,
1540 porosite_face,nu_som,
1541 coeff_perio,matrice);
1542 }
1543
1544 for (n_bord=0; n_bord<nb_bords; n_bord++)
1545 {
1546 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
1547 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1548 num1=0;
1549 num2=le_bord.nb_faces();
1550
1551 if (sub_type(Periodique,la_cl.valeur()))
1552 {
1553 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1554 int faceAss=0;
1555
1556 for (ind_face=num1; ind_face<num2; ind_face++)
1557 {
1558 face=le_bord.num_face(ind_face);
1559 faceAss=le_bord.num_face(la_cl_perio.face_associee(ind_face));
1560
1561 //Take the smallest face index to ensure no boundary face is missed
1562 coeff_matrice_som_perio(face,faceAss,liste_som,
1563 gradient0,gradient1,
1564 porosite_face,nu_som,
1565 coeff_perio,matrice);
1566
1567 }
1568 }
1569 else if (sub_type(Symetrie,la_cl.valeur()))
1570 for (ind_face=num1; ind_face<num2; ind_face++)
1571 {
1572 face=le_bord.num_face(ind_face);
1573
1574 coeff_matrice_som_symetrie(face,liste_som,
1575 gradient0,gradient1,
1576 porosite_face,nu_som,
1577 coeff_perio,matrice);
1578 }
1579
1580 else
1581 for (ind_face=num1; ind_face<num2; ind_face++)
1582 {
1583 face=le_bord.num_face(ind_face);
1584
1585 coeff_matrice_som_CL(face,liste_som,
1586 gradient0,gradient1,
1587 porosite_face,nu_som,
1588 coeff_perio,matrice);
1589 }
1590 }
1591}
1592
1594ajouter_contribution_aretes(const DoubleTab& inconnue,const DoubleVect& porosite_face,
1595 const DoubleTab& nu,Matrice_Morse& matrice) const
1596{
1597}
1598
1599//Function that computes the matrix coefficients for an INTERNAL face.
1601coeff_matrice_som(const int face,IntVect& liste_som,
1602 DoubleTab& gradient0, DoubleTab& gradient1,
1603 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1604 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1605{
1606 const Domaine_VEF& domaine_VEF=domaine_vef();
1607
1608 const auto& tab1=matrice.get_tab1();
1609 const auto& tab2=matrice.get_tab2();
1610
1611 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1612
1613 const int nb_faces=domaine_VEF.nb_faces();
1614
1615 int face_C=0;
1616 int face2=0,face2_C=0;
1617 int som_loc=0,som=0;
1618 int som_loc0=0,som_loc1=0;
1619 int compi=0,compj=0;
1620 int elem0=0,elem1=0;
1621 int i=0;
1622 int nnz=0;
1623
1624 double coeff_som=0.,coeff_mat=0.;
1625 double coeff_diff=0.;
1626 double psc=0.;
1627 double delta=decentrage_;
1628
1629 double coeff_conv=1.;
1630 if (alphaE) coeff_conv=(1.-convexite_);
1631
1632 //Some checks
1633 assert(gradient0.nb_dim()==2);
1634 assert(gradient0.dimension(0)==dimension);
1635 assert(gradient0.dimension(1)==dimension+2);
1636 assert(gradient1.nb_dim()==1);
1637 assert(gradient1.dimension(0)==dimension);
1638 assert(liste_som.size()==dimension+2);
1639
1640 //
1641 //P1 part of the discrete Laplacian
1642 //
1643 liste_som=-1;
1644 gradient0=0.;
1645 gradient_som(face,nnz,liste_som,gradient0);
1646
1647
1648 /* gradient associated with "face": compute the diagonal */
1649 /* coefficient of the matrix for the unknown */
1650 coeff_mat=0.;
1651 for (som_loc=0; som_loc<nnz; som_loc++)
1652 {
1653 som=liste_som(som_loc);
1654 coeff_som=volume_aux_sommets(som)*coeff_;
1655
1656 psc=0.;
1657 for (compj=0; compj<dimension; compj++)
1658 psc+=gradient0(compj,som_loc)
1659 *gradient0(compj,som_loc);
1660
1661 psc*=coeff_som;
1662 psc*=nu_som(som);
1663
1664 coeff_mat+=psc;
1665 }
1666 coeff_mat*=coeff_conv;
1667
1668 for (compi=0; compi<dim_ch_; compi++)
1669 {
1670 face_C=face*dim_ch_+compi;
1671 matrice(face_C,face_C)+=coeff_mat;
1672 }
1673
1674
1675 /* compute the off-diagonal coefficients of the Laplacian matrix */
1676 /* since the matrix is block diagonal, compute the dot product */
1677 /* only once before assigning it to the different */
1678 /* components of the matrix */
1679 face_C=face*dim_ch_;
1680 auto debut=tab1[face_C]-1;
1681 auto size=tab1[face_C+1]-tab1[face_C];
1682
1683 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> already filled
1684 {
1685 face2_C=tab2[debut+i]-1;
1686 face2=face2_C/dim_ch_;//integer division
1687
1688 if (face2>face)//for operator symmetry
1689 {
1690 coeff_mat=0.;
1691 for (som_loc=0; som_loc<nnz; som_loc++)
1692 {
1693 som=liste_som(som_loc);
1694 coeff_som=volume_aux_sommets(som)*coeff_;
1695 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1696
1697 if (elem0!=-1)//the two faces "see" each other
1698 {
1699 assert(som_loc0!=-1);
1700 gradient1=0.;
1701 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1702
1703 psc=0.;
1704 for (compj=0; compj<dimension; compj++)
1705 psc+=gradient0(compj,som_loc)
1706 *gradient1(compj);
1707
1708 psc*=coeff_som;
1709 psc*=nu_som(som);
1710 coeff_mat+=psc;
1711 }
1712 }
1713 coeff_mat*=coeff_conv;
1714 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1715 coeff_mat+=coeff_diff;
1716
1717 for (compi=0; compi<dim_ch_; compi++)
1718 {
1719 face_C=face*dim_ch_+compi;
1720 face2_C=face2*dim_ch_+compi;
1721
1722 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
1723 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
1724 if (face2<nb_faces)
1725 {
1726 matrice(face2_C,face_C)+=coeff_mat;
1727 matrice(face2_C,face2_C)-=coeff_diff;
1728 }
1729 }
1730 }
1731 }
1732}
1733
1734//Function that computes the matrix coefficients for a BOUNDARY face
1735//that is neither periodic nor symmetric.
1737coeff_matrice_som_CL(const int face,IntVect& liste_som,
1738 DoubleTab& gradient0, DoubleTab& gradient1,
1739 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1740 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1741{
1742 const Domaine_VEF& domaine_VEF=domaine_vef();
1743
1744 const auto& tab1=matrice.get_tab1();
1745 const auto& tab2=matrice.get_tab2();
1746
1747 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1748
1749 const int nb_faces=domaine_VEF.nb_faces();
1750
1751 int face_C=0;
1752 int face2=0,face2_C=0;
1753 int som_loc=0,som=0;
1754 int som_loc0=0,som_loc1=0;
1755 int compi=0,compj=0;
1756 int elem0=0,elem1=0;
1757 int i=0;
1758 int nnz=0;
1759
1760 double coeff_som=0.,coeff_mat=0.;
1761 double coeff_diff=0.;
1762 double psc=0.;
1763 double delta=decentrage_;
1764
1765 double coeff_conv=1.;
1766 if (alphaE) coeff_conv=(1.-convexite_);
1767
1768 //Some checks
1769 assert(gradient0.nb_dim()==2);
1770 assert(gradient0.dimension(0)==dimension);
1771 assert(gradient0.dimension(1)==dimension+2);
1772 assert(gradient1.nb_dim()==1);
1773 assert(gradient1.dimension(0)==dimension);
1774 assert(liste_som.size()==dimension+2);
1775
1776 //
1777 //P1 part of the discrete Laplacian
1778 //
1779 liste_som=-1;
1780 gradient0=0.;
1781 gradient_som_CL(face,nnz,liste_som,gradient0);
1782
1783
1784 /* gradient associated with "face": compute the diagonal */
1785 /* coefficient of the matrix for the unknown */
1786 coeff_mat=0.;
1787 for (som_loc=0; som_loc<nnz; som_loc++)
1788 {
1789 som=liste_som(som_loc);
1790 coeff_som=volume_aux_sommets(som)*coeff_;
1791
1792 psc=0.;
1793 for (compj=0; compj<dimension; compj++)
1794 psc+=gradient0(compj,som_loc)
1795 *gradient0(compj,som_loc);
1796
1797 psc*=coeff_som;
1798 psc*=nu_som(som);
1799
1800 coeff_mat+=psc;
1801 }
1802 coeff_mat*=coeff_conv;
1803
1804 for (compi=0; compi<dim_ch_; compi++)
1805 {
1806 face_C=face*dim_ch_+compi;
1807 matrice(face_C,face_C)+=coeff_mat;
1808 }
1809
1810
1811 /* compute the off-diagonal coefficients of the Laplacian matrix */
1812 /* since the matrix is block diagonal, compute the dot product */
1813 /* only once before assigning it to the different */
1814 /* components of the matrix */
1815 face_C=face*dim_ch_;
1816 auto debut=tab1[face_C]-1;
1817 auto size=tab1[face_C+1]-tab1[face_C];
1818
1819 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> already filled
1820 {
1821 face2_C=tab2[debut+i]-1;
1822 face2=face2_C/dim_ch_;//integer division
1823
1824 if (face2>face)//for operator symmetry
1825 {
1826 coeff_mat=0.;
1827 for (som_loc=0; som_loc<nnz; som_loc++)
1828 {
1829 som=liste_som(som_loc);
1830 coeff_som=volume_aux_sommets(som)*coeff_;
1831 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1832
1833 if (elem0!=-1)//the two faces "see" each other
1834 {
1835 assert(som_loc0!=-1);
1836 gradient1=0.;
1837 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1838
1839 psc=0.;
1840 for (compj=0; compj<dimension; compj++)
1841 psc+=gradient0(compj,som_loc)
1842 *gradient1(compj);
1843
1844 psc*=coeff_som;
1845 psc*=nu_som(som);
1846 coeff_mat+=psc;
1847 }
1848 }
1849 coeff_mat*=coeff_conv;
1850 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1851 coeff_mat+=coeff_diff;
1852
1853 for (compi=0; compi<dim_ch_; compi++)
1854 {
1855 face_C=face*dim_ch_+compi;
1856 face2_C=face2*dim_ch_+compi;
1857
1858 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
1859 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
1860 if (face2<nb_faces)
1861 {
1862 matrice(face2_C,face_C)+=coeff_mat;
1863 matrice(face2_C,face2_C)-=coeff_diff;
1864 }
1865 }
1866 }
1867 }
1868}
1869
1870//Function that computes the matrix coefficients for a boundary face
1871//that is a SYMMETRY face.
1873coeff_matrice_som_symetrie(const int face,IntVect& liste_som,
1874 DoubleTab& gradient0, DoubleTab& gradient1,
1875 const DoubleVect& porosite_face,const DoubleTab& nu_som,
1876 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
1877{
1878 const Domaine_VEF& domaine_VEF=domaine_vef();
1879
1880 const auto& tab1=matrice.get_tab1();
1881 const auto& tab2=matrice.get_tab2();
1882
1883 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
1884
1885 const int nb_faces=domaine_VEF.nb_faces();
1886
1887 int face_C=0;
1888 int face2=0,face2_C=0;
1889 int som_loc=0,som=0;
1890 int som_loc0=0,som_loc1=0;
1891 int compi=0,compj=0;
1892 int elem0=0,elem1=0;
1893 int i=0;
1894 int nnz=0;
1895
1896 double coeff_som=0.,coeff_mat=0.;
1897 double coeff_diff=0.;
1898 double psc=0.;
1899 double delta=decentrage_;
1900
1901 double coeff_conv=1.;
1902 if (alphaE) coeff_conv=(1.-convexite_);
1903
1904 //Some checks
1905 assert(gradient0.nb_dim()==2);
1906 assert(gradient0.dimension(0)==dimension);
1907 assert(gradient0.dimension(1)==dimension+2);
1908 assert(gradient1.nb_dim()==1);
1909 assert(gradient1.dimension(0)==dimension);
1910 assert(liste_som.size()==dimension+2);
1911
1912 //
1913 //P1 part of the discrete Laplacian
1914 //
1915 liste_som=-1;
1916 gradient0=0.;
1917 gradient_som_CL(face,nnz,liste_som,gradient0);
1918
1919
1920 /* gradient associated with "face": compute the diagonal */
1921 /* coefficient of the matrix for the unknown */
1922 coeff_mat=0.;
1923 for (som_loc=0; som_loc<nnz; som_loc++)
1924 {
1925 som=liste_som(som_loc);
1926 coeff_som=volume_aux_sommets(som)*coeff_;
1927
1928 psc=0.;
1929 for (compj=0; compj<dimension; compj++)
1930 psc+=gradient0(compj,som_loc)
1931 *gradient0(compj,som_loc);
1932
1933 psc*=coeff_som;
1934 psc*=nu_som(som);
1935
1936 coeff_mat+=psc;
1937 }
1938 coeff_mat*=coeff_conv;
1939
1940 for (compi=0; compi<dim_ch_; compi++)
1941 {
1942 face_C=face*dim_ch_+compi;
1943 matrice(face_C,face_C)+=coeff_mat;
1944 }
1945
1946
1947 /* compute the off-diagonal coefficients of the Laplacian matrix */
1948 /* since the matrix is block diagonal, compute the dot product */
1949 /* only once before assigning it to the different */
1950 /* components of the matrix */
1951 /* NOTE: the matrix is modified to account for symmetry BCs, */
1952 /* but the associated modifications are not computed here -> */
1953 /* this is handled by Op_VEF_Face::modifier_pour_Cl() */
1954 face_C=face*dim_ch_;
1955 auto debut=tab1[face_C]-1;
1956 auto size=tab1[face_C+1]-tab1[face_C];
1957 size-=(dim_ch_-1);//-> to avoid computing unnecessary coefficients
1958
1959 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> already filled
1960 {
1961 face2_C=tab2[debut+i]-1;
1962 face2=face2_C/dim_ch_;//integer division
1963
1964 if (face2>face)//for operator symmetry
1965 {
1966 coeff_mat=0.;
1967 for (som_loc=0; som_loc<nnz; som_loc++)
1968 {
1969 som=liste_som(som_loc);
1970 coeff_som=volume_aux_sommets(som)*coeff_;
1971 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
1972
1973 if (elem0!=-1)//the two faces "see" each other
1974 {
1975 assert(som_loc0!=-1);
1976 gradient1=0.;
1977 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
1978
1979 psc=0.;
1980 for (compj=0; compj<dimension; compj++)
1981 psc+=gradient0(compj,som_loc)
1982 *gradient1(compj);
1983
1984 psc*=coeff_som;
1985 psc*=nu_som(som);
1986 coeff_mat+=psc;
1987 }
1988 }
1989 coeff_mat*=coeff_conv;
1990 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
1991 coeff_mat+=coeff_diff;
1992
1993 for (compi=0; compi<dim_ch_; compi++)
1994 {
1995 face_C=face*dim_ch_+compi;
1996 face2_C=face2*dim_ch_+compi;
1997
1998 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
1999 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
2000 if (face2<nb_faces)
2001 {
2002 matrice(face2_C,face_C)+=coeff_mat;
2003 matrice(face2_C,face2_C)-=coeff_diff;
2004 }
2005 }
2006 }
2007 }
2008}
2009
2010//Function that computes the matrix coefficients for a PERIODIC face.
2012coeff_matrice_som_perio(const int face,const int faceAss, IntVect& liste_som,
2013 DoubleTab& gradient0, DoubleTab& gradient1,
2014 const DoubleVect& porosite_face,const DoubleTab& nu_som,
2015 const DoubleTab& coeff_perio,Matrice_Morse& matrice) const
2016{
2017 const Domaine_VEF& domaine_VEF=domaine_vef();
2018
2019 const auto& tab1=matrice.get_tab1();
2020 const auto& tab2=matrice.get_tab2();
2021
2022 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2023
2024 const int nb_faces=domaine_VEF.nb_faces();
2025
2026 int face_C=0;
2027 int face2=0,face2_C=0;
2028 int som_loc=0,som=0;
2029 int som_loc0=0,som_loc1=0;
2030 int compi=0,compj=0;
2031 int elem0=0,elem1=0;
2032 int i=0;
2033 int nnz=0;
2034
2035 double coeff_som=0.,coeff_mat=0.;
2036 double coeff_diff=0.;
2037 double psc=0.;
2038 double delta=decentrage_;
2039
2040 double coeff_conv=1.;
2041 if (alphaE) coeff_conv=(1.-convexite_);
2042
2043 //Some checks
2044 assert(gradient0.nb_dim()==2);
2045 assert(gradient0.dimension(0)==dimension);
2046 assert(gradient0.dimension(1)==dimension+2);
2047 assert(gradient1.nb_dim()==1);
2048 assert(gradient1.dimension(0)==dimension);
2049 assert(liste_som.size()==dimension+2);
2050
2051 //
2052 //P1 part of the discrete Laplacian
2053 //
2054 liste_som=-1;
2055 gradient0=0.;
2056 gradient_som(face,nnz,liste_som,gradient0);
2057
2058
2059 /* gradient associated with "face": compute the diagonal */
2060 /* coefficient of the matrix for the unknown */
2061 coeff_mat=0.;
2062 for (som_loc=0; som_loc<nnz; som_loc++)
2063 {
2064 som=liste_som(som_loc);
2065 coeff_som=volume_aux_sommets(som)*coeff_;
2066
2067 psc=0.;
2068 for (compj=0; compj<dimension; compj++)
2069 psc+=gradient0(compj,som_loc)
2070 *gradient0(compj,som_loc);
2071
2072 psc*=coeff_som;
2073 psc*=nu_som(som);
2074
2075 coeff_mat+=psc;
2076 }
2077 coeff_mat*=coeff_conv;
2078
2079 for (compi=0; compi<dim_ch_; compi++)
2080 {
2081 face_C=face*dim_ch_+compi;
2082 matrice(face_C,face_C)+=coeff_mat;
2083 }
2084
2085
2086 /* compute the off-diagonal coefficients of the Laplacian matrix */
2087 /* since the matrix is block diagonal, compute the dot product */
2088 /* only once before assigning it to the different */
2089 /* components of the matrix */
2090 face_C=face*dim_ch_;
2091 auto debut=tab1[face_C]-1;
2092 auto size=tab1[face_C+1]-tab1[face_C];
2093
2094 for (i=1; i<size; i++) //i=0 -> face2_C=face_C -> already filled
2095 {
2096 face2_C=tab2[debut+i]-1;
2097 face2=face2_C/dim_ch_;//integer division
2098
2099 if (face2>face)//for operator symmetry
2100 {
2101 coeff_mat=0.;
2102 for (som_loc=0; som_loc<nnz; som_loc++)
2103 {
2104 som=liste_som(som_loc);
2105 coeff_som=volume_aux_sommets(som)*coeff_;
2106 isInStencil(face2,som,elem0,som_loc0,elem1,som_loc1);
2107
2108 if (elem0!=-1)//the two faces "see" each other
2109 {
2110 assert(som_loc0!=-1);
2111 gradient1=0.;
2112 gradient_som(face2,som,elem0,som_loc0,elem1,som_loc1,gradient1);
2113
2114 psc=0.;
2115 for (compj=0; compj<dimension; compj++)
2116 psc+=gradient0(compj,som_loc)
2117 *gradient1(compj);
2118
2119 psc*=coeff_som;
2120 psc*=nu_som(som);
2121 coeff_mat+=psc;
2122 }
2123 }
2124 coeff_mat*=coeff_conv;
2125 coeff_diff=-1.*delta*maximum(0.,coeff_mat);
2126 coeff_mat+=coeff_diff;
2127
2128 for (compi=0; compi<dim_ch_; compi++)
2129 {
2130 face_C=face*dim_ch_+compi;
2131 face2_C=face2*dim_ch_+compi;
2132
2133 matrice(face_C,face2_C)+=coeff_mat*coeff_perio(face2);
2134 matrice(face_C,face_C)-=coeff_diff*coeff_perio(face2);
2135 if (face2<nb_faces)
2136 {
2137 matrice(face2_C,face_C)+=coeff_mat*coeff_perio(face);
2138 matrice(face2_C,face2_C)-=coeff_diff*coeff_perio(face);
2139 }
2140 }
2141 }
2142 }
2143}
2144
2146ajouter_contribution(const DoubleTab& inconnue,Matrice_Morse& matrice) const
2147{
2148 const Domaine_VEF& domaine_VEF=domaine_vef();
2149 const Domaine& domaine=domaine_VEF.domaine();
2150
2151 //Flag to account for porosity
2152 const int marq=phi_psi_diffuse(equation());
2153
2154 //Lines to account for porosity
2155 const DoubleVect& porosite_elem=equation().milieu().porosite_elem();
2156 DoubleVect porosite_face(equation().milieu().porosite_face());
2157 if (!marq) porosite_face=1.;
2158
2159 //Lines to account for diffusivity
2160 DoubleTab nu,nu_p1,nu_pA;
2161 remplir_nu(nu_);
2162 modif_par_porosite_si_flag(nu_,nu,!marq,porosite_elem);
2163
2164 //REMAINING: handle face porosity
2165 if (alphaE)
2166 ajouter_contribution_elem(inconnue,porosite_face,nu,matrice);
2167 if (alphaS)
2168 {
2169 domaine.creer_tableau_sommets(nu_p1);
2170 remplir_nu_p1(nu,nu_p1);
2171 ajouter_contribution_som(inconnue,porosite_face,nu_p1,matrice);
2172 }
2173 if (alphaA)
2174 {
2175 domaine_VEF.creer_tableau_aretes(nu_pA);
2176 remplir_nu_pA(nu,nu_pA);
2177 ajouter_contribution_aretes(inconnue,porosite_face,nu_pA,matrice);
2178 }
2179
2180 if (test_) test();
2181}
2182
2183/*! @brief Compute the diffusivity "nu_p1" at mesh vertices from the element diffusivity "nu_elem".
2184 *
2185 * Assumes that nu_elem has its virtual space up to date,
2186 * that nu_p1 is sized with nb_dim==1 using the domaine.md_vector_sommets() structure.
2187 * On exit the virtual space of nu_p1 is updated.
2188 *
2189 * The interpolator computes for each vertex the (unweighted) average of
2190 * the diffusivities over the elements adjacent to that vertex.
2191 *
2192 */
2194remplir_nu_p1(const DoubleTab& nu_elem,DoubleTab& nu_p1) const
2195{
2196 const Domaine_VEF& domaine_VEF=domaine_vef();
2197 const Domaine& domaine=domaine_VEF.domaine();
2198 const Domaine& dom=domaine;
2199
2200 const int nb_som = dom.nb_som();
2201 const int nb_elem_tot=domaine.nb_elem_tot();
2202 const int nb_som_elem=domaine.nb_som_elem();
2203
2204 int elem=0;
2205 int som_loc=0,som=0;
2206
2207 const IntTab& elem_som=domaine.les_elems();
2208
2209 ArrOfInt nb_elem_per_som(nb_som); // Initialised to zero by default
2210
2211 assert(nu_elem.get_md_vector() == domaine.md_vector_elements());
2212 assert(nu_p1.get_md_vector() == dom.md_vector_sommets());
2213 // The virtual space of nu_elem must be up to date.
2214 assert_espace_virtuel_vect(nu_elem);
2215
2216 //Effective computation of "nu_som"
2217
2218 nu_p1=0.;
2219
2220 for (elem=0; elem<nb_elem_tot; elem++)
2221 {
2222 const double nu = nu_elem[elem];
2223 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2224 {
2225 som=elem_som(elem,som_loc);
2226 // Do not compute values for virtual vertices
2227 // note BM: the previous algorithm did not compute those values correctly either
2228 if (som < nb_som)
2229 {
2230 som=dom.get_renum_som_perio(som);
2231 nu_p1(som) += nu;
2232 nb_elem_per_som[som]++;
2233 }
2234 }
2235 }
2236
2237 for (som = 0; som < nb_som; som++)
2238 {
2239 const int som_perio = dom.get_renum_som_perio(som);
2240 int nvoisins = nb_elem_per_som[som_perio];
2241 if (nvoisins > 0)
2242 {
2243 // The first time we encounter this vertex, perform the division.
2244 // This also handles the case where the vertex has no neighbouring elements.
2245 nu_p1(som_perio) /= nvoisins;
2246 nb_elem_per_som[som_perio] = 0;
2247 }
2248 if (som != som_perio)
2249 nu_p1(som) = nu_p1(som_perio);
2250 }
2251 // The previous code apparently did not need virtual space exchange.
2252 // In my opinion (BM) this was a coincidence due to computing with epaisseur2
2253 // (computation on nb_som_tot, so vertices of thickness-1 elements are fine but
2254 // not those of thickness-2 elements)
2255 // I prefer this code: (removing it causes discrepancies in parallel)
2256 nu_p1.echange_espace_virtuel();
2257}
2258
2259//Function that computes the diffusivity at mesh edges
2260//from the element diffusivity
2261//CONSTRAINT: the element diffusivity "nu_elem" must
2262// already have been computed and is treated
2263// as an input parameter
2264//CONSTRAINT: the vertex diffusivity "nu_som" must
2265// already have been SIZED to the correct
2266// size and is treated as an output parameter
2267//CONSTRAINT: the interpolator chosen for computing
2268// "nu_som" is such that for a given vertex s
2269// * L is the list of elements containing vertex s
2270// * the diffusivity at s is the geometric mean
2271// of the "nu_elem" values of L
2273remplir_nu_pA(const DoubleTab& nu_elem,DoubleTab& nu_pA) const
2274{
2275 Cerr << "Op_Diff_VEFP1NCP1B_Face::remplir_nu_pA() not coded" << finl;
2276 Cerr << "Exit" << finl;
2277 exit();
2278}
2279
2280
2281//Build a list associating, for each given face, the neighbouring faces
2282//in the sense of the support of the P1B diffusion operator.
2283//An intermediate list is used that gives, for a given vertex,
2284//the list of faces "seeing" that vertex in the sense of the P1B
2285//diffusion operator.
2286void Op_Diff_VEFP1NCP1B_Face::liste_face(IntLists& liste,int& nnz) const
2287{
2288 const Domaine_VEF& domaine_VEF = domaine_vef();
2289 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
2290 const Domaine& domaine = domaine_VEF.domaine();
2291 const Domaine& dom=domaine;
2292
2293
2294 const IntTab& som_elem=domaine.les_elems();
2295 const IntTab& elem_faces=domaine_VEF.elem_faces();
2296 const IntTab& face_voisins=domaine_VEF.face_voisins();
2297
2298 const int firstFaceInt=domaine_VEF.premiere_face_int();
2299 const int nb_som_tot=dom.nb_som_tot();
2300 const int nb_elem_tot=domaine_VEF.nb_elem_tot();
2301 const int nb_som_elem=domaine.nb_som_elem();
2302 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
2303 const int nb_faces_elem=domaine.nb_faces_elem();
2304 const int nb_bords=domaine_VEF.nb_front_Cl();
2305
2306 int face=0,face2=0;
2307 int face_loc=0;
2308 int elem=0,elem_loc=0;
2309 int som=0,som_loc=0;
2310 int i=0,size=0;
2311 int n_bord=0,ind_face=0;
2312 int num1=0,num2=0;
2313 int tmp=0;
2314
2315 IntTab faces_perio(nb_faces_tot);
2316 ArrOfBit fait(nb_faces_tot);
2317 IntLists sommets_faces(nb_som_tot);
2318
2319 //A second array working on periodic faces must be created;
2320 //otherwise the matrix might not be consistent with the explicit operator
2321 for (face=0; face<nb_faces_tot; face++)
2322 faces_perio(face)=face;
2323
2324 for (n_bord=0; n_bord<nb_bords; n_bord++)
2325 {
2326 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2327 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2328
2329 num1=0;
2330 num2=le_bord.nb_faces_tot();
2331
2332 if (sub_type(Periodique,la_cl.valeur()))
2333 {
2334 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
2335 int faceAss=0;
2336
2337 for (ind_face=num1; ind_face<num2; ind_face++)
2338 {
2339 face=le_bord.num_face(ind_face);
2340 faceAss=la_cl_perio.face_associee(ind_face);
2341 faceAss=le_bord.num_face(faceAss);
2342
2343 // Test to iterate over only half the periodic faces,
2344 // since the following algorithm accounts for this choice.
2345 // NOTE: this test also works in parallel where virtual faces
2346 // are not sorted.
2347 if (face<faceAss)
2348 {
2349 faces_perio(face)=faceAss;
2350 faces_perio(faceAss)=face;
2351 }
2352 }
2353 }
2354 }
2355
2356 //Connectivity related to vertices
2357 for (elem=0; elem<nb_elem_tot; elem++)
2358 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2359 {
2360 som=som_elem(elem,som_loc);
2361 som=dom.get_renum_som_perio(som);
2362
2363 for (face_loc=0; face_loc<nb_faces_elem; face_loc++)
2364 {
2365 face=elem_faces(elem,face_loc);
2366
2367 sommets_faces[som].add(face);
2368 if (faces_perio(face)!=face)
2369 sommets_faces[som].add(faces_perio(face));
2370 }
2371 }
2372
2373 nnz=0;
2374 liste.dimensionner(nb_faces_tot);
2375 //IMPORTANT NOTE: PERIODIC FACES MUST ABSOLUTELY BE FILLED FIRST, OTHERWISE:
2376 //-THE MATRIX WILL NOT BE PERIODIC
2377 //-SOME COEFFICIENTS COULD BE MISSED
2378 for (n_bord=0; n_bord<nb_bords; n_bord++)
2379 {
2380 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2381 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2382
2383 num1=0;
2384 num2=le_bord.nb_faces_tot();
2385
2386 if (sub_type(Periodique,la_cl.valeur()))
2387 {
2388 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
2389 int faceAss=0;
2390
2391 for (ind_face=num1; ind_face<num2; ind_face++)
2392 {
2393 face=le_bord.num_face(ind_face);
2394 faceAss=la_cl_perio.face_associee(ind_face);
2395 faceAss=le_bord.num_face(faceAss);
2396
2397 // Test to iterate over only half the periodic faces,
2398 // since the following algorithm accounts for this choice.
2399 // NOTE: this test also works in parallel where virtual faces
2400 // are not sorted.
2401 if (face<faceAss)
2402 {
2403 //Reset the fait array
2404 fait=0;
2405
2406 //for periodicity
2407 size=liste[face].size();
2408 for (i=0; i<size; i++)
2409 fait.setbit(liste[face][i]);
2410
2411 //So that the first element of the list is "face"
2412 //accounting for periodicity
2413 if (size!=0)
2414 {
2415 tmp=liste[face][0];
2416 liste[face][0]=face;
2417 liste[face].add(tmp);
2418 tmp=liste[faceAss][0];
2419 liste[faceAss][0]=faceAss;
2420 liste[faceAss].add(tmp);
2421 }
2422 else
2423 {
2424 liste[face].add(face);
2425 liste[faceAss].add(faceAss);
2426 }
2427
2428 fait.setbit(face);
2429 fait.setbit(faceAss);
2430 nnz+=2;//because 2 coefficients are added
2431
2432 for (elem_loc=0; elem_loc<2; elem_loc++)
2433 {
2434 elem=face_voisins(face,elem_loc);
2435 assert(elem!=-1);
2436
2437 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2438 {
2439 som=som_elem(elem,som_loc);
2440 som=dom.get_renum_som_perio(som);
2441
2442 size=sommets_faces[som].size();
2443 for (i=0; i<size; i++)
2444 {
2445 face2=sommets_faces[som][i];
2446
2447 if (!fait[face2])
2448 {
2449 fait.setbit(face2);
2450 liste[face].add(face2);
2451 liste[faceAss].add(face2);
2452 liste[face2].add(face);
2453 liste[face2].add(faceAss);
2454 nnz+=4;//because 4 coefficients are added
2455 }
2456
2457 }//end loop over "i"
2458 }//end loop over "som_loc"
2459 }//end loop over "elem_loc"
2460 }//end if on "face<faceAss"
2461 }//end loop over "ind_face"
2462 }//end Periodique
2463 }//end loop over n_bord
2464
2465 //Other boundary conditions
2466 for (n_bord=0; n_bord<nb_bords; n_bord++)
2467 {
2468 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
2469 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2470
2471 num1=0;
2472 num2=le_bord.nb_faces_tot();
2473
2474 if (!sub_type(Periodique,la_cl.valeur()))
2475 for (ind_face=num1; ind_face<num2; ind_face++)
2476 {
2477 face=le_bord.num_face(ind_face);
2478
2479 //Reset the fait array
2480 fait=0;
2481
2482 //for periodicity
2483 size=liste[face].size();
2484 for (i=0; i<size; i++)
2485 fait.setbit(liste[face][i]);
2486
2487 //So that the first element of the list is "face"
2488 //accounting for periodicity
2489 if (size!=0)
2490 {
2491 tmp=liste[face][0];
2492 liste[face][0]=face;
2493 liste[face].add(tmp);
2494 }
2495 else
2496 liste[face].add(face);
2497
2498 fait.setbit(face);
2499 nnz++;
2500
2501 elem=face_voisins(face,0);
2502 assert(elem!=-1);
2503
2504 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2505 {
2506 som=som_elem(elem,som_loc);
2507 som=dom.get_renum_som_perio(som);
2508
2509 size=sommets_faces[som].size();
2510 for (i=0; i<size; i++)
2511 {
2512 face2=sommets_faces[som][i];
2513
2514 if (!fait[face2])
2515 {
2516 fait.setbit(face2);
2517 liste[face].add(face2);
2518 nnz++;
2519 }
2520
2521 }//end loop over "i"
2522 }//end loop over "som_loc"
2523 }//end else on !Periodique
2524 }//end loop over n_bord
2525
2526 for (face=firstFaceInt; face<nb_faces_tot; face++)
2527 if (!domaine_VEF.est_une_face_virt_bord(face))
2528 {
2529 //Reset the fait array
2530 fait=0;
2531
2532 //for periodicity
2533 size=liste[face].size();
2534 for (i=0; i<size; i++)
2535 fait.setbit(liste[face][i]);
2536
2537 //So that the first element of the list is "face"
2538 //accounting for periodicity
2539 if (size!=0)
2540 {
2541 tmp=liste[face][0];
2542 liste[face][0]=face;
2543 liste[face].add(tmp);
2544 }
2545 else
2546 liste[face].add(face);
2547
2548 fait.setbit(face);
2549 nnz++;
2550
2551 for (elem_loc=0; elem_loc<2; elem_loc++)
2552 {
2553 elem=face_voisins(face,elem_loc);
2554
2555 if (elem!=-1) //for internal joint face
2556 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2557 {
2558 som=som_elem(elem,som_loc);
2559 som=dom.get_renum_som_perio(som);
2560
2561 size=sommets_faces[som].size();
2562 for (i=0; i<size; i++)
2563 {
2564 face2=sommets_faces[som][i];
2565
2566 if (!fait[face2])
2567 {
2568 fait.setbit(face2);
2569 liste[face].add(face2);
2570 nnz++;
2571 }
2572
2573 }//end loop over "i"
2574 }//end loop over "som_loc"
2575 }//end loop over "elem_loc"
2576 }//end loop over "face"
2577}
2578
2579//Function that computes, for a given face "face" and a vertex "som"
2580//in the stencil of "face", the gradient associated with "face" at vertex "som"
2581//WARNING: this function must only be used for gradient computation
2582// to fill a COLUMN of the matrix
2583//CONSTRAINT: "face" is the index of the face at which the gradient is to be
2584// computed. Face "face" is an INTERNAL or PERIODIC face.
2585//CONSTRAINT: the vertex "som" parameter is assumed to be the
2586// index of a vertex AFTER periodic renumbering
2587//CONSTRAINT: vertex "som" MUST belong to the stencil of "face"
2588//CONSTRAINT: "elem0" and "elem1" are the indices of elements
2589// containing both "face" AND "som". If one element index
2590// is -1, then "face" and "som" do not belong to the same element.
2591// NOTE: elem0 is always assumed to be different from -1.
2592//CONSTRAINT: "som_loc0" and "som_loc1" are the local indices
2593// of "som_glob" in "elem0" and "elem1" respectively.
2594// If one element is -1, the corresponding local vertex index is -1.
2595//CONSTRAINT: the output parameter "grad" containing the evaluation
2596// of the gradient associated with "face" at vertex "som" is
2597// assumed to be CORRECTLY sized BEFORE calling this function
2599gradient_som(const int face,const int som_glob,
2600 const int elem0, const int som_loc0,
2601 const int elem1, const int som_loc1,
2602 DoubleTab& grad) const
2603{
2604 const Domaine_VEF& domaine_VEF = domaine_vef();
2605
2606 const DoubleTab& face_normales=domaine_VEF.face_normales();
2607 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2608
2609 const IntTab& elem_faces=domaine_VEF.elem_faces();
2610 const IntTab& face_voisins=domaine_VEF.face_voisins();
2611
2612 const double coeff=1./dimension;
2613 const double coeff_som=coeff/(dimension+1);
2614
2615 int face_opp=0,compj=0;
2616 int elem=0;
2617 double signe=0.;
2618
2619 assert(grad.nb_dim()==1);
2620
2621 //
2622 //Gradient computation
2623 //
2624
2625 /* Look at the first neighbouring element */
2626 assert(elem0!=-1);
2627 assert(som_loc0!=-1);
2628
2629 //Compute the local gradient
2630 face_opp = elem_faces(elem0,som_loc0);
2631 signe=1.;
2632 if(elem0!=face_voisins(face_opp,0)) signe=-1.;
2633
2634 for(compj=0; compj<dimension; compj++)
2635 grad(compj)=coeff_som*signe*
2636 face_normales(face_opp,compj);
2637
2638 /* Look at the second neighbouring element */
2639 if (elem1==-1)
2640 {
2641 /* Several possibilities:
2642 - "face" is a real internal face
2643 - "face" is a virtual internal face
2644 - "face" is a real boundary face
2645 - "face" is a virtual boundary face
2646 - "face" is a joint face */
2647 assert(som_loc1==-1);
2648 elem=face_voisins(face,1);
2649 assert(face_voisins(face,0)!=-1);
2650
2651 /* "face" is a boundary face */
2652 if (elem==-1 && face_opp!=face)
2653 for (compj=0; compj<dimension; compj++)
2654 grad(compj)+=coeff*face_normales(face,compj) ;
2655 }
2656 else
2657 {
2658 assert(som_loc1!=-1);
2659 face_opp=elem_faces(elem1,som_loc1);
2660 signe=1.;
2661 if(elem1!=face_voisins(face_opp,0)) signe=-1.;
2662
2663 //Compute the local gradient
2664 for(compj=0; compj<dimension; compj++)
2665 grad(compj)+=coeff_som*signe*
2666 face_normales(face_opp,compj);
2667 }
2668
2669 grad/=(coeff_*volume_aux_sommets(som_glob));
2670}
2671
2672//For a given face, compute the gradient associated with that face
2673//for each vertex where the gradient is nonzero.
2674//WARNING: this function must only be used to compute
2675// gradients when filling a LINE of the matrix.
2676//CONSTRAINT: the array "grad" must be correctly
2677// dimensioned BEFORE calling this function.
2678//INPUT : "face" is the global index of the INTERNAL
2679// or PERIODIC face whose gradient is to be computed.
2680//OUTPUT: "som_glob" is a list containing all vertices
2681// included in the stencil of "face".
2682//OUTPUT: "nnz" is the number of vertices included in the stencil
2683// of face.
2685gradient_som(const int face,int& nnz, IntVect& som_glob,DoubleTab& grad) const
2686{
2687 const Domaine_VEF& domaine_VEF=domaine_vef();
2688 const Domaine& domaine=domaine_VEF.domaine();
2689 const Domaine& dom=domaine;
2690
2691 const DoubleTab& face_normales=domaine_VEF.face_normales();
2692 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2693
2694 const IntTab& elem_faces=domaine_VEF.elem_faces();
2695 const IntTab& face_voisins=domaine_VEF.face_voisins();
2696 const IntTab& elem_som=domaine.les_elems();
2697
2698 const double coeff=1./dimension;
2699 const double coeff_som=coeff/(dimension+1);
2700
2701 const int nb_som_elem=domaine.nb_som_elem();
2702
2703 int face_opp=0,compj=0;
2704 int som_loc=0,som=0;
2705 int loc=0;
2706 int elem=0;
2707
2708 double signe=0.;
2709 double volume=0.;
2710
2711 assert(som_glob.size()==dimension+2);
2712 assert(grad.nb_dim()==2);
2713 assert(grad.dimension(1)==dimension+2);
2714
2715 //
2716 //Gradient computation
2717 //
2718
2719 nnz=0;
2720 /* Look at the first neighbouring element */
2721 elem=face_voisins(face,0);
2722 assert(elem!=-1);
2723
2724 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2725 {
2726 som=elem_som(elem,som_loc);
2727 som=dom.get_renum_som_perio(som);
2728
2729 face_opp=elem_faces(elem,som_loc);
2730 signe=1.;
2731 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2732
2733 //Add to the list and increment the counter
2734 som_glob(som_loc)=som;
2735 nnz++;
2736
2737 //Compute the local gradient
2738 for(compj=0; compj<dimension; compj++)
2739 grad(compj,som_loc)=coeff_som*signe*
2740 face_normales(face_opp,compj);
2741 }
2742 assert(nnz==nb_som_elem);
2743
2744 /* Look at the second neighbouring element */
2745 elem=face_voisins(face,1);
2746 assert(elem!=-1);
2747
2748 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2749 {
2750 som=elem_som(elem,som_loc);
2751 som=dom.get_renum_som_perio(som);
2752
2753 face_opp=elem_faces(elem,som_loc);
2754 signe=1.;
2755 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2756
2757 //Locate in the already-built list
2758 for (loc=0; loc<nnz; loc++)
2759 if (som_glob[loc]==som)
2760 break;
2761
2762 //Add to the list and increment the counter
2763 if (loc==nnz)
2764 {
2765 som_glob(nnz)=som;
2766 nnz++;
2767 }
2768
2769 //Compute the local gradient
2770 for(compj=0; compj<dimension; compj++)
2771 grad(compj,loc)+=coeff_som*signe*
2772 face_normales(face_opp,compj);
2773 }
2774 assert(nnz<=(dimension+2));
2775
2776 for (som_loc=0; som_loc<nnz; som_loc++)
2777 {
2778 som=som_glob(som_loc);
2779 volume=coeff_*volume_aux_sommets(som);
2780
2781 //Divide by the lumped mass matrix
2782 for(compj=0; compj<dimension; compj++)
2783 grad(compj,som_loc)/=volume;
2784 }
2785}
2786
2787//For a given face, compute the gradient associated with that face
2788//for each vertex where the gradient is nonzero.
2789//WARNING: this function must only be used to compute
2790// gradients when filling a LINE of the matrix.
2791//CONSTRAINT: the array "grad" must be correctly
2792// dimensioned BEFORE calling this function.
2793//INPUT : "face" is the global index of the NON-PERIODIC
2794// BOUNDARY face whose gradient is to be computed.
2795//OUTPUT: "som_glob" is a list containing all vertices
2796// included in the stencil of "face".
2797//OUTPUT: "nnz" is the number of vertices included in the stencil
2798// of face.
2800gradient_som_CL(const int face,int& nnz, IntVect& som_glob,DoubleTab& grad) const
2801{
2802 const Domaine_VEF& domaine_VEF=domaine_vef();
2803 const Domaine& domaine=domaine_VEF.domaine();
2804 const Domaine& dom=domaine;
2805
2806 const DoubleTab& face_normales=domaine_VEF.face_normales();
2807 const DoubleVect& volume_aux_sommets=domaine_VEF.volume_aux_sommets();
2808
2809 const IntTab& elem_faces=domaine_VEF.elem_faces();
2810 const IntTab& face_voisins=domaine_VEF.face_voisins();
2811 const IntTab& elem_som=domaine.les_elems();
2812 const IntTab& face_sommets=domaine_VEF.face_sommets();
2813
2814 const double coeff=1./dimension;
2815 const double coeff_som=coeff/(dimension+1);
2816
2817 const int nb_som_elem=domaine.nb_som_elem();
2818 const int nb_som_face=domaine_VEF.nb_som_face();
2819
2820 int face_opp=0,compj=0;
2821 int som_loc=0,som=0;
2822 int loc=0;
2823 int elem=0;
2824
2825 double signe=0.;
2826 double volume=0.;
2827
2828 assert(som_glob.size()==dimension+2);
2829 assert(grad.nb_dim()==2);
2830 assert(grad.dimension(1)==dimension+2);
2831
2832 //
2833 //Gradient computation
2834 //
2835
2836 nnz=0;
2837 /* Look at the first neighbouring element */
2838 elem=face_voisins(face,0);
2839 assert(elem!=-1);
2840
2841 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2842 {
2843 som=elem_som(elem,som_loc);
2844 som=dom.get_renum_som_perio(som);
2845
2846 face_opp=elem_faces(elem,som_loc);
2847 signe=1.;
2848 if(elem!=face_voisins(face_opp,0)) signe=-1.;
2849
2850 //Add to the list and increment the counter
2851 som_glob(som_loc)=som;
2852 nnz++;
2853
2854 //Compute the local gradient
2855 for(compj=0; compj<dimension; compj++)
2856 grad(compj,som_loc)=coeff_som*signe*
2857 face_normales(face_opp,compj);
2858 }
2859 assert(nnz==nb_som_elem);
2860
2861 /* Look at the second neighbouring element */
2862 assert(face_voisins(face,1)==-1);
2863
2864 for (som_loc=0; som_loc<nb_som_face; som_loc++) //vertices of "face"
2865 {
2866 som=face_sommets(face,som_loc);
2867 som=dom.get_renum_som_perio(som);
2868
2869 for (loc=0; loc<nnz; loc++)
2870 if (som_glob(loc)==som)
2871 break;
2872 assert(som_loc<nnz);
2873
2874 for (compj=0; compj<dimension; compj++)
2875 grad(compj,loc)+=coeff*face_normales(face,compj) ;
2876 }
2877 assert(nnz<=(dimension+2));
2878
2879 for (som_loc=0; som_loc<nnz; som_loc++)
2880 {
2881 som=som_glob(som_loc);
2882 volume=coeff_*volume_aux_sommets(som);
2883
2884 //Divide by the lumped mass matrix
2885 for(compj=0; compj<dimension; compj++)
2886 grad(compj,som_loc)/=volume;
2887 }
2888}
2889
2890
2891//Function checking whether "som_glob" is in the stencil of "face".
2892//CONSTRAINT: "som_glob" MUST be a PERIODIC vertex index.
2893//OUTPUT: the indices of the elements in the stencil of "face" that contain
2894// vertex "som_glob". If the vertex is not contained
2895// in one of the stencil elements of "face", the index of
2896// that element is set to -1.
2897//OUTPUT: som_loc0 and som_loc1 are the local indices of som_glob
2898// in elem0 and elem1 respectively.
2899// If the vertex is not contained in one of the stencil elements of "face",
2900// the corresponding local vertex index is set to -1.
2901void Op_Diff_VEFP1NCP1B_Face::isInStencil(int face,int som_glob,
2902 int& elem0, int& som_loc0,
2903 int& elem1, int& som_loc1) const
2904{
2905 const Domaine_VEF& domaine_VEF=domaine_vef();
2906 const Domaine& domaine=domaine_VEF.domaine();
2907 const Domaine& dom=domaine;
2908
2909 const IntTab& face_voisins=domaine_VEF.face_voisins();
2910 const IntTab& elem_som=domaine.les_elems();
2911
2912 const int nb_som_elem=domaine.nb_som_elem();
2913
2914 int elem00=0,elem11=0;
2915 int som_loc=0,som=0;
2916
2917 elem00=face_voisins(face,0);
2918 assert(elem00!=-1);
2919
2920 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2921 {
2922 som=elem_som(elem00,som_loc);
2923 som=dom.get_renum_som_perio(som);
2924
2925 if (som_glob==som)
2926 {
2927 som_loc0=som_loc;
2928 elem0=elem00;
2929 break;
2930 }
2931 }
2932 if (som_loc==nb_som_elem)
2933 {
2934 elem0=-1;
2935 som_loc0=-1;
2936 }
2937
2938 elem11=face_voisins(face,1);
2939 if (elem11==-1)
2940 {
2941 elem1=-1;
2942 som_loc1=-1;
2943 }
2944 else
2945 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
2946 {
2947 som=elem_som(elem11,som_loc);
2948 som=dom.get_renum_som_perio(som);
2949
2950 if (som_glob==som)
2951 {
2952 som_loc1=som_loc;
2953 elem1=elem11;
2954 break;
2955 }
2956 }
2957 if (som_loc==nb_som_elem)
2958 {
2959 elem1=-1;
2960 som_loc1=-1;
2961 }
2962
2963 //Sort the output
2964 if (elem0==-1 && elem1!=-1)
2965 {
2966 elem0=elem1;
2967 elem1=-1;
2968 som_loc0=som_loc1;
2969 som_loc1=-1;
2970 }
2971}
2972
2974{
2975 const Domaine_VEF& domaine_VEF = domaine_vef();
2976
2977 const int nb_faces_tot=domaine_VEF.nb_faces_tot();
2978 const int nb_comp = inconnue_->valeurs().line_size();
2979
2980 int face=0;
2981 int i=0,size=0;
2982 int comp=0,nnz=0,face_f77=0,face_C=0;
2983 int nb_faces_of_symetry=0;
2984 int next=0;
2985
2986 ArrOfBit is_symetry(nb_faces_tot);
2987
2988 auto& tab1 = matrice.get_set_tab1();
2989 auto& tab2 = matrice.get_set_tab2();
2990
2991 IntLists faces_faces;
2992
2993 if (alphaE && !alphaS && !alphaA)
2994 Op_VEF_Face::dimensionner(le_dom_vef.valeur(), la_zcl_vef.valeur(), matrice);
2995
2996 if (alphaS)
2997 {
2998 //Compute the face list
2999 liste_face(faces_faces,nnz);
3000 isFaceOfSymetry(is_symetry,nb_faces_of_symetry);
3001
3002 //Size the matrix arrays
3003 //NOTE: by construction, this sizing will always be LARGER
3004 //than the default sizing from OP_VEF_FACE.
3005 //NOTE: to account for constraints due to symmetry faces,
3006 //the matrix sizing must be slightly enlarged.
3007 size=nnz*nb_comp;//sizing without symmetry faces
3008 // size+=nb_faces_of_symetry*(nb_comp-1)*nb_comp;//sizing with symmetry faces
3009 // for each symmetry face, for each component, add nb_comp coefficients for each linked face
3010 for (face=0; face<nb_faces_tot; face++)
3011 if (is_symetry[face])
3012 {
3013 int nb_v=faces_faces[face].size();
3014 size+=nb_v*(nb_comp-1)*nb_comp;
3015 }
3016
3017 matrice.dimensionner(nb_faces_tot*nb_comp,size);
3018
3019 //Initialise the known values for tab1
3020 tab1[nb_faces_tot*nb_comp]=size+1;
3021 tab1[0]=1;
3022
3023 //Fill tab1
3024
3025 /* for the other components of face 0 */
3026 size=faces_faces[0].size();
3027 if (is_symetry[0]) size*=(nb_comp);
3028 for (comp=1; comp<nb_comp; comp++)
3029 {
3030 face_C=comp;
3031 tab1[face_C]=tab1[face_C-1]+size;
3032 }
3033
3034 /* for the other faces */
3035 for (face=1; face<nb_faces_tot; face++)
3036 {
3037 size=faces_faces[face-1].size();
3038 if (is_symetry[face-1]) size*=(nb_comp);
3039 for (comp=0; comp<nb_comp; comp++)
3040 {
3041 face_C=face*nb_comp+comp;
3042 tab1[face_C]=tab1[face_C-1]+size;
3043 size=faces_faces[face].size();
3044 if (is_symetry[face]) size*=(nb_comp);
3045 }
3046 }
3047
3048 //Fill tab2
3049 for (face=0; face<nb_faces_tot; face++)
3050 {
3051 size=faces_faces[face].size();
3052
3053 for (comp=0; comp<nb_comp; comp++)
3054 {
3055 auto debut=tab1[face*nb_comp+comp]-1;
3056
3057 for (i=0; i<size; i++)
3058 {
3059 face_C=faces_faces[face][i]*nb_comp+comp;
3060 face_f77=face_C+1;
3061 tab2[debut+i]=face_f77;
3062 }//end loop over "i"
3063
3064 }//end loop over "comp"
3065
3066 }//end loop over "face"
3067
3068 for (face=0; face<nb_faces_tot; face++)
3069 if (is_symetry[face])
3070 {
3071 size=faces_faces[face].size();
3072
3073 for (comp=0; comp<nb_comp; comp++)
3074 {
3075 auto debut=tab1[face*nb_comp+comp]-1;
3076 debut+=size;
3077 for (int voi=0; voi<size; voi++)
3078 {
3079 int face2=faces_faces[face][voi];
3080 for (i=0; i<nb_comp-1; i++)
3081 {
3082 //remainder of the integer division
3083 next=(comp+i+1)%nb_comp;
3084 face_C=face2*nb_comp+next;
3085 face_f77=face_C+1;
3086 tab2[debut+i]=face_f77;
3087 // Cerr <<face*nb_comp+comp<<" face "<<face << " comp "<< comp<< " face2 "<< face2 << " comp "<<next <<" jface2 "<< face_C<<finl;
3088 assert(debut+i<tab1[face*nb_comp+comp+1]-1);
3089 }
3090 debut+=nb_comp-1;
3091 }
3092
3093 }//end loop over "comp"
3094
3095 }//end loop over "face"
3096
3097 }//end if on "alphaS"
3098
3099 if (alphaA)
3100 {
3101 Cerr << "Error in Op_Dift_VEFP1NCP1B_Face::dimensionner(Matrice_Morse&)" << finl;
3102 Cerr << "Sizing of the implicit matrix with the alphaA option"
3103 << " is not yet implemented" << finl;
3104 Cerr << "Exiting program" << finl;
3105 exit();
3106 }
3107}
3108
3109//Function that initialises the is_symetry array passed as argument:
3110//-if a face "f" is a symmetry face then is_symetry(f)=1
3111//-if a face "f" is not a symmetry face then is_symetry(f)=0
3112//The function also returns the total number of symmetry faces (argument nnz).
3113//NOTE: the array "is_symetry" must be dimensioned to nb_faces_tot
3114//BEFORE calling this function.
3115void Op_Diff_VEFP1NCP1B_Face::isFaceOfSymetry(ArrOfBit& is_symetry,int& nnz) const
3116{
3117 const Domaine_VEF& domaine_VEF=domaine_vef();
3118 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
3119
3120 const int nb_bords=domaine_VEF.nb_front_Cl();
3121
3122 int n_bord=0;
3123 int num1=0,num2=0;
3124 int ind_face=0;
3125
3126 assert(is_symetry.size_array()==domaine_VEF.nb_faces_tot());
3127
3128 //Pre-initialisation
3129 nnz=0;
3130 is_symetry=0;
3131
3132 //Modification for symmetry faces
3133 for (n_bord=0; n_bord<nb_bords; n_bord++)
3134 {
3135 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3136 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3137
3138 num1=0;
3139 num2=le_bord.nb_faces_tot();
3140
3141 if (sub_type(Symetrie,la_cl.valeur()))
3142 {
3143 nnz+=num2;
3144
3145 for (ind_face=num1; ind_face<num2; ind_face++)
3146 is_symetry.setbit(le_bord.num_face(ind_face));
3147 }
3148 }
3149}
3150
3151
3152
3153//////////////////////////////////////////////////////////
3154//Test functions
3155/////////////////////////////////////////////////////////
3156
3158{
3159 const Domaine_VEF& domaine_VEF=domaine_vef();
3160 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
3161 const Domaine& domaine = domaine_VEF.domaine();
3162 const Domaine& dom=domaine;
3163
3164 const Solveur_Masse_base& solveur_masse=equation().solv_masse();
3165
3166 const int nb_bords=domaine_VEF.nb_front_Cl();
3167 const int firstFaceInt=domaine_VEF.premiere_face_int();
3168 const int nb_som_tot=dom.nb_som_tot();
3169
3170 const DoubleTab& unknown = equation().inconnue().valeurs();
3171 const DoubleTab& xv=domaine_VEF.xv();
3172 const DoubleTab& xs=dom.les_sommets();
3173
3174 DoubleTab inco(unknown);
3175 DoubleVect& incoV = inco;
3176 incoV=0.;
3177
3178 //DoubleTab tmp(inco);
3179
3180 DoubleTab resu(unknown);
3181 DoubleVect& resuV = resu;
3182 DoubleTab resuMat(unknown);
3183 const DoubleVect& resuMatV = resuMat;
3184 DoubleTab gradientMat(dimension,dimension+2);
3185
3186
3187 IntVect som_glob(dimension+2);
3188
3189 //Flag to account for porosity
3190 const int marq=phi_psi_diffuse(equation());
3191
3192 //Lines to account for porosity
3193 const DoubleVect& poroE=equation().milieu().porosite_elem();
3194 DoubleVect poroF(equation().milieu().porosite_face());
3195 if (!marq) poroF=1.;
3196
3197 //Lines to account for diffusivity
3198 DoubleTab nu;
3199 remplir_nu(nu_);
3200 modif_par_porosite_si_flag(nu_,nu,!marq,poroE);
3201
3202 DoubleTab nu_p1;
3203 dom.creer_tableau_sommets(nu_p1);
3204 remplir_nu_p1(nu,nu_p1);
3205
3206 //Various useful variables
3207 int face=0;
3208 int faceAss=0;
3209 int comp=0;
3210 int size0=domaine_VEF.nb_faces();
3211 int i=0,j=0;
3212 int nnz=0;
3213 int compi=0,compj=0;
3214 int som=0;
3215 int n_bord=0;
3216 int num1=0,num2=0,ind_face=0;
3217 int ii=0;
3218
3219 int size1 = unknown.line_size();
3220
3221 Matrice_Morse matrice;
3222 dimensionner(matrice);
3223 if (alphaS) ajouter_contribution_som(inco,poroF,nu_p1,matrice);
3224 else if (alphaE) ajouter_contribution_elem(inco,poroF,nu,matrice);
3225
3226 bool test1=false;
3227 double max=0.;
3228
3229 DoubleTab gradient1(dimension);
3230
3231 Motcle type;
3233 type="_PAR";
3234 else
3235 type="_SEQ";
3236
3237 Motcles les_mots(8);
3238 {
3239 les_mots[0] = "matrice";
3240 les_mots[1] = "result";
3241 les_mots[2] = "res";
3242 les_mots[3] = "resMat";
3243 les_mots[4] = "grad";
3244 les_mots[5] = "gradMat";
3245 les_mots[6] = "div";
3246 les_mots[7] = "ligne_mat";
3247 }
3248 Motcle proc(Process::me());
3249 proc+=".txt";
3250
3251 for (i=0; i<les_mots.size(); i++)
3252 {
3253 les_mots[i]+=type;
3254 les_mots[i]+=proc;
3255 }
3256
3257 ofstream mat(les_mots[0].getChar());
3258 const Matrice_Morse& matConst=matrice;
3259 for (i=0; i<domaine_VEF.nb_faces(); i++)
3260 {
3261 for (j=0; j<matConst.nb_colonnes(); j++)
3262 mat<<matConst(i,j)<<",";
3263 mat<<endl;
3264 }
3265
3266 double coeff_diag=0.;
3267 double sum_coeff_extra_diag=0.;
3268 ofstream ligneMat(les_mots[7].getChar());
3269 for (i=0; i<matConst.nb_lignes(); i++)
3270 {
3271 coeff_diag=matConst(i,i);
3272 ligneMat<<"Ligne : "<<i<<endl;
3273 ligneMat<<"Coeff diag : "<<coeff_diag<<endl;
3274
3275 ligneMat<<"Coeff extra diag : ";
3276 sum_coeff_extra_diag=0.;
3277 for (j=0; j<matConst.nb_colonnes(); j++)
3278 if (j!=i) sum_coeff_extra_diag+=matConst(i,j);
3279 ligneMat<<sum_coeff_extra_diag<<endl;
3280
3281 ligneMat<<"Coeff extra diag par colonne : ";
3282 sum_coeff_extra_diag=0.;
3283 for (j=0; j<matConst.nb_colonnes(); j++)
3284 if (j!=i) sum_coeff_extra_diag+=matConst(j,i);
3285 ligneMat<<sum_coeff_extra_diag<<endl;
3286 }
3287
3288
3289 Motcle gradi("grad1");
3290 gradi+=type;
3291 gradi+=proc;
3292 int elem=0;
3293 int elem0=0,elem1=0;
3294 int som_loc0=1,som_loc1=1;
3295 int som_loc=0;
3296 const int nb_som_elem=domaine.nb_som_elem();
3297 const IntTab& face_voisins=domaine_VEF.face_voisins();
3298 const IntTab& elem_som=domaine.les_elems();
3299 ofstream grad1(gradi.getChar());
3300 for (face=0; face<size0; face++)
3301 {
3302 grad1<<"Face : "<<face<<endl;
3303 grad1<<"(";
3304 for (i=0; i<dimension; i++)
3305 grad1<<xv(face,i)<<",";
3306 grad1<<")"<<endl;
3307
3308 for (ii=0; ii<2; ii++)
3309 {
3310 elem=face_voisins(face,ii);
3311 if (elem!=-1)
3312 for (som_loc=0; som_loc<nb_som_elem; som_loc++)
3313 {
3314 som=elem_som(elem,som_loc);
3315 som=dom.get_renum_som_perio(som);
3316 isInStencil(face,som,elem0,som_loc0,elem1,som_loc1);
3317
3318 gradient1=0.;
3319 gradient_som(face,som,elem0,som_loc0,
3320 elem1,som_loc1,gradient1);
3321
3322 grad1<<som<<"(";
3323 for (i=0; i<dimension; i++)
3324 grad1<<xs(som,i)<<",";
3325 grad1<<"):(";
3326 for (compj=0; compj<dimension; compj++)
3327 grad1<<gradient1(compj)<<",";
3328 grad1<<")"<<endl;
3329 }
3330 }
3331 }
3332
3333 ofstream result(les_mots[1].getChar());
3334 ofstream res(les_mots[2].getChar());
3335 ofstream resMat(les_mots[3].getChar());
3336 ofstream grad(les_mots[4].getChar());
3337 ofstream gradMat(les_mots[5].getChar());
3338 ofstream div(les_mots[6].getChar());
3339
3340 for (face=firstFaceInt; face<size0; face++)
3341 {
3342 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3344
3345 //Version explicite
3346 gradient_p1_=0.;
3348
3349 //Check the gradients
3350 grad<<"Face interne : "<<face*size1+comp<<endl;
3351 grad<<"(";
3352 for (i=0; i<dimension; i++)
3353 grad<<xv(face,i)<<",";
3354 grad<<")"<<endl;
3355 for (som=0; som<nb_som_tot; som++)
3356 {
3357 grad <<som<<"(";
3358 for (i=0; i<dimension; i++)
3359 grad<<xs(som,i)<<",";
3360 grad<<"):(";
3361 for (compi=0; compi<dim_ch_; compi++)
3362 for (compj=0; compj<dimension; compj++)
3363 grad<<gradient_p1_(som,compi,compj)<<",";
3364 grad<<")"<<endl;
3365 }
3366
3367 gradientMat=0.;
3368 som_glob=-1;
3369 gradient_som(face,nnz,som_glob,gradientMat);
3370
3371 gradMat<<"Face interne : "<<face*size1+comp<<endl;
3372 gradMat<<"(";
3373 for (i=0; i<dimension; i++)
3374 gradMat<<xv(face,i)<<",";
3375 gradMat<<")"<<endl;
3376 for (i=0; i<nnz; i++)
3377 {
3378 gradMat<<som_glob[i]<<"(";
3379 for (ii=0; ii<dimension; ii++)
3380 gradMat<<xs(som_glob[i],ii)<<",";
3381 gradMat<<"):(";
3382 for (compj=0; compj<dimension; compj++)
3383 gradMat<<gradientMat(compj,i)<<",";
3384 gradMat<<")"<<endl;
3385 }
3386
3387 resu=0.;
3389 corriger_Cl_test(resu);
3390 solveur_masse.appliquer(resu);
3391 div<<"Face interne : "<<face*size1+comp<<endl;
3392 div<<"(";
3393 for (i=0; i<dimension; i++)
3394 div<<xv(face,i)<<",";
3395 div<<")"<<endl;
3396 for (i=0; i<size0; i++)
3397 {
3398 div<<i<<"(";
3399 for (ii=0; ii<dimension; ii++)
3400 div<<xv(i,ii)<<",";
3401 div<<"):=(";
3402 for (j=0; j<size1; j++)
3403 div<<resu[i*size1+j]<<",";
3404 div<<")"<<endl;
3405 }
3406
3407 resu*=-1.;
3408 res<<"Face interne : "<<face*size1+comp<<endl;
3409 res<<"(";
3410 for (i=0; i<dimension; i++)
3411 res<<xv(face,i)<<",";
3412 res<<")"<<endl;
3413 for (i=0; i<size0; i++)
3414 {
3415 res<<i<<"(";
3416 for (ii=0; ii<dimension; ii++)
3417 res<<xv(i,ii)<<",";
3418 res<<"):=(";
3419 for (j=0; j<size1; j++)
3420 res<<resu[i*size1+j]<<",";
3421 res<<")"<<endl;
3422 }
3423
3424 //Version matricielle
3425 resuMat=0.;
3426 matrice.ajouter_multTab_(inco,resuMat);
3427 solveur_masse.appliquer(resuMat);
3428 resuMat.echange_espace_virtuel();
3429 resMat<<"Face interne :"<<face*size1+comp<<endl;
3430 resMat<<"(";
3431 for (i=0; i<dimension; i++)
3432 resMat<<xv(face,i)<<",";
3433 resMat<<")"<<endl;
3434 for (i=0; i<size0; i++)
3435 {
3436 resMat<<i<<"(";
3437 for (ii=0; ii<dimension; ii++)
3438 resMat<<xv(i,ii)<<",";
3439 resMat<<"):=(";
3440 for (j=0; j<size1; j++)
3441 resMat<<resuMatV[i*size1+j]<<",";
3442 resMat<<")"<<endl;
3443 }
3444
3445 //Difference between the results
3446 resu-=resuMat;
3447
3448 //Display of differences
3449 max=resu.local_max_abs_vect();
3450 if (max>1.e-14)
3451 {
3452 result<<"Diff pour face interne : "<<face*size1+comp<<endl;
3453 result<<"(";
3454 for (i=0; i<dimension; i++)
3455 result<<xv(face,i)<<",";
3456 result<<")"<<endl;
3457 for (i=0; i<size0; i++)
3458 {
3459 test1=false;
3460 for (j=0; j<size1; j++)
3461 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3462
3463 if (test1)
3464 {
3465 result<<i<<"(";
3466 for (ii=0; ii<dimension; ii++)
3467 result<<xv(i,ii)<<",";
3468 result<<"):=(";
3469 for (j=0; j<size1; j++)
3470 result <<resuV[i*size1+j]<<",";
3471 result <<")"<<endl;
3472 }
3473 }
3474 }
3475 else
3476 {
3477 result<<"Diff pour face interne : "<<face*size1+comp<<endl;
3478 result<<"Maximum : "<<max<<endl;
3479 }
3480
3481 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3483 }
3484
3485
3486 for (n_bord=0; n_bord<nb_bords; n_bord++)
3487 {
3488 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3489 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3490
3491 num1=0;
3492 num2=le_bord.nb_faces_tot();
3493
3494 //Modification to account for Dirichlet boundary conditions
3495 //-> the mass matrix must zero everything out
3496 if (sub_type(Dirichlet_homogene,la_cl.valeur()))
3497 {
3498 //Testing is pointless in this case
3499 }
3500
3501 else if (sub_type(Dirichlet,la_cl.valeur()))
3502 for (ind_face=num1; ind_face<num2; ind_face++)
3503 {
3504 face=le_bord.num_face(ind_face);
3505
3506 //Version explicite
3507 gradient_p1_=0.;
3509
3510 //Check the gradients
3511 grad<<"Face Dirichlet : "<<face*size1+comp<<endl;
3512 grad<<"(";
3513 for (i=0; i<dimension; i++)
3514 grad<<xv(face,i)<<",";
3515 grad<<")"<<endl;
3516 for (som=0; som<nb_som_tot; som++)
3517 {
3518 grad <<som<<"(";
3519 for (i=0; i<dimension; i++)
3520 grad<<xs(som,i)<<",";
3521 grad<<"):(";
3522 for (compi=0; compi<dim_ch_; compi++)
3523 for (compj=0; compj<dimension; compj++)
3524 grad<<gradient_p1_(som,compi,compj)<<",";
3525 grad<<")"<<endl;
3526 }
3527
3528 gradientMat=0.;
3529 som_glob=-1;
3530 gradient_som_CL(face,nnz,som_glob,gradientMat);
3531
3532 gradMat<<"Face Dirichlet : "<<face*size1+comp<<endl;
3533 gradMat<<"(";
3534 for (i=0; i<dimension; i++)
3535 gradMat<<xv(face,i)<<",";
3536 gradMat<<")"<<endl;
3537 for (i=0; i<nnz; i++)
3538 {
3539 gradMat<<som_glob[i]<<"(";
3540 for (ii=0; ii<dimension; ii++)
3541 gradMat<<xs(som_glob[i],ii)<<",";
3542 gradMat<<"):(";
3543 for (compj=0; compj<dimension; compj++)
3544 gradMat<<gradientMat(compj,i)<<",";
3545 gradMat<<")"<<endl;
3546 }
3547
3548 for (i=0; i<size0; i++)
3549 for (j=0; j<size1; j++)
3550 resuV[i*size1+j]=0.;
3551 }
3552
3553 else if (sub_type(Periodique,la_cl.valeur()))
3554 {
3555 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
3556
3557 assert(num2%2==0);
3558 for (ind_face=num1; ind_face<num2; ind_face++)
3559 {
3560 face=le_bord.num_face(ind_face);
3561 faceAss=le_bord.num_face(la_cl_perio.face_associee(ind_face));
3562
3563 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3564 if (Process::je_suis_maitre()) incoV[faceAss*size1+comp]=1.;
3566
3567 //Version explicite
3568 gradient_p1_=0.;
3570
3571 //Check the gradients
3572 grad <<"Face perio : "<<face*size1+comp<<endl;
3573 grad<<"(";
3574 for (i=0; i<dimension; i++)
3575 grad<<xv(face,i)<<",";
3576 grad<<")"<<endl;
3577 for (som=0; som<nb_som_tot; som++)
3578 {
3579 grad <<som<<"(";
3580 for (i=0; i<dimension; i++)
3581 grad<<xs(som,i)<<",";
3582 grad<<"):(";
3583 for (compi=0; compi<dim_ch_; compi++)
3584 for (compj=0; compj<dimension; compj++)
3585 grad<<gradient_p1_(som,compi,compj)<<",";
3586 grad<<")"<<endl;
3587 }
3588
3589 gradientMat=0.;
3590 som_glob=-1;
3591 gradient_som(face,nnz,som_glob,gradientMat);
3592
3593 gradMat<<"Face perio : "<<face*size1+comp<<endl;
3594 gradMat<<"(";
3595 for (i=0; i<dimension; i++)
3596 gradMat<<xv(face,i)<<",";
3597 gradMat<<")"<<endl;
3598 for (i=0; i<nnz; i++)
3599 {
3600 gradMat<<som_glob[i]<<"(";
3601 for (ii=0; ii<dimension; ii++)
3602 gradMat<<xs(som_glob[i],ii)<<",";
3603 gradMat<<"):(";
3604 for (compj=0; compj<dimension; compj++)
3605 gradMat<<gradientMat(compj,i)<<",";
3606 gradMat<<")"<<endl;
3607 }
3608
3609 resu=0.;
3611 corriger_Cl_test(resu);
3612 solveur_masse.appliquer(resu);
3613 div<<"Face perio : "<<face*size1+comp<<endl;
3614 div<<"(";
3615 for (i=0; i<dimension; i++)
3616 div<<xv(face,i)<<",";
3617 div<<")"<<endl;
3618 for (i=0; i<size0; i++)
3619 {
3620 div<<i<<"(";
3621 for (ii=0; ii<dimension; ii++)
3622 div<<xv(i,ii)<<",";
3623 div<<"):=(";
3624 for (j=0; j<size1; j++)
3625 div<<resu[i*size1+j]<<",";
3626 div<<")"<<endl;
3627 }
3628
3629 resu*=-1.;
3630 res<<"Face perio : "<<face*size1+comp<<endl;
3631 res<<"(";
3632 for (i=0; i<dimension; i++)
3633 res<<xv(face,i)<<",";
3634 res<<")"<<endl;
3635 for (i=0; i<size0; i++)
3636 {
3637 res<<i<<"(";
3638 for (ii=0; ii<dimension; ii++)
3639 res<<xv(i,ii)<<",";
3640 res<<"):=(";
3641 for (j=0; j<size1; j++)
3642 res<<resu[i*size1+j]<<",";
3643 res<<")"<<endl;
3644 }
3645
3646 //Version matricielle
3647 resuMat=0.;
3648 matrice.ajouter_multTab_(inco,resuMat);
3649 solveur_masse.appliquer(resuMat);
3650 resuMat.echange_espace_virtuel();
3651 resMat<<"Face perio :"<<face*size1+comp<<endl;
3652 resMat<<"(";
3653 for (i=0; i<dimension; i++)
3654 resMat<<xv(face,i)<<",";
3655 resMat<<")"<<endl;
3656 for (i=0; i<size0; i++)
3657 {
3658 resMat<<i<<"(";
3659 for (ii=0; ii<dimension; ii++)
3660 resMat<<xv(i,ii)<<",";
3661 resMat<<"):=(";
3662 for (j=0; j<size1; j++)
3663 resMat<<resuMatV[i*size1+j]<<",";
3664 resMat<<")"<<endl;
3665 }
3666
3667 //Difference between the results
3668 resu-=resuMat;
3669
3670 //Display of differences
3671 max=resu.local_max_abs_vect();
3672 if (max>1.e-14)
3673 {
3674 result<<"Diff pour face perio : "<<face*size1+comp<<endl;
3675 result<<"(";
3676 for (i=0; i<dimension; i++)
3677 result<<xv(face,i)<<",";
3678 result<<")"<<endl;
3679 for (i=0; i<size0; i++)
3680 {
3681 test1=false;
3682 for (j=0; j<size1; j++)
3683 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3684
3685 if (test1)
3686 {
3687 result<<i<<"(";
3688 for (ii=0; ii<dimension; ii++)
3689 result<<xv(i,ii)<<",";
3690 result<<"):=(";
3691 for (j=0; j<size1; j++)
3692 result <<resuV[i*size1+j]<<",";
3693 result <<")"<<endl;
3694 }
3695 }
3696 }
3697 else
3698 {
3699 result<<"Diff pour face perio : "<<face*size1+comp<<endl;
3700 result<<"Maximum : "<<max<<endl;
3701 }
3702
3703 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3704 if (Process::je_suis_maitre()) incoV[faceAss*size1+comp]=0.;
3706 }
3707 }//end Perio
3708 else
3709 for (ind_face=num1; ind_face<num2; ind_face++)
3710 {
3711 face=le_bord.num_face(ind_face);
3712 if (Process::je_suis_maitre()) incoV[face*size1+comp]=1.;
3714
3715 //Version explicite
3716 gradient_p1_=0.;
3718
3719 //Check the gradients
3720 grad <<"Face CL : "<<face*size1+comp<<endl;
3721 grad<<"(";
3722 for (i=0; i<dimension; i++)
3723 grad<<xv(face,i)<<",";
3724 grad<<")"<<endl;
3725 for (som=0; som<nb_som_tot; som++)
3726 {
3727 grad <<som<<"(";
3728 for (i=0; i<dimension; i++)
3729 grad<<xs(som,i)<<",";
3730 grad<<"):(";
3731 for (compi=0; compi<dim_ch_; compi++)
3732 for (compj=0; compj<dimension; compj++)
3733 grad<<gradient_p1_(som,compi,compj)<<",";
3734 grad<<")"<<endl;
3735 }
3736
3737 gradientMat=0.;
3738 som_glob=-1;
3739 gradient_som_CL(face,nnz,som_glob,gradientMat);
3740
3741 gradMat<<"Face CL : "<<face*size1+comp<<endl;
3742 gradMat<<"(";
3743 for (i=0; i<dimension; i++)
3744 gradMat<<xv(face,i)<<",";
3745 gradMat<<")"<<endl;
3746 for (i=0; i<nnz; i++)
3747 {
3748 gradMat<<som_glob[i]<<"(";
3749 for (ii=0; ii<dimension; ii++)
3750 gradMat<<xs(som_glob[i],ii)<<",";
3751 gradMat<<"):(";
3752 for (compj=0; compj<dimension; compj++)
3753 gradMat<<gradientMat(compj,i)<<",";
3754 gradMat<<")"<<endl;
3755 }
3756
3757 resu=0.;
3759 corriger_Cl_test(resu);
3760 solveur_masse.appliquer(resu);
3761 div<<"Face CL : "<<face*size1+comp<<endl;
3762 div<<"(";
3763 for (i=0; i<dimension; i++)
3764 div<<xv(face,i)<<",";
3765 div<<")"<<endl;
3766 for (i=0; i<size0; i++)
3767 {
3768 div<<i<<"(";
3769 for (ii=0; ii<dimension; ii++)
3770 div<<xv(i,ii)<<",";
3771 div<<"):=(";
3772 for (j=0; j<size1; j++)
3773 div<<resu[i*size1+j]<<",";
3774 div<<")"<<endl;
3775 }
3776
3777 resu*=-1.;
3778 res<<"Face CL : "<<face*size1+comp<<endl;
3779 res<<"(";
3780 for (i=0; i<dimension; i++)
3781 res<<xv(face,i)<<",";
3782 res<<")"<<endl;
3783 for (i=0; i<size0; i++)
3784 {
3785 test1=false;
3786 for (j=0; j<size1; j++)
3787 test1|=(std::fabs(resuV[i*size1+j])>max);
3788
3789 if (test1)
3790 {
3791 res<<i<<"(";
3792 for (ii=0; ii<dimension; ii++)
3793 res<<xv(i,ii)<<",";
3794 res<<"):=(";
3795 for (j=0; j<size1; j++)
3796 res<<resu[i*size1+j]<<",";
3797 res<<")"<<endl;
3798 }
3799 }
3800
3801 //Version matricielle
3802 resuMat=0.;
3803 matrice.ajouter_multTab_(inco,resuMat);
3804 solveur_masse.appliquer(resuMat);
3805 resuMat.echange_espace_virtuel();
3806 resMat<<"Face CL :"<<face*size1+comp<<endl;
3807 resMat<<"(";
3808 for (i=0; i<dimension; i++)
3809 resMat<<xv(face,i)<<",";
3810 resMat<<")"<<endl;
3811 for (i=0; i<size0; i++)
3812 {
3813 resMat<<i<<"(";
3814 for (ii=0; ii<dimension; ii++)
3815 resMat<<xv(i,ii)<<",";
3816 resMat<<"):=(";
3817 for (j=0; j<size1; j++)
3818 resMat<<resuMatV[i*size1+j]<<",";
3819 resMat<<")"<<endl;
3820 }
3821
3822 //Difference between the results
3823 resu-=resuMat;
3824
3825 //Display of differences
3826 max=resu.local_max_abs_vect();
3827 if (max>1.e-14)
3828 {
3829 result<<"Diff pour face CL : "<<face*size1+comp<<endl;
3830 result<<"(";
3831 for (i=0; i<dimension; i++)
3832 result<<xv(face,i)<<",";
3833 result<<")"<<endl;
3834 for (i=0; i<size0; i++)
3835 {
3836 test1=false;
3837 for (j=0; j<size1; j++)
3838 test1|=(std::fabs(resuV[i*size1+j])>1.e-14);
3839
3840 if (test1)
3841 {
3842 result<<i<<"(";
3843 for (ii=0; ii<dimension; ii++)
3844 result<<xv(i,ii)<<",";
3845 result<<"):=(";
3846 for (j=0; j<size1; j++)
3847 result <<resuV[i*size1+j]<<",";
3848 result <<")"<<endl;
3849 }
3850 }
3851 }
3852 else
3853 {
3854 result<<"Diff pour face CL : "<<face*size1+comp<<endl;
3855 result<<"Maximum : "<<max<<endl;
3856 }
3857
3858 if (Process::je_suis_maitre()) incoV[face*size1+comp]=0.;
3860 }//end other CLs
3861 }//end loop over n_bord
3862 exit();
3863}
3864
3866{
3867 const Domaine_Cl_VEF& domaine_Cl_VEF=la_zcl_vef.valeur();
3868 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
3869
3870 const int nb_bords =les_cl.size();
3871 int n_bord=0, num1=0, num2=0;
3872 int face=0, face_associee=0;
3873 int ind_face=0, comp=0;
3874
3875 for (n_bord=0; n_bord<nb_bords; n_bord++)
3876 {
3877 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
3878 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
3879
3880 num1=0;
3881 num2=le_bord.nb_faces();
3882
3883 if (sub_type(Periodique,la_cl.valeur()))
3884 {
3885 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
3886
3887 for (ind_face=num1; ind_face<num2; ind_face++)
3888 {
3889 face = le_bord.num_face(ind_face);
3890 face_associee=
3891 le_bord.num_face(la_cl_perio.face_associee(ind_face));
3892
3893 if (face<face_associee)
3894 for (comp=0; comp<dim_ch_; comp++)
3895 {
3896 resu[face*dim_ch_+comp]+=resu[face_associee*dim_ch_+comp];
3897 resu[face_associee*dim_ch_+comp]=resu[face*dim_ch_+comp];
3898 }
3899 }
3900 }
3901 }
3903}
int_t size_array() const
Returns the size of the array in bits.
Definition ArrOfBit.h:45
void setbit(int_t i) const
Set bit e to 1.
Definition ArrOfBit.h:73
class Champ_Don_Fonc_xyz This class represents a data field that is a function
: class Champ_Don_lu This class represents a data field read from a file with the following conventio...
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
Champ_Uniforme_Morceaux This class represents a piecewise constant-in-space field.
Champ_Uniforme Represents a field that is constant in space and time.
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Champ_front_txyz Derived class of Champ_front_var representing
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()
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
int_t nb_aretes_tot() const
returns the total number of edges (real+virtual).
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
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
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
Returns the number of faces of type i of the geometric elements that make up the domain.
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
Creates an array with one "row" per mesh vertex.
Definition Domaine.cpp:999
int_t nb_som_tot() const
Returns the total number of vertices of the domain i.e. the number of real and virtual vertices on th...
Definition Domaine.h:123
int_t nb_som() const
Returns the number of vertices of the domain.
Definition Domaine.h:121
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
int nb_cond_lim() const
Returns the number of boundary conditions.
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VEF
Definition Domaine_VEF.h:53
const DoubleVect & volume_aux_sommets() const
Definition Domaine_VEF.h:89
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
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
Returns the total number of 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
Returns the index of the i-th vertex of face num_face.
Definition Domaine_VF.h:582
virtual double surface(int i) const
Definition Domaine_VF.h:53
int est_une_face_virt_bord(int) const
Returns 1 if face is a virtual boundary face, 0 otherwise.
Definition Domaine_VF.h:680
int nb_som_face() const
Returns the number of vertices per face.
Definition Domaine_VF.h:493
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
Definition Domaine_VF.h:512
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
int nb_som_tot() const
Classe Echange_externe_impose: This class represents the special case of the class.
virtual double h_imp(int num) const
Returns the value of the imposed heat exchange coefficient on the i-th component.
virtual double T_ext(int num) const
Returns the value of the imposed temperature on the i-th component of the boundary field.
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()
Returns the mass solver associated with the equation.
virtual const Champ_Inc_base & inconnue() const =0
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the 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
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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
Matrix-matrix multiply-accumulate operation (saxpy) (matrix X represented by an array).
DoubleVect & porosite_elem()
Definition Milieu_base.h:58
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
Classe Neumann_homogene This class is the base class of the hierarchy of homogeneous Neumann-type bou...
Classe Neumann_paroi This boundary condition corresponds to an imposed flux for the.
Neumann_sortie_libre This class represents an open boundary without imposed velocity.
Classe Neumann_val_ext This class is the base class of the hierarchy of.
Classe Neumann This class is the base class of the hierarchy of Neumann-type boundary conditions.
Definition Neumann.h:31
virtual double flux_impose(int i) const
Returns the value of the imposed flux on the i-th component of the field representing the flux at the...
Definition Neumann.cpp:35
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
Size/initialize the matrix.
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
Computes 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
Compute the diffusivity "nu_p1" at mesh vertices from the element diffusivity "nu_elem".
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
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
class Op_Diff_VEF_Face
const Champ_base & diffusivite() const override
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
int phi_psi_diffuse(const Equation_base &eq) const
Determine whether to compute div(phi nu grad Psi) or div(nu grad 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
Dimensioning of the matrix that will receive the coefficients from convection and diffusion for the f...
void modifier_flux(const Operateur_base &) const
DoubleTab flux_bords_
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:391
static bool is_parallel()
Definition Process.cpp:108
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
double temps_courant() const
Returns the current time.
Solveur_Masse_base Represents the mass matrix of an equation.
virtual DoubleTab & appliquer(DoubleTab &) const
Returns appliquer_impl(x/temporal_coefficient) if a temporal coefficient is set, otherwise returns ap...
Base class for output streams.
Definition Sortie.h:52
virtual void declare_support_masse_volumique(int ok)
The constructor of a derived class that uses the density field must call this function with the value...
Symetrie On symmetry faces, the following properties hold:
Definition Symetrie.h:37
int size() const
Definition TRUSTLists.h:86
void dimensionner(int)
Resizes an array of lists.
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")