TrioCFD 1.9.9_beta
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}
class Champ_Don_base base class of Given Fields (not calculated)
DoubleTab & valeurs() override
Returns the array of field values at the current time.
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
Returns the total number of faces.
Definition Domaine_VF.h:471
double volumes(int i) const
Definition Domaine_VF.h:113
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
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 Domaine_dis_base This class is the base of the hierarchy of discretized domains.
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()
Returns the source terms associated with the equation.
int calculate_time_derivative() const
Sources les_sources
virtual int preparer_calcul()
Everything that does not depend on other possible problems.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Returns the problem associated with the equation.
virtual void associer_sch_tps_base(const Schema_Temps_base &)
Associates the time scheme with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Returns the discretized domain associated with the equation.
virtual double calculer_pas_de_temps() const
Calculation of the next time step.
: class Navier_Stokes_Variable_Density
int preparer_calcul() override
cf Equation_base::preparer_calcul() Assembly of the pressure solver and
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
Associates the time scheme with the equation.
void discretiser() override
Discretizes the equation.
virtual void calculer_la_pression_en_pa() override
Computes "la_pression_en_pa" from "la_pression".
const Champ_Don_base & diffusivite_pour_transport() const override
Navier_Stokes_std This class carries the terms of the momentum equation.
Operateur_Diff terme_diffusif
const Milieu_base & milieu() const override
Returns the physical medium of the equation (Fluide_base upcast to Milieu_base).
Operateur_Grad gradient
Operateur_Conv terme_convectif
const Champ_Inc_base & inconnue() const override
Returns the velocity (unknown field of the equation) (const version).
virtual void projeter()
Computes the solution U of the equations: | M(U-V)/dt + BtP = 0.
Operateur_Div divergence
virtual int projection_a_faire()
void discretiser() override
Discretizes the equation.
const Operateur & operateur(int) const override
Returns the i-th operator of the equation: - terme_diffusif if i = 0.
int nombre_d_operateurs() const override
Returns the number of operators in the equation: 2 for the standard Navier-Stokes equations.
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
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const =0
const Discretisation_base & discretisation() const
Returns the discretization associated with the problem.
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
class Schema_Implicite_base Base class for all implicit time schemes.
class Schema_Temps_base
double temps_courant() const
Returns the current time.
virtual void modifier_second_membre(const Equation_base &eqn, DoubleTab &secmem)
Base class for output streams.
Definition Sortie.h:52
void mettre_a_jour(double temps)
Time update of all sources in the list.
Definition Sources.cpp:109
DoubleTab & ajouter(DoubleTab &) const
Adds the contribution of all sources in the list to the array passed as parameter,...
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")