TrioCFD 1.9.9_beta
TrioCFD documentation
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(); // Plan for passive scalar equations
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 << "Reading the penalization value along direction " << i+1 <<" :" << tab(i) << finl;
99 }
101 is >> mot ;
102 }
103 }
104 else
105 {
106 Cerr << "Error while reading the parameters of the L2 penalization " << finl;
107 Cerr << "We expected: " << 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 Associates a physical medium to the equation; the medium is cast to Fluide_base.
120 *
121 * @param un_milieu the physical medium to associate
122 * @throws the medium is not of type 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() + " : the fluid " + un_milieu.que_suis_je() + " is not of 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; /* nothing found */
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; /* nothing found */
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 Returns the name of the application domain of the equation.
282 *
283 * Here "Thermique".
284 *
285 * @return the name of the application domain of the 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 // Setting up the ghost domain method
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 // IBC and boundary layer transport
319 DoubleTrav secmem_conv_vr(derivee);
320 //advect the variable with the IBC velocity
321 transport_ibc(secmem_conv_vr, derivee);
322 //subtract this 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 // temperature penalization
345 penalisation_L2(derivee);
346 return derivee;
347 }
348}
349
354
355// Adds contributions from operators and 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 of the contribuer_a_avec method
361 for (int op=0; op<nombre_d_operateurs(); op++)
362 operateur(op).l_op_base().tester_contribuer_a_avec(inco, matrice);
363
364 // Contributions from operators and sources:
365 // [Vol/dt+A]Inco(n+1)=sum(residual)+Vol/dt*Inco(n)
366 // Typically: if Op=flux(Inco) then the implicit matrix A contains a contribution -dflux/dInco
367 // Example: convective flux operator in VDF:
368 // Op=T*u*S and A=-d(T*u*S)/dT=-u*S
371 {
372 if ( probleme().discretisation().que_suis_je() == "EF")
373 {
374 // Compute sum(residual) via contribuer_au_second_membre (typically for non-implicitized BCs)
375 // This approach requires coding 3 methods (contribuer_a_avec, contribuer_au_second_membre, and ajouter for the explicit scheme)
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 not implemented for " << que_suis_je() << ":assembler" << finl;
390 Cerr << "with discretization " << probleme().discretisation().que_suis_je() << "" << finl;
392 }
393 // // Compute sum(residual) via contribuer_au_second_membre (typically for non-implicitized BCs)
394 // // This approach requires coding 3 methods (contribuer_a_avec, contribuer_au_second_membre, and ajouter for the explicit scheme)
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 // Compute sum(residual) via sum(operator)+sources+A*Inco(n)
407 // This approach requires coding only two methods (contribuer_a_avec and ajouter)
408 // Slightly more expensive computationally but less code to write/maintain
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; // the time derivative is multiplied by rhoCp for 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); // Add A*Inco(n)
432 // PL (11/04/2018): It would be nice to compute the source contributions first
433 // as in the VIA_CONTRIBUER_AU_SECOND_MEMBRE case, but Canal_perio_3D (periodic keps
434 // crashes: there is a periodicity error in the source terms of the KEps model...
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 //Have the IBCs been modified?
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 //Have the IBCs been modified?
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 the global IBC characteristic function (elements and 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 //global IBC characteristic function at the current time
550
551 // compute the thick indicator
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 // special post-processing for corners
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 // For a local treatment per indicatrice (necessary if using imposed velocity)
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 // convect the variable field with the fluid velocity for IBC faces
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 //keep the contribution only for cells whose fat indicator is != 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 // safety check
631 if (schema_temps().facteur_securite_pas() > 1.0)
632 {
633 Cerr << "Convection_Diffusion_Temperature::mise_en_place_domaine_fantome safety factor must be <= 1"<<finl;
635 }
636
637 // current global penalized IBC characteristic function
638 IntTrav indicatrice_totale;
639 IntTrav indicatrice_face_totale ;
640 calcul_indic_pena_global(indicatrice_totale,indicatrice_face_totale);
641 // current state
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 //ghost cell treatment (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; //number of ghost cells ibc -> fluid
653 int k_cor=0; //number of ghost cells (ibc -> fluid) corrected
654 int k_cor2=0; //number of ghost cells (fluid -> ibc) corrected
655 int u=0; //number of fluid -> ibc cells
656 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
657 {
658 //ghost cells (currently fluid, previously ibc) => modify 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 // loop over faces to determine the variable value for strictly fluid neighbouring cells
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) // the neighbour exists
671 {
672 if ((indic_pena_global(voisin) == indicatrice_totale(voisin)) && (indic_pena_global(voisin) == indicatrice_totale(i_elem))) // strictly fluid at both time steps
673 {
674 somme_inc += solution(voisin);
675 ++coeff;
676 }
677 else // save the neighbour index
678 {
679 stok_vois(i_face) = voisin;
680 }
681 }
682 }
683 // If no fluid cells found, check neighbours of neighbours
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) )// the neighbour exists and is not i_elem
693 {
694 if ((indic_pena_global(voisin_v) == indicatrice_totale(voisin_v)) && (indic_pena_global(voisin_v) == indicatrice_totale(i_elem))) // strictly fluid at both time steps
695 {
696 somme_inc += solution(voisin_v);
697 ++coeff;
698 }
699 }
700 }
701 }
702 }
703 // define a new value of the variable for the ghost cell
704 if (coeff > 0.)
705 {
706 solution(i_elem) = somme_inc / coeff;
707 k_cor += 1;
708 }
709 }
710 //cells currently ibc and previously fluid
711 if (indic_pena_global(i_elem) == 0 && indicatrice_totale(i_elem) != 0)
712 {
713 ++u;
714 // loop over faces to determine the variable value for strictly ibc neighbouring cells
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) // the neighbour exists
721 {
722 // strictly ibc at both time steps (the same) because solution was modified above
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 // save the neighbour index
729 {
730 stok_vois(i_face) = voisin;
731 }
732 }
733 }
734 // If no ibc cells found, check neighbours of neighbours
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) )// the neighbour exists and is not i_elem
744 {
745 if ((indic_pena_global(voisin_v) == indicatrice_totale(voisin_v)) && (indic_pena_global(voisin_v) == indicatrice_totale(i_elem))) // strictly ibc at both time steps (the same) because solution was modified above
746 {
747 somme_inc += solution(voisin_v);
748 ++coeff;
749 }
750 }
751 }
752 }
753 }
754 // define a new value of the variable for the ghost cell
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 : fluid -> ibc : "<<u<< " elem. (of which "<<k_cor2<<" corrected) and ibc -> fluid : ";
770 Cout<<k<<" elem.(of which "<<k_cor<<" corrected)"<<finl;
771 Cout <<" nb ibc elem. : "<<x<<" and nb fluid elem. : "<<j<<" out of a total of : "<<nb_elem<<finl;
772 if ((u != k_cor2) || (k !=k_cor))
773 {
774 Cerr <<"Mise_en_place_domaine_fantome : Not all ghost cells have been corrected"<<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 // compute the global IBC characteristic function for the neighbourhood temperature 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 // global penalized IBC characteristic function
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 // loop over ibcs
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 // characteristic function (0 or 1) for all IBCs
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 : Warning: the elements of the indicator functions overlap "<<finl;
823 exit();
824 }
825 indicatrice_totale(k_elem) = w+1;
826 ++x;
827 }
828 }
829 // characteristic function (IBC number) for all IBCs
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 : Warning: the faces of the indicator functions overlap "<<finl;
844 exit();
845 }
846 indicatrice_face_totale(i) = w+1;
847 ++xf;
848 }
849 }
850 }
851 Cout<<"Calcul_indic_pena_global : Number of elements of the global IBC indicator: "<<x;
852 Cout<<" and number of 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 // compute the global IBC characteristic function for the neighbourhood temperature T_voisinage
870
871 //compute T_voisinage for all elements
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 // the unknown must be scalar
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 // loop over faces of the 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 // case: no fluid neighbour
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 of the global L2 penalization field
923 DoubleTrav pena_glob(inc); //initialise a zero
924 DoubleTrav tab_(inc); //initialise a zero
925 DoubleTrav denom(inc); //initialise a zero
926
927 //loop over IBCs
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 //check dimensions: tab t obstacle = nb dimensions of the unknown
933 if ( tab.dimension(0) != inc.line_size() )
934 {
935 Cerr << " penalisation_L2: The imposed and computed temperature fields do not have the same dimensions" <<finl;
936 Cerr << " Dimension of the imposed temperature field "<< tab.dimension(0) << finl;
937 Cerr << " Dimension of the temperature field computed by TRUST "<<inc.line_size() <<finl;
938 Cerr << " Number of elements stored in the unknown " <<inc.size() <<finl;
940 }
942 const DoubleTab& indicatrice = nom_eq.get_indicatrice().valeurs();
943
944 DoubleTrav pena_loc(indicatrice);
945 // Determine the penalization term for the current IBC
946 // loop over elements
947 for (int j = 0; j<nb_elem ; ++j)
948 {
949 //compute the characteristic function Ksi for the current IBC -> pena_loc
950 if (indicatrice(j) > 0.)
951 {
952 double coeff_p=1.;
953 pena_loc(j) = coeff_p;
954 //compute the denominator of the penalization term ( Sigma_ibc Ksi_ibc(j) )
955 denom(j) += coeff_p;
956
957 //determine the value to impose T_ref
958 double tref_j = 0.;
959 switch (choix_pena)
960 {
961 case 0 :
962 // approximation of T_ref by T_ref = T_imp
963 tref_j = tab(0);
964 break;
965 case 1 :
966 // approximation of T_ref by T_ref = T+dt*derivative
967 tref_j = inc(j) + dt*u_old(j);
968 break;
969 case 2 :
970 // approximation of T_imp by T_ref= tau*T_imp + (1-tau)*T_neighbour
971 // approximation of T_neighbour by T_neighbour= 1/n * sum(1,n)(T_surrounding+dt*derivative_surrounding)
972 tref_j = (indicatrice(j)*tab(0)+(1.-indicatrice(j))*(t_voisinage(j)+dt*u_voisinage(j)));
973 break;
974 case 3 :
975 // approximation of T_imp by T_ref= [(1-tau)*T_neighbour + (1/2)*T_imp] / (3/2 -tau)
976 // approximation of T_neighbour by T_neighbour= 1/n * sum(1,n)(T_surrounding+dt*derivative_surrounding)
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 of T_imp by T_ref= T_imp if tau=1, else T_ref=T_neighbour
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: invalid choix_pena "<< choix_pena <<finl;
992 exit();
993 break;
994 }
995 // store Sigma_ibc Ksi_ibc(j) Tref_ibc for post-processing
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 // Apply the L2 penalization of the time derivative: (dT_t_* + pena_glob) / ( 1 + (dt*Sigma_ibc Ksi_ibc(j)) / eta )
1006 // Tref is the arithmetic mean of Tref_j when 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 // Save fluxes
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 // Method to compute the total flux on the IBCs
1073
1074 //Compute T_n+1 after penalization
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 // loop over IBCs
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) //loop over the number of IBCs
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 //Filter: 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 //Note: rho and cp are constant
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 // Sum over all parallel processes
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 //write output
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 //budget for Derivee_temps_temperature_fluide
1144 //Note: rho and cp are constant
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); //fluid
1149 }
1150
1151 // Sum contributions from all processors in parallel
1152 Flux_temp_externe = mp_sum(Flux_temp_externe); //fluid
1153
1154 //write output
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 /* valeur_aux_bords can only be used if ch_rho has a 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 // rho is assumed to be a champ_uniforme: use the field array directly
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}
class Champ_Don_base base class of Given Fields (not calculated)
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
void mettre_a_jour(double temps) override
Time update of the field.
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
DoubleTab valeur_aux_bords() const override
Returns the field value at the boundary faces.
virtual DoubleTab & valeurs()=0
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
virtual DoubleTab valeur_aux_bords() const
Returns the field value at the boundary faces.
double temps() const
Returns the time of the field.
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
Convection_Diffusion_Temperature Special case of 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
Returns the name of the application domain of the equation.
const Champ_base & get_champ(const Motcle &nom) const override
void associer_milieu_base(const Milieu_base &) override
Associates a physical medium to the equation; the medium is cast to 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
Discretizes the equation.
DoubleTab & filtrage_si_appart_ibc(DoubleTab &, DoubleTab &)
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
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
Everything that does not depend on other possible problems.
const Operateur & operateur(int) const override
Returns the operator at the given index: returns terme_diffusif if i = 0,.
int nombre_d_operateurs() const override
Returns the number of operators in the equation: 2 for a diffusion equation.
void temperature(const Schema_Temps_base &, Domaine_dis_base &, OWN_PTR(Champ_Inc_base)&, int nb_comp=1) const
class Discret_Thyd This class is the base class representing a discretization
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
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
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
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in 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
class Equation_base The role of an equation is the calculation of one or more fields....
virtual void set_param(Param &titi) const override
const Nom & le_nom() const override
Returns the name of the 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()
Returns the source terms associated with the equation.
const Discretisation_base & discretisation() const
Returns the discretization associated with the equation.
virtual const Champ_Inc_base & inconnue() const =0
int calculate_time_derivative() const
Sources les_sources
virtual int preparer_calcul()
Everything that does not depend on other possible problems.
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()
Returns the discretized boundary condition domain associated with the equation.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Returns the problem associated with the equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
virtual void discretiser()
Discretizes the 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()
Returns the discretized domain associated with the equation.
const Nom & le_nom() const override
Returns the name of the field.
Base class for an incompressible fluid and its properties:
Definition Fluide_base.h:36
Represents a real fluid and its physical properties:
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Matrix-vector multiply-accumulate operation (saxpy).
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
auto & get_set_coeff()
Milieu_base This class is the base of the (physical) medium hierarchy.
Definition Milieu_base.h:50
virtual const Champ_Don_base & capacite_calorifique() const
Returns the heat capacity of the medium (const version).
virtual const Champ_base & masse_volumique() const
Returns the mass density of the medium (const version).
A character string (Nom) in uppercase.
Definition Motcle.h:26
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
Nom & suffix(const char *const)
Suffix extraction: Nom x("azerty");.
Definition Nom.cpp:266
const std::string & getString() const
Definition Nom.h:92
An array of character strings (VECT(Nom)).
Definition Noms.h:26
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
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
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
Returns the discretization associated with the problem.
bool & reprise_effectuee()
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
static double mp_sum(double)
Computes the sum of x over all processors in the current group.
Definition Process.cpp:145
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
SFichier is to the C++ ofstream class what Sortie is to the C++ ostream class.
Definition SFichier.h:29
class Schema_Temps_base
int nb_impr() const
Returns the number of outputs performed.
double pas_de_temps() const
Returns the current time step (delta_t).
virtual void modifier_second_membre(const Equation_base &eqn, DoubleTab &secmem)
double temps_init() const
Returns the initial time.
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Base class for output streams.
Definition Sortie.h:52
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
Contribution to the implicit matrix of source terms. By default, no contribution.
Definition Sources.cpp:201
DoubleTab & ajouter(DoubleTab &) const
Adds the contribution of all sources in the list to the array passed as parameter,...
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")
Transport_Interfaces_base This class is the base class for interface transport equations.
virtual void check_indicatrice_is_up_to_date()=0
virtual const Champ_base & get_indicatrice()=0
virtual int get_mesh_tag() const =0