TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Navier_Stokes_Variable_Density.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
17#include <Navier_Stokes_Variable_Density.h>
18#include <Fluide_Incompressible.h>
19#include <Probleme_base.h>
20#include <Schema_Implicite_base.h>
21#include <Debog.h>
22
23Implemente_instanciable( Navier_Stokes_Variable_Density, "Navier_Stokes_Variable_Density", Navier_Stokes_std ) ;
24
26{
28 return os;
29}
30
32{
34 const Navier_Stokes_Variable_Density::Interface_Milieu& milieu = dynamic_cast<const Navier_Stokes_Variable_Density::Interface_Milieu&>(le_fluide.valeur());
35 terme_diffusif->associer_champ_masse_volumique(milieu.masse_volumique_variable());
36 return is;
37}
38
40{
41 if (sub_type(Schema_Implicite_base, un_schema_en_temps))
42 {
43 Cerr << "implicit scheme not available (yet) with Navier_Stokes_Variable_Density variant of the Navier-Stokes equations" << finl;
44 Cerr << "you should use an explicit scheme and, if you wish, activate the implicit treatment of the diffusion operator in the velocity prediction step" << finl;
45 exit();
46 }
47 Equation_base::associer_sch_tps_base(un_schema_en_temps);
48}
49
51{
52 return le_fluide->viscosite_dynamique();
53}
54
56{
58 const Domaine_dis_base& domaine_dis= le_dom_dis.valeur();
59 rho_faces_.typer("Champ_Fonc_Face");
60 probleme().discretisation().nommer_completer_champ_physique(domaine_dis, "masse_volumique_faces","kg/m^3", rho_faces_, probleme());
61 champs_compris_.ajoute_champ(rho_faces_);
62 rho_faces_->valeurs() = inconnue().valeurs();
63 assembleur_pression_->set_resoudre_increment_pression(1);
64 assembleur_pression_->set_resoudre_en_u(0);
65}
66
68{
69 const double temps = schema_temps().temps_courant();
70 sources().mettre_a_jour(temps);
72
73 // begin modification of Navier_Stokes_std::preparer_calcul()
75 const DoubleTab& tab_rho = milieu.masse_volumique_variable().valeurs();
76 DoubleTab& tab_rho_faces = rho_faces_->valeurs();
77 rho_aux_faces(tab_rho, tab_rho_faces);
78 tab_rho_faces.echange_espace_virtuel();
79 assembleur_pression_->assembler_rho_variable(matrice_pression_, rho_faces_);
80 // end modification of Navier_Stokes_std::preparer_calcul()
81
82 Debog::verifier("Navier_Stokes_std::preparer_calcul, la_pression av projeter", la_pression->valeurs());
84 projeter();
85
86 // Au cas ou une cl de pression depend de u que l'on vient de modifier
87 le_dom_Cl_dis->mettre_a_jour(temps);
88 Debog::verifier("Navier_Stokes_std::preparer_calcul, la_pression ap projeter", la_pression->valeurs());
89
90 // Initialisation du champ de pression (resolution de Laplacien(P)=0 avec les conditions limites en pression)
91 // Permet de demarrer la resolution avec une bonne approximation de la pression (important pour le Piso ou P!=0)
92 if (!probleme().reprise_effectuee() && methode_calcul_pression_initiale_ != 3)
93 {
94 Cout << "Estimation du champ de pression au demarrage:" << finl;
95 DoubleTrav secmem(la_pression->valeurs());
96 DoubleTrav vpoint(gradient_P->valeurs());
97 gradient.calculer(la_pression->valeurs(), gradient_P->valeurs());
98 // begin modification of Navier_Stokes_std::preparer_calcul()
99 gradient_P->valeurs() /= tab_rho_faces;
100 // end modification of Navier_Stokes_std::preparer_calcul()
101 vpoint -= gradient_P->valeurs();
102
104 for (int op = 0; op < nombre_d_operateurs(); op++)
105 operateur(op).ajouter(vpoint);
107 {
108 int mod = 0;
109 if (le_schema_en_temps->pas_de_temps() == 0)
110 {
111 double dt = std::max(le_schema_en_temps->pas_temps_min(), calculer_pas_de_temps());
112 dt = std::min(dt, le_schema_en_temps->pas_temps_max());
113 le_schema_en_temps->set_dt() = (dt);
114 mod = 1;
115 }
116 sources().ajouter(vpoint);
117 if (mod)
118 le_schema_en_temps->set_dt() = 0;
119 }
120
121 solveur_masse->appliquer(vpoint);
122 vpoint.echange_espace_virtuel();
123 divergence.calculer(vpoint, secmem);
124 secmem *= -1;
125 secmem.echange_espace_virtuel();
126
127 assembleur_pression_->modifier_secmem_pour_incr_p(la_pression->valeurs(), 1, secmem);
128 DoubleTrav inc_pre(la_pression->valeurs());
129 solveur_pression_.resoudre_systeme(matrice_pression_.valeur(), secmem, inc_pre);
130 Cerr << "Pressure increment computed successfully" << finl;
131
132 // On veut que l'espace virtuel soit a jour, donc all_items
133 operator_add(la_pression->valeurs(), inc_pre, VECT_ALL_ITEMS);
134 }
135 // Mise a jour pression
136 la_pression->changer_temps(temps);
138 // Calcul des forces de pression:
139 gradient->calculer_flux_bords();
140
141 // Calcul gradient_P (ToDo rendre coherent avec ::mettre_a_jour()):
142 gradient.calculer(la_pression->valeurs(), gradient_P->valeurs());
143 // begin modification of Navier_Stokes_std::preparer_calcul()
144 gradient_P->valeurs() /= tab_rho_faces;
145 // end modification of Navier_Stokes_std::preparer_calcul()
146 gradient_P->changer_temps(temps);
147
148 // Calcul divergence_U
149 divergence.calculer(la_vitesse->valeurs(), divergence_U->valeurs());
150 divergence_U->changer_temps(temps);
151
152 if (le_traitement_particulier)
153 le_traitement_particulier->preparer_calcul_particulier();
154
155 Debog::verifier("Navier_Stokes_std::preparer_calcul, vitesse", inconnue());
156 Debog::verifier("Navier_Stokes_std::preparer_calcul, pression", la_pression);
157
158 return 1;
159}
160
162{
163 const double dt = le_schema_en_temps->pas_de_temps();
165 const DoubleTab& tab_rho = milieu.masse_volumique_variable().valeurs();
166 DoubleTab& tab_rho_faces = rho_faces_->valeurs();
167 rho_aux_faces(tab_rho, tab_rho_faces);
168 tab_rho_faces.echange_espace_virtuel();
169 // matrix associated with - V ∇ ⋅ ( 1 / 𝜌⁽ⁿ⁺¹⁾ ∇[] ) where V is the diagonal volume operator (solveur_masse)
170 assembleur_pression_->assembler_rho_variable(matrice_pression_, rho_faces_);
171 solveur_pression_->reinit();
172
173 // ------------------------------
174 // step 1: velocity v⋆ prediction
175 // ------------------------------
176 // vpoint temporary container is initialized
177 vpoint = 0.;
178 // vpoint -= V ( ∇ P⁽ⁿ⁾ / 𝜌⁽ⁿ⁺¹⁾ )
179 gradient.calculer(la_pression->valeurs(), gradient_P->valeurs());
180 gradient_P->valeurs() /= tab_rho_faces;
181 vpoint -= gradient_P->valeurs();
182 // vpoint += V ( F⁽ⁿ⁺¹⁾ / 𝜌⁽ⁿ⁺¹⁾ ) (les_ssources are already divided by rho)
183 les_sources.ajouter(vpoint);
184 // vpoint -= V ( v⁽ⁿ⁾ ⋅ ∇ v⁽ⁿ⁾ ) (terme_convectif considered on the rhs, so minus sign alread accounted for)
185 DoubleTrav conv(vpoint);
186 if (schema_temps().diffusion_implicite())
187 {
188 derivee_en_temps_conv(conv, la_vitesse->valeurs());
189 }
190 else
191 {
192 terme_convectif.calculer(la_vitesse->valeurs(), conv);
193 }
194 vpoint += conv;
195
197 derivee_en_temps().valeurs() = vpoint;
198 schema_temps().modifier_second_membre((*this), vpoint);
199
200 if (schema_temps().diffusion_implicite())
201 {
202 // secmem is obtained from vpoint -> the right hand side of the equation to be solved for impliciting the diffusion term
203 DoubleTrav secmem(vpoint);
204 secmem = vpoint;
205 solveur_masse->appliquer(secmem);
206 // secmem = (- ∇ P⁽ⁿ⁾ + F⁽ⁿ⁺¹⁾ - 𝜌⁽ⁿ⁺¹⁾(v⁽ⁿ⁾ ⋅ ∇ v⁽ⁿ⁾))
207 secmem *= tab_rho_faces;
208 secmem.echange_espace_virtuel();
209 // vpoint temporary container is set to v⁽ⁿ⁾
210 vpoint = la_vitesse->valeurs();
211 vpoint.echange_espace_virtuel();
212 // solve (𝜌⁽ⁿ⁺¹⁾/ 𝛿t v⋆ + ∇ ⋅ 𝜏(v⋆)) = secmem
213 // vpoint in input = v⁽ⁿ⁾
214 // vpoint in output = (v⋆ - v⁽ⁿ⁾) / 𝛿t
215 Equation_base::Gradient_conjugue_diff_impl(secmem, vpoint, tab_rho_faces.dimension(0), tab_rho_faces);
216 }
217 else
218 {
219 // vpoint += V ( ∇ ⋅ 𝜏(v⁽ⁿ⁾) ) / 𝜌⁽ⁿ⁺¹⁾
220 DoubleTrav diff(vpoint);
221 terme_diffusif.calculer(la_vitesse->valeurs(), diff);
222 diff /= tab_rho_faces;
223 vpoint += diff;
224 solveur_masse->appliquer(vpoint);
225 // vpoint = (v⋆ - v⁽ⁿ⁾) / 𝛿t
226 }
227 vpoint.echange_espace_virtuel();
228
229 // -----------------------------------------------------------------------------
230 // step 2: projection for calculating the pressure increment P⁽ⁿ⁺¹⁾ = P⁽ⁿ⁾ + 𝛿 P
231 // -----------------------------------------------------------------------------
232 // secmem temporary container = V ∇ ⋅ v⁽ⁿ⁾ / 𝛿t
233 DoubleTrav secmem(la_pression->valeurs());
234 divergence.calculer(la_vitesse->valeurs(), secmem);
235 secmem /= dt;
236 // secmem += V ∇ ⋅ (v⋆ - v⁽ⁿ⁾) / 𝛿t
237 divergence.ajouter(vpoint, secmem);
238 secmem *= -1;
239 assembleur_pression_->modifier_secmem(secmem);
240 secmem.echange_espace_virtuel();
241
242 // solution of the Poisson problem - V ∇ ⋅ ( 1 / 𝜌⁽ⁿ⁺¹⁾ ∇ 𝛿 P ) = V ∇ ⋅ v⁽ⁿ⁾ / 𝛿t + V ∇ ⋅ (v⋆ - v⁽ⁿ⁾) / 𝛿t
243 DoubleTrav inc_pre(la_pression->valeurs());
244 solveur_pression_.resoudre_systeme(matrice_pression_.valeur(), secmem, inc_pre);
245 // update pressure P⁽ⁿ⁺¹⁾ = P⁽ⁿ⁾ + 𝛿 P
246 la_pression->valeurs() += inc_pre;
247 assembleur_pression_->modifier_solution(la_pression->valeurs());
248 la_pression->valeurs().echange_espace_virtuel();
249
250 // --------------------------------------------------------------
251 // step 3: velocity correction v⁽ⁿ⁺¹⁾ = v⋆ − 𝛿 t/𝜌⁽ⁿ⁺¹⁾ (∇ ⋅ 𝛿 P)
252 // --------------------------------------------------------------
253 // at this stage vpoint is (v⋆ - v⁽ⁿ⁾) / 𝛿t
254 //
255 // vpoint += ∇ ⋅ P⁽ⁿ⁾ / 𝜌⁽ⁿ⁺¹⁾
256 solveur_masse->appliquer(gradient_P->valeurs());
257 vpoint += gradient_P->valeurs();
258 // calculate V ( ∇ ⋅ P⁽ⁿ⁺¹⁾ / 𝜌⁽ⁿ⁺¹⁾ )
259 gradient.calculer(la_pression->valeurs(), gradient_P->valeurs());
260 gradient_P->valeurs() /= tab_rho_faces;
261 gradient_P->valeurs().echange_espace_virtuel();
262 // vpoint -= ∇ ⋅ P⁽ⁿ⁺¹⁾ / 𝜌⁽ⁿ⁺¹⁾
263 DoubleTrav gradP(gradient_P->valeurs());
264 gradP = gradient_P->valeurs();
265 solveur_masse->appliquer(gradP);
266 vpoint -= gradP;
267 vpoint.echange_espace_virtuel();
268 // at this stage vpoint is (v⁽ⁿ⁺¹⁾ - v⁽ⁿ⁾) / 𝛿t
269 return vpoint;
270}
271
276
277//DoubleTab& Navier_Stokes_Variable_Density::corriger_derivee_impl(DoubleTab& derivee)
278//{
279// solveur_masse->set_name_of_coefficient_temporel(rho_faces_->le_nom());
280// Navier_Stokes_std::corriger_derivee_impl(derivee);
281// solveur_masse->set_name_of_coefficient_temporel("no_coeff");
282// return derivee;
283//}
284
285
287{
288 DoubleTab& tab_rho_faces = rho_faces_->valeurs();
289 operator_divide(gradP, tab_rho_faces, VECT_ALL_ITEMS);
290}
291
292void Navier_Stokes_Variable_Density::rho_aux_faces(const DoubleTab& tab_rho, DoubleTab& tab_rho_face)
293{
294 const Domaine_VF& domaineVF = ref_cast(Domaine_VF, domaine_dis());
295 const IntTab& face_voisins = domaineVF.face_voisins();
296 const DoubleVect& volumes = domaineVF.volumes();
297 int nbfaces = domaineVF.nb_faces();
298 const int nbfaces_bord = domaineVF.premiere_face_int();
299 int el0, el1;
300 double vol0, vol1;
301 //
302 for (int fac = 0; fac < nbfaces_bord; fac++)
303 {
304 el0 = face_voisins(fac, 0);
305 if (el0 != -1)
306 {
307 tab_rho_face(fac) = tab_rho(el0);
308 }
309 else
310 {
311 el1 = face_voisins(fac, 1);
312 tab_rho_face(fac) = tab_rho(el1);
313 }
314 }
315
316 for (int fac = nbfaces_bord; fac < nbfaces; fac++)
317 {
318 el0 = face_voisins(fac, 0);
319 el1 = face_voisins(fac, 1);
320 vol0 = volumes(el0);
321 vol1 = volumes(el1);
322 tab_rho_face(fac) = (vol0 * tab_rho(el0) + vol1 * tab_rho(el1)) / (vol0 + vol1);
323 }
324}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
void nommer_completer_champ_physique(const Domaine_dis_base &domaine_vdf, const Nom &nom_champ, const Nom &unite, Champ_base &champ, const Probleme_base &pbi) const
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
double volumes(int i) const
Definition Domaine_VF.h:113
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
DoubleTab & derivee_en_temps_conv(DoubleTab &, const DoubleTab &)
Add convection term In: solution is the unknown I.
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
int calculate_time_derivative() const
Sources les_sources
virtual int preparer_calcul()
Tout ce qui ne depend pas des autres problemes eventuels.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
virtual void associer_sch_tps_base(const Schema_Temps_base &)
S'associe au schema_en_temps.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
virtual double calculer_pas_de_temps() const
Calcul du prochain pas de temps.
: class Navier_Stokes_Variable_Density
int preparer_calcul() override
cf Equation_base::preparer_calcul() Assemblage du solveur pression et
DoubleTab & derivee_en_temps_inco(DoubleTab &) override
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
void associer_sch_tps_base(const Schema_Temps_base &) override
S'associe au schema_en_temps.
void discretiser() override
Dicretise l'equation.
virtual void calculer_la_pression_en_pa() override
Calcul de "la_pression_en_pa" en fonction de "la_pression".
const Champ_Don_base & diffusivite_pour_transport() const override
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
Operateur_Diff terme_diffusif
const Milieu_base & milieu() const override
Renvoie le milieu physique de l'equation (le Fluide_base upcaste en Milieu_base).
Operateur_Grad gradient
Operateur_Conv terme_convectif
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
virtual void projeter()
Calcule la solution U des equations: | M(U-V)/dt + BtP = 0.
Operateur_Div divergence
virtual int projection_a_faire()
void discretiser() override
Dicretise l'equation.
const Operateur & operateur(int) const override
Renvoie le i-eme operateur de l'equation: - le terme_diffusif si i = 0.
int nombre_d_operateurs() const override
Renvoie le nombre d'operateurs de l'equation: Pour Navier Stokes Standard c'est 2.
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
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const =0
const Discretisation_base & discretisation() const
Renvoie la discretisation associee au probleme.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
class Schema_Implicite_base Classe de base pour tous les schemas en temps implicite
class Schema_Temps_base
double temps_courant() const
Renvoie le temps courant.
virtual void modifier_second_membre(const Equation_base &eqn, DoubleTab &secmem)
Classe de base des flux de sortie.
Definition Sortie.h:52
void mettre_a_jour(double temps)
Mise a jour en temps, de toute les sources de la liste.
Definition Sources.cpp:109
DoubleTab & ajouter(DoubleTab &) const
Ajoute la contribution de toutes les sources de la liste au tableau passe en parametre,...
Definition Sources.cpp:85
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")