TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Schema_Temps_IJK_base.cpp
1/****************************************************************************
2* Copyright (c) 2024, 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 <Schema_Temps_IJK_base.h>
17#include <Probleme_FTD_IJK_base.h>
18#include <EFichier.h>
19#include <Param.h>
20#include <Perf_counters.h>
21
22Implemente_base(Schema_Temps_IJK_base,"Schema_Temps_IJK_base",Schema_Temps_base);
23// XD schema_temps_base_IJK objet_u schema_temps_base_IJK INHERITS_BRACE Basic class for time schemes. This scheme will
24// XD_CONT be associated with a problem and the equations of this problem.
25//
27{
28 os << "dt " << dt_ << finl;
29 os << "temps_courant " << temps_courant_ << finl ;
30 os << "tinit " << tinit_ << finl;
31 os << "timestep_facsec " << timestep_facsec_ << finl ;
32 os << "nb_pas_dt_max " << nb_pas_dt_max_ << finl;
33 os << "max_simu_time " << max_simu_time_ << finl ;
34 os << "tstep_init " << tstep_init_ << finl;
35 os << "use_tstep_init " << use_tstep_init_ << finl ;
36 os << "dt_sauvegarde " << dt_sauvegarde_ << finl ;
37 os << "cfl " << cfl_ << finl ;
38 os << "fo " << fo_ << finl ;
39 os << "oh " << oh_ << finl ;
40 os << "fin " << finl;
41 return os;
42}
43
45{
46 Cerr << "Reading of data for a " << que_suis_je() << " time scheme" << finl;
47 Param param(que_suis_je());
48 set_param(param);
49 param.lire_avec_accolades_depuis(is);
51 lu_ = 1;
52 stop_file_ = nom_du_cas() + Nom(".stop");
53 return is;
54}
55
57{
58// Schema_Temps_base::set_param(param);
59
60 param.ajouter("tinit", &tinit_, Param::REQUIRED); // XD_ADD_P floattant
61 // XD_CONT initial time
62 param.ajouter("timestep", &dt_, Param::REQUIRED); // XD_ADD_P floattant
63 // XD_CONT Upper limit of the timestep
64 param.ajouter("timestep_facsec", &timestep_facsec_); // XD_ADD_P floattant
65 // XD_CONT Security factor on timestep
66 param.ajouter("cfl", &cfl_); // XD_ADD_P floattant
67 // XD_CONT To provide a value of the limiting CFL number used for setting the timestep
68 param.ajouter("fo", &fo_); // XD_ADD_P floattant
69 // XD_CONT not_set
70 param.ajouter("oh", &oh_); // XD_ADD_P floattant
71 // XD_CONT not_set
72 param.ajouter("nb_pas_dt_max", &nb_pas_dt_max_, Param::REQUIRED); // XD_ADD_P entier
73 // XD_CONT maximum limit for the number of timesteps
74 param.ajouter("max_simu_time", &max_simu_time_); // XD_ADD_P double
75 // XD_CONT maximum limit for the simulation time
76 param.ajouter("tstep_init", &tstep_init_); // XD_ADD_P entier
77 // XD_CONT index first interation for recovery
78 param.ajouter("use_tstep_init", &use_tstep_init_); // XD_ADD_P entier
79 // XD_CONT use tstep init for constant post-processing step
80 param.ajouter("dt_sauvegarde", &dt_sauvegarde_); // XD_ADD_P entier
81 // XD_CONT saving frequency (writing files for computation restart)
82 param.ajouter_non_std( "tcpumax",(this)); // XD_ADD_P double
83 // XD_CONT CPU time limit (must be specified in hours) for which the calculation is stopped (1e30s by default).
84
85 param.ajouter_flag("enable_dt_oh_ideal_length_factor", &enable_dt_oh_ideal_length_factor_);
86 param.ajouter_flag("first_step_interface_smoothing", &first_step_interface_smoothing_);
87}
88
90{
91 param.ajouter("tinit", &temps_courant_);
92 param.ajouter("tstep_init", &tstep_init_);
93}
94
96{
98 (!ref_cast(Probleme_FTD_IJK_base, mon_probleme.valeur()).get_reprise() && temps_courant_ == 0.));
99 if (tstep_init_)
100 use_tstep_init_ = 1;
101}
102
103// Methode de calcul du pas de temps max base sur CFL, Oh et Fo
104// Pour les maillages uniformes uniquement.
105// On choisi de mettre le facteur 0.5 dans dt_cfl et dt_fo
106// pour que le calcul soit stable avec un CFL <=1.0 et Fo <= 1.0.
107// Sinon, il faudrait recommander CFL <= 0.5 et Fo <=0.5 ce qui n'est pas la valeur par defaut...
108double Schema_Temps_IJK_base::find_timestep(const double max_timestep, const double cfl, const double fo, const double oh)
109{
110 statistics().begin_count(STD_COUNTERS::compute_dt,statistics().get_last_opened_counter_level()+1);
111
112 // XXX pffff pas const car Thermals classe est tout xxxx ....
113 Probleme_FTD_IJK_base& pb_ijk = ref_cast(Probleme_FTD_IJK_base, mon_probleme.valeur());
114
115 dt_cfl_ = 1.e20;
116 double dxmin = 1.e20;
117 // On ne connait pas la longueur minimum du maillage lagrangien, mais on en prend une approximation :
118 // lg \approx 1.7 delta
119 double lg_cube = 1.;
120 double lg_cube_raw = 1.;
121 for (int dir = 0; dir < 3; dir++)
122 {
123 const IJK_Field_double& v = pb_ijk.eq_ns().get_velocity()[dir];
124 double max_v = 1.e-20; // Pas zero pour la division a la fin...
125 const int ni = v.ni();
126 const int nj = v.nj();
127 const int nk = v.nk();
128 for (int k = 0; k < nk; k++)
129 for (int j = 0; j < nj; j++)
130 for (int i = 0; i < ni; i++)
131 max_v = std::max(max_v, fabs(v(i, j, k)));
132 max_v = Process::mp_max(max_v);
133 const Domaine_IJK& geom = v.get_domaine();
134#ifndef VARIABLE_DZ
135 const double delta = geom.get_constant_delta(dir);
136#else
137 const ArrOfDouble& tab_dz=geom.get_delta(dir);
138 const double delta = Process::mp_min(min_array(tab_dz));
139#endif
140 lg_cube *= 1.7 * delta;
141 lg_cube_raw *= delta;
142 dxmin = std::min(delta, dxmin);
143 // QUESTION GAB : pourquoi on ne reprend pas dxmin ?
144 if (max_v > 0)
145 dt_cfl_ = std::min(dt_cfl_, delta / max_v * 0.5);
146 }
147 dt_cfl_ *= cfl;
150
151 const double mu_l = pb_ijk.milieu_ijk().get_mu_liquid(), rho_l = pb_ijk.milieu_ijk().get_rho_liquid(), mu_v = pb_ijk.milieu_ijk().get_mu_vapour(), rho_v = pb_ijk.milieu_ijk().get_rho_vapour();
152
153 dt_fo_liq_ = dxmin * dxmin / ((mu_l / rho_l) + 1.e-20) * fo * 0.125;
154 dt_fo_vap_ = dxmin * dxmin / ((mu_v / rho_v) + 1.e-20) * fo * 0.125;
155 dt_fo_ = std::min(dt_fo_liq_, dt_fo_vap_);
156 if (pb_ijk.eq_ns().get_disable_diffusion_qdm())
157 dt_fo_ = 1.e20;
158
159 /*
160 * Popinet et.al 2018 (review surface tension calculation)
161 * Au cas ou sigma = 0, on utilise (sigma + 1e-20)
162 */
163 double ideal_length_factor = 1.7;
164
165 if (pb_ijk.has_interface())
166 ideal_length_factor = pb_ijk.get_remaillage_ft_ijk().get_facteur_longueur_ideale();
167
168 double max_sigma = -1e10;
169 /*if (!interfaces_.maillage_ft_ijk().Surfactant_facettes().get_disable_surfactant())
170 {
171 // alors on a une tension de surface variable
172 // Il faut prendre le max de la tension de surface dans le critere de stabilite ?
173 const int nb_som=interfaces_.maillage_ft_ijk().nb_sommets();
174 const ArrOfDouble& sigma_sommets = interfaces_.maillage_ft_ijk().Surfactant_facettes().get_sigma_sommets();
175 for (int i = 0; i < nb_som; i++)
176 {
177 if (max_sigma<sigma_sommets[i])
178 max_sigma= sigma_sommets[i];
179 }
180 max_sigma=Process::mp_max(max_sigma);
181 }
182 else*/
183 max_sigma = pb_ijk.milieu_ijk().sigma();
184
186 dt_oh_ = sqrt((rho_l + rho_v) / (2 * M_PI) * lg_cube_raw * pow(ideal_length_factor, 3) / (max_sigma + 1e-20)) * oh;
187 else
188 dt_oh_ = sqrt((rho_l + rho_v) / 2. * lg_cube / (max_sigma + 1e-20)) * oh;
189 if (pb_ijk.eq_ns().get_disable_convection_qdm())
190 dt_oh_ = 1.e20;
191
192 // Seems underestimated !
193 // const double dt_oh = sqrt((rho_liquide_+rho_vapeur_)/2. * lg_cube/(sigma_+1e-20) ) * oh;
194
195 const double dt_eq_velocity = 1. / (1. / dt_cfl_ + 1. / dt_fo_ + 1. / dt_oh_);
196
197
198 double dt_thermals = 1.e20;
199
200 if (pb_ijk.has_thermals())
201 pb_ijk.get_ijk_thermals().compute_timestep(dt_thermals, dxmin);
202
203 // to enforce max simulation time
204 const double dt_max_for_simu_time = std::max(0.0, max_simu_time_ - temps_courant_);
205
206 const double dt = std::min({max_timestep, timestep_facsec_ * std::min(dt_eq_velocity, dt_thermals), dt_max_for_simu_time});
207
208
209
211 {
212 int reset = (!pb_ijk.get_reprise()) && (nb_pas_dt_ == 0);
213 SFichier fic = Ouvrir_fichier(".dt_ev", "tstep\ttime\ttimestep\tdt_cfl\tdt_fo\tdt_oh\tdt_diff_th", reset);
214 fic << nb_pas_dt_ << " " << temps_courant_ << " " << dt;
215 fic << " " << dt_cfl_ << " " << dt_fo_ << " " << dt_oh_;
216 fic << " " << dt_thermals; // If no thermal equation, value will be large.
217 fic << finl;
218 fic.close();
219 }
220 statistics().end_count(STD_COUNTERS::compute_dt);
221
222 /* a bouger un jour dans mettre_a_jour ... existe pas pour le moment */
225
226 if (je_suis_maitre())
227 temps_cpu_ecoule_ = statistics().get_time_since_last_open(STD_COUNTERS::total_execution_time);
228
229 envoyer_broadcast(temps_cpu_ecoule_,0);
230
231 assert(dt > 0);
232
233
234
235 return dt;
236}
237
239{
240 stop = false;
241 int stop_i = 0;
242
243 // 1. verification du fichier stop
244 if (!get_disable_stop())
245 {
246 if (je_suis_maitre())
247 {
248 EFichier f;
249 stop_i = f.ouvrir(stop_file_);
250 if (stop_i) // file exists, check if it contains 1
251 f >> stop_i;
252 }
253 envoyer_broadcast(stop_i, 0);
254
255 if (stop_i)
256 {
257 Cerr << "---------------------------------------------------------" << finl
258 << "The problem " << pb_base().le_nom() << " wants to stop : stop file detected" << finl << finl;
259 }
260 }
261
262 // 2. verification nb_pas_dt_max
263 if (get_tstep() == get_nb_timesteps() - 1)
264 {
265 stop_i = 1;
266 Cerr << "---------------------------------------------------------" << finl
267 << "The problem " << pb_base().le_nom() << " wants to stop : the maximum number of time steps reached" << finl << finl;
268 }
269
270 // 3. verification tmax
272 {
273 stop_i = 1;
274 Cerr << "---------------------------------------------------------" << finl
275 << "The problem " << pb_base().le_nom() << " wants to stop : final time reached" << finl << finl;
276 }
277
278 // 4. verification tcpu_max
280 {
281 stop_i = 1;
282 Cerr << "---------------------------------------------------------" << finl
283 << "The problem " << pb_base().le_nom() << " wants to stop : max cpu time reached" << finl << finl;
284 }
285
286 stop = stop_i;
287}
288
290{
291 if (timestep_facsec_ > 0. && !stop)
292 {
293 // WTF - find_timestep non const ?!!
294 Schema_Temps_IJK_base& sh_non_cst = const_cast<Schema_Temps_IJK_base&>(*this); // FIXME
295 sh_non_cst.dt_ = sh_non_cst.find_timestep(max_timestep_, cfl_, fo_, oh_);
296 }
297
298 return dt_;
299}
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
double get_constant_delta(int direction) const
Returns the size of cells in a direction.
const ArrOfDouble & get_delta(int direction) const
Returns the array of mesh cell sizes in requested direction.
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Definition EFichier.h:29
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::in)
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const Domaine_IJK & get_domaine() const
void compute_timestep(double &dt_thermals, const double dxmin)
const IJK_Field_vector3_double & get_velocity() const
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
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
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_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
Fluide_Diphasique_IJK & milieu_ijk()
const Navier_Stokes_FTD_IJK & eq_ns() const
const Remaillage_FT_IJK & get_remaillage_ft_ijk() const
const IJK_Thermals & get_ijk_thermals() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
static double mp_min(double)
Definition Process.cpp:386
static double mp_max(double)
Definition Process.cpp:376
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
const double & get_facteur_longueur_ideale() const
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
double computeTimeStep(bool &stop) const override
double find_timestep(const double max_timestep, const double cfl, const double fo, const double oh)
void check_stop_criteria(bool &stop) const
void set_param(Param &) const override
class Schema_Temps_base
double dt_
Pas de temps de calcul.
virtual int stop() const
Renvoie 1 si il y lieu de stopper le calcul pour differente raisons: - le temps final est atteint.
Probleme_base & pb_base()
Classe de base des flux de sortie.
Definition Sortie.h:52