TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Rayo_semi_transp_solver_VDF.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 <Frontiere_ouverte_temperature_imposee_rayo_semi_transp.h>
17#include <Echange_externe_impose_rayo_semi_transp.h>
18#include <Echange_global_impose_rayo_semi_transp.h>
19#include <Echange_contact_rayo_semi_transp_VDF.h>
20#include <Frontiere_ouverte_rayo_semi_transp.h>
21#include <Neumann_paroi_rayo_semi_transp_VDF.h>
22#include <Rayo_semi_transp_solver_VDF.h>
23#include <Champ_front_uniforme.h>
24#include <Eq_rayo_semi_transp.h>
25#include <Pb_rayo_semi_transp.h>
26#include <Flux_radiatif_VDF.h>
27#include <Champ_Uniforme.h>
28#include <Domaine_VDF.h>
29#include <Domaine_VDF.h>
30#include <Fluide_base.h>
31#include <Symetrie.h>
32#include <Debog.h>
33
34Implemente_instanciable(Rayo_semi_transp_solver_VDF, "Rayo_semi_transp_solver_VDF", Rayo_semi_transp_solver_base);
35
36Sortie& Rayo_semi_transp_solver_VDF::printOn(Sortie& s) const { return s << que_suis_je() << finl; }
38
40{
41 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
42 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
43 return domaine_VF.domaine().nb_elem_tot();
44}
45
47{
48 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
49 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
50 return domaine_VF.domaine().nb_elem();
51}
52
53/*! @brief modifie la matrice pour prendre en compte la presence de faces rayonnantes au voisinage des elements de bord
54 *
55 * @return le flot d'entree modifie
56 */
58{
59 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
60 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
62
63 const auto& fluide = eq_rayo.fluide();
64 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, eq_rayo.domaine_dis());
65 const IntTab& face_voisins = zvdf.face_voisins();
66 const DoubleVect& face_surfaces = zvdf.face_surfaces();
67
68 // On fait une boucle sur les conditions aux limites associees a l'equations
69 for (int num_cl = 0; num_cl < les_cl.size(); num_cl++)
70 {
71 Cond_lim& la_cl = eq_rayo.domaine_Cl_dis().les_conditions_limites(num_cl);
72 if (sub_type(Flux_radiatif_VDF, la_cl.valeur()))
73 {
74 Flux_radiatif_VDF& cl_radiatif = ref_cast(Flux_radiatif_VDF, la_cl.valeur());
75 const DoubleTab& epsilon = cl_radiatif.emissivite().valeurs();
76 const DoubleTab& long_rayo = fluide.longueur_rayo().valeurs();
77 const DoubleTab& kappa = fluide.kappa().valeurs();
78 const double A = cl_radiatif.A();
79
80 if (sub_type(Front_VF, la_cl->frontiere_dis()))
81 {
82 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
83 const int ndeb = le_bord.num_premiere_face();
84 const int nfin = ndeb + le_bord.nb_faces();
85 assert(cl_radiatif.emissivite().nb_comp() == 1);
86 assert(fluide.longueur_rayo().nb_comp() == 1);
87 assert(fluide.kappa().nb_comp() == 1);
88
89 for (int face = ndeb; face < nfin; face++)
90 {
91 int elem = face_voisins(face, 0);
92
93 if (elem == -1)
94 elem = face_voisins(face, 1);
95
96
97 double eF = zvdf.dist_norm_bord(face);
98 double k = -123., l_r = -123.;
99
100 if (sub_type(Champ_Uniforme, fluide.kappa()))
101 {
102 k = kappa(0, 0);
103 l_r = long_rayo(0, 0);
104 }
105 else
106 {
107 k = kappa(elem, 0);
108 l_r = long_rayo(elem, 0);
109 }
110
111 double epsi = -123.;
112
113 if (sub_type(Champ_front_uniforme, cl_radiatif.emissivite()))
114 epsi = epsilon(0, 0);
115 else
116 epsi = epsilon(face - ndeb, 0);
117
118 const double numer_coeff = l_r * face_surfaces(face);
119 double denum_coeff = 3 * k * epsi;
120
121 denum_coeff = 1 / denum_coeff;
122 denum_coeff *= A * (2 - epsi);
123 denum_coeff = denum_coeff + eF;
124
125 const double coeff = numer_coeff / denum_coeff;
126
127 // On rajoute ce coefficient sur la diagonale de la matrice de discretisation
128 if (epsi < DMINFLOAT) { /* Do nothing */}
129 else
130 matrice(elem, elem) += coeff;
131 }
132 }
133 else
134 {
135 Cerr << "Erreur dans Rayo_semi_transp_solver_VDF::modifier_matrice()" << finl;
136 Cerr << "la frontiere associee a la_cl ne derive pas de Front_VF" << finl;
138 }
139 }
140 else if (sub_type(Symetrie, la_cl.valeur()))
141 {
142 /* Do nothing */
143 }
144 else
145 Process::exit("La condition a la limite utilisee n'est pas connue pour l'equation de rayonnement !");
146 }
147}
148
150{
151 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
152 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
153 Operateur_Diff& terme_diffusif = eq_rayo.terme_diffusif_rayo();
154
155 const auto& fluide = eq_rayo.fluide();
156 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
157 const int nb_elem_tot = domaine_VF.nb_elem_tot();
158
159 const DoubleTab& irradi = eq_rayo.inconnue().valeurs();
160
161 matrice.clean();
162
163 // Prise en compte de la partie div((1/3K)grad(irradiance)) dans la matrice de discretisation.
164 terme_diffusif->contribuer_a_avec(irradi, matrice);
165
166 // Modification de la matrice pour prendre en compte le second membre en K*irradiance
167 const DoubleTab& kappa = fluide.kappa().valeurs();
168
169 // on verifie
170 if (matrice.ordre() != nb_elem_tot)
172
173 Cerr << "Ordre de la matrice OK" << finl;
174 assert(fluide.kappa().nb_comp() == 1);
175
176 double k = -123.;
177 for (int i = 0; i < matrice.ordre(); i++)
178 {
179 if (sub_type(Champ_Uniforme, fluide.kappa()))
180 k = kappa(0, 0);
181 else
182 k = kappa(i, 0);
183
184 const double vol = domaine_VF.volumes(i);
185
186 matrice(i, i) = matrice(i, i) + k * vol;
187 }
188
189 // On modifie la matrice pour prendre en compte l'effet des parois rayonnantes sur les elements de bord
191}
192
194{
195 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
196 Operateur_Diff& terme_diffusif = eq_rayo.terme_diffusif_rayo();
197 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
198 SolveurSys& solveur = eq_rayo.solveur_rayo();
199
200 const auto& fluide = eq_rayo.fluide();
201 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
202 const int nb_elem = domaine_VF.nb_elem();
203 const DoubleTab& kappa = fluide.kappa().valeurs();
204
205 /*
206 * Remarque : l'assemblage de la matrice est realise une fois pour toute au debut du
207 * calcul, ce qui n'est valable que pour les cas ou kappa ne depend pas du temps
208 */
209
210 //calcul du second membre
211 DoubleTrav secmem(eq_rayo.inconnue().valeurs());
212 secmem = 0.;
213
214 // recuper T du pb fluide ....
215 Probleme_base& pb_fluide = eq_rayo.pb_rayo_semi_transp().probleme_fluide();
216
217 assert(pb_fluide.equation(1).inconnue().le_nom() == "temperature");
218 const DoubleTab& temper = pb_fluide.equation(1).inconnue().valeurs();
219 const DoubleTab& indice = fluide.indice().valeurs();
220 const double sigma = eq_rayo.pb_rayo_semi_transp().valeur_sigma();
221 assert(fluide.indice().nb_comp());
222 assert(fluide.kappa().nb_comp() == 1);
223
224 double n = -123., k = -123.;
225 for (int elem = 0; elem < nb_elem; elem++)
226 {
227 if (sub_type(Champ_Uniforme, fluide.indice()))
228 n = indice(0, 0);
229 else
230 n = indice(elem, 0);
231
232 if (sub_type(Champ_Uniforme, fluide.kappa()))
233 k = kappa(0, 0);
234 else
235 k = kappa(elem, 0);
236
237 const double vol = domaine_VF.volumes(elem);
238 const double T = temper(elem);
239 secmem(elem) += +4 * n * n * sigma * pow(T, 4) * k * vol;
240 }
241
242 // On met a jour les champs associes aux conditions aux limites
243 // avant d'evaluer leur contribution dans la matrice de discretisation
245 terme_diffusif->contribuer_au_second_membre(secmem);
246
247 if (solveur->que_suis_je() == "Solv_GCP")
248 if (sub_type(Champ_Uniforme, fluide.kappa()))
249 {
250 Matrice matrice_tmp;
251 eq_rayo.dimensionner_Mat_Bloc_Morse_Sym(matrice_tmp);
252 eq_rayo.Mat_Morse_to_Mat_Bloc(matrice_tmp);
253 solveur.resoudre_systeme(matrice_tmp.valeur(), secmem, eq_rayo.inconnue().valeurs());
254 }
255 else
256 {
257 Cerr << "Erreur dans Rayo_semi_transp_solver_VDF::resoudre() ! On ne peut pas resoudre l'equation" << finl;
258 Cerr << "de rayonnement semi transparent avec le solveur : " << solveur->que_suis_je() << "car kappa n'est pas constant, donc, la_matrice n'est pas symetrique" << finl;
260 }
261 else if (solveur->que_suis_je() == "Solv_Gmres")
262 if (Process::nproc() == 1)
263 solveur.resoudre_systeme(matrice, secmem, eq_rayo.inconnue().valeurs());
264 else
265 {
266 Cerr << "Erreur dans Rayo_semi_transp_solver_VDF::resoudre() ! On ne peut pas resoudre un probleme" << finl;
267 Cerr << "de rayonnement semi transparent en parallele en utilisant le solveur Solv_Gmres. Si vous traitez" << finl;
268 Cerr << "un probleme avec kappa constant, vous contournerez cette limitation en utilisant le solveur GCP avec un preconditionnement GCP" << finl;
270 }
271 else
272 {
273 Cerr << "Erreur dans Rayo_semi_transp_solver_VDF::resoudre() ! On ne peut pas utiliser le solveur : " << solveur->que_suis_je() << finl;
274 Cerr << "pour resoudre l'equation de rayonnement dans un probleme de rayonnement semi transparent" << finl;
276 }
277
278 Debog::verifier("Rayo_semi_transp_solver_VEF::resoudre irradiance ", eq_rayo.inconnue().valeurs());
279}
280
282{
283 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
284 const auto& fluide = eq_rayo.fluide();
285
286 // recherche des conditions aux limites associes au l'equation de temperature
287 Conds_lim& les_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites();
289 assert(eq_temp.inconnue().le_nom() == "temperature");
290
291 // Boucle sur les conditions aux limites de l'equation de rayonnement
292 Conds_lim& les_cl_temp = eq_temp.domaine_Cl_dis().les_conditions_limites();
293 for (int num_cl_rayo = 0; num_cl_rayo < les_cl_rayo.size(); num_cl_rayo++)
294 {
295 Cond_lim& la_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites(num_cl_rayo);
296 if (sub_type(Flux_radiatif_VDF, la_cl_rayo.valeur()))
297 {
298 Flux_radiatif_VDF& la_cl_rayon = ref_cast(Flux_radiatif_VDF, la_cl_rayo.valeur());
299 // Recherche des temperatures de bord pour cette frontiere
300 Nom nom_cl_rayo = la_cl_rayo->frontiere_dis().le_nom();
301
303 int test_remplissage_Tb = 0;
304 for (int num_cl_temp = 0; num_cl_temp < les_cl_temp.size(); num_cl_temp++)
305 {
306 Cond_lim& la_cl_temp = eq_temp.domaine_Cl_dis().les_conditions_limites(num_cl_temp);
307 Nom nom_cl_temp = la_cl_temp->frontiere_dis().le_nom();
308 if (nom_cl_temp == nom_cl_rayo)
309 {
310 if (sub_type(Neumann_paroi_rayo_semi_transp_VDF, la_cl_temp.valeur()))
311 {
312 Neumann_paroi_rayo_semi_transp_VDF& la_cl_temper = ref_cast(Neumann_paroi_rayo_semi_transp_VDF, la_cl_temp.valeur());
313 test_remplissage_Tb = 1;
314 la_cl_temper.calculer_temperature_bord(temps);
315 Tb = la_cl_temper.temperature_bord();
316 }
317 else if (sub_type(Echange_contact_rayo_semi_transp_VDF, la_cl_temp.valeur()))
318 {
319 Echange_contact_rayo_semi_transp_VDF& la_cl_temper = ref_cast(Echange_contact_rayo_semi_transp_VDF, la_cl_temp.valeur());
320 test_remplissage_Tb = 1;
321 la_cl_temper.calculer_temperature_bord(temps);
322 Tb = la_cl_temper.temperature_bord();
323 }
324 else if (sub_type(Echange_externe_impose_rayo_semi_transp, la_cl_temp.valeur()))
325 {
326 Echange_externe_impose_rayo_semi_transp& la_cl_temper = ref_cast(Echange_externe_impose_rayo_semi_transp, la_cl_temp.valeur());
327 test_remplissage_Tb = 1;
328 la_cl_temper.calculer_temperature_bord(temps);
329 Tb = la_cl_temper.temperature_bord();
330 }
331 else if (sub_type(Frontiere_ouverte_temperature_imposee_rayo_semi_transp, la_cl_temp.valeur()))
332 {
334 test_remplissage_Tb = 1;
335 la_cl_temper.calculer_temperature_bord(temps);
336 Tb = la_cl_temper.temperature_bord();
337 }
338 else if (sub_type(Frontiere_ouverte_rayo_semi_transp, la_cl_temp.valeur()))
339 {
340 Frontiere_ouverte_rayo_semi_transp& la_cl_temper = ref_cast(Frontiere_ouverte_rayo_semi_transp, la_cl_temp.valeur());
341 test_remplissage_Tb = 1;
342 la_cl_temper.calculer_temperature_bord(temps);
343 Tb = la_cl_temper.temperature_bord();
344 }
345 else if (sub_type(Echange_global_impose_rayo_semi_transp, la_cl_temp.valeur()))
346 {
347 Echange_global_impose_rayo_semi_transp& la_cl_temper = ref_cast(Echange_global_impose_rayo_semi_transp, la_cl_temp.valeur());
348 test_remplissage_Tb = 1;
349 la_cl_temper.calculer_temperature_bord(temps);
350 Tb = la_cl_temper.temperature_bord();
351 }
352 else
353 {
354 Cerr << "Erreur dans Rayo_semi_transp_solver_VDF::evaluer_cl_rayonnement ! Le cas d'une CL thermique " << la_cl_temp->que_suis_je() << " n'est pas code" << finl;
356 }
357 }
358 }
359
360 // On n'a pas remplie le tableau des temperatures de bord !!!!
361 if (test_remplissage_Tb == 0)
362 Cerr << "Rayo_semi_transp_solver_VDF::evaluer_cl_rayonnement -- On n'a pas remplie le tableau des temperatures de bord !!!!" << finl;
363
364 const Domaine_VF& zvf = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
365 la_cl_rayon.evaluer_cl_rayonnement(Tb.valeur(), fluide.kappa(), fluide.longueur_rayo(), fluide.indice(), zvf, eq_rayo.pb_rayo_semi_transp().valeur_sigma(), temps);
366 }
367 else if (sub_type(Symetrie, la_cl_rayo.valeur()))
368 {
369 /* Do nothing */
370 }
371 else
372 {
373 Cerr << "La condition a la limite " << la_cl_rayo->que_suis_je() << " n'est pas connue pour l'equation de rayonnement !" << finl;
375 }
376 }
377}
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_front_base Classe de base pour la hierarchie des champs aux frontieres.
virtual DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ.
classe Champ_front_uniforme Classe derivee de Champ_front_base qui represente les
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
int_t nb_elem_tot() const
Definition Domaine.h:132
int_t nb_elem() const
Definition Domaine.h:131
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VDF
Definition Domaine_VDF.h:64
double dist_norm_bord(int num_face) const override
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
double volumes(int i) const
Definition Domaine_VF.h:113
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int nb_elem_tot() const
const Domaine & domaine() const
classe Echange_contact_rayo_semi_transp_VDF Cette classe est utilisee pour realiser un couplage entre...
void calculer_temperature_bord(double temps)
la methode mettre_a_jour(temps) a pour role de remplire le tableau T_ext avec les temperatures de par...
Champ_front_base & temperature_bord()
Renvoie le champ_front des temperatures de bord.
classe Echange_externe_impose_rayo_semi_transp cette classe est utilisee pour imposer une temperature...
classe Echange_global_impose_rayo_semi_transp cette classe est utilisee pour imposer une temperature ...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const Pb_rayo_semi_transp & pb_rayo_semi_transp() const
Matrice_Morse & matrice_rayo()
void dimensionner_Mat_Bloc_Morse_Sym(Matrice &matrice_tmp)
void Mat_Morse_to_Mat_Bloc(Matrice &matrice_tmp)
SolveurSys & solveur_rayo()
Operateur_Diff & terme_diffusif_rayo()
const Champ_Inc_base & inconnue() const override
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual const Champ_Inc_base & inconnue() const =0
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
virtual int nb_comp() const
Definition Field_base.h:56
void evaluer_cl_rayonnement(Champ_front_base &Tb, const Champ_Don_base &, const Champ_Don_base &, const Champ_Don_base &, const Domaine_VF &, const double, double)
Champ_front_base & emissivite()
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
void clean() override
Remplit la matrice avec des zeros.
int ordre() const override
Renvoie l'ordre de la matrice: - le nombre de lignes si la matrice est carree.
Classe Matrice Classe generique de la hierarchie des matrices.
Definition Matrice.h:34
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur_Diff Classe generique de la hierarchie des operateurs representant un terme
const double & valeur_sigma() const
Probleme_base & probleme_fluide()
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
virtual const Equation_base & equation(int) const =0
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
void evaluer_cl_rayonnement(double temps) override
void modifier_matrice() override
modifie la matrice pour prendre en compte la presence de faces rayonnantes au voisinage des elements ...
OBS_PTR(Eq_rayo_semi_transp) eq_rayo_semi_transp_
class SolveurSys Un SolveurSys represente n'importe qu'elle classe
Definition SolveurSys.h:32
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37