TrioCFD 1.9.9_beta
TrioCFD documentation
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 Modify the matrix to account for the presence of radiating faces near boundary elements.
52 *
53 * @return the modified input stream
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 // Loop over the boundary conditions associated with the equation
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 // Add this coefficient to the diagonal of the discretization matrix
103 matrice(face, face) += coeff;
104 }
105 }
106 else
107 {
108 Cerr << "Error in Rayo_semi_transp_solver_VEF::modifier_matrice()" << finl;
109 Cerr << "the boundary associated with la_cl does not derive from Front_VF" << finl;
111 }
112 }
113 else if (sub_type(Symetrie, la_cl.valeur()))
114 {
115 /* Do nothing */
116 }
117 else
118 Process::exit("The boundary condition used is not recognized for the radiation equation!");
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 // Account for the div((1/3K)grad(irradiance)) part in the discretization matrix.
137 terme_diffusif->contribuer_a_avec(irradi, matrice);
138
139 // Modify the matrix to account for the right-hand side term in K*irradiance
140 const DoubleTab& kappa = fluide.kappa().valeurs();
141
142 // verify
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 // Modify the matrix to account for the effect of radiating walls on boundary elements
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 * Note: the matrix assembly is performed once at the beginning of
179 * the computation, which is only valid for cases where kappa does not depend on time
180 */
181
182 //compute the right-hand side
183 DoubleTrav secmem(eq_rayo.inconnue().valeurs());
184 secmem = 0.;
185
186 // retrieve T from the fluid problem ....
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 // Update the fields associated with the boundary conditions
217 // before evaluating their contribution in the discretization matrix
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 << "Error in Rayo_semi_transp_solver_VEF::resoudre() ! Cannot solve the semi-transparent radiation equation" << finl;
233 Cerr << "with the solver: " << solveur->que_suis_je() << " because kappa is not constant, so the matrix is not symmetric" << 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 << "Error in Rayo_semi_transp_solver_VEF::resoudre() ! Cannot solve a semi-transparent radiation problem" << finl;
242 Cerr << "in parallel using the Solv_Gmres solver. If you have a problem with constant kappa," << finl;
243 Cerr << "you can work around this limitation by using the GCP solver with GCP preconditioning" << finl;
245 }
246 else
247 {
248 Cerr << "Error in Rayo_semi_transp_solver_VEF::resoudre() ! Cannot use the solver: " << solveur->que_suis_je() << finl;
249 Cerr << "to solve the radiation equation in a semi-transparent radiation problem" << 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 // find the boundary conditions associated with the temperature equation
262 Conds_lim& les_cl_rayo = eq_rayo.domaine_Cl_dis().les_conditions_limites();
264 assert(eq_temp.inconnue().le_nom() == "temperature");
265
266 // Loop over the boundary conditions of the radiation equation
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 // Find boundary temperatures for this boundary
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 << "Error in Rayo_semi_transp_solver_VEF::evaluer_cl_rayonnement ! The case of a thermal BC " << la_cl_temp->que_suis_je() << " is not implemented" << finl;
317 }
318 }
319 }
320
321 // The boundary temperature array was not filled!!!!
322 if (test_remplissage_Tb == 0)
323 Cerr << "Rayo_semi_transp_solver_VEF::evaluer_cl_rayonnement -- The boundary temperature array has not been filled!!!!" << 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 << "The boundary condition " << la_cl_rayo.que_suis_je() << " is not recognized for the radiation equation!" << finl;
336 }
337 }
338}
339
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
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VEF
Definition Domaine_VEF.h:53
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
Returns the total number of 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
Returns the neighbouring element of num_face in 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
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
static int dimension
Definition Objet_U.h:94
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 modifier_matrice() override
Modify the matrix to account for the presence of radiating faces near boundary elements.
void evaluer_cl_rayonnement(double temps) override
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
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
Temperature_imposee_paroi_rayo_semi_transp class: used to impose a wall temperature.