TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Convection_Diffusion_Temperature.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 <Convection_Diffusion_Temperature.h>
17#include <Navier_Stokes_std.h>
18#include <Probleme_base.h>
19#include <Fluide_reel_base.h>
20#include <Discret_Thyd.h>
21#include <Frontiere_dis_base.h>
22#include <Param.h>
23#include <Transport_Interfaces_base.h>
24#include <TRUSTTrav.h>
25#include <SFichier.h>
26#include <Domaine_VF.h>
27#include <Matrice_Morse.h>
28#include <Champ_Uniforme.h>
29#include <Perf_counters.h>
30
31Implemente_instanciable(Convection_Diffusion_Temperature,"Convection_Diffusion_Temperature",Convection_Diffusion_Temperature_base);
32// XD convection_diffusion_temperature eqn_base convection_diffusion_temperature INHERITS_BRACE Energy equation
33// XD_CONT (temperature diffusion convection).
34// XD attr penalisation_l2_ftd bloc_lecture penalisation_l2_ftd OPT to activate or not (the default is Direct Forcing
35// XD_CONT method) the Penalized Direct Forcing method to impose the specified temperature on the solid-fluid interface.
36
38
40{
41 assert(la_temperature);
42 assert(le_fluide);
44 //Nom unite;
45 //if (dimension+bidim_axi==2) unite="[W/m]";
46 //else unite="[W]";
47 Nom num=inconnue().le_nom(); // On prevoir le cas d'equation de scalaires passifs
48 num.suffix("temperature");
49 Nom nom="Convection_chaleur";
50 nom+=num;
51 terme_convectif.set_fichier(nom);
52 //terme_convectif.set_description((Nom)"Convective heat transfer rate=Integral(-rho*cp*T*u*ndS) "+unite);
53 terme_convectif.set_description((Nom)"Convective heat transfer rate=Integral(-rho*cp*T*u*ndS) [W] if SI units used");
54 nom="Diffusion_chaleur";
55 nom+=num;
56 terme_diffusif.set_fichier(nom);
57 //terme_diffusif.set_description((Nom)"Conduction heat transfer rate=Integral(lambda*grad(T)*ndS) "+unite);
58 terme_diffusif.set_description((Nom)"Conduction heat transfer rate=Integral(lambda*grad(T)*ndS) [W] if SI units used");
59 solveur_masse->set_name_of_coefficient_temporel("rho_cp_comme_T");
60 return is;
61}
62
64{
66 param.ajouter_non_std("penalisation_L2_FTD",(this));
67}
68
70{
71 if (un_mot=="penalisation_L2_FTD")
72 {
73 is_penalized = 1;
74 eta = 1.e-12;
75 Cerr << " Equation_base :: penalisation_L2_FTD" << finl;
76 Cerr << "Equation_base: modele penalisation ibc = "<< choix_pena << finl;
77 Nom mot, nom_equation;
78 int dim;
79 is >> mot;
80 Motcle accolade_fermee="}", accolade_ouverte="{";
81 if (mot == accolade_ouverte)
82 {
83 is >> mot;
84 while (mot != accolade_fermee)
85 {
86 nom_equation = mot;
87
88 Cerr << "penalisation_L2_FTD equation: "<< nom_equation << finl;
89 const Transport_Interfaces_base& eq = ref_cast(Transport_Interfaces_base,probleme().get_equation_by_name(nom_equation));
90 ref_penalisation_L2_FTD.add(eq);
91
92 is >> dim;
93 DoubleTab tab = DoubleTab();
94 tab.resize(dim);
95 for ( int i = 0 ; i<dim ; i++)
96 {
97 is >> tab(i);
98 Cerr << "Lecture de la valeur de la penalisation suivant la direction " << i+1 <<" :" << tab(i) << finl;
99 }
101 is >> mot ;
102 }
103 }
104 else
105 {
106 Cerr << "Erreur a la lecture des parametres de la penalisation L2 " << finl;
107 Cerr << "On attendait : " << accolade_ouverte << finl;
108 exit();
109 }
110 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
113 }
114 else
116 return 1;
117}
118
119/*! @brief Associe un milieu physique a l'equation, le milieu est en fait caste en Fluide_base.
120 *
121 * @param (Milieu_base& un_milieu)
122 * @throws le milieu n'est pas un Fluide_base
123 */
125{
126 if (sub_type(Fluide_base,un_milieu)) associer_fluide(ref_cast(Fluide_base, un_milieu));
127 else Process::exit(que_suis_je() + " : le fluide " + un_milieu.que_suis_je() + " n'est pas de type Fluide_base!");
128}
129
131{
132 if (!sub_type(Fluide_reel_base,le_fluide.valeur()))
133 if (!le_fluide->has_conductivite() || !le_fluide->has_capacite_calorifique() || !le_fluide->has_beta_t())
134 {
135 Cerr << "You have not defined the following physical properties of the fluid " << finl;
136 Cerr << "needed to solve the energy equation: " << que_suis_je() << finl;
137 if (!le_fluide->has_conductivite()) Cerr << " Thermal conductivity (lambda)"<< finl;
138 if (!le_fluide->has_capacite_calorifique()) Cerr << " Specific heat capacity (Cp)"<< finl;
139 if (!le_fluide->has_beta_t()) Cerr << " Thermal expansion coefficient (beta_th)"<< finl;
140 exit();
141 }
142
143 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
144 Cerr << "Energy equation discretization" << finl;
145 dis.temperature(schema_temps(), domaine_dis(), la_temperature);
146 champs_compris_.ajoute_champ(la_temperature);
147
149
150 Cerr << "Convection_Diffusion_Temperature::discretiser() ok" << finl;
151}
152
157
158inline int string2int(const char* digit, int& result)
159{
160 result = 0;
161
162 //--- Convert each digit char and add into result.
163 while (*digit >= '0' && *digit <='9')
164 {
165 result = (result * 10) + (*digit - '0');
166 digit++;
167 }
168
169 //--- Check that there were no non-digits at end.
170 if (*digit != 0)
171 {
172 return 0;
173 }
174
175 return 1;
176}
177
179{
181
182 Noms noms_compris = champs_compris_.liste_noms_compris();
183 noms_compris.add("gradient_temperature");
184 noms_compris.add("h_echange_");
185
186 if (opt == DESCRIPTION)
187 Cerr << que_suis_je() << " : " << noms_compris << finl;
188 else
189 nom.add(noms_compris);
190}
191
193{
195
196 if (motlu == "gradient_temperature")
197 {
198 if (!gradient_temperature)
199 {
200 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
201 dis.grad_T(domaine_dis(),domaine_Cl_dis(),la_temperature,gradient_temperature);
202 champs_compris_.ajoute_champ(gradient_temperature);
203 }
204 }
205
206 Motcle nom_mot(motlu),temp_mot(nom_mot);
207 if (nom_mot.debute_par("H_ECHANGE"))
208 {
209 if (!h_echange)
210 {
211 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
212 temp_mot.suffix("H_ECHANGE_");
213 int temperature;
214 string2int(temp_mot,temperature);
215 dis.h_conv(domaine_dis(),domaine_Cl_dis(),la_temperature,h_echange,nom_mot,temperature);
216 champs_compris_.ajoute_champ(h_echange);
217 }
218 }
219}
220
221bool Convection_Diffusion_Temperature::has_champ(const Motcle& nom, OBS_PTR(Champ_base)& ref_champ) const
222{
223 if (nom == "gradient_temperature")
224 {
226 return true;
227 }
228
229 if (h_echange)
230 if (nom == h_echange->le_nom())
231 {
233 return true;
234 }
235
238
239 return false; /* rien trouve */
240}
241
243{
244 if (nom == "gradient_temperature")
245 return true;
246
247 if (h_echange)
248 if (nom == h_echange->le_nom())
249 return true;
250
252 return true;
253
254 return false; /* rien trouve */
255}
256
258{
259 if (nom == "gradient_temperature")
260 {
261 double temps_init = schema_temps().temps_init();
262 Champ_Fonc_base& ch_gt = ref_cast_non_const(Champ_Fonc_base, gradient_temperature.valeur());
263 if (((ch_gt.temps() != la_temperature->temps()) || (ch_gt.temps() == temps_init)) && (la_temperature->mon_equation_non_nul()))
264 ch_gt.mettre_a_jour(la_temperature->temps());
265 return champs_compris_.get_champ(nom);
266 }
267
268 if (h_echange)
269 if (nom == h_echange->le_nom())
270 {
271 double temps_init = schema_temps().temps_init();
272 Champ_Fonc_base& ch_hconv = ref_cast_non_const(Champ_Fonc_base, h_echange.valeur());
273 if (((ch_hconv.temps() != la_temperature->temps()) || (ch_hconv.temps() == temps_init)) && (la_temperature->mon_equation_non_nul()))
274 ch_hconv.mettre_a_jour(la_temperature->temps());
275 return champs_compris_.get_champ(nom);
276 }
277
279}
280
281/*! @brief Renvoie le nom du domaine d'application de l'equation.
282 *
283 * Ici "Thermique".
284 *
285 * @return (Motcle&) le nom du domaine d'application de l'equation
286 */
288{
289 static Motcle domaine = "Thermique";
290 return domaine;
291}
292
294{
296 if (!is_penalized)
297 {
299 }
300 else
301 {
302 const double rhoCp = get_time_factor();
303 // Specific code if temperature equation is penalized
304 derivee=inconnue().valeurs();
305 // Mise en place d'une methode de mise en place d'un domaine fantome
307 DoubleTab& inc=inconnue().valeurs();
308 inc = derivee;
309
310 DoubleTrav secmem(derivee);
311
312 if (nombre_d_operateurs()>1)
313 {
314 derivee_en_temps_conv(secmem, derivee);
315 secmem *= rhoCp;
316 }
317
318 // Transport des ibcs et de la couche limite
319 DoubleTrav secmem_conv_vr(derivee);
320 //on advecte la variable avec la vitesse ibc
321 transport_ibc(secmem_conv_vr, derivee);
322 //on retranche cette advection
323 secmem -= secmem_conv_vr;
324
325 DoubleTab derivee_conv;
326 derivee_conv.copy(secmem, RESIZE_OPTIONS::COPY_INIT);
327
328 les_sources.ajouter(secmem);
329
330 filtrage_si_appart_ibc(derivee_conv,secmem);
331 secmem.echange_espace_virtuel();
332
334 {
335 // Store dI/dt(n) = M-1 secmem :
336 derivee_en_temps().valeurs()=secmem;
337 solveur_masse->appliquer(derivee_en_temps().valeurs());
338 schema_temps().modifier_second_membre((*this),secmem); // Change secmem for some schemes (eg: Adams_Bashforth)
339 }
340
341 solveur_masse->appliquer(secmem);
343
344 // penalisation de la temperature
345 penalisation_L2(derivee);
346 return derivee;
347 }
348}
349
354
355// ajoute les contributions des operateurs et des sources
356void Convection_Diffusion_Temperature::assembler(Matrice_Morse& matrice, const DoubleTab& inco, DoubleTab& resu)
357{
358 const double rhoCp = get_time_factor();
359
360 // Test de verification de la methode contribuer_a_avec
361 for (int op=0; op<nombre_d_operateurs(); op++)
362 operateur(op).l_op_base().tester_contribuer_a_avec(inco, matrice);
363
364 // Contribution des operateurs et des sources:
365 // [Vol/dt+A]Inco(n+1)=somme(residu)+Vol/dt*Inco(n)
366 // Typiquement: si Op=flux(Inco) alors la matrice implicite A contient une contribution -dflux/dInco
367 // Exemple: Op flux convectif en VDF:
368 // Op=T*u*S et A=-d(T*u*S)/dT=-u*S
371 {
372 if ( probleme().discretisation().que_suis_je() == "EF")
373 {
374 // On calcule somme(residu) par contribuer_au_second_membre (typiquement CL non implicitees)
375 // Cette approche necessite de coder 3 methodes (contribuer_a_avec, contribuer_au_second_membre et ajouter pour l'explicite)
376 sources().contribuer_a_avec(inco,matrice);
377 statistics().end_count(STD_COUNTERS::matrix_assembly,0,0);
378 sources().ajouter(resu);
379 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
380 matrice.ajouter_multvect(inco, resu); // Add source residual first
381 for (int op = 0; op < nombre_d_operateurs(); op++)
382 {
383 operateur(op).l_op_base().contribuer_a_avec(inco, matrice);
385 }
386 }
387 else
388 {
389 Cerr << "VIA_CONTRIBUER_AU_SECOND_MEMBRE pas code pour " << que_suis_je() << ":assembler" << finl;
390 Cerr << "avec discretisation " << probleme().discretisation().que_suis_je() << "" << finl;
392 }
393 // // On calcule somme(residu) par contribuer_au_second_membre (typiquement CL non implicitees)
394 // // Cette approche necessite de coder 3 methodes (contribuer_a_avec, contribuer_au_second_membre et ajouter pour l'explicite)
395 // sources().contribuer_a_avec(inco,matrice);
396 // sources().ajouter(resu);
397 // matrice.ajouter_multvect(inco, resu); // Add source residual first
398 // for (int op = 0; op < nombre_d_operateurs(); op++)
399 // {
400 // operateur(op).l_op_base().contribuer_a_avec(inco, matrice);
401 // operateur(op).l_op_base().contribuer_au_second_membre(resu);
402 // }
403 }
404 else if (type_codage==Discretisation_base::VIA_AJOUTER)
405 {
406 // On calcule somme(residu) par somme(operateur)+sources+A*Inco(n)
407 // Cette approche necessite de coder seulement deux methodes (contribuer_a_avec et ajouter)
408 // Donc un peu plus couteux en temps de calcul mais moins de code a ecrire/maintenir
409 for (int op=0; op<nombre_d_operateurs(); op++)
410 {
411 Matrice_Morse mat(matrice);
412 mat.get_set_coeff() = 0.0;
413 operateur(op).l_op_base().contribuer_a_avec(inco, mat);
414 if (op == 1) mat *= rhoCp; // la derivee est multipliee par rhoCp pour la convection
415 matrice += mat;
416 statistics().end_count(STD_COUNTERS::matrix_assembly,0,0);
417 {
418 DoubleTab resu_tmp(resu);
419 resu_tmp = 0.;
420 operateur(op).ajouter(inco, resu_tmp);
421 if (op == 1) resu_tmp *= rhoCp;
422 resu += resu_tmp;
423 }
424 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
425 }
426
427 sources().contribuer_a_avec(inco,matrice);
428 statistics().end_count(STD_COUNTERS::matrix_assembly,0,0);
429 sources().ajouter(resu);
430 statistics().begin_count(STD_COUNTERS::matrix_assembly,statistics().get_last_opened_counter_level()+1);
431 matrice.ajouter_multvect(inco, resu); // Ajout de A*Inco(n)
432 // PL (11/04/2018): On aimerait bien calculer la contribution des sources en premier
433 // comme dans le cas VIA_CONTRIBUER_AU_SECOND_MEMBRE mais le cas Canal_perio_3D (keps
434 // periodique plante: il y'a une erreur de periodicite dans les termes sources du modele KEps...
435 }
436 else
437 {
438 Cerr << "Unknown value in Equation_base::assembler for " << (int)type_codage << finl;
440 }
441}
442
443void Convection_Diffusion_Temperature::assembler_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
444{
445 if (discretisation().is_poly_family() || probleme().que_suis_je().debute_par("Pb_Multiphase"))
446 {
447 Equation_base::assembler_blocs(matrices, secmem, semi_impl);
448 return;
449 }
450 const double rhoCp = get_time_factor();
451 /* mise a zero */
452 secmem = 0;
453 for (auto &&i_m : matrices) i_m.second->get_set_coeff() = 0;
454 matrices_t mats2;
455 for (auto &&i_m : matrices)
456 {
457 Matrice_Morse* mat2 = new Matrice_Morse;
458 *mat2=*i_m.second;
459 mats2[i_m.first] = mat2;
460 }
461
462 /* operateurs, sources, masse */
463 for (int i = 0; i < nombre_d_operateurs(); i++)
464 {
465 DoubleTab secmem_tmp(secmem);
466 secmem_tmp = 0.;
467 for (auto &&i_m : mats2)
468 mats2[i_m.first]->get_set_coeff() = 0;
469
470 operateur(i).l_op_base().ajouter_blocs(mats2, secmem_tmp, semi_impl);
471
472 if (i == 1)
473 {
474 secmem_tmp *= rhoCp;
475 for (auto &&i_m : mats2) *i_m.second *= rhoCp;
476 }
477
478 for (auto &&i_m : matrices) *i_m.second += *mats2[i_m.first];
479 secmem += secmem_tmp;
480
481 }
482 statistics().end_count(STD_COUNTERS::ajouter_blocs,0,0);
483
484 statistics().begin_count(STD_COUNTERS::source_terms,statistics().get_last_opened_counter_level()+1);
485 for (int i = 0; i < les_sources.size(); i++)
486 les_sources(i)->ajouter_blocs(matrices, secmem, semi_impl);
487 statistics().end_count(STD_COUNTERS::source_terms);
488
489 statistics().begin_count(STD_COUNTERS::ajouter_blocs,statistics().get_last_opened_counter_level()+1);
490
491 const std::string& nom_inco = inconnue().le_nom().getString();
492 Matrice_Morse *mat = matrices.count(nom_inco)?matrices.at(nom_inco):nullptr;
493 if(mat) mat->ajouter_multvect(inconnue().valeurs(), secmem);
494
495 for (auto &&i_m : mats2)
496 delete i_m.second;
497
498}
500{
501 //Les ibcs ont elles ete modifiees ?
502 int maj = 0;
503 int tag_all = 0;
504 for ( int w = 0; w<ref_penalisation_L2_FTD.size() ; ++w)
505 {
506 Transport_Interfaces_base& nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[w].valeur());
507 tag_all += nom_eq.get_mesh_tag();
508 }
509 if (tag_all == tag_indic_pena_global) maj = 1;
510 return maj;
511}
512
514{
515 //Les ibcs ont elles ete modifiees ?
516 int maj = 0;
517 int tag_all = 0;
518 for ( int w = 0; w<ref_penalisation_L2_FTD.size() ; ++w)
519 {
520 Transport_Interfaces_base& nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[w].valeur());
521 tag_all += nom_eq.get_mesh_tag();
522 }
523 if (tag_all != tag_indic_pena_global)
524 {
525 tag_indic_pena_global = tag_all;
526 maj = 1;
527 }
528 return maj;
529}
530
532{
533 // Set de la fonction characteristique ibc globlale (element et faces)
535 if (maj == 0)
536 {
539 assert(maj == 1);
540 }
541}
542
543void Convection_Diffusion_Temperature::transport_ibc(DoubleTrav& secmem_conv_vr, DoubleTab& inco_conv_vr)
544{
545 secmem_conv_vr = 0.;
546 const double rhoCp = get_time_factor();
547
548 //fonction characteristique globale ibc au temps courant
550
551 // on calcule l indicatrice epaisse
552 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
553 const IntTab& faces_elem = domaine_vf.face_voisins();
554 IntTrav indic_pena_global_fat(indic_pena_global);
555 for (int i_face = 0; i_face < indic_face_pena_global.size(); i_face++)
556 {
557 if (indic_face_pena_global(i_face) > 0.)
558 {
559 const int voisin_0 = faces_elem(i_face, 0);
560 if (voisin_0 >= 0) indic_pena_global_fat(voisin_0) = 1;
561 const int voisin_1 = faces_elem(i_face, 1);
562 if (voisin_1 >= 0) indic_pena_global_fat(voisin_1) = 1;
563 }
564 }
565 // post-traitement particulier pour les coins
566 const IntTab& elem_faces = domaine_vf.elem_faces();
567 const int nb_faces_elem = elem_faces.dimension(1);
568 const int nb_elem = indic_pena_global.dimension(0);
569 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
570 {
571 if (indic_pena_global_fat(i_elem) == 0)
572 {
573 int coeff = 0;
574 for (int i_face = 0; i_face < nb_faces_elem; i_face++)
575 {
576 const int face = elem_faces(i_elem, i_face);
577 const int voisin = faces_elem(face, 0) + faces_elem(face, 1) - i_elem;
578 if (voisin >= 0)
579 {
580 if (indic_pena_global_fat(voisin) != 0)
581 {
582 ++coeff;
583 }
584 }
585 }
586 if (coeff > 1) indic_pena_global_fat(i_elem) = 1;
587 }
588 }
589
590 // Si on veut un traitement local a chaque indicatrice (necessaire si on utilise vitesse imposee)
591 // IntTrav indic_pena_fat(indic_pena_global);
592 // for (int w = 0; w < ref_penalisation_L2_FTD.size(); w++)
593 // {
594 // Transport_Interfaces_base & nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[w].valeur());
595 // // on calcul le filtre local a l ibc
596 // const DoubleTab & indicatrice_face = nom_eq.get_compute_indicatrice_faces().valeurs();
597 // indic_pena_fat = 0;
598 // for (int i_face = 0; i_face < indicatrice_face.size(); i_face++)
599 // {
600 // if (indicatrice_face(i_face) > 0.)
601 // {
602 // const int voisin_0 = faces_elem(i_face, 0);
603 // if (voisin_0 >= 0) indic_pena_fat(voisin_0) = 1;
604 // const int voisin_1 = faces_elem(i_face, 1);
605 // if (voisin_1 >= 0) indic_pena_fat(voisin_1) = 1;
606 // }
607 // }
608 // indic_pena_global_fat += indic_pena_fat;
609 // }
610
611 // on convecte le champ de variable avec la vitesse fluide pour les faces ibc
612 if ( nombre_d_operateurs() > 1 )
613 {
614 derivee_en_temps_conv(secmem_conv_vr, inco_conv_vr);
615 secmem_conv_vr *= rhoCp;
616 }
617
618 //on ne garde la contribution que pour les cellules dont indicatrice fat est <> 0
619 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
620 {
621 if (indic_pena_global_fat(i_elem) == 0) secmem_conv_vr(i_elem) = 0.;
622 }
623}
624
626{
628 if (maj == 1) return;
629
630 // garde-fou
631 if (schema_temps().facteur_securite_pas() > 1.0)
632 {
633 Cerr << "Convection_Diffusion_Temperature::mise_en_place_domaine_fantome Facteur securite doit etre <= 1"<<finl;
635 }
636
637 // fonction characteristique globale ibc penalisees actuelle
638 IntTrav indicatrice_totale;
639 IntTrav indicatrice_face_totale ;
640 calcul_indic_pena_global(indicatrice_totale,indicatrice_face_totale);
641 // etat des lieux actuel
642 const int nb_elem = indicatrice_totale.dimension(0);
643 int x=0;
644 int j=0;
645 for (int k_elem =0 ; k_elem <nb_elem; ++k_elem) ((indicatrice_totale(k_elem)!=0) ? ++x : ++j);
646
647 //traitement cellules fantomes (if any)
648 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
649 const IntTab& elem_faces = domaine_vf.elem_faces();
650 const IntTab& faces_elem = domaine_vf.face_voisins();
651 const int nb_faces_elem = elem_faces.dimension(1);
652 int k=0; //nb cellules fantomes ibc -> fluide
653 int k_cor=0; //nb cellules fantomes (ibc -> fluide) corrigees
654 int k_cor2=0; //nb cellules fantomes (fluide -> ibc) corrigees
655 int u=0; //nb cellules fluide -> ibc
656 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
657 {
658 //cellules fantomes (actuellement fluide et precedement ibc) => on modifie solution
659 double somme_inc = 0.;
660 double coeff = 0.;
661 if (indic_pena_global(i_elem) != 0 && indicatrice_totale(i_elem) == 0)
662 {
663 ++k;
664 // boucle sur les faces pour determiner la valeur de la variable pour les cellules voisines strictement fluide
665 IntTrav stok_vois(nb_faces_elem);
666 for (int i_face = 0; i_face < nb_faces_elem; i_face++)
667 {
668 const int face = elem_faces(i_elem, i_face);
669 const int voisin = faces_elem(face, 0) + faces_elem(face, 1) - i_elem;
670 if (voisin >= 0) // le voisin existe
671 {
672 if ((indic_pena_global(voisin) == indicatrice_totale(voisin)) && (indic_pena_global(voisin) == indicatrice_totale(i_elem))) // strictement fluide aux deux pas de temps
673 {
674 somme_inc += solution(voisin);
675 ++coeff;
676 }
677 else // On sauve le numero du voisin
678 {
679 stok_vois(i_face) = voisin;
680 }
681 }
682 }
683 // Si on n a pas trouve de cellules fluide, on regarde les voisins des voisins
684 if (coeff == 0.)
685 {
686 for (int i_vois = 0; i_vois < nb_faces_elem; i_vois++)
687 {
688 for (int ii_face = 0; ii_face < nb_faces_elem; ii_face++)
689 {
690 const int face_v = elem_faces(stok_vois(i_vois), ii_face);
691 const int voisin_v = faces_elem(face_v, 0) + faces_elem(face_v, 1) - stok_vois(i_vois);
692 if ((voisin_v >= 0) && (voisin_v != i_elem) )// le voisin existe et pas i_elem
693 {
694 if ((indic_pena_global(voisin_v) == indicatrice_totale(voisin_v)) && (indic_pena_global(voisin_v) == indicatrice_totale(i_elem))) // strictement fluide aux deux pas de temps
695 {
696 somme_inc += solution(voisin_v);
697 ++coeff;
698 }
699 }
700 }
701 }
702 }
703 // definition d une nouvelle valleur de la variable pour la cellule fantome
704 if (coeff > 0.)
705 {
706 solution(i_elem) = somme_inc / coeff;
707 k_cor += 1;
708 }
709 }
710 //cellules actuellement ibc et precedement fluide
711 if (indic_pena_global(i_elem) == 0 && indicatrice_totale(i_elem) != 0)
712 {
713 ++u;
714 // boucle sur les faces pour determiner la valeur de la variable pour les cellules voisines strictement ibc
715 IntTrav stok_vois(nb_faces_elem);
716 for (int i_face = 0; i_face < nb_faces_elem; i_face++)
717 {
718 const int face = elem_faces(i_elem, i_face);
719 const int voisin = faces_elem(face, 0) + faces_elem(face, 1) - i_elem;
720 if (voisin >= 0) // le voisin existe
721 {
722 // strictement ibc aux deux pas de temps (la meme) car solution a ete modifiee ci-dessus
723 if ((indic_pena_global(voisin) == indicatrice_totale(voisin)) && (indic_pena_global(voisin) == indicatrice_totale(i_elem)))
724 {
725 somme_inc += solution(voisin);
726 ++coeff;
727 }
728 else // On sauve le numero du voisin
729 {
730 stok_vois(i_face) = voisin;
731 }
732 }
733 }
734 // Si on n a pas trouve de cellules ibc, on regarde les voisins des voisins
735 if (coeff == 0.)
736 {
737 for (int i_vois = 0; i_vois < nb_faces_elem; i_vois++)
738 {
739 for (int ii_face = 0; ii_face < nb_faces_elem; ii_face++)
740 {
741 const int face_v = elem_faces(stok_vois(i_vois), ii_face);
742 const int voisin_v = faces_elem(face_v, 0) + faces_elem(face_v, 1) - stok_vois(i_vois);
743 if ((voisin_v >= 0) && (voisin_v != i_elem) )// le voisin existe et pas i_elem
744 {
745 if ((indic_pena_global(voisin_v) == indicatrice_totale(voisin_v)) && (indic_pena_global(voisin_v) == indicatrice_totale(i_elem))) // strictement ibc aux deux pas de temps (la meme) car solution a ete modifiee ci-dessus
746 {
747 somme_inc += solution(voisin_v);
748 ++coeff;
749 }
750 }
751 }
752 }
753 }
754 // definition d une nouvelle valleur de la variable pour la cellule fantome
755 if (coeff > 0.)
756 {
757 solution(i_elem) = somme_inc / coeff;
758 k_cor2 += 1;
759 }
760 else
761 {
762 solution(i_elem) = tab_penalisation_L2_FTD[indicatrice_totale(i_elem)-1](0);
763 k_cor2 += 1;
764 }
765 }
766 }
767 solution.echange_espace_virtuel();
768 // Debog::verifier("Convection_Diffusion_Temperature::mise_en_place_domaine_fantome solution ",solution);
769 Cout <<"Mise_en_place_domaine_fantome : fluide -> ibc : "<<u<< " elem. (dont "<<k_cor2<<" corrigees) et ibc -> fluide : ";
770 Cout<<k<<" elem.(dont "<<k_cor<<" corrigees)"<<finl;
771 Cout <<" nb elem. ibc : "<<x<<" et nb elem fluide : "<<j<<" sur un total de : "<<nb_elem<<finl;
772 if ((u != k_cor2) || (k !=k_cor))
773 {
774 Cerr <<"Mise_en_place_domaine_fantome : Les cellules fantomes ne sont pas toutes corrigees"<<finl;
775 exit();
776 }
777
778 indic_pena_global = indicatrice_totale;
779 indic_face_pena_global = indicatrice_face_totale;
781 assert(maj == 1);
782}
783
784DoubleTab& Convection_Diffusion_Temperature::filtrage_si_appart_ibc(DoubleTab& u_conv, DoubleTab& u)
785{
786 // caclul de la fonction caracteristique globale des ibc pour le calcul de T_voisinage
788
789 for (int j = 0 ; j< indic_pena_global.size() ; ++j)
790 {
791 if ( indic_pena_global(j) != 0) u(j) = u_conv(j);
792 }
794 // Debog::verifier("Convection_Diffusion_Temperature::filtrage_si_appart_ibc u ",u);
795 return u;
796}
797
798void Convection_Diffusion_Temperature::calcul_indic_pena_global(IntTab& indicatrice_totale, IntTab& indicatrice_face_totale)
799{
800 // fonction characteristique globale ibc penalisees
801 indicatrice_totale.copy(indic_pena_global);
802 indicatrice_face_totale.copy(indic_face_pena_global);
803 indicatrice_totale = 0;
804 indicatrice_face_totale = 0;
805 int x=0;
806 int xf=0;
807 const int nb_elem = indicatrice_totale.dimension_tot(0);
808 const int nfaces = indicatrice_face_totale.dimension_tot(0);
809 // boucle sur les ibc
810 for ( int w = 0 ; w<ref_penalisation_L2_FTD.size() ; ++w)
811 {
812 Transport_Interfaces_base& nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[w].valeur());
814 const DoubleTab& indicatrice = nom_eq.get_indicatrice().valeurs();
815 // fonction characteristique (0 ou 1) pour l'ensemble des ibc
816 for (int k_elem =0 ; k_elem <nb_elem; ++k_elem)
817 {
818 if (indicatrice(k_elem)>0.)
819 {
820 if(indicatrice_totale(k_elem) != 0)
821 {
822 Cerr<<"calcul_indic_pena_global : Attention: les elements des indicatrices se chevauchent "<<finl;
823 exit();
824 }
825 indicatrice_totale(k_elem) = w+1;
826 ++x;
827 }
828 }
829 // fonction characteristique (numero ibc) pour l'ensemble des ibc
830 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
831 const IntTab& face_voisins = domaine_vf.face_voisins();
832 for (int i = 0; i < nfaces ; i++)
833 {
834 const int elem0 = face_voisins(i, 0);
835 const int elem1 = face_voisins(i, 1);
836 double indi = 0.;
837 if (elem0 >= 0) indi = indicatrice(elem0);
838 if (elem1 >= 0) indi += indicatrice(elem1);
839 if(indi > 0.)
840 {
841 if(indicatrice_face_totale(i) != 0)
842 {
843 Cerr<<"calcul_indic_pena_global : Attention: les faces des indicatrices se chevauchent "<<finl;
844 exit();
845 }
846 indicatrice_face_totale(i) = w+1;
847 ++xf;
848 }
849 }
850 }
851 Cout<<"Calcul_indic_pena_global : Nb d elements de l indicatrice globale des IBCs: "<<x;
852 Cout<<" et nb de faces : "<<xf<<finl;
853 indicatrice_totale.echange_espace_virtuel();
854 indicatrice_face_totale.echange_espace_virtuel();
855 // Debog::verifier("Convection_Diffusion_Temperature::calcul_indic_pena_global indicatrice_totale ",indicatrice_totale);
856 // Debog::verifier("Convection_Diffusion_Temperature::calcul_indic_pena_global indicatrice_face_totale ",indicatrice_face_totale);
857}
858
860{
861 // garde-fou
862 assert(ref_penalisation_L2_FTD.size() != 0);
863 assert(ref_penalisation_L2_FTD.size() == tab_penalisation_L2_FTD.size());
864
865 const double dt = schema_temps().pas_de_temps();
866 DoubleTab u_old(u);
867
868 // caclul de la fonction caracteristique globale des ibc pour le calcul de T_voisinage
870
871 //calcul de T_voisinage pour tous les elemnts
872 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
873 const IntTab& elem_faces = domaine_vf.elem_faces();
874 const IntTab& faces_elem = domaine_vf.face_voisins();
875 const int nb_faces_elem = elem_faces.dimension(1);
876 const DoubleTab& inc=inconnue().valeurs();
877 // inconnue doit etre scalaire
878 assert(inc.line_size() == 1);
879 DoubleTrav t_voisinage(inc);
880 DoubleTrav u_voisinage(u);
881 const int nb_elem = u.dimension_tot(0);
882 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
883 {
884 double somme = 0.;
885 double somme_deriv = 0.;
886 double coeff = 0.;
887
888 if( indic_pena_global(i_elem) != 0)
889 {
890 // boucle sur les faces de l element
891 for (int i_face = 0; i_face < nb_faces_elem; i_face++)
892 {
893 const int face = elem_faces(i_elem, i_face);
894 const int voisin = faces_elem(face, 0) + faces_elem(face, 1) - i_elem;
895 if (voisin >= 0)
896 {
897 if (indic_pena_global(voisin) == 0)
898 {
899 somme += inc(voisin);
900 somme_deriv += u(voisin);
901 coeff += 1.;
902 }
903 }
904 }
905 }
906
907 if (coeff > 0.)
908 {
909 t_voisinage(i_elem) = somme / coeff;
910 u_voisinage(i_elem) = somme_deriv / coeff;
911 }
912 else
913 {
914 // cas pas de voisin dans le fluide
915 t_voisinage(i_elem) = inc(i_elem);
916 u_voisinage(i_elem) = u(i_elem);
917 }
918 }
919 t_voisinage.echange_espace_virtuel();
920 u_voisinage.echange_espace_virtuel();
921
922 //determination du champ global de penalisation L2
923 DoubleTrav pena_glob(inc); //initialise a zero
924 DoubleTrav tab_(inc); //initialise a zero
925 DoubleTrav denom(inc); //initialise a zero
926
927 //boucle ibc
928 for ( int i = 0 ; i < ref_penalisation_L2_FTD.size() ; ++i)
929 {
930 Transport_Interfaces_base& nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[i].valeur());
931 const DoubleTab& tab = tab_penalisation_L2_FTD[i];
932 //verification dimensions tab t obstacle = nb dim de l inconnu
933 if ( tab.dimension(0) != inc.line_size() )
934 {
935 Cerr << " penalisation_L2: Les champs de temperature impose et calcule n'ont pas les memes dimensions" <<finl;
936 Cerr << " Dimension du champ de temperature impose "<< tab.dimension(0) << finl;
937 Cerr << " Dimension du champ de temperature calcule par TRUST "<<inc.line_size() <<finl;
938 Cerr << " Nombre d'elements stockes au dans l'iconnue " <<inc.size() <<finl;
940 }
942 const DoubleTab& indicatrice = nom_eq.get_indicatrice().valeurs();
943
944 DoubleTrav pena_loc(indicatrice);
945 // Determination du terme de penalisation pour l ibc courante
946 // boucle sur les elements
947 for (int j = 0; j<nb_elem ; ++j)
948 {
949 //calcul de la fonction characteristique Ksi de l ibc courante -> pena_loc
950 if (indicatrice(j) > 0.)
951 {
952 double coeff_p=1.;
953 pena_loc(j) = coeff_p;
954 //calcul du denominateur du terme de penalisation ( Sigma_ibc Ksi_ibc(j) )
955 denom(j) += coeff_p;
956
957 //determination valeur a imposer T_ref
958 double tref_j = 0.;
959 switch (choix_pena)
960 {
961 case 0 :
962 // approximation de T_ref par T_ref = T_imp
963 tref_j = tab(0);
964 break;
965 case 1 :
966 // approximation de T_ref par T_ref = T+dt*derivee
967 tref_j = inc(j) + dt*u_old(j);
968 break;
969 case 2 :
970 // approximation de T_imp par T_ref= tau*T_imp + (1-tau)*T_voisin
971 // approximation de T_voisin par T_voisin= 1/n * somme(1,n)(T_environnant+dt*derivee_environnant)
972 tref_j = (indicatrice(j)*tab(0)+(1.-indicatrice(j))*(t_voisinage(j)+dt*u_voisinage(j)));
973 break;
974 case 3 :
975 // approximation de T_imp par T_ref= [(1-tau)*T_voisin + (1/2)*T_imp] / (3/2 -tau)
976 // approximation de T_voisin par T_voisin= 1/n * somme(1,n)(T_environnant+dt*derivee_environnant)
977 tref_j = ((1.-indicatrice(j))*(t_voisinage(j)+dt*u_voisinage(j))+0.5*tab(0))/(1.5-indicatrice(j));
978 break;
979 case 4 :
980 // approximation de T_imp par T_ref= T_imp si tau=1 sinon T_ref=T_voisin
981 if (indicatrice(j) == 1.)
982 {
983 tref_j = tab(0);
984 }
985 else
986 {
987 tref_j = (t_voisinage(j)+dt*u_voisinage(j));
988 }
989 break;
990 default:
991 Cerr << "Penalisation_L2: choix_pena invalide "<< choix_pena <<finl;
992 exit();
993 break;
994 }
995 // sauvegarde de Sigma_ibc Ksi_ibc(j) Tref_ibc pour post-traitement
996 tab_(j) += tref_j;
997 // penalisation_global = Sigma_ibc Ksi_ibc(j)*(Tref_ibc - inc) / eta;
998 pena_loc(j) *= (tref_j-inc(j));
999 pena_loc(j) /= eta;
1000 pena_glob(j) += pena_loc(j);
1001 }
1002 }
1003 }
1004
1005 // Realisation de la penalisation L2 de la derivee en temps: (dT_t_* + pena_glob) / ( 1 + (dt*Sigma_ibc Ksi_ibc(j)) / eta )
1006 // Tref est la moyenne arithmetique de Tref_j lorsque 0<eta<<1
1007 for (int j = 0 ; j<nb_elem ; ++j)
1008 {
1009 u(j) = u_old(j) + pena_glob(j);
1010 u(j) /= (1. + denom(j)*dt/eta);
1011 }
1013
1014 // Sauvegarde des flux
1015 ecrire_fichier_pena_th(u_old,u,tab_,denom);
1016
1017 // Debog::verifier("Convection_Diffusion_Temperature::penalisation_L2 u ",u);
1018 return u;
1019}
1020
1021void ouvrir_fichier_pena_th(SFichier& os, const Nom& type, const int flag, const Transport_Interfaces_base& equation)
1022{
1023 // flag nul on n'ouvre pas le fichier
1024 if (flag==0)
1025 return ;
1026 Nom fichier=Objet_U::nom_du_cas();
1027 fichier+="_";
1028 fichier+=type;
1029 fichier+="_";
1030 fichier+=equation.le_nom();
1031 fichier+=".out";
1032 const Schema_Temps_base& sch=equation.probleme().schema_temps();
1033 const int precision=sch.precision_impr();
1034 // On cree le fichier a la premiere impression avec l'en tete
1035 if (sch.nb_impr()==1 && !equation.probleme().reprise_effectuee())
1036 {
1037 os.ouvrir(fichier);
1038 SFichier& fic=os;
1039 Nom espace="\t\t";
1040 fic << (Nom)"# Impression puissance thermique";
1041 fic << " interface " << equation.le_nom();
1042 fic << " en W" << "." << finl;
1043 fic << finl << "# Temps";
1044
1045 Nom ch=espace;
1046 ch+="P";
1047 fic << ch << finl;
1048 }
1049 // Sinon on l'ouvre
1050 else
1051 {
1052 os.ouvrir(fichier,ios::app);
1053 }
1054 os.precision(precision);
1055 os.setf(ios::scientific);
1056}
1057
1058void Convection_Diffusion_Temperature::ecrire_fichier_pena_th(DoubleTab& u_old, DoubleTab& u, DoubleTab& tref, DoubleTab& denom)
1059{
1060
1061 if (le_schema_en_temps->limpr())
1062 {
1063
1064 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1065 const DoubleVect& vol_maille = domaine_vf.volumes();
1066 const Fluide_base& fluide_inc = ref_cast(Fluide_base, milieu());
1067 const DoubleTab& tab_rho = fluide_inc.masse_volumique().valeurs();
1068 const double rho = tab_rho(0,0);
1069 const DoubleTab& tab_cp = fluide_inc.capacite_calorifique().valeurs();
1070 const double cp = tab_cp(0,0);
1071
1072 // Methode pour calculer le flux total sur les ibc
1073
1074 //Calcul de T_n+1 apres penalisation
1075 const DoubleTab& inc=inconnue().valeurs();
1076 const int nb_elem = u.dimension(0);
1077 const double dt = schema_temps().pas_de_temps();
1078 DoubleTab tkp1(inc);
1079 for (int k = 0 ; k<nb_elem ; ++k) tkp1(k) += u(k)*dt;
1080
1081 //Terme de penalisation: Sigma_ibc Ksi_ibc * ( T_n+1 - Tref_ibc) / eta
1082 DoubleTrav F(inc);
1083 for (int j = 0; j<nb_elem; ++j) F(j) = (tref(j)-denom(j)*tkp1(j))/eta;
1084
1085 // boucle sur les IBC
1086
1087 DoubleTrav filtre(nb_elem);
1088 DoubleTrav filtre_glob(nb_elem);
1089 const double temps_flux = le_schema_en_temps->temps_courant();
1090 Nom espace=" \t";
1091
1092 for ( int i = 0 ; i < ref_penalisation_L2_FTD.size() ; ++i) //boucle sur le nombre d'ibc
1093 {
1094 Transport_Interfaces_base& nom_eq = ref_cast(Transport_Interfaces_base,ref_penalisation_L2_FTD[i].valeur());
1095 const DoubleTab& indicatrice = nom_eq.get_indicatrice().valeurs();
1096 double Flux_pena= 0.;
1097 double Flux_pena_old= 0.;
1098 double Flux_temp_interne= 0.;
1099 //Filtre ibc (1) / non ibc (0)
1100 filtre = 0.;
1101 for ( int j = 0 ; j<nb_elem ; ++j)
1102 {
1103 if (indicatrice(j) > 0.)
1104 {
1105 filtre(j) = 1.;
1106 filtre_glob(j)=1.;
1107 }
1108 //bilans
1109 //Attention rho et cp constants
1110 Flux_pena_old += u_old(j) * filtre(j) *rho *cp *vol_maille(j);
1111 Flux_pena += F(j) * filtre(j) * vol_maille(j) *rho *cp;
1112 Flux_temp_interne += filtre(j)*rho*cp*vol_maille(j)*u(j);
1113 }
1114
1115 // Ajout des differents processeurs en //
1116 Flux_pena_old = mp_sum(Flux_pena_old);
1117 Flux_pena = mp_sum(Flux_pena);
1118 Flux_temp_interne = mp_sum(Flux_temp_interne);
1119
1120 //ecriture
1122 {
1123 SFichier FTE;
1124 ouvrir_fichier_pena_th(FTE,"Puissance_penalisation_thermique_ibc",1,nom_eq);
1125 FTE << temps_flux;
1126 FTE << espace << Flux_pena;
1127 FTE << finl;
1128
1129 SFichier FTI;
1130 ouvrir_fichier_pena_th(FTI,"Puissance_thermique_ibc",1,nom_eq);
1131 FTI << temps_flux;
1132 FTI << espace << Flux_pena_old;
1133 FTI << finl;
1134
1135 SFichier FTTI;
1136 ouvrir_fichier_pena_th(FTTI,"Derivee_temps_temperature_ibc",1,nom_eq);
1137 FTTI << temps_flux;
1138 FTTI << espace << Flux_temp_interne;
1139 FTTI << finl;
1140 }
1141 }
1142
1143 //bilan Derivee_temps_temperature_fluide
1144 //Attention rho et cp constants
1145 double Flux_temp_externe= 0.;
1146 for (int j = 0; j<nb_elem; ++j)
1147 {
1148 Flux_temp_externe += (1.-filtre_glob(j)) *rho *cp *vol_maille(j) * u(j); //fluide
1149 }
1150
1151 // Ajout des differents processeurs en //
1152 Flux_temp_externe = mp_sum(Flux_temp_externe); //fluide
1153
1154 //ecriture
1156 {
1157 SFichier fichier;
1158 Nom fichier_nom=Objet_U::nom_du_cas();
1159 fichier_nom+="_";
1160 fichier_nom+="Derivee_temps_temperature_fluide.out";
1161 if (le_schema_en_temps->nb_impr()==1 && !probleme().reprise_effectuee())
1162 {
1163 fichier.ouvrir(fichier_nom);
1164 }
1165 else
1166 {
1167 fichier.ouvrir(fichier_nom,ios::app);
1168 }
1169 //if (fichier)
1170 {
1171 (fichier) <<temps_flux<<" \t"<<Flux_temp_externe<<finl;
1172
1173 }
1174 }
1175 }
1176}
1177
1178void Convection_Diffusion_Temperature::calculer_rho_cp_T(const Objet_U& obj, DoubleTab& val, DoubleTab& bval, tabs_t& deriv)
1179{
1180 const Equation_base& eqn = ref_cast(Equation_base, obj);
1181 const Fluide_base& fl = ref_cast(Fluide_base, eqn.milieu());
1182 const Champ_Inc_base& ch_T = eqn.inconnue();
1183 const Champ_base& ch_rho = fl.masse_volumique();
1184 assert(sub_type(Champ_Uniforme, ch_rho));
1185 const Champ_Don_base& ch_cp = fl.capacite_calorifique();
1186 const DoubleTab& cp = fl.capacite_calorifique().valeurs(), &rho = ch_rho.valeurs(), &T = ch_T.valeurs();
1187
1188 /* valeurs du champ */
1189 const int N = val.line_size(), Nl = val.dimension_tot(0), cCp = sub_type(Champ_Uniforme, ch_cp);
1190 for (int i = 0; i < Nl; i++)
1191 for (int n = 0; n < N; n++) val(i, n) = rho(0, n) * cp(!cCp * i, n) * T(i, n);
1192
1193 /* on ne peut utiliser valeur_aux_bords que si ch_rho a un domaine_dis_base */
1194 DoubleTab b_cp = cCp ? cp : ch_cp.valeur_aux_bords(), b_T = ch_T.valeur_aux_bords();
1195 int Nb = b_T.dimension_tot(0);
1196 // on suppose que rho est un champ_uniforme : on utilise directement le tableau du champ
1197 for (int i = 0; i < Nb; i++)
1198 for (int n = 0; n < N; n++) bval(i, n) = b_cp(!cCp * i, n) * rho(0, n) * b_T(i, n);
1199
1200 DoubleTab& d_T = deriv["temperature"];
1201 d_T.resize(Nl, N);
1202 for (int i = 0; i < Nl; i++)
1203 for (int n = 0; n < N; n++) d_T(i, n) = rho(0, n) * cp(!cCp * i, n);
1204
1205}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
void mettre_a_jour(double temps) override
Mise a jour en temps du champ.
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
DoubleTab valeur_aux_bords() const override
renvoie la valeur du champ aux faces de bord
virtual DoubleTab & valeurs()=0
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual DoubleTab valeur_aux_bords() const
renvoie la valeur du champ aux faces de bord
double temps() const
Renvoie le temps du champ.
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
const Champ_base & get_champ(const Motcle &nom) const override
void get_noms_champs_postraitables(Noms &nom, Option opt=NONE) const override
classe Convection_Diffusion_Temperature Cas particulier de Convection_Diffusion_std
void ecrire_fichier_pena_th(DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &)
static void calculer_rho_cp_T(const Objet_U &obj, DoubleTab &val, DoubleTab &bval, tabs_t &deriv)
const Champ_Inc_base & inconnue() const override
const Motcle & domaine_application() const override
Renvoie le nom du domaine d'application de l'equation.
const Champ_base & get_champ(const Motcle &nom) const override
void associer_milieu_base(const Milieu_base &) override
Associe un milieu physique a l'equation, le milieu est en fait caste en Fluide_base.
DoubleTab & derivee_en_temps_inco(DoubleTab &) override
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
void get_noms_champs_postraitables(Noms &nom, Option opt=NONE) const override
void discretiser() override
Discretise l'equation.
DoubleTab & filtrage_si_appart_ibc(DoubleTab &, DoubleTab &)
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
void creer_champ(const Motcle &motlu) override
void assembler_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={}) const override
void assembler(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem) override
int preparer_calcul() override
Tout ce qui ne depend pas des autres problemes eventuels.
const Operateur & operateur(int) const override
Renvoie l'operateur specifie par son index: renvoie terme_diffusif si i = 0.
int nombre_d_operateurs() const override
Renvoie le nombre d'operateurs de l'equation: 2 pour une equation de diffusion.
void temperature(const Schema_Temps_base &, Domaine_dis_base &, OWN_PTR(Champ_Inc_base)&, int nb_comp=1) const
classe Discret_Thyd Cette classe est la classe de base representant une discretisation
virtual void h_conv(const Domaine_dis_base &z, const Domaine_Cl_dis_base &zcl, const Champ_Inc_base &eqn, OWN_PTR(Champ_Fonc_base)&ch, Motcle &nom, int temp_ref) const
virtual void grad_T(const Domaine_dis_base &z, const Domaine_Cl_dis_base &zcl, const Champ_Inc_base &eqn, OWN_PTR(Champ_Fonc_base)&ch) const
virtual type_calcul_du_residu codage_du_calcul_du_residu() const
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
class Domaine_VF
Definition Domaine_VF.h:44
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
double volumes(int i) const
Definition Domaine_VF.h:113
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 face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual void set_param(Param &titi) const override
const Nom & le_nom() const override
Renvoie le nom de l'equation.
virtual const Milieu_base & milieu() const =0
DoubleTab & derivee_en_temps_conv(DoubleTab &, const DoubleTab &)
Add convection term In: solution is the unknown I.
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
virtual const Champ_Inc_base & inconnue() const =0
int calculate_time_derivative() const
Sources les_sources
virtual int preparer_calcul()
Tout ce qui ne depend pas des autres problemes eventuels.
virtual DoubleTab & derivee_en_temps_inco(DoubleTab &)
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
virtual void discretiser()
Discretise l'equation.
Champs_compris champs_compris_
virtual void assembler_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={}) const
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
classe Fluide_base Cette classe represente un d'un fluide incompressible ainsi que
Definition Fluide_base.h:38
Classe Fluide_reel_base Cette classe represente un fluide reel ainsi que.
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Operation de multiplication-accumulation (saxpy) matrice vecteur.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
auto & get_set_coeff()
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
virtual const Champ_Don_base & capacite_calorifique() const
Renvoie la capacite calorifique du milieu.
virtual const Champ_base & masse_volumique() const
Renvoie la masse volumique du milieu.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Nom & suffix(const char *const)
Extraction de suffixe : Nom x("azerty");.
Definition Nom.cpp:271
const std::string & getString() const
Definition Nom.h:92
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
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
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
virtual void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
DOES NOTHING - to override in derived classes.
void tester_contribuer_a_avec(const DoubleTab &, const Matrice_Morse &)
virtual void contribuer_au_second_membre(DoubleTab &) const
DOES NOTHING - to override in derived classes.
virtual void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const
virtual Operateur_base & l_op_base()=0
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const =0
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
const Discretisation_base & discretisation() const
Renvoie la discretisation associee au probleme.
bool & reprise_effectuee()
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
class Schema_Temps_base
int nb_impr() const
Renvoie le nombre d'impressions effectuees.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual void modifier_second_membre(const Equation_base &eqn, DoubleTab &secmem)
double temps_init() const
Renvoie le temps initial.
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
contribution a la matrice implicite des termes sources par defaut pas de contribution
Definition Sources.cpp:201
DoubleTab & ajouter(DoubleTab &) const
Ajoute la contribution de toutes les sources de la liste au tableau passe en parametre,...
Definition Sources.cpp:85
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
void copy(const TRUSTTab &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:622
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
classe Transport_Interfaces_base Cette classe constitue la classe de base des equations de transport ...
virtual void check_indicatrice_is_up_to_date()=0
virtual const Champ_base & get_indicatrice()=0
virtual int get_mesh_tag() const =0