TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
EDO_Pression_th_VEF_Gaz_Parfait.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 <EDO_Pression_th_VEF_Gaz_Parfait.h>
17#include <Frontiere_ouverte_rho_u_impose.h>
18#include <Fluide_Quasi_Compressible.h>
19#include <Neumann_sortie_libre.h>
20#include <Navier_Stokes_std.h>
21#include <Schema_Temps_base.h>
22#include <Loi_Etat_GP_QC.h>
23#include <Domaine_VEF.h>
24#include <Champ_P1NC.h>
25#include <Dirichlet.h>
26
27Implemente_instanciable(EDO_Pression_th_VEF_Gaz_Parfait, "EDO_Pression_th_VEF_Gaz_Parfait", EDO_Pression_th_VEF);
28
29Sortie& EDO_Pression_th_VEF_Gaz_Parfait::printOn(Sortie& os) const { return os << que_suis_je() << finl; }
30
32
33/*! @brief Resoud l'EDO
34 *
35 * @param (double Pth_n) La pression a l'etape precedente
36 * @return (double) La nouvelle valeur de la pression
37 */
39{
40
41 int traitPth = le_fluide_->getTraitementPth();
42
43 if (traitPth == 2) // Pth constant
44 return Pth_n;
45
46 double present = le_fluide_->vitesse().equation().schema_temps().temps_courant();
47 double dt = le_fluide_->vitesse().equation().schema_temps().pas_de_temps();
48 double futur = present + dt;
49 const DoubleTab& tab_tempnp1 = le_fluide_->inco_chaleur().valeurs(futur); // T(n+1)
50 const DoubleTab& tab_tempn = le_fluide_->inco_chaleur().valeurs(present); // T(n)
51 int nb_faces = le_dom->nb_faces();
52 double Pth = 0;
53
54 const Domaine_VEF& domaine_vef = ref_cast(Domaine_VEF, le_dom.valeur());
55
56 if (traitPth == 0) // EDO
57 {
58 const DoubleTab& tab_rho = le_fluide_->masse_volumique().valeurs(); // n+1/2
59 const double rho_moy = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tab_rho, FAUX_EN_PERIO);
60 DoubleTrav tab_tmp(tab_rho); // copie de rho
61 tab_tmp = tab_rho;
62 assert(tab_tmp.size() == nb_faces);
63 const double invdt = 1. / dt;
64 CDoubleArrView tempn = static_cast<const ArrOfDouble&>(tab_tempn).view_ro();
65 CDoubleArrView tempnp1 = static_cast<const ArrOfDouble&>(tab_tempnp1).view_ro();
66 DoubleArrView tmp = static_cast<ArrOfDouble&>(tab_tmp).view_wo();
67 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, nb_faces), KOKKOS_LAMBDA(const int i)
68 {
69 tmp[i] *= (tempnp1[i] - tempn[i]) / tempnp1[i] * invdt;
70 });
71 end_gpu_timer(__KERNEL_NAME__);
72 double S = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tab_tmp, FAUX_EN_PERIO);
73
74 //////////////////
75 S /= rho_moy;
76 // double Pth = (Pth_n + S*dt/V);
77 //double Pth = Pth_n/(1- S*dt);
78 Pth = Pth_n / (1 - S * dt);
79 //test pour faire apparaitre la difference sur Pth
80 //Pth *= 1e10;
81 }
82
83 else if (traitPth == 1) // Conservation masse (WEC mars 2008)
84 {
85
86 // On veut Masse(n+1) - Masse(n) = dt * Debits_aux_bords
87 // or Masse = Pth / R * sum(Vi/Ti) en volume
88 // et Debit = Pth / R * sum(Sj.Uj/Tj) aux faces Dirichlet
89
90 // Donc si on note masse_n = sum(Vi/Ti(n))
91 // debit_u_imp = sum(Sj.Uj(impose)/Tj(n+1)) pour les vitesses imposees
92 // et debit_rho_u_imp = sum(Sj.Uj(impose)/Tj(n+1)) pour les rho_u imposes
93 // ou U(impose) = (rho.U)(impose) / rho(Pth(n),T(n+1))
94 // il faut Pth(n+1)*masse_np1 - Pth(n)*masse_n = Pth(n+1) * debit_u_imp * dt
95 // + Pth(n) * debit_rho_u_imp * dt
96
97 // Attention il faudrait prendre en compte les porosites dans les integrales !!!
98
99 double debit_u_imp = 0, debit_rho_u_imp = 0;
100
101 // On veut que rho_np1 soit calcule avec T(n+1) et Pth_n pour les CLs en rho_u impose
102 le_fluide_->calculer_masse_volumique();
103
104 // Calcul de masse_n et masse_np1
105 DoubleTrav tab_tmp;
106 tab_tmp.copy(tab_tempn, RESIZE_OPTIONS::NOCOPY_NOINIT); // copier uniquement la structure
107
108 CDoubleArrView tempn = static_cast<const ArrOfDouble&>(tab_tempn).view_ro();
109 DoubleArrView tmp = static_cast<ArrOfDouble&>(tab_tmp).view_wo();
110 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, nb_faces), KOKKOS_LAMBDA(const int i)
111 {
112 tmp(i) = 1. / tempn(i);
113 });
114 end_gpu_timer(__KERNEL_NAME__);
115 const double masse_n = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tab_tmp, FAUX_EN_PERIO);
116
117 CDoubleArrView tempnp1 = static_cast<const ArrOfDouble&>(tab_tempnp1).view_ro();
118 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, nb_faces), KOKKOS_LAMBDA(const int i)
119 {
120 tmp(i) = 1. / tempnp1(i);
121 });
122 end_gpu_timer(__KERNEL_NAME__);
123 const double masse_np1 = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tab_tmp, FAUX_EN_PERIO);
124
125 // Calcul de debit_u_imp et debit_rho_u_imp
126 for (int n_bord = 0; n_bord < le_dom->nb_front_Cl(); n_bord++)
127 {
128 const Cond_lim_base& la_cl = le_dom_Cl->les_conditions_limites(n_bord).valeur();
129 if (sub_type(Dirichlet, la_cl))
130 {
131 const Dirichlet& diri = ref_cast(Dirichlet, la_cl);
132 const Front_VF& la_front_dis = ref_cast(Front_VF, la_cl.frontiere_dis());
133 int ndeb = la_front_dis.num_premiere_face();
134 int nfin = ndeb + la_front_dis.nb_faces();
135 int dim = Objet_U::dimension;
136 CDoubleTabView val_imp = diri.tab_val_imp(futur).view_ro();
137 CDoubleTabView face_normales = le_dom->face_normales().view_ro();
138 CIntTabView face_voisins = le_dom->face_voisins().view_ro();
139 double debit = 0;
140 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), range_1D(ndeb, nfin), KOKKOS_LAMBDA(const int face, double& debit_local)
141 {
142 double debit_v = 0;
143 for (int d = 0; d < dim; d++)
144 debit_v += face_normales(face, d) * val_imp(face - ndeb, d) / tempnp1(face);
145 int n0 = face_voisins(face, 0);
146 if (n0 == -1)
147 debit_v = -debit_v;
148 debit_local += debit_v;
149 }, debit);
150 end_gpu_timer(__KERNEL_NAME__);
151 if (sub_type(Frontiere_ouverte_rho_u_impose, la_cl))
152 debit_rho_u_imp += debit;
153 else
154 debit_u_imp += debit;
155 }
156 else if (sub_type(Neumann_sortie_libre, la_cl))
157 {
158 Cerr << la_cl.que_suis_je() << " est incompatible avec le traitement conservation_masse." << finl;
159 exit();
160 }
161 }
162 // On fait la somme sur les procs
163 // Optimization: combine 2 mp_sum into 1 collective call
164 mp_sum_for_each(debit_u_imp, debit_rho_u_imp);
165
166 // Calcul de Pth(n+1)
167 Pth = Pth_n * (masse_n - dt * debit_rho_u_imp) / (masse_np1 + dt * debit_u_imp);
168 }
169
170 return Pth;
171}
172
174{
175
176 const int traitPth = le_fluide_->getTraitementPth();
177 if (traitPth == 2)
178 return; // rien a faire
179 else if (traitPth == 0)
180 {
181 for (int n_bord = 0; n_bord < le_dom->nb_front_Cl(); n_bord++)
182 {
183 const Cond_lim& la_cl = le_dom_Cl->les_conditions_limites(n_bord);
184 if (sub_type(Neumann_sortie_libre, la_cl.valeur()))
185 return; // rien a faire
186 }
187
188 Cerr << "EDO_Pression_th_VEF_Gaz_Parfait::" << __func__ << " not yet coded ! Call the 911 !!" << finl;
190 }
191 else
192 {
193 const double present = le_fluide_->vitesse().equation().schema_temps().temps_courant();
194 const double dt = le_fluide_->vitesse().equation().schema_temps().pas_de_temps();
195 const double futur = present + dt;
196 const DoubleTab& tempnp1 = le_fluide_->inco_chaleur().valeurs(futur); // T(n+1)
197 const DoubleTab& tempn = le_fluide_->inco_chaleur().valeurs(present); // T(n)
198 const int nb_faces = le_dom->nb_faces();
199 const Domaine_VEF& domaine_vef = ref_cast(Domaine_VEF, le_dom.valeur());
200
201 // On veut Masse(n+1) - Masse(n) = dt * Debits_aux_bords
202 // or Masse = Pth / R * sum(Vi/Ti) en volume
203 // et Debit = Pth / R * sum(Sj.Uj/Tj) aux faces Dirichlet
204
205 // Donc si on note masse_n = sum(Vi/Ti(n))
206 // debit_u_imp = sum(Sj.Uj(impose)/Tj(n+1)) pour les vitesses imposees
207 // et debit_rho_u_imp = sum(Sj.Uj(impose)/Tj(n+1)) pour les rho_u imposes
208 // ou U(impose) = (rho.U)(impose) / rho(Pth(n),T(n+1))
209 // il faut Pth(n+1)*masse_np1 - Pth(n)*masse_n = Pth(n+1) * debit_u_imp * dt
210 // + Pth(n) * debit_rho_u_imp * dt
211
212 // Attention il faudrait prendre en compte les porosites dans les integrales !!!
213
214 double debit_u_imp = 0, debit_rho_u_imp = 0;
215
216 // On veut que rho_np1 soit calcule avec T(n+1) et Pth_n pour les CLs en rho_u impose
217 le_fluide_->calculer_masse_volumique();
218
219 // Calcul de masse_n et masse_np1
220 DoubleVect tmp;
221 tmp.copy(tempn, RESIZE_OPTIONS::NOCOPY_NOINIT); // copier uniquement la structure
222 for (int i = 0; i < nb_faces; i++)
223 tmp[i] = 1. / tempn[i];
224 const double masse_n = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tmp, FAUX_EN_PERIO);
225 for (int i = 0; i < nb_faces; i++)
226 tmp[i] = 1. / tempnp1[i];
227 const double masse_np1 = Champ_P1NC::calculer_integrale_volumique(domaine_vef, tmp, FAUX_EN_PERIO);
228
229 // Calcul de debit_u_imp et debit_rho_u_imp
230 for (int n_bord = 0; n_bord < le_dom->nb_front_Cl(); n_bord++)
231 {
232 const Cond_lim_base& la_cl = le_dom_Cl->les_conditions_limites(n_bord).valeur();
233 if (sub_type(Dirichlet, la_cl))
234 {
235 const Dirichlet& diri = ref_cast(Dirichlet, la_cl);
236 const Front_VF& la_front_dis = ref_cast(Front_VF, la_cl.frontiere_dis());
237 int ndeb = la_front_dis.num_premiere_face();
238 int nfin = ndeb + la_front_dis.nb_faces();
239 for (int face = ndeb; face < nfin; face++)
240 {
241 double debit_v = 0;
242 for (int d = 0; d < dimension; d++)
243 debit_v += le_dom->face_normales(face, d) * diri.val_imp_au_temps(futur, face - ndeb, d) / tempnp1(face);
244 int n0 = le_dom->face_voisins(face, 0);
245 if (n0 == -1)
246 debit_v = -debit_v;
247 if (sub_type(Frontiere_ouverte_rho_u_impose, la_cl))
248 debit_rho_u_imp += debit_v;
249 else
250 debit_u_imp += debit_v;
251 }
252 }
253 else if (sub_type(Neumann_sortie_libre, la_cl))
254 {
255 Cerr << la_cl.que_suis_je() << " est incompatible avec le traitement conservation_masse." << finl;
256 exit();
257 }
258 }
259 // On fait la somme sur les procs
260 // Optimization: combine 2 mp_sum into 1 collective call
261 mp_sum_for_each(debit_u_imp, debit_rho_u_imp);
262
263 // Calcul de Pth(n+1)
264 for (int f = 0; f < nb_faces; f++)
265 Pth_n(f) = Pth_n(f) * (masse_n - dt * debit_rho_u_imp) / (masse_np1 + dt * debit_u_imp);
266 }
267}
static double calculer_integrale_volumique(const Domaine_VEF &, const DoubleVect &, Ok_Perio ok)
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
virtual double val_imp_au_temps(double temps, int i) const
Renvoie la valeur imposee sur la i-eme composante du champ a la frontiere au temps precise.
Definition Dirichlet.cpp:54
virtual const DoubleTab & tab_val_imp(double temps=DMAXFLOAT) const
Definition Dirichlet.cpp:75
class Domaine_VEF
Definition Domaine_VEF.h:54
classe EDO_Pression_th_VEF_Gaz_Parfait Cette classe represente l'EDO sur la pression associee au sche...
double resoudre(double) override
Resoud l'EDO.
classe EDO_Pression_th_VEF Cette classe represente l'EDO sur la pression associee au schema de
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
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
Frontiere ouverte sur laquelle on impose le flux massique rho.
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
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
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:207
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
void copy(const TRUSTTab &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:622
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
_SIZE_ size() const
Definition TRUSTVect.tpp:45
void copy(const TRUSTArray< _TYPE_, _SIZE_ > &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)