TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_Amont_old_VEF_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_Conv_Amont_old_VEF_Face.h>
17#include <Neumann_sortie_libre.h>
18#include <Hexaedre_VEF.h>
19#include <Milieu_base.h>
20#include <Periodique.h>
21
22Implemente_instanciable(Op_Conv_Amont_old_VEF_Face,"Op_Conv_Amont_old_VEF_P1NC",Op_Conv_VEF_base);
23// XD convection_amont_old convection_deriv amont_old NO_BRACE Only for VEF discretization, obsolete keyword, see amont.
24
26{
27 return s << que_suis_je() ;
28}
29
31{
32 return s ;
33}
34
35
36//// convbis correspond au calcul de -1*terme_convection
37//
38static void convbis(const double psc,const int num1,const int num2,
39 const DoubleTab& transporte,const int ncomp,
40 DoubleTab& resu, DoubleVect& fluent)
41{
42 int comp,amont;
43 double flux;
44
45 if (psc >= 0)
46 {
47 amont = num1;
48 fluent[num2] += psc;
49 }
50 else
51 {
52 amont = num2;
53 fluent[num1] -= psc;
54 }
55
56 for (comp=0; comp<ncomp; comp++)
57 {
58 flux = transporte(amont,comp)*psc;
59 resu(num1,comp) -= flux;
60 resu(num2,comp) += flux;
61 }
62}
63static void convbisimplicite(const double psc,const int num1,const int num2,
64 const DoubleTab& transporte,const int ncomp,
65 Matrice_Morse& matrice)
66{
67 const auto& tab1 = matrice.get_set_tab1();
68 const auto& tab2 = matrice.get_set_tab2();
69 auto& coeff = matrice.get_set_coeff();
70
71 for (int comp=0; comp<ncomp; comp++)
72 {
73 if (psc >=0)
74 {
75 for (auto k=tab1[num1*ncomp+comp]-1; k<tab1[num1*ncomp+comp+1]-1; k++)
76 {
77 if (tab2[k]-1== num1*ncomp+comp)
78 coeff(k) += psc;
79 }
80 for (auto k=tab1[num2*ncomp+comp]-1; k<tab1[num2*ncomp+comp+1]-1; k++)
81 {
82 if (tab2[k]-1== num1*ncomp+comp)
83 coeff(k) -= psc;
84 }
85 }
86 else
87 {
88 for (auto k=tab1[num1*ncomp+comp]-1; k<tab1[num1*ncomp+comp+1]-1; k++)
89 {
90 if (tab2[k]-1== num2*ncomp+comp)
91 coeff(k) += psc;
92 }
93 for (auto k=tab1[num2*ncomp+comp]-1; k<tab1[num2*ncomp+comp+1]-1; k++)
94 {
95 if (tab2[k]-1== num2*ncomp+comp)
96 coeff(k) -= psc;
97 }
98 }
99 }
100}
101
102
103DoubleTab& Op_Conv_Amont_old_VEF_Face::ajouter(const DoubleTab& transporte,
104 DoubleTab& resu) const
105{
106 // Cerr<<"Op_Conv_Amont_old_VEF_Face::ajouter"<<finl;
107 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
108 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
109 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
110 const IntTab& elem_faces = domaine_VEF.elem_faces();
111 const DoubleTab& face_normales = domaine_VEF.face_normales();
112 const auto& facette_normales = domaine_VEF.facette_normales();
113 const DoubleVect& porosite_face = equation().milieu().porosite_face();
114 const Domaine& domaine = domaine_VEF.domaine();
115 const Elem_VEF_base& type_elem=domaine_VEF.type_elem();
116 const int nfa7 = type_elem.nb_facette();
117 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
118 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
119 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
120 int nfac = domaine.nb_faces_elem();
121 int nsom = domaine.nb_som_elem();
122 int nb_som_facette = domaine.type_elem()->nb_som_face();
123 const Elem_geom_base& elem_geom = domaine.type_elem().valeur();
124 if ( sub_type(Hexaedre_VEF,elem_geom))
125 {
126 nb_som_facette--;
127 }
128
129 // MODIF SB su 10/09/03
130 // Pour les 3 elements suivants, il y a autant de sommets que de face
131 // constituant l'element geometrique
132 // PB avec les hexa, 8 sommets et 6 faces, donc l'utilisation du tableau
133 // face[i] ne fonctionne plus
134 // la methode retenue pour eviter de calculer la vitesse aux sommets sans
135 // les fonctions de forme n'est donc pas utilisable,
136 // pour l'hexa on n'a pas acces a la face.
137 // il existe le tableau Face=>sommets mais pas l'inverse.
138 // trop couteux et pour le moment on n'etend pas les porosites aux hexa
139 // ||(nom_elem=="Quadri_VEF")
140 int istetra=0;
141 Nom nom_elem=type_elem.que_suis_je();
142 if ((nom_elem=="Tetra_VEF")||(nom_elem=="Tri_VEF"))
143 istetra=1;
144
145 // Pour le traitement de la convection on distingue les polyedres
146 // standard qui ne "voient" pas les conditions aux limites et les
147 // polyedres non standard qui ont au moins une face sur le bord.
148 // Un polyedre standard a n facettes sur lesquelles on applique le
149 // schema de convection.
150 // Pour un polyedre non standard qui porte des conditions aux limites
151 // de Dirichlet, une partie des facettes sont portees par les faces.
152 // En bref pour un polyedre le traitement de la convection depend
153 // du type (triangle, tetraedre ...) et du nombre de faces de Dirichlet.
154
155 double psc;
156 int poly,face_adj,fa7,i,j,n_bord,num_face, rang ,itypcl, num10,num20,num_som;
157 const int ncomp_ch_transporte = transporte.line_size();
158
159 IntVect face(nfac);
160 DoubleVect vs(dimension);
161 DoubleVect vc(dimension);
162 DoubleTab vsom(nsom,dimension);
163 DoubleVect cc(dimension);
164
165 // On remet a zero le tableau qui sert pour
166 // le calcul du pas de temps de stabilite
167 fluent_ = 0;
168
169 // Traitement particulier pour les faces de periodicite
170
171 int nb_faces_perio = 0;
172 // Boucle pour compter le nombre de faces de periodicite
173 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
174 {
175 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
176 if (sub_type(Periodique,la_cl.valeur()))
177 {
178 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
179 nb_faces_perio += le_bord.nb_faces();
180 }
181 }
182
183 DoubleTab tab(nb_faces_perio,ncomp_ch_transporte);
184 // Boucle pour remplir tab
185 nb_faces_perio=0;
186 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
187 {
188 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
189 if (sub_type(Periodique,la_cl.valeur()))
190 {
191 // const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
192 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
193 int num1 = le_bord.num_premiere_face();
194 int num2 = num1 + le_bord.nb_faces();
195 for (num_face=num1; num_face<num2; num_face++)
196 {
197 for (int comp=0; comp<ncomp_ch_transporte; comp++)
198 tab(nb_faces_perio,comp) = resu(num_face,comp);
199 nb_faces_perio++;
200 }
201 }
202 }
203
204 IntVect compteur(nsom);
205 compteur = 0;
206 vsom=0.;
207
208 // Les polyedres non standard sont ranges en 2 groupes dans le Domaine_VEF:
209 // - polyedres bords et joints
210 // - polyedres bords et non joints
211 // On traite les polyedres en suivant l'ordre dans lequel ils figurent
212 // dans le domaine
213
214 // boucle sur les polys
215 const IntTab& KEL=type_elem.KEL();
216 for (poly=0; poly<nb_elem_tot; poly++)
217 {
218 rang = rang_elem_non_std(poly);
219 if (rang==-1)
220 itypcl=0;
221 else
222 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
223
224 // calcul des numeros des faces du polyedre
225 for (face_adj=0; face_adj<nfac; face_adj++)
226 face[face_adj]= elem_faces(poly,face_adj);
227 // on conserve cette partie
228 for (j=0; j<dimension; j++)
229 {
230 vs[j] = la_vitesse.valeurs()(face[0],j)*porosite_face(face[0]);
231 for (i=1; i<nfac; i++)
232 vs[j]+= la_vitesse.valeurs()(face[i],j)*porosite_face(face[i]);
233 }
234
235 // calcul de la vitesse aux sommets des polyedres
236 // int ncomp;
237 if (istetra==1)
238 {
239 for (j=0; j<nsom; j++)
240 for (int ncomp=0; ncomp<Objet_U::dimension; ncomp++)
241 vsom(j,ncomp) =vs[ncomp] - Objet_U::dimension*la_vitesse.valeurs()(face[j],ncomp)*porosite_face(face[j]);
242 }
243 else
244 {
245 // pour que cela soit valide avec les hexa
246 // On va utliser les fonctions de forme implementees dans la classe Champs_P1_impl ou Champs_Q1_impl
247 // int ncomp;
248 for (j=0; j<nsom; j++)
249 {
250 num_som = domaine.sommet_elem(poly,j);
251 for (int ncomp=0; ncomp<dimension; ncomp++)
252 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
253 }
254 }
255
256 type_elem.calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
257
258 // Boucle sur les facettes du polyedre
259 for (fa7=0; fa7<nfa7; fa7++)
260 {
261 if (rang==-1)
262 for (i=0; i<dimension; i++)
263 cc[i] = facette_normales(poly,fa7,i);
264 else
265 for (i=0; i<dimension; i++)
266 cc[i] = normales_facettes_Cl(rang,fa7,i);
267
268 // On applique le schema de convection a chaque sommet de la facette
269 // On traite le ou les sommets qui sont aussi des sommets du polyedre
270 for (i=0; i<nb_som_facette-1; i++)
271 {
272 psc =0;
273 for (j=0; j<dimension; j++)
274 psc+= vsom(KEL(i+2,fa7),j)*cc[j];
275
276 // Boucle sur les facettes du polyedre
277 psc /= nb_som_facette;
278 num10 = face[KEL(0,fa7)];
279 num20 = face[KEL(1,fa7)];
280 //psc *= (porosite_face(num1)+porosite_face(num2))/2. ;
281
282 convbis(psc,num10,num20,transporte,ncomp_ch_transporte,resu,fluent_);
283 }
284 // On traite le sommet confondu avec le centre de gravite du polyedre
285 psc=0;
286 for (j=0; j<dimension; j++)
287 psc += vc[j]*cc[j];
288 psc /= nb_som_facette;
289 num10 = face[KEL(0,fa7)];
290 num20 = face[KEL(1,fa7)];
291 //psc *= (porosite_face(num1)+porosite_face(num2))/2. ;
292
293 convbis(psc,num10,num20,transporte,ncomp_ch_transporte,resu,fluent_);
294 }
295
296 } // fin de la boucle
297 // if(Process::is_sequential())
298 // Process::Journal()<<"OpVEFFaAmont ap interne resu[8]="<<resu(8,0)<<","<<resu(8,1)<<finl;
299 // if((Process::nproc()==2)&&(Process::me()==0))
300 // Process::Journal()<<"OpVEFFaAmont ap interne resu[4]="<<resu(4,0)<<","<<resu(4,1)<<finl;
301
302 int voisine;
303 nb_faces_perio = 0;
304 double diff1,diff2;
305
306 // Dimensionnement du tableau des flux convectifs au bord du domaine
307 // de calcul
308 DoubleTab& flux_b = flux_bords_;
309 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
310 flux_b = 0.;
311
312 // Boucle sur les bords pour traiter les conditions aux limites
313 // il y a prise en compte d'un terme de convection pour les
314 // conditions aux limites de Neumann_sortie_libre seulement
315
316 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
317 {
318
319 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
320
321 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
322 {
323 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
324 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
325 int num1 = le_bord.num_premiere_face();
326 int num2 = num1 + le_bord.nb_faces();
327 for (num_face=num1; num_face<num2; num_face++)
328 {
329 psc =0;
330 for (i=0; i<dimension; i++)
331 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i)*porosite_face(num_face);
332 if (psc>0)
333 {
334 for (i=0; i<ncomp_ch_transporte; i++)
335 {
336 resu(num_face,i) -= psc*transporte(num_face,i);
337 flux_b(num_face,i) -= psc*transporte(num_face,i);
338 }
339 }
340 else
341 {
342 for (i=0; i<ncomp_ch_transporte; i++)
343 {
344 resu(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
345 flux_b(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
346 }
347 fluent_[num_face] -= psc;
348 }
349 }
350 }
351 else if (sub_type(Periodique,la_cl.valeur()))
352 {
353 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
354 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
355 int num1 = le_bord.num_premiere_face(), num2 = num1 + le_bord.nb_faces();
356 IntVect fait(le_bord.nb_faces());
357 fait = 0;
358 for (num_face=num1; num_face<num2; num_face++)
359 {
360 if (fait[num_face-num1] == 0)
361 {
362 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
363 for (int comp=0; comp<ncomp_ch_transporte; comp++)
364 {
365 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
366 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
367 resu(voisine,comp) += diff1;
368 resu(num_face,comp) += diff2;
369 flux_b(voisine,comp) += diff1;
370 flux_b(num_face,comp) += diff2;
371 }
372
373 fait[num_face-num1]= 1;
374 fait[voisine-num1] = 1;
375 }
376 nb_faces_perio++;
377 }
378 }
379 }
380 modifier_flux(*this);
381 return resu;
382
383}
384
385
386void Op_Conv_Amont_old_VEF_Face::ajouter_contribution(const DoubleTab& transporte, Matrice_Morse& matrice ) const
387{
388 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
389 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
390 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
391 const IntTab& elem_faces = domaine_VEF.elem_faces();
392 const DoubleTab& face_normales = domaine_VEF.face_normales();
393 const auto& facette_normales = domaine_VEF.facette_normales();
394 const Domaine& domaine = domaine_VEF.domaine();
395 const Elem_VEF_base& type_elem = domaine_VEF.type_elem();
396 const int nfa7 = type_elem.nb_facette();
397 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
398 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
399 const DoubleVect& porosite_face = equation().milieu().porosite_face();
400 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
401 int nfac = domaine.nb_faces_elem(), nsom = domaine.nb_som_elem(), nb_som_facette = domaine.type_elem()->nb_som_face();
402
403 // Pour le traitement de la convection on distingue les polyedres
404 // standard qui ne "voient" pas les conditions aux limites et les
405 // polyedres non standard qui ont au moins une face sur le bord.
406 // Un polyedre standard a n facettes sur lesquelles on applique le
407 // schema de convection.
408 // Pour un polyedre non standard qui porte des conditions aux limites
409 // de Dirichlet, une partie des facettes sont portees par les faces.
410 // En bref pour un polyedre le traitement de la convection depend
411 // du type (triangle, tetraedre ...) et du nombre de faces de Dirichlet.
412
413 double psc;
414 //DoubleTab pscl=0;
415 int poly,face_adj,fa7,i,j,n_bord, num_face, rang ,itypcl, num10,num20,num_som;
416 const int ncomp_ch_transporte = transporte.line_size();
417
418 IntVect face(nfac);
419 DoubleVect vs(dimension);
420 DoubleVect vc(dimension);
421 DoubleTab vsom(nsom,dimension);
422 DoubleVect cc(dimension);
423 auto& tab1 = matrice.get_set_tab1();
424 auto& tab2 = matrice.get_set_tab2();
425 auto& coeff = matrice.get_set_coeff();
426
427 // Traitement particulier pour les faces de periodicite
428 int voisine, nb_faces_perio = 0;
429 double diff1,diff2;
430
431 // Boucle pour compter le nombre de faces de periodicite
432 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
433 {
434 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
435 if (sub_type(Periodique,la_cl.valeur()))
436 {
437 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
438 nb_faces_perio += le_bord.nb_faces();
439 }
440 }
441
442 DoubleTab tab(nb_faces_perio,ncomp_ch_transporte);
443
444 // Boucle pour remplir tab
445 nb_faces_perio=0;
446 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
447 {
448 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
449 if (sub_type(Periodique,la_cl.valeur()))
450 {
451 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
452 int num1 = le_bord.num_premiere_face();
453 int num2 = num1 + le_bord.nb_faces();
454 for (num_face=num1; num_face<num2; num_face++)
455 {
456 for (int comp=0; comp<ncomp_ch_transporte; comp++)
457 tab(nb_faces_perio,comp) = coeff(num_face*ncomp_ch_transporte+comp);
458 nb_faces_perio++;
459 }
460 }
461 }
462
463 // Les polyedres non standard sont ranges en 2 groupes dans le Domaine_VEF:
464 // - polyedres bords et joints
465 // - polyedres bords et non joints
466 // On traite les polyedres en suivant l'ordre dans lequel ils figurent
467 // dans le domaine
468
469 // boucle sur les polys
470 const IntTab& KEL=type_elem.KEL();
471 for (poly=0; poly<nb_elem_tot; poly++)
472 {
473
474 rang = rang_elem_non_std(poly);
475 if (rang==-1)
476 itypcl=0;
477 else
478 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
479
480 // calcul des numeros des faces du polyedre
481 for (face_adj=0; face_adj<nfac; face_adj++)
482 face[face_adj]= elem_faces(poly,face_adj);
483
484 // calcul de la vitesse aux sommets des polyedres
485 for (j=0; j<dimension; j++)
486 {
487 vs[j] = la_vitesse.valeurs()(face[0],j);
488 for (i=1; i<nfac; i++)
489 vs[j]+= la_vitesse.valeurs()(face[i],j);
490 }
491
492 // calcul de la vitesse aux sommets des polyedres
493 // On va utliser les fonctions de forme implementees dans la classe Champs_P1_impl ou Champs_Q1_impl
494
495 int ncomp;
496 for (j=0; j<nsom; j++)
497 {
498 num_som = domaine.sommet_elem(poly,j);
499 for(int kk=0; kk<Objet_U::dimension; kk++)
500 for (ncomp=0; ncomp<dimension; ncomp++)
501 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
502 }
503
504 // calcul de vc
505 type_elem.calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
506
507 // Boucle sur les facettes du polyedre
508
509 for (fa7=0; fa7<nfa7; fa7++)
510 {
511 if (rang==-1)
512 for (i=0; i<dimension; i++)
513 cc[i] = facette_normales(poly,fa7,i);
514 else
515 for (i=0; i<dimension; i++)
516 cc[i] = normales_facettes_Cl(rang,fa7,i);
517
518 // On applique le schema de convection a chaque sommet de la facette
519 // On traite le ou les sommets qui sont aussi des sommets du polyedre
520
521 for (i=0; i<nb_som_facette-1; i++)
522 {
523 psc =0;
524
525 /////////////////////////////////////////////////////////////////////
526 // Remplissage du tableau de coefficients correspondant a convbis
527 /////////////////////////////////////////////////////////////////////
528
529 for (j=0; j<dimension; j++)
530 psc += vsom(KEL(i+2,fa7),j)*cc[j];
531 psc/= nb_som_facette;
532 num10 = face[KEL(0,fa7)];
533 num20 = face[KEL(1,fa7)];
534 convbisimplicite(psc,num10,num20,transporte,ncomp_ch_transporte,matrice);
535
536 } // fin de boucle sur les sommets des facettes.
537
538 // on traite le sommet confondu avec le centre de gravite du polyedre
539 psc=0;
540 for (j=0; j<dimension; j++)
541 psc += vc[j]*cc[j];
542 psc /= nb_som_facette;
543 num10 = face[KEL(0,fa7)];
544 num20 = face[KEL(1,fa7)];
545 convbisimplicite(psc,num10,num20,transporte,ncomp_ch_transporte,matrice);
546
547 } // fin de boucle sur les facettes.
548
549 } // fin de boucle sur les polyedres.
550
551 // Boucle sur les bords pour traiter les conditions aux limites
552 // il y a prise en compte d'un terme de convection pour les
553 // conditions aux limites de Neumann_sortie_libre seulement
554
555 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
556 {
557 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
558 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
559 {
560 // const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
561 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
562 int num1 = le_bord.num_premiere_face();
563 int num2 = num1 + le_bord.nb_faces();
564 for (num_face=num1; num_face<num2; num_face++)
565 {
566 psc =0;
567 for (i=0; i<dimension; i++)
568 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i);
569 if (psc>0)
570 {
571 for (j=0; j<ncomp_ch_transporte; j++)
572 {
573 for (auto k=tab1[num_face*ncomp_ch_transporte+j]-1; k<tab1[num_face*ncomp_ch_transporte+j+1]-1; k++)
574 {
575 if (tab2[k]-1==num_face*ncomp_ch_transporte+j)
576 coeff(k) += psc;
577 }
578 }
579 }
580 else /*psc < 0 */
581 {
582 for (j=0; j<ncomp_ch_transporte; j++)
583 {
584 for (auto k=tab1[num_face*ncomp_ch_transporte+j]-1; k<tab1[num_face*ncomp_ch_transporte+j+1]-1; k++)
585 {
586 if (tab2[k]-1==num_face*ncomp_ch_transporte+j)
587 coeff(k) += 0;
588 }
589 }
590 }
591 }
592 }
593 else if (sub_type(Periodique,la_cl.valeur()))
594 {
595 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
596 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
597 int num1 = le_bord.num_premiere_face();
598 int num2 = num1 + le_bord.nb_faces();
599 IntVect fait(le_bord.nb_faces());
600 fait = 0;
601 for (num_face=num1; num_face<num2; num_face++)
602 {
603 if (fait[num_face-num1] == 0)
604 {
605 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
606 for (int comp=0; comp<ncomp_ch_transporte; comp++)
607 {
608 diff1 = -1*tab(nb_faces_perio,comp);
609 diff2 = -1*tab(nb_faces_perio+voisine-num_face,comp);
610
611 for (auto k=tab1[num_face*ncomp_ch_transporte+comp]-1; k<tab1[num_face*ncomp_ch_transporte+1+comp]-1; k++)
612 if (tab2[k]-1==num_face*ncomp_ch_transporte+comp)
613 coeff(k) += diff2;
614
615 for (auto k=tab1[voisine*ncomp_ch_transporte+comp]-1; k<tab1[voisine*ncomp_ch_transporte+1+comp]-1; k++)
616 if (tab2[k]-1==voisine*ncomp_ch_transporte+comp)
617 coeff(k) += diff1;
618 }
619
620 fait[num_face-num1]= 1;
621 fait[voisine-num1] = 1;
622 }
623 nb_faces_perio++;
624 }
625 }
626 }
627}
628
630{
631 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
632 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
633 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
634 const DoubleTab& face_normales = domaine_VEF.face_normales();
635 //const Domaine& domaine = domaine_VEF.domaine();
636 //int nfac = domaine.nb_faces_elem();
637 double psc;
638 int i,n_bord, num_face;
639 const int ncomp = resu.line_size();
640
641 //IntVect face(nfac);
642
643 // Traitement particulier pour les faces de periodicite
644 int voisine, nb_faces_perio = 0;
645 double diff1,diff2;
646
647 // Boucle pour compter le nombre de faces de periodicite
648 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
649 {
650 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
651 if (sub_type(Periodique,la_cl.valeur()))
652 {
653 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
654 nb_faces_perio += le_bord.nb_faces();
655 }
656 }
657
658 DoubleTab tab(nb_faces_perio,ncomp);
659 // Boucle pour remplir tab
660 nb_faces_perio=0;
661 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
662 {
663 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
664 if (sub_type(Periodique,la_cl.valeur()))
665 {
666 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
667 int num1 = le_bord.num_premiere_face();
668 int num2 = num1 + le_bord.nb_faces();
669 for (num_face=num1; num_face<num2; num_face++)
670 {
671 for (int comp=0; comp<ncomp; comp++)
672 tab(nb_faces_perio,comp) = resu(num_face,comp);
673
674 nb_faces_perio++;
675 }
676 }
677 }
678 // Boucle sur les bords pour traiter les conditions aux limites
679 // il y a prise en compte d'un terme de convection pour les
680 // conditions aux limites de Neumann_sortie_libre seulement
681
682 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
683 {
684 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
685 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
686 {
687 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
688 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
689 int num1 = le_bord.num_premiere_face();
690 int num2 = num1 + le_bord.nb_faces();
691 for (num_face=num1; num_face<num2; num_face++)
692 {
693 psc =0;
694 for (i=0; i<dimension; i++)
695 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i);
696 if (psc>0)
697 for (i=0; i<ncomp; i++)
698 resu(num_face,i) += 0;
699 else
700 for (i=0; i<ncomp; i++)
701 resu(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
702 }
703 }
704 else if (sub_type(Periodique,la_cl.valeur()))
705 {
706 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
707 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
708 int num1 = le_bord.num_premiere_face();
709 int num2 = num1 + le_bord.nb_faces();
710 IntVect fait(le_bord.nb_faces());
711 fait = 0;
712 for (num_face=num1; num_face<num2; num_face++)
713 {
714 if (fait[num_face-num1] == 0)
715 {
716 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
717 for (int comp=0; comp<ncomp; comp++)
718 {
719 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
720 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
721 resu(voisine,comp) += diff1;
722 resu(num_face,comp) += diff2;
723 }
724
725 fait[num_face-num1]= 1;
726 fait[voisine-num1] = 1;
727 }
728 nb_faces_perio++;
729 }
730 }
731 }
732}
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual double valeur_a_sommet_compo(int, int, int) const
renvoi la compo eme corrdonne des valeurs a l'element le_poly au sommet sommet
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
int type_elem_Cl(int i) const
DoubleTab & normales_facettes_Cl()
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:86
const Elem_VEF_base & type_elem() const
Definition Domaine_VEF.h:75
auto & facette_normales()
Definition Domaine_VEF.h:84
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
virtual void calcul_vc(const ArrOfInt &, ArrOfDouble &, const ArrOfDouble &, const DoubleTab &, const Champ_Inc_base &, int, const DoubleVect &) const =0
const IntTab & KEL() const
virtual int nb_facette() const =0
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
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
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
auto & get_set_tab2()
auto & get_set_coeff()
auto & get_set_tab1()
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
double val_ext(int i) const override
Renvoie la valeur de la i-eme composante du champ impose a l'exterieur de la frontiere.
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
class Op_Conv_Amont_old_VEF_Face
void contribue_au_second_membre(DoubleTab &) const
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void ajouter_contribution(const DoubleTab &, Matrice_Morse &) const
class Op_Conv_VEF_base
const Champ_Inc_base & vitesse() const
void modifier_flux(const Operateur_base &) const
DoubleTab flux_bords_
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
Classe de base des flux de sortie.
Definition Sortie.h:52
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
int line_size() const
Definition TRUSTVect.tpp:67