TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Sch_CN_EX_iteratif.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 <Sch_CN_EX_iteratif.h>
17#include <Probleme_base.h>
18#include <Navier_Stokes_std.h>
19#include <Param.h>
20#include <SFichier.h>
21
22Implemente_instanciable(Sch_CN_EX_iteratif,"Sch_CN_EX_iteratif",Sch_CN_iteratif);
23// XD Sch_CN_EX_iteratif Sch_CN_iteratif Sch_CN_EX_iteratif INHERITS_BRACE This keyword also describes a Crank-Nicholson
24// XD_CONT method of second order accuracy but here, for scalars, because of instablities encountered when dt>dt_CFL,
25// XD_CONT the Crank Nicholson scheme is not applied to scalar quantities. Scalars are treated according to
26// XD_CONT Euler-Explicite scheme at the end of the CN treatment for velocity flow fields (by doing p Euler explicite
27// XD_CONT under-iterations at dt<=dt_CFL). Parameters are the sames (but default values may change) compare to the
28// XD_CONT Sch_CN_iterative scheme plus a relaxation keyword: niter_min (2 by default), niter_max (6 by default),
29// XD_CONT niter_avg (3 by default), facsec_max (20 by default), seuil (0.05 by default)
30
32{
34}
35
36
38{
39 seuil=0.05;
40 niter_min=2;
41 niter_max=6;
42 niter_avg=3;
43 facsec_max=20;
44
46
47 return s;
48}
49
51{
52 param.ajouter("omega",&omega); // XD attr omega floattant omega OPT relaxation factor (0.1 by default)
54}
55
56/*! @brief Ne tient compte que de l'equation de Navier Stokes du probleme (s'il y en a une) Les autres ne sont pas limitantes : elles font autant de sous-pas de temps que necessaire.
57 *
58 * Code honteusement recopie de Probleme_base::calculer_pas_de_temps()
59 *
60 *
61 */
63{
64 imprimer(Cout);
65 // dt_=dt_max_; La majoration par dt_max_ est faite dans corriger_dt_calcule
66 dt_stab_=DMAXFLOAT;
67 const Probleme_base& prob=pb_base();
68
69 for(int i=0; i<prob.nombre_d_equations(); i++)
70 {
71 const Equation_base& eqn=prob.equation(i);
72 if (sub_type(Navier_Stokes_std,eqn))
73 {
75 break; // Max une equation de Navier Stokes par probleme
76 }
77 }
78}
80{
81 Probleme_base& pb = pb_base();
82 Equation_base& eqn = pb.equation(i);
83
84 // Choix selon que l'equation est de type Navier_Stokes ou non
85 if (sub_type(Navier_Stokes_std,eqn))
86 return iterateTimeStepOnNS(i,converged);
87 else
88 return iterateTimeStepOnOther(i,converged);
89}
90
91// Tres similaire a Sch_CN_iteratif::iterateTimeStepOnEquation mais on applique
92// un facteur d'attenuation omega entre les iterations.
93
94bool Sch_CN_EX_iteratif::iterateTimeStepOnNS(int i,bool& converged)
95{
96
97 Probleme_base& pb = pb_base();
98 Equation_base& eqn = pb.equation(i);
99
100 double temps_intermediaire=temps_futur(1);
101 double temps_final=temps_futur(2);
102 double dt_intermediaire=temps_intermediaire-temps_courant();
103 double dt_final=temps_final-temps_courant();
104
105 DoubleTab& present = eqn.inconnue().valeurs();
106 DoubleTab& intermediaire = eqn.inconnue().valeurs(temps_intermediaire);
107 DoubleTab& final = eqn.inconnue().valeurs(temps_final);
108
109 DoubleTab dudt(present);
110
111 DoubleTab delta(intermediaire);
112 DoubleTab old(intermediaire);
113
114 // On impose les CLs Dirichlet au temps intermediaire.
115 // En effet, les operateurs de diffusion n'utilisent que
116 // l'inconnue et ne vont pas lire les CLs.
117 // Cela permet en particulier d'avoir l'egalite des flux en pb
118 // couple thermique VEF avec Chap_front_contact_VEF, meme avant convergence.
119 // WEC : /!\ la vitesse au temps intermediaire
120 // n'est pas forcement a divergence nulle.
121 eqn.domaine_Cl_dis().imposer_cond_lim(eqn.inconnue(),temps_intermediaire);
122
123 // Calcul de la derivee dudt pour la valeur intermediaire de l'inconnue.
124 // Bidouille : Comme les operateurs prennent par defaut le present,
125 // on avance temporairement l'inconnue.
126
127 eqn.inconnue().avancer();
128 eqn.derivee_en_temps_inco(dudt);
129 eqn.inconnue().reculer();
130
131 // Mise a jour des valeurs de l'inconnue aux temps intermediaire et final
132 // intermediaire = present + dt_intermediaire * dudt;
133 // intermediaire = (1-omega)*new_intermediaire + omega*old_intermediaire
134 // final = present + dt_final * dudt;
135 intermediaire = dudt;
136 intermediaire*= dt_intermediaire;
137 intermediaire+= present;
138 intermediaire*= (1-omega);
139 old*= omega;
140 intermediaire+= old;
141 eqn.domaine_Cl_dis().imposer_cond_lim(eqn.inconnue(),temps_intermediaire);
142 intermediaire.echange_espace_virtuel();
143 final = dudt;
144 final*= dt_final;
145 final+= present;
146
147 eqn.domaine_Cl_dis().imposer_cond_lim(eqn.inconnue(),temps_final);
148 final.echange_espace_virtuel();
149
150 delta*=-1;
151 delta+=intermediaire; // delta = Contient u(n+1/2,p+1) - u(n+1/2,p)
152
153 // Si l'equation a diverge
154 if (divergence(present,intermediaire,delta,iteration))
155 {
156 converged=false;
157 return false;
158 }
159
160 // Si l'equation a converge
161 if (convergence(present,intermediaire,delta,iteration))
162 {
163 converged=true;
164 delta=final;
165 delta-=present;
166 delta/=dt_final;
167 update_critere_statio(delta, eqn);
168 }
169 else
170 {
172 converged=false;
173 }
174 return true;
175
176}
177
178// Faire plusieurs pas de temps d'Euler explicite a facsec<=1
179// On impose qu'un pas de temps tombe pile sur le temps intermediaire
180// et un autre pile sur le temps final.
181
183{
184 Probleme_base& pb = pb_base();
185 Equation_base& eqn = pb.equation(i);
186
187 double dt_eq=eqn.calculer_pas_de_temps();
188
189 double temps_intermediaire=temps_futur(1);
190 double temps_final=temps_futur(2);
191 double dt_1=temps_intermediaire-temps_courant();
192 double dt_2=temps_final-temps_intermediaire;
193
194 DoubleTab& present = eqn.inconnue().valeurs();
195 DoubleTab& intermediaire = eqn.inconnue().valeurs(temps_intermediaire);
196 DoubleTab& final = eqn.inconnue().valeurs(temps_final);
197
198 DoubleTab dIdt(present); // Pour dimensionner.
199
200 // Voir Schema_Temps_base::limpr pour information sur epsilon et modf
201 double nb_dt_1, nb_dt_2;
202 modf(ceil(dt_1/dt_eq), &nb_dt_1); // Nombre de pas de temps dans le premier, le deuxieme intervalle.
203 modf(ceil(dt_2/dt_eq), &nb_dt_2);
204
205 double dt_eq_1=dt_1/nb_dt_1; // Duree des pas de temps dans le premier, le deuxieme intervalle.
206 double dt_eq_2=dt_2/nb_dt_2;
207
208 // Calculs sur le premier pas de temps
209 intermediaire=present;
210 for (double k=0.; k<nb_dt_1; k=k+1.)
211 {
212
213 // Calcul de la derivee dIdt sur la valeur intermediaire de l'inconnue.
214 // Bidouille : Comme les operateurs prennent par defaut le present,
215 // on avance temporairement l'inconnue.
216 eqn.inconnue().avancer();
217 eqn.derivee_en_temps_inco(dIdt);
218 eqn.inconnue().reculer();
219
220 // intermediaire = intermediaire + dt_eq_1 * dIdt
221 dIdt*=dt_eq_1;
222 intermediaire+= dIdt;
223 intermediaire.echange_espace_virtuel();
224
225 }
226
227 // On impose les CLs au temps intermediaire
228 eqn.domaine_Cl_dis().imposer_cond_lim(eqn.inconnue(),temps_intermediaire);
229
230
231 // Calculs (idem) sur le deuxieme pas de temps
232 final=intermediaire;
233 for (double k=0.; k<nb_dt_2; k=k+1.)
234 {
235
236 // Calcul de la derivee dIdt sur la valeur finale de l'inconnue.
237 eqn.inconnue().avancer();
238 eqn.inconnue().avancer();
239 eqn.derivee_en_temps_inco(dIdt);
240 eqn.inconnue().reculer();
241 eqn.inconnue().reculer();
242
243 // intermediaire = intermediaire + dt_eq_2 * dIdt
244 dIdt*=dt_eq_2;
245 final+= dIdt;
247
248 }
249 dIdt=final;
250 dIdt-=present;
251 dIdt/=dt_2;
252 update_critere_statio(dIdt, eqn);
253 // On impose les CLs au temps final
254 eqn.domaine_Cl_dis().imposer_cond_lim(eqn.inconnue(),temps_final);
255
256 converged=true;
257 return true;
258
259}
260
261
263{
264
265 if (facsec_!=last_facsec) // On n'ajuste qu'une fois pour un initTimeStep.
266 return;
267
268 switch (cv)
269 {
270 case DIVERGENCE:
271 // le critere de divergence a ete atteint
273 omega=0.5*(0.5+omega); // fait tendre omega vers 0.5
274 break;
275 case NON_CONVERGENCE:
276 // ni le critere de divergence ni le critere de convergence
277 // n'ont ete atteints en niter_max iterations
279 omega=0.5*(0.5+omega); // (0.5+3*omega)/4; // fait tendre omega vers 0.5, plus lentement
280 break;
282 // le critere de convergence a ete atteint en plus que niter_avg
283 // iterations
285 if(omega>0.1)
286 omega*=0.95;
287 break;
289 // le critere de convergence a ete atteint en moins que niter_avg
290 // iterations
292 if(omega>0.1)
293 omega*=0.75;
294 break;
295 case CONVERGENCE_OK:
296 // le critere de convergence a ete atteint en niter_avg iterations
297 facsec_=last_facsec*1.01;
298 break;
299 default:
300 break;
301 }
302 facsec_=std::min(facsec_,facsec_max);
303}
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
Champ_Inc_base & avancer(int i=1)
Avance le pointeur courant de i pas de temps, dans la liste des valeurs temporelles conservees.
Champ_Inc_base & reculer(int i=1)
Recule le pointeur courant de i pas de temps, dans la liste des valeurs temporelles conservees.
virtual void imposer_cond_lim(Champ_Inc_base &, double)=0
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual const Champ_Inc_base & inconnue() const =0
virtual DoubleTab & derivee_en_temps_inco(DoubleTab &)
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
virtual double calculer_pas_de_temps() const
Calcul du prochain pas de temps.
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
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
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
classe Sch_CN_EX_iteratif
virtual bool iterateTimeStepOnOther(int i, bool &converged)
void mettre_a_jour_dt_stab() override
Ne tient compte que de l'equation de Navier Stokes du probleme (s'il y en a une) Les autres ne sont p...
virtual bool iterateTimeStepOnNS(int i, bool &converged)
void ajuster_facsec(type_convergence cv) override
void set_param(Param &titi) const override
bool iterateTimeStepOnEquation(int i, bool &converged) override
Calcule une iteration de la resolution sur l'equation i.
classe Sch_CN_iteratif Schema en temps alternant un demi-pas de temps d'Euler implicite et un demi-pa...
virtual bool divergence(const DoubleTab &u0, const DoubleTab &up1, const DoubleTab &delta, int p) const
Indique si le calcul iteratif a diverge.
virtual bool convergence(const DoubleTab &u0, const DoubleTab &up1, const DoubleTab &delta, int p) const
Indique si le calcul iteratif a converge.
void set_param(Param &titi) const override
double temps_futur(int i) const override
Renvoie le le temps a la i-eme valeur future.
double temps_courant() const
Renvoie le temps courant.
Probleme_base & pb_base()
virtual void imprimer(Sortie &os) const
Imprime le pas de temps sur un flot de sortie s'il y a lieu.
double dt_stab_
Pas de temps de stabilite.
void update_critere_statio(const DoubleTab &tab_critere, Equation_base &equation)
//Actualisation de stationnaire_atteint_ et residu_ (critere residu_<seuil_statio_)
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")