TrioCFD 1.9.9_beta
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 Modifies the matrix to account for the presence of radiating faces near boundary elements.
54 *
55 * @return the modified input stream
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 // Loop over boundary conditions associated with the equation
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 // Add this coefficient to the diagonal of the discretization matrix
128 if (epsi < DMINFLOAT) { /* Do nothing */}
129 else
130 matrice(elem, elem) += coeff;
131 }
132 }
133 else
134 {
135 Cerr << "Error in Rayo_semi_transp_solver_VDF::modifier_matrice()" << finl;
136 Cerr << "the boundary associated with la_cl does not derive from Front_VF" << finl;
138 }
139 }
140 else if (sub_type(Symetrie, la_cl.valeur()))
141 {
142 /* Do nothing */
143 }
144 else
145 Process::exit("The boundary condition used is not recognized for the radiation equation!");
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 // Account for the div((1/3K)grad(irradiance)) part in the discretization matrix.
164 terme_diffusif->contribuer_a_avec(irradi, matrice);
165
166 // Modify the matrix to account for the right-hand side term K*irradiance
167 const DoubleTab& kappa = fluide.kappa().valeurs();
168
169 // verify
170 if (matrice.ordre() != nb_elem_tot)
172
173 Cerr << "Matrix order 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 // Modify the matrix to account for the effect of radiating walls on boundary elements
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 * Note: the matrix assembly is performed once at the start of the
207 * computation, which is only valid when kappa does not depend on time.
208 */
209
210 //compute the right-hand side
211 DoubleTrav secmem(eq_rayo.inconnue().valeurs());
212 secmem = 0.;
213
214 // retrieve T from the fluid problem ....
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 // Update the fields associated with boundary conditions
243 // before evaluating their contribution in the discretization matrix
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 << "Error in Rayo_semi_transp_solver_VDF::resoudre()! Cannot solve the equation" << finl;
258 Cerr << "of semi-transparent radiation with the solver: " << solveur->que_suis_je() << " because kappa is not constant, therefore the matrix is not symmetric" << 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 << "Error in Rayo_semi_transp_solver_VDF::resoudre()! Cannot solve a problem" << finl;
267 Cerr << "of semi-transparent radiation in parallel using the Solv_Gmres solver. If you treat" << finl;
268 Cerr << "a problem with constant kappa, you can bypass this limitation by using the GCP solver with GCP preconditioning" << finl;
270 }
271 else
272 {
273 Cerr << "Error in Rayo_semi_transp_solver_VDF::resoudre()! Cannot use the solver: " << solveur->que_suis_je() << finl;
274 Cerr << "to solve the radiation equation in a semi-transparent radiation problem" << 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 // Search for boundary conditions associated with the temperature equation
287 Conds_lim& les_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites();
289 assert(eq_temp.inconnue().le_nom() == "temperature");
290
291 // Loop over boundary conditions of the radiation equation
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 // Search for boundary temperatures for this boundary
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 << "Error in Rayo_semi_transp_solver_VDF::evaluer_cl_rayonnement! The case of a thermal BC " << la_cl_temp->que_suis_je() << " is not implemented" << finl;
356 }
357 }
358 }
359
360 // The boundary temperature array was not filled!!!!
361 if (test_remplissage_Tb == 0)
362 Cerr << "Rayo_semi_transp_solver_VDF::evaluer_cl_rayonnement -- The boundary temperature array was not filled!!!!" << 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 << "The boundary condition " << la_cl_rayo->que_suis_je() << " is not recognized for the radiation equation!" << finl;
375 }
376 }
377}
DoubleTab & valeurs() override
Returns the array of field values at the current time.
Champ_Uniforme Represents a field that is constant in space and time.
class Champ_front_base Base class for the hierarchy of boundary fields.
virtual DoubleTab & valeurs() override
Returns the array of field values.
class Champ_front_uniforme Derived class of Champ_front_base representing
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
class Conds_lim This class represents a vector of boundary conditions.
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
Returns the i-th boundary condition.
class Domaine_VDF
Definition Domaine_VDF.h:61
double dist_norm_bord(int num_face) const override
Returns the normal distance for a boundary face (Cartesian coordinates).
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
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
int nb_elem_tot() const
const Domaine & domaine() const
class Echange_contact_rayo_semi_transp_VDF
void calculer_temperature_bord(double temps)
The mettre_a_jour(temps) method fills the T_ext array with wall temperatures.
Champ_front_base & temperature_bord()
Returns the boundary temperature champ_front.
class Echange_externe_impose_rayo_semi_transp
class Echange_global_impose_rayo_semi_transp
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
class Equation_base The role of an equation is the calculation of one or more fields....
virtual const Champ_Inc_base & inconnue() const =0
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Returns the discretized boundary condition domain associated with the equation.
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.
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
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
void clean() override
Remplit la matrice avec des zeros.
int ordre() const override
Returns the order of the matrix: - the number of rows if the matrix is square.
Matrice class - Generic class in the matrix hierarchy.
Definition Matrice.h:34
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
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
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Operateur_Diff Generic class of the hierarchy of operators representing a diffusion.
const double & valeur_sigma() const
Probleme_base & probleme_fluide()
class Probleme_base It is a Probleme_U that is not a coupling.
virtual const Equation_base & equation(int) const =0
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
void evaluer_cl_rayonnement(double temps) override
void modifier_matrice() override
Modifies the matrix to account for the presence of radiating faces near boundary elements.
OBS_PTR(Eq_rayo_semi_transp) eq_rayo_semi_transp_
class SolveurSys A SolveurSys represents any class
Definition SolveurSys.h:32
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
Base class for output streams.
Definition Sortie.h:52
Symetrie On symmetry faces, the following properties hold:
Definition Symetrie.h:37