TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Rayo_semi_transp_solver_VEF.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 <Temperature_imposee_paroi_rayo_semi_transp.h>
18#include <Frontiere_ouverte_rayo_semi_transp.h>
19#include <Neumann_paroi_rayo_semi_transp_VEF.h>
20#include <Rayo_semi_transp_solver_VEF.h>
21#include <Champ_front_uniforme.h>
22#include <Eq_rayo_semi_transp.h>
23#include <Pb_rayo_semi_transp.h>
24#include <Flux_radiatif_VEF.h>
25#include <Champ_Uniforme.h>
26#include <Domaine_Cl_VEF.h>
27#include <Domaine_VEF.h>
28#include <Fluide_base.h>
29#include <Symetrie.h>
30#include <Debog.h>
31
32Implemente_instanciable(Rayo_semi_transp_solver_VEF, "Rayo_semi_transp_solver_VEF", Rayo_semi_transp_solver_base);
33
34Sortie& Rayo_semi_transp_solver_VEF::printOn(Sortie& s) const { return s << que_suis_je() << finl; }
36
38{
39 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
40 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
41 return domaine_VF.nb_faces_tot();
42}
43
45{
46 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
47 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
48 return domaine_VF.nb_faces();
49}
50
51/*! @brief modifie la matrice pour prendre en compte la presence de faces rayonnantes au voisinage des elements de bord
52 *
53 * @return le flot d'entree modifie
54 */
56{
57 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
58 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
60
61 const Domaine_VEF& zvef = ref_cast(Domaine_VEF, eq_rayo.domaine_dis());
62 const IntTab& face_voisins = zvef.face_voisins();
63 const DoubleTab& face_normales = zvef.face_normales();
64
65 // On fait une boucle sur les conditions aux limites associees a l'equations
66 for (int num_cl = 0; num_cl < les_cl.size(); num_cl++)
67 {
68 Cond_lim& la_cl = eq_rayo.domaine_Cl_dis().les_conditions_limites(num_cl);
69 if (sub_type(Flux_radiatif_VEF, la_cl.valeur()))
70 {
71 Flux_radiatif_VEF& cl_radiatif = ref_cast(Flux_radiatif_VEF, la_cl.valeur());
72 const DoubleTab& epsilon = cl_radiatif.emissivite().valeurs();
73 double A = cl_radiatif.A();
74
75 if (sub_type(Front_VF, la_cl->frontiere_dis()))
76 {
77 assert(cl_radiatif.emissivite().nb_comp() == 1);
78 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
79 const int ndeb = le_bord.num_premiere_face();
80 const int nfin = ndeb + le_bord.nb_faces();
81 for (int face = ndeb; face < nfin; face++)
82 {
83 int elem = face_voisins(face, 0);
84 if (elem == -1)
85 elem = face_voisins(face, 1);
86
87 double epsi = -123.;
88 if (sub_type(Champ_front_uniforme, cl_radiatif.emissivite()))
89 epsi = epsilon(0, 0);
90 else
91 epsi = epsilon(face - ndeb, 0);
92
93 double surface = 0;
94 for (int i = 0; i < dimension; i++)
95 surface += (face_normales(face, i) * face_normales(face, i));
96
97 surface = sqrt(surface);
98
99 double coeff = epsi * surface;
100 coeff /= A * (2 - epsi);
101
102 // On rajoute ce coefficient sur la diagonale de la matrice de discretisation
103 matrice(face, face) += coeff;
104 }
105 }
106 else
107 {
108 Cerr << "Erreur dans Rayo_semi_transp_solver_VEF::modifier_matrice()" << finl;
109 Cerr << "la frontiere associee a la_cl ne derive pas de Front_VF" << finl;
111 }
112 }
113 else if (sub_type(Symetrie, la_cl.valeur()))
114 {
115 /* Do nothing */
116 }
117 else
118 Process::exit("La condition a la limite utilisee n'est pas connue pour l'equation de rayonnement !");
119 }
120}
121
123{
124 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
125 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
126 Operateur_Diff& terme_diffusif = eq_rayo.terme_diffusif_rayo();
127
128 const auto& fluide = eq_rayo.fluide();
129 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
130 const DoubleVect& volumes_entrelaces = domaine_VF.volumes_entrelaces();
131
132 const DoubleTab& irradi = eq_rayo.inconnue().valeurs();
133
134 matrice.clean();
135
136 // Prise en compte de la partie div((1/3K)grad(irradiance)) dans la matrice de discretisation.
137 terme_diffusif->contribuer_a_avec(irradi, matrice);
138
139 // Modification de la matrice pour prendre en compte le second membre en K*irradiance
140 const DoubleTab& kappa = fluide.kappa().valeurs();
141
142 // on verifie
143 if (matrice.ordre() != domaine_VF.nb_faces_tot())
145
146 Cerr << "Ordre de la matrice OK" << finl;
147 assert(fluide.kappa().nb_comp() == 1);
148
149 double k = -123.;
150 for (int i = 0; i < matrice.ordre(); i++)
151 {
152 if (sub_type(Champ_Uniforme, fluide.kappa()))
153 k = kappa(0, 0);
154 else
155 k = kappa(i, 0);
156
157 double vol = volumes_entrelaces(i);
158 matrice(i, i) = matrice(i, i) + k * vol;
159 }
160
161 // On modifie la matrice pour prendre en compte l'effet des parois rayonnantes sur les elements de bord
163}
164
166{
167 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
168 Operateur_Diff& terme_diffusif = eq_rayo.terme_diffusif_rayo();
169 Matrice_Morse& matrice = eq_rayo.matrice_rayo();
170 SolveurSys& solveur = eq_rayo.solveur_rayo();
171
172 const auto& fluide = eq_rayo.fluide();
173 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
174 const DoubleVect& volumes_entrelaces = domaine_VF.volumes_entrelaces();
175 const int nb_faces = domaine_VF.nb_faces();
176
177 /*
178 * Remarque : l'assemblage de la matrice est realise une fois pour toute au debut du
179 * calcul, ce qui n'est valable que pour les cas ou kappa ne depend pas du temps
180 */
181
182 //calcul du second membre
183 DoubleTrav secmem(eq_rayo.inconnue().valeurs());
184 secmem = 0.;
185
186 // recuper T du pb fluide ....
187 Probleme_base& pb_fluide = eq_rayo.pb_rayo_semi_transp().probleme_fluide();
188
189 assert(pb_fluide.equation(1).inconnue().le_nom() == "temperature");
190 const DoubleTab& temper = pb_fluide.equation(1).inconnue().valeurs();
191
192 const DoubleTab& indice = fluide.indice().valeurs();
193 const DoubleTab& kappa = fluide.kappa().valeurs();
194 const double sigma = eq_rayo.pb_rayo_semi_transp().valeur_sigma();
195 assert(fluide.indice().nb_comp() == 1);
196 assert(fluide.kappa().nb_comp() == 1);
197
198 double n = -123., k = -123.;
199 for (int face = 0; face < nb_faces; face++)
200 {
201 if (sub_type(Champ_Uniforme, fluide.indice()))
202 n = indice(0, 0);
203 else
204 n = indice(face, 0);
205
206 if (sub_type(Champ_Uniforme, fluide.kappa()))
207 k = kappa(0, 0);
208 else
209 k = kappa(face, 0);
210
211 double vol = volumes_entrelaces(face);
212 double T = temper(face);
213 secmem(face) += +4 * n * n * sigma * pow(T, 4) * k * vol;
214 }
215
216 // On met a jour les champs associes aux conditions aux limites
217 // avant d'evaluer leur contribution dans la matrice de discretisation
219 terme_diffusif->contribuer_au_second_membre(secmem);
220 secmem.echange_espace_virtuel();
221
222 if (solveur->que_suis_je() == "Solv_GCP")
223 if (sub_type(Champ_Uniforme, fluide.kappa()))
224 {
225 Matrice matrice_tmp;
226 eq_rayo.dimensionner_Mat_Bloc_Morse_Sym(matrice_tmp);
227 eq_rayo.Mat_Morse_to_Mat_Bloc(matrice_tmp);
228 solveur.resoudre_systeme(matrice_tmp.valeur(), secmem, eq_rayo.inconnue().valeurs());
229 }
230 else
231 {
232 Cerr << "Erreur dans Rayo_semi_transp_solver_VEF::resoudre() ! On ne peut pas resoudre l'equation" << finl;
233 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;
235 }
236 else if (solveur->que_suis_je() == "Solv_Gmres")
237 if (Process::nproc() == 1)
238 solveur.resoudre_systeme(matrice, secmem, eq_rayo.inconnue().valeurs());
239 else
240 {
241 Cerr << "Erreur dans Rayo_semi_transp_solver_VEF::resoudre() ! On ne peut pas resoudre un probleme" << finl;
242 Cerr << "de rayonnement semi transparent en parallele en utilisant le solveur Solv_Gmres. Si vous traitez" << finl;
243 Cerr << "un probleme avec kappa constant, vous contournerez cette limitation en utilisant le solveur GCP avec un preconditionnement GCP" << finl;
245 }
246 else
247 {
248 Cerr << "Erreur dans Rayo_semi_transp_solver_VEF::resoudre() ! On ne peut pas utiliser le solveur : " << solveur->que_suis_je() << finl;
249 Cerr << "pour resoudre l'equation de rayonnement dans un probleme de rayonnement semi transparent" << finl;
251 }
252
253 Debog::verifier("Rayo_semi_transp_solver_VEF::resoudre irradiance ", eq_rayo.inconnue().valeurs());
254}
255
257{
258 Eq_rayo_semi_transp& eq_rayo = eq_rayo_semi_transp_.valeur();
259 const auto& fluide = eq_rayo.fluide();
260
261 // recherche des conditions aux limites associes au l'equation de temperature
262 Conds_lim& les_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites();
264 assert(eq_temp.inconnue().le_nom() == "temperature");
265
266 // Boucle sur les conditions aux limites de l'equation de rayonnement
267 Conds_lim& les_cl_temp = eq_temp.domaine_Cl_dis().les_conditions_limites();
268 for (int num_cl_rayo = 0; num_cl_rayo < les_cl_rayo.size(); num_cl_rayo++)
269 {
270 Cond_lim& la_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites(num_cl_rayo);
271 if (sub_type(Flux_radiatif_VEF, la_cl_rayo.valeur()))
272 {
273 Flux_radiatif_VEF& la_cl_rayon = ref_cast(Flux_radiatif_VEF, la_cl_rayo.valeur());
274 // Recherche des temperatures de bord pour cette frontiere
275 Nom nom_cl_rayo = la_cl_rayo->frontiere_dis().le_nom();
276
278 int test_remplissage_Tb = 0;
279 for (int num_cl_temp = 0; num_cl_temp < les_cl_temp.size(); num_cl_temp++)
280 {
281 Cond_lim& la_cl_temp = eq_temp.domaine_Cl_dis().les_conditions_limites(num_cl_temp);
282 Nom nom_cl_temp = la_cl_temp->frontiere_dis().le_nom();
283 if (nom_cl_temp == nom_cl_rayo)
284 {
285 if (sub_type(Neumann_paroi_rayo_semi_transp_VEF, la_cl_temp.valeur()))
286 {
287 Neumann_paroi_rayo_semi_transp_VEF& la_cl_temper = ref_cast(Neumann_paroi_rayo_semi_transp_VEF, la_cl_temp.valeur());
288 test_remplissage_Tb = 1;
289 la_cl_temper.calculer_temperature_bord(temps);
290 Tb = la_cl_temper.temperature_bord();
291 }
292 else if (sub_type(Temperature_imposee_paroi_rayo_semi_transp, la_cl_temp.valeur()))
293 {
295 test_remplissage_Tb = 1;
296 la_cl_temper.calculer_temperature_bord(temps);
297 Tb = la_cl_temper.temperature_bord();
298 }
299 else if (sub_type(Frontiere_ouverte_temperature_imposee_rayo_semi_transp, la_cl_temp.valeur()))
300 {
302 test_remplissage_Tb = 1;
303 la_cl_temper.calculer_temperature_bord(temps);
304 Tb = la_cl_temper.temperature_bord();
305 }
306 else if (sub_type(Frontiere_ouverte_rayo_semi_transp, la_cl_temp.valeur()))
307 {
308 Frontiere_ouverte_rayo_semi_transp& la_cl_temper = ref_cast(Frontiere_ouverte_rayo_semi_transp, la_cl_temp.valeur());
309 test_remplissage_Tb = 1;
310 la_cl_temper.calculer_temperature_bord(temps);
311 Tb = la_cl_temper.temperature_bord();
312 }
313 else
314 {
315 Cerr << "Erreur dans Rayo_semi_transp_solver_VEF::evaluer_cl_rayonnement ! Le cas d'une CL thermique " << la_cl_temp->que_suis_je() << " n'est pas code" << finl;
317 }
318 }
319 }
320
321 // On n'a pas remplie le tableau des temperatures de bord !!!!
322 if (test_remplissage_Tb == 0)
323 Cerr << "Rayo_semi_transp_solver_VEF::evaluer_cl_rayonnement -- On n'a pas remplie le tableau des temperatures de bord !!!!" << finl;
324
325 const Domaine_VF& zvf = ref_cast(Domaine_VF, eq_rayo.domaine_dis());
326 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);
327 }
328 else if (sub_type(Symetrie, la_cl_rayo.valeur()))
329 {
330 /* Do nothing */
331 }
332 else
333 {
334 Cerr << "La condition a la limite " << la_cl_rayo.que_suis_je() << " n'est pas connue pour l'equation de rayonnement !" << finl;
336 }
337 }
338}
339
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
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
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
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
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 modifier_matrice() override
modifie la matrice pour prendre en compte la presence de faces rayonnantes au voisinage des elements ...
void evaluer_cl_rayonnement(double temps) override
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
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
classe Temperature_imposee_paroi_rayo_semi_transp cette classe est utilisee pour imposer une temperat...