TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Navier_Stokes_FTD_IJK.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 <Navier_Stokes_FTD_IJK_tools.h>
17#include <Schema_Euler_explicite_IJK.h>
18#include <Probleme_FTD_IJK_tools.h>
19#include <Navier_Stokes_FTD_IJK.h>
20#include <Probleme_FTD_IJK_base.h>
21#include <Fluide_Diphasique_IJK.h>
22#include <Schema_RK3_IJK.h>
23#include <Option_IJK.h>
24#include <Param.h>
25#include <Perf_counters.h>
26
27#define COMPLEMENT_ANTI_DEVIATION_RESIDU
28// #define VARIABLE_DZ
29// #define PROJECTION_DE_LINCREMENT_DV
30
31Implemente_instanciable_sans_constructeur(Navier_Stokes_FTD_IJK, "Navier_Stokes_FTD_IJK", Equation_base);
32// XD Navier_Stokes_FTD_IJK eqn_base Navier_Stokes_FTD_IJK INHERITS_BRACE Navier-Stokes equations.
33
35{
36 terme_source_correction_.resize_array(3); // Initialement a zero, puis sera calcule a chaque iter.
38 correction_force_.resize_array(3); // Par defaut, les flags d'activations sont a zero (ie inactif).
40
41 vol_bulles_.resize_array(0); // Initialement a zero, puis sera calcule a chaque iter.
42 vol_bulles_ = 0.;
43
44 expression_variable_source_.dimensionner_force(3);
45 expression_vitesse_initiale_.dimensionner_force(3);
46}
47
49{
50 return os<< que_suis_je() << " " << le_nom();
51}
52
54{
55 Cerr<<"Reading of data for a "<<que_suis_je()<<" equation"<<finl;
56 Param param(que_suis_je());
57 set_param(param);
58 param.lire_avec_accolades_depuis(is);
59 return is;
60}
61
63{
64 /*
65 * BASE
66 */
67 param.ajouter("multigrid_solver", &poisson_solver_, Param::REQUIRED); // XD_ADD_P multigrid_solver
68 // XD_CONT not_set
69 param.ajouter("vitesse_entree_dir", &vitesse_entree_dir_);
70 param.ajouter("vitesse_entree_compo_to_force", &vitesse_entree_compo_to_force_);
71 param.ajouter("stencil_vitesse_entree", &stencil_vitesse_entree_);
72 param.ajouter("vitesse_entree", &vitesse_entree_); // XD_ADD_P floattant
73 // XD_CONT Velocity to prescribe at inlet
74 param.ajouter("expression_vx_init", &expression_vitesse_initiale_[0]); // XD_ADD_P chaine
75 // XD_CONT initial field for x-velocity component (parser of x,y,z)
76 param.ajouter("expression_vy_init", &expression_vitesse_initiale_[1]); // XD_ADD_P chaine
77 // XD_CONT initial field for y-velocity component (parser of x,y,z)
78 param.ajouter("expression_vz_init", &expression_vitesse_initiale_[2]); // XD_ADD_P chaine
79 // XD_CONT initial field for z-velocity component (parser of x,y,z)
80 param.ajouter("expression_p_init", &expression_pression_initiale_); // XD_ADD_P chaine
81 // XD_CONT initial pressure field (optional)
82 param.ajouter("velocity_diffusion_op", &velocity_diffusion_op_); // XD_ADD_P chaine
83 // XD_CONT Type of velocity diffusion scheme
84 param.ajouter("velocity_convection_op", &velocity_convection_op_); // XD_ADD_P chaine
85 // XD_CONT Type of velocity convection scheme
86
87 // ATTENTION les fichiers reprises sont des fichiers .lata ou sauv.lata
88 // On peut reprendre uniquement la vitesse ou uniquement rho dans un fichier de post:
89 param.ajouter("fichier_reprise_vitesse", &fichier_reprise_vitesse_); // XD_ADD_P chaine
90 // XD_CONT not_set
91 param.ajouter("timestep_reprise_vitesse", &timestep_reprise_vitesse_); // XD_ADD_P chaine
92 // XD_CONT not_set
93
94 param.ajouter("boundary_conditions", &boundary_conditions_, Param::REQUIRED);
95
96 param.ajouter_flag("projection_initiale", &projection_initiale_demandee_);
97 param.ajouter_flag("disable_solveur_poisson", &disable_solveur_poisson_); // XD_ADD_P rien
98 // XD_CONT Disable pressure poisson solver
99 param.ajouter_flag("disable_diffusion_qdm", &disable_diffusion_qdm_); // XD_ADD_P rien
100 // XD_CONT Disable diffusion operator in momentum
101 param.ajouter_flag("disable_convection_qdm", &disable_convection_qdm_); // XD_ADD_P rien
102 // XD_CONT Disable convection operator in momentum
103
104 // XXX Equation non resolu : renomer
105 param.ajouter_flag("frozen_velocity", &frozen_velocity_); // XD_ADD_P chaine
106 // XD_CONT not_set
107
108 param.ajouter_flag("velocity_reset", &velocity_reset_); // XD_ADD_P chaine
109 // XD_CONT not_set
110 param.ajouter_flag("resolution_fluctuations", &resolution_fluctuations_); // XD_ADD_P rien
111 // XD_CONT Disable pressure poisson solver
112 param.ajouter_flag("use_harmonic_viscosity", &use_harmonic_viscosity_);
113 param.ajouter_flag("harmonic_nu_in_diff_operator", &harmonic_nu_in_diff_operator_); // XD_ADD_P rien
114 // XD_CONT Disable pressure poisson solver
115 param.ajouter_flag("use_inv_rho_for_mass_solver_and_calculer_rho_v", &use_inv_rho_for_mass_solver_and_calculer_rho_v_); // XD_ADD_P chaine
116 // XD_CONT not_set
117 param.ajouter_flag("use_inv_rho_in_poisson_solver", &use_inv_rho_in_poisson_solver_); // XD_ADD_P flag
118 // XD_CONT not_set
119 param.ajouter_flag("diffusion_alternative", &diffusion_alternative_); // XD_ADD_P chaine
120 // XD_CONT not_set
121 param.ajouter_flag("test_etapes_et_bilan", &test_etapes_et_bilan_); // XD_ADD_P flag
122 // XD_CONT not_set
123 param.ajouter_flag("ajout_init_a_reprise", &add_initial_field_); // XD_ADD_P chaine
124 // XD_CONT not_set
125 param.ajouter_flag("improved_initial_pressure_guess", &improved_initial_pressure_guess_); // XD_ADD_P chaine
126 // XD_CONT not_set
127 param.ajouter_flag("include_pressure_gradient_in_ustar", &include_pressure_gradient_in_ustar_); // XD_ADD_P chaine
128 // XD_CONT not_set
129
130
131 /*
132 * FT
133 */
134 param.ajouter("upstream_dir", &upstream_dir_); // XD_ADD_P entier
135 // XD_CONT Direction to prescribe the velocity
136 param.ajouter("vitesse_upstream", &vitesse_upstream_); // XD_ADD_P floattant
137 // XD_CONT Velocity to prescribe at 'nb_diam_upstream_' before bubble 0.
138 param.ajouter("expression_vitesse_upstream", &expression_vitesse_upstream_); // XD_ADD_P chaine
139 // XD_CONT Analytical expression to set the upstream velocity
140 param.ajouter("upstream_velocity_bubble_factor", &upstream_velocity_bubble_factor_);
141 param.ajouter("upstream_velocity_bubble_factor_deriv", &upstream_velocity_bubble_factor_deriv_);
142 param.ajouter("upstream_velocity_bubble_factor_integral", &upstream_velocity_bubble_factor_integral_);
143 param.ajouter("velocity_bubble_scope", &velocity_bubble_scope_);
144 param.ajouter("upstream_stencil", &upstream_stencil_); // XD_ADD_P int
145 // XD_CONT Width on which the velocity is set
146 param.ajouter("nb_diam_upstream", &nb_diam_upstream_); // XD_ADD_P floattant
147 // XD_CONT Number of bubble diameters upstream of bubble 0 to prescribe the velocity.
148 param.ajouter("nb_diam_ortho_shear_perio", &nb_diam_ortho_shear_perio_); // XD_ADD_P chaine
149 // XD_CONT not_set
150 param.ajouter("vol_bulle_monodisperse", &vol_bulle_monodisperse_); // XD_ADD_P chaine
151 // XD_CONT not_set
152 param.ajouter("diam_bulle_monodisperse", &diam_bulle_monodisperse_); // XD_ADD_P chaine
153 // XD_CONT not_set
154 param.ajouter("coeff_evol_volume", &coeff_evol_volume_); // XD_ADD_P chaine
155 // XD_CONT not_set
156 param.ajouter("vol_bulles", &vol_bulles_); // XD_ADD_P chaine
157 // XD_CONT not_set
158 param.ajouter("reprise_vap_velocity_tmoy", &vap_velocity_tmoy_); // XD_ADD_P chaine
159 // XD_CONT not_set
160 param.ajouter("reprise_liq_velocity_tmoy", &liq_velocity_tmoy_); // XD_ADD_P chaine
161 // XD_CONT not_set
162 param.ajouter_flag("disable_source_interf", &disable_source_interf_); // XD_ADD_P rien
163 // XD_CONT Disable computation of the interfacial source term
164 param.ajouter_flag("upstream_velocity_measured", &upstream_velocity_measured_);
165 param.ajouter_flag("harmonic_nu_in_calc_with_indicatrice", &harmonic_nu_in_calc_with_indicatrice_); // XD_ADD_P rien
166 // XD_CONT Disable pressure poisson solver
167 param.ajouter_flag("refuse_patch_conservation_QdM_RK3_source_interf", &refuse_patch_conservation_QdM_RK3_source_interf_); // XD_ADD_P rien
168 // XD_CONT experimental Keyword, not for use
169 param.ajouter_flag("suppression_rejetons", &suppression_rejetons_); // XD_ADD_P chaine
170 // XD_CONT not_set
171
172
173 /*
174 * Sources
175 */
176 param.ajouter("p_seuil_max", &p_seuil_max_); // XD_ADD_P floattant
177 // XD_CONT not_set, default 10000000
178 param.ajouter("p_seuil_min", &p_seuil_min_); // XD_ADD_P floattant
179 // XD_CONT not_set, default -10000000
180 param.ajouter("coef_ammortissement", &coef_ammortissement_); // XD_ADD_P floattant
181 // XD_CONT not_set
182 param.ajouter("coef_immobilisation", &coef_immobilisation_); // XD_ADD_P floattant
183 // XD_CONT not_set
184 param.ajouter("expression_derivee_force", &expression_derivee_acceleration_); // XD_ADD_P chaine
185 // XD_CONT expression of the time-derivative of the X-component of a source-term (see terme_force_ini for the initial
186 // XD_CONT value). terme_force_ini : initial value of the X-component of the source term (see expression_derivee_force
187 // XD_CONT for time evolution)
188 param.ajouter("terme_force_init", &terme_source_acceleration_); // XD_ADD_P chaine
189 // XD_CONT not_set
190 param.ajouter("terme_force_init_z", &terme_source_acceleration_z_); // XD_ADD_P chaine
191 // XD_CONT not_set
192 param.ajouter("correction_force", &correction_force_); // XD_ADD_P chaine
193 // XD_CONT not_set
194 param.ajouter_flag("compute_force_init", &compute_force_init_); // XD_ADD_P flag
195 // XD_CONT not_set
196
197 param.ajouter("expression_variable_source_x", &expression_variable_source_[0]); // XD_ADD_P chaine
198 // XD_CONT not_set
199 param.ajouter("expression_variable_source_y", &expression_variable_source_[1]); // XD_ADD_P chaine
200 // XD_CONT not_set
201 param.ajouter("expression_variable_source_z", &expression_variable_source_[2]); // XD_ADD_P chaine
202 // XD_CONT not_set
203 param.ajouter("facteur_variable_source_init", &facteur_variable_source_); // XD_ADD_P chaine
204 // XD_CONT not_set
205 param.ajouter("expression_derivee_facteur_variable_source", &expression_derivee_facteur_variable_source_); // XD_ADD_P chaine
206 // XD_CONT not_set
207
208 param.ajouter("expression_potential_phi", &expression_potential_phi_); // XD_ADD_P chaine
209 // XD_CONT parser to define phi and make a momentum source Nabla phi.
210
211 param.ajouter("forcage", &forcage_); // XD_ADD_P bloc_lecture
212 // XD_CONT not_set
213 param.ajouter("corrections_qdm", &qdm_corrections_); // XD_ADD_P bloc_lecture
214 // XD_CONT not_set
215
216 // Correcteur PID
217 param.ajouter("Kp", &Kp_);
218 param.ajouter("Kd", &Kd_);
219
220 // Nb de mailles sur lesquelles on applique le force upstream pour le shear perio
221 param.ajouter("epaisseur_maille", &epaisseur_maille_);
222
223 // Matrice non symetrique pour le shear perio
224 param.ajouter("No_Sym", &NoSym_);
225
226 // Postpro sur les surfaces de controle
227 param.ajouter("delta", &delta_);
228 param.ajouter("L", &L_);
229
230 // Postpro sur les volumes de controle
231 param.ajouter("L_vol_controle", &L_boite_vol_controle_);
232
233
234 /*
235 * Sources FT
236 */
237 param.ajouter("coef_mean_force", &coef_mean_force_); // XD_ADD_P floattant
238 // XD_CONT not_set
239 param.ajouter("coef_force_time_n", &coef_force_time_n_); // XD_ADD_P floattant
240 // XD_CONT not_set
241 param.ajouter("coef_rayon_force_rappel", &coef_rayon_force_rappel_); // XD_ADD_P floattant
242 // XD_CONT not_set
243 param.ajouter_flag("correction_semi_locale_volume_bulle", &correction_semi_locale_volume_bulle_);
244}
245
247{
248 /*
249 * BASE
250 */
251 param.ajouter("terme_acceleration_init", &terme_source_acceleration_);
252 param.ajouter("terme_acceleration_init_z", &terme_source_acceleration_z_);
253 param.ajouter("fichier_reprise_vitesse", &fichier_reprise_vitesse_);
254 param.ajouter("timestep_reprise_vitesse", &timestep_reprise_vitesse_);
255 param.ajouter("forcage", &forcage_);
256 param.ajouter("corrections_qdm", &qdm_corrections_);
257
258 /*
259 * FT
260 */
261 param.ajouter("vitesse_upstream_reprise", &vitesse_upstream_reprise_);
262 param.ajouter("velocity_bubble_old", &velocity_bubble_old_);
263 param.ajouter("reprise_vap_velocity_tmoy", &vap_velocity_tmoy_);
264 param.ajouter("reprise_liq_velocity_tmoy", &liq_velocity_tmoy_);
265}
266
268{
269 if (!sub_type(Probleme_FTD_IJK_base, pb))
270 {
271 Cerr << "Error for the method Navier_Stokes_FTD_IJK::associer_pb_base\n";
272 Cerr << " Navier_Stokes_FTD_IJK equation must be associated to\n";
273 Cerr << " a Probleme_FTD_IJK_base problem type\n";
275 }
276 mon_probleme = pb;
277 if (nom_ == "??")
278 {
279 nom_ = pb.le_nom();
280 nom_ += que_suis_je();
281 }
282}
283
285{
286 if (!le_fluide_)
287 {
288 Cerr << "You forgot to associate a fluid to the problem named " << probleme().le_nom() << finl;
290 }
291 return le_fluide_.valeur();
292}
293
295{
296 if (!le_fluide_)
297 {
298 Cerr << "You forgot to associate a fluid to the problem named " << probleme().le_nom() << finl;
300 }
301 return le_fluide_.valeur();
302}
303
305{
306 if (sub_type(Fluide_Diphasique_IJK, un_milieu))
307 {
308 const Milieu_base& un_fluide = ref_cast(Milieu_base, un_milieu);
309 le_fluide_ = un_fluide;
310 }
311 else
312 {
313 Cerr << "Error of fluid type for the method Navier_Stokes_FTD_IJK::associer_milieu_base" << finl;
315 }
316}
317
319{
320 return ref_cast(Probleme_FTD_IJK_base, mon_probleme.valeur());
321}
322
324{
325 return ref_cast(Probleme_FTD_IJK_base, mon_probleme.valeur());
326}
327
328void Navier_Stokes_FTD_IJK::Fill_postprocessable_fields(std::vector<FieldInfo_t>& chps)
329{
330 std::vector<FieldInfo_t> c =
331 {
332 // Name / Localisation (elem, face, ...) / Nature (scalare, vector) / Located on interface?
333
334 { "VELOCITY", Entity::FACE, Nature_du_champ::vectoriel, false },
335 { "VITESSE", Entity::FACE, Nature_du_champ::vectoriel, false },
336 { "VELOCITY_FT", Entity::FACE, Nature_du_champ::vectoriel, false },
337 { "PRESSURE", Entity::ELEMENT, Nature_du_champ::scalaire, false },
338 { "PRESSION", Entity::ELEMENT, Nature_du_champ::scalaire, false },
339 { "PRESSURE_RHS", Entity::ELEMENT, Nature_du_champ::scalaire, false },
340 { "PRESSION_RHS", Entity::ELEMENT, Nature_du_champ::scalaire, false },
341 { "SOURCE_QDM_INTERF", Entity::FACE, Nature_du_champ::vectoriel, false },
342 { "SHIELD_REPULSTION", Entity::FACE, Nature_du_champ::vectoriel, false },
343 { "SHIELD_REPULSTION_ABS", Entity::FACE, Nature_du_champ::vectoriel, false },
344 { "RHO", Entity::ELEMENT, Nature_du_champ::scalaire, false },
345 { "DENSITY", Entity::ELEMENT, Nature_du_champ::scalaire, false },
346 { "MU", Entity::ELEMENT, Nature_du_champ::scalaire, false },
347 { "VISCOSITY", Entity::ELEMENT, Nature_du_champ::scalaire, false },
348 { "EXTERNAL_FORCE", Entity::FACE, Nature_du_champ::vectoriel, false },
349 };
350 chps.insert(chps.end(), c.begin(), c.end());
351}
352
354{
355 for (const auto& n : champs_compris_.liste_noms_compris())
356 noms.add(n);
357 for (const auto& n : champs_compris_.liste_noms_compris_vectoriel())
358 noms.add(n);
359}
360
361const IJK_Field_vector3_double& Navier_Stokes_FTD_IJK::get_IJK_field_vector(const Motcle& nom)
362{
363
364 if (nom=="EXTERNAL_FORCE")
365 {
366 if ( coef_immobilisation_ > 1e-16)
367 {
368 if (!probleme_ijk().get_interface().get_forcing_method())
369 for (int dir = 0; dir < 3; dir++)
371 }
372 else
373 Cerr << "Posttraitement demande pour EXTERNAL_FORCE but ignored because coef_immobilisation_ <= 1e-16" << endl;
374 }
375
376 if (has_champ_vectoriel(nom))
377 return champs_compris_.get_champ_vectoriel(nom);
378
379 Cerr << "ERROR in Navier_Stokes_FTD_IJK::get_IJK_field_vector : " << finl;
380 Cerr << "Requested field '" << nom << "' is not recognized by Navier_Stokes_FTD_IJK::get_IJK_field_vector()." << finl;
381 throw;
382}
383
384const IJK_Field_double& Navier_Stokes_FTD_IJK::get_IJK_field(const Motcle& nom)
385{
386 if (has_champ(nom))
387 return champs_compris_.get_champ(nom);
388
389 Cerr << "ERROR in Navier_Stokes_FTD_IJK::get_IJK_field : " << finl;
390 Cerr << "Requested field '" << nom << "' is not recognized by Navier_Stokes_FTD_IJK::get_IJK_field()." << finl;
391 throw;
392}
393
395{
397 {
398 disable_solveur_poisson_ = 1; // automatically force the suppression of the poisson solver
400 {
401 interfaces_->freeze(); // Stop the interfacial displacement.
402 Cout << "The option frozen_velocity automatically freeze the interface motion " << "by activating the flag interfaces_.frozen_" << finl;
403 }
404 }
405
406 if ((expression_potential_phi_ != "??") && ((expression_variable_source_[0] != "??") || (expression_variable_source_[1] != "??") || (expression_variable_source_[2] != "??")))
407 {
408 Cerr << "expression_potential_phi and expression_variable_source are used together" << "nabla(phi) will be added to the expression given for the variable source" << finl;
409 //Process::exit();
410 }
411
413 {
414 Cerr << "When using pressure increment in u^star, expression_p_init " << expression_pression_initiale_ << "becomes a required parameter. " << finl;
416 }
417
418 // Si on utilise un seul groupe et qu'on impose un volume unique a toutes les bulles,
419 if (vol_bulle_monodisperse_ >= 0.)
420 {
421 if (vol_bulles_.size_array() != 0)
422 {
423 Cerr << "Attention, conflit entre les options : vol_bulle_monodisperse_ et vol_bulles." << "Merci de choisir" << finl;
425 }
426 }
427
428 // On utilise inv_rho pour l'un ou l'autre... Il faut donc le calculer :
430
431 // Avec cette option, on travaille avec nu :
433 {
434 Cerr << "Option diffusion_alternative activee : le champ mu contient nu (la viscosite dynamique)" << finl;
435 Cerr << "TODO FIXME " << finl;
437 }
438
440 {
441 if (vol_bulle_monodisperse_ != -1)
442 diam_bulle_monodisperse_ = pow(6. * vol_bulle_monodisperse_ / (M_PI), 1. / 3.);
443 else
445
447 }
448
449 // Preparation de l'expression derivee de l'acceleration
450 std::string tmpstring(expression_derivee_acceleration_);
451 parser_derivee_acceleration_.setString(tmpstring);
453 parser_derivee_acceleration_.addVar("rappel_moyen");
454 parser_derivee_acceleration_.addVar("force");
455 parser_derivee_acceleration_.addVar("v_moyen");
456 parser_derivee_acceleration_.addVar("ur");
457 parser_derivee_acceleration_.addVar("ul");
458 parser_derivee_acceleration_.addVar("uv");
460 parser_derivee_acceleration_.addVar("rhov_moyen");
461 parser_derivee_acceleration_.addVar("tauw");
462 parser_derivee_acceleration_.parseString();
463
464 std::string tmpstring2(expression_derivee_facteur_variable_source_);
465 parser_derivee_facteur_variable_source_.setString(tmpstring2);
467 parser_derivee_facteur_variable_source_.addVar("rappel_moyen");
468 parser_derivee_facteur_variable_source_.addVar("facteur_sv");
471 parser_derivee_facteur_variable_source_.addVar("rhov_moyen");
474
475}
476
478{
479 Cout << "Lecture vitesse initiale dans fichier " << fichier_reprise_vitesse << " timestep= " << timestep_reprise_vitesse_ << finl;
480 const Nom& geom_name = velocity_[0].get_domaine().le_nom();
481 lire_dans_lata(fichier_reprise_vitesse, timestep_reprise_vitesse_, geom_name, "VELOCITY", velocity_[0], velocity_[1], velocity_[2]); // fonction qui lit un champ a partir d'un lata .
482
484 {
485 compose_field_data(velocity_[0], expression_vitesse_initiale_[0]);
486 compose_field_data(velocity_[1], expression_vitesse_initiale_[1]);
487 compose_field_data(velocity_[2], expression_vitesse_initiale_[2]);
488// velocity_[0].data() += expression_vitesse_initiale_;
489// velocity_[1].data() += expression_vitesse_initiale_;
490// velocity_[2].data() += expression_vitesse_initiale_;
491 }
492
493 velocity_[0].echange_espace_virtuel(2);
494 velocity_[1].echange_espace_virtuel(2);
495 velocity_[2].echange_espace_virtuel(2);
496#ifdef CONVERT_AT_READING_FROM_NURESAFE_TO_ADIM_TRYGGVASON_FOR_LIQUID_VELOCITY
497 const double coef = 14.353432757182377;
498 for (int dir=0; dir< 3; dir++)
499 velocity_[dir].data() *= coef;
500#endif
501}
502
504{
505 if (expression_vitesse_initiale_.size() != 3)
506 {
507 Cerr << "Erreur dans l'initialisation: la vitesse initiale doit etre fournie avec trois expressions" << finl;
509 }
510 else
511 {
512 Cout << "Initialisation vitesse \nvx = " << expression_vitesse_initiale[0] << "\nvy = " << expression_vitesse_initiale[1] << "\nvz = " << expression_vitesse_initiale[2] << finl;
513 for (int i = 0; i < 3; i++)
514 {
515 // Cette methode parcours ni(), nj() et nk() et donc pas les ghost...
516 set_field_data(velocity_[i], expression_vitesse_initiale[i]);
517 }
518
519 velocity_[0].echange_espace_virtuel(2);
520 velocity_[1].echange_espace_virtuel(2);
521 velocity_[2].echange_espace_virtuel(2);
522 }
523}
524
525// Maj indicatrice rho mu met indicatrice a indicatrice next
526// et maj rho et mu en fonction de la nouvelle indicatrice
528{
529 // En monophasique, les champs sont a jours donc on zap :
531 return;
532
533// static Stat_Counter_Id calculer_rho_mu_indicatrice_counter_ = statistiques().new_counter(2, "Calcul Rho Mu Indicatrice");
534// statistiques().begin_count(calculer_rho_mu_indicatrice_counter_);
535
536 const double rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour(), mu_l = milieu_ijk().get_mu_liquid(), mu_v = milieu_ijk().get_mu_vapour();
537
538 // En diphasique sans bulle (pour cas tests)
539 if (interfaces_->get_nb_bulles_reelles() == 0)
540 {
541 rho_field_.data() = rho_l;
542 rho_field_.echange_espace_virtuel(rho_field_.ghost());
543 if (use_inv_rho_)
544 {
545 inv_rho_field_.data() = 1. / rho_l;
546 inv_rho_field_.echange_espace_virtuel(inv_rho_field_.ghost());
547 }
548 molecular_mu_.data() = mu_l;
549 molecular_mu_.echange_espace_virtuel(molecular_mu_.ghost());
550
551 if (parcourir)
552 interfaces_->parcourir_maillage();
553 return;
554 }
555
556 if (parcourir)
558
559 // Nombre de mailles du domaine NS :
560 const int nx = interfaces_->I().ni();
561 const int ny = interfaces_->I().nj();
562 const int nz = interfaces_->I().nk();
563 for (int k = 0; k < nz; k++)
564 for (int j = 0; j < ny; j++)
565 for (int i = 0; i < nx; i++)
566 {
567 double chi_l = interfaces_->I(i, j, k);
568 rho_field_(i, j, k) = rho_l * chi_l + (1. - chi_l) * rho_v;
569 if (harmonic_nu_in_calc_with_indicatrice_ == 1 and chi_l != 0. and chi_l != 1.)
570 {
571 molecular_mu_(i, j, k) = 1. / (chi_l / mu_l + (1. - chi_l) / mu_v);
572 }
573 else
574 {
575 molecular_mu_(i, j, k) = mu_l * chi_l + (1. - chi_l) * mu_v;
576 }
577 }
578
579 if (use_inv_rho_)
580 {
581 for (int k = 0; k < nz; k++)
582 for (int j = 0; j < ny; j++)
583 for (int i = 0; i < nx; i++)
584 {
585 inv_rho_field_(i, j, k) = 1. / rho_field_(i,j,k);
586 //double chi_l = interfaces_->I(i, j, k);
587 //inv_rho_field_(i, j, k) = chi_l / rho_l + (1-chi_l) / rho_v;
588 }
589 }
590
591// if (use_harmonic_viscosity_)
592// for (int k=0; k < nz; k++)
593// for (int j=0; j < ny; j++)
594// for (int i=0; i < nx; i++)
595// {
596// double chi_l = interfaces_.I(i,j,k);
597// rho_field_(i,j,k) = rho_liquide_ * chi_l + (1.- chi_l) * rho_vapeur_;
598// molecular_mu_(i,j,k) = (mu_liquide_ * mu_vapeur_) / (chi_l * mu_vapeur_ + (1.- chi_l) * mu_liquide_);
599// }
600// else
601// for (int k=0; k < nz; k++)
602// for (int j=0; j < ny; j++)
603// for (int i=0; i < nx; i++)
604// {
605// double chi_l = interfaces_.I(i,j,k);
606// rho_field_(i,j,k) = rho_liquide_ * chi_l + (1.- chi_l) * rho_vapeur_;
607// molecular_mu_(i,j,k) = mu_liquide_ * chi_l + (1.- chi_l) * mu_vapeur_ ;
608// }
609
610 //Mise a jour des espaces virtuels des champs :
611 rho_field_.echange_espace_virtuel(rho_field_.ghost());
612 if (use_inv_rho_)
613 inv_rho_field_.echange_espace_virtuel(inv_rho_field_.ghost());
614 molecular_mu_.echange_espace_virtuel(molecular_mu_.ghost());
615
616// statistiques().end_count(calculer_rho_mu_indicatrice_counter_);
617}
618
620{
621 Cerr << "Navier_Stokes_FTD_IJK::initialise_ns_fields()" << finl;
622 const Probleme_FTD_IJK_base& pb_ijk = probleme_ijk();
623 const Domaine_IJK& dom_ijk = pb_ijk.domaine_ijk();
624
626 {
627 if (dom_ijk.get_nb_elem_local(2) < 4 )
628 {
629 Cerr << "Nb of cells / proc in z-direction must be >=4 for shear periodic run" << finl;
630 Cerr << "Nb of cells / proc in z-direction must be >=8 for shear periodic run if only one proc on z-direction" << finl;
631 Cerr << "Or find an other way to stock indic_ghost_zmin and zmax than IJK_Field" << finl;
633 }
634 if (dom_ijk.get_offset_local(0)!=0.)
635 {
636 Cerr << " Shear_periodic conditions works only without splitting in i-direction " << finl;
637 Cerr << "if splitting in i-direction --> get_neighbour_processor has to be changed" << finl;
639 }
640 }
641
642
643 allocate_velocity(d_velocity_, dom_ijk, 1, "D_VELOCITY");
644 d_velocity_.nommer("D_VELOCITY");
645 champs_compris_.ajoute_champ_vectoriel(d_velocity_);
646
648 {
652 };
653
654 for (auto field : fields)
655 allocate_velocity(*field, dom_ijk, 1);
656 }
657
659 pressure_ghost_cells_.data() = 0.;
660 pressure_ghost_cells_.echange_espace_virtuel(pressure_ghost_cells_.ghost());
661
662 const double mu_l = milieu_ijk().get_mu_liquid(),
663 rho_l = milieu_ijk().get_rho_liquid(),
664 mu_v = milieu_ijk().get_mu_vapour(),
665 rho_v = milieu_ijk().get_rho_vapour();
666
667 // if interp_monofluide == 2 --> reconstruction uniquement sur rho, mu. Pas sur P !
668 if (!Option_IJK::DISABLE_DIPHASIQUE && boundary_conditions_.get_correction_interp_monofluide() == 1)
669 {
670 pressure_.allocate(dom_ijk, Domaine_IJK::ELEM, 3, 0, 1, "PRESSURE", false, 1, rho_v, rho_l, use_inv_rho_in_poisson_solver_);
671 }
672 else
673 pressure_.allocate(dom_ijk, Domaine_IJK::ELEM, 3);
674 pressure_.nommer("PRESSURE");
675 pressure_.add_synonymous("PRESSION");
676 champs_compris_.ajoute_champ(pressure_);
677
679 {
680 d_pressure_.allocate(dom_ijk, Domaine_IJK::ELEM, 1);
681 if ( sub_type(Schema_RK3_IJK, schema_temps_ijk()) )
682 RK3_F_pressure_.allocate(dom_ijk, Domaine_IJK::ELEM, 1);
683 }
684
685 // On utilise aussi rhov pour le bilan de forces et pour d'autres formes de convection...
686 allocate_velocity(rho_v_, dom_ijk, 2);
687
688 pressure_rhs_.allocate(dom_ijk, Domaine_IJK::ELEM, 1, "PRESSURE_RHS");
689 pressure_rhs_.add_synonymous("PRESSION_RHS");
690 champs_compris_.ajoute_champ(pressure_rhs_);
691
692
693 I_ns_.allocate(dom_ijk, Domaine_IJK::ELEM, 2);
694 kappa_ns_.allocate(dom_ijk, Domaine_IJK::ELEM, 2);
695
696 if (!Option_IJK::DISABLE_DIPHASIQUE && (boundary_conditions_.get_correction_interp_monofluide() == 1 || boundary_conditions_.get_correction_interp_monofluide() == 2))
697 {
698 molecular_mu_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, 0, 1, "VISCOSITY", false, 2, mu_v, mu_l, 0);
699 rho_field_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, 0, 1, "DENSITY", false, 2, rho_v, rho_l, 0);
702 if (use_inv_rho_)
703 {
704 inv_rho_field_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, 0, 1, "INV_RHO", false, 2, 1. / rho_v, 1. / rho_l);
707 }
708 }
709 else
710 {
713 molecular_mu_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, "VISCOSITY");
714 rho_field_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, "DENSITY");
715 if (use_inv_rho_)
716 {
717 inv_rho_field_.allocate(dom_ijk, Domaine_IJK::ELEM, 2, "INV_RHO");
720 }
721 }
722
723 rho_field_.nommer("DENSITY");
724 rho_field_.add_synonymous("RHO");
725 champs_compris_.ajoute_champ(rho_field_);
726 molecular_mu_.nommer("VISCOSITY");
727 molecular_mu_.add_synonymous("MU");
728 champs_compris_.ajoute_champ(molecular_mu_);
729
730 if (schema_temps_ijk().get_first_step_interface_smoothing())
731 {
732 allocate_velocity(zero_field_ft_, pb_ijk.get_domaine_ft(), pb_ijk.get_thermal_probes_ghost_cells());
733 for (int dir = 0; dir < 3; dir++)
734 zero_field_ft_[dir].data() = 0.;
735 zero_field_ft_.echange_espace_virtuel();
736 }
737
739 {
740 allocate_velocity(laplacien_velocity_, dom_ijk, 1);
741 unit_.allocate(dom_ijk, Domaine_IJK::ELEM, 2);
742 unit_.data() = 1.;
743 unit_.echange_espace_virtuel(unit_.ghost());
744 }
745
746 if (velocity_convection_op_.get_convection_op_option_rank() == non_conservative_rhou)
747 div_rhou_.allocate(dom_ijk, Domaine_IJK::ELEM, 1);
748 allocate_velocity(psi_velocity_, dom_ijk, 2);
749
750
751 // Allocation du terme source variable spatialement:
752 if ((expression_variable_source_[0] != "??") || (expression_variable_source_[1] != "??") || (expression_variable_source_[2] != "??") || (expression_potential_phi_ != "??"))
753 {
754 allocate_velocity(variable_source_, dom_ijk, 1, "VARIABLE_SOURCE");
756 potential_phi_.allocate(dom_ijk, Domaine_IJK::ELEM, 1);
757 for (int dir = 0; dir < 3; dir++)
758 variable_source_[dir].data() = 0.;
759 potential_phi_.data() = 0.;
760 champs_compris_.ajoute_champ_vectoriel(variable_source_);
761 }
762
763
764 // GB : Je ne sais pas si on a besoin d'un ghost... Je crois que oui. Lequel?
765 // Si la a vitesse ft doit transporter les sommets virtuels des facettes reelles,
766 // alors il faut un domaine ghost de la taille de la longueur maximale des arretes.
767 // allocate_velocity(velocity_ft_, domaine_ft_, 0);
768 /*
769 * FIXME: Allocate based on the thermal subproblems
770 * as the thermal probes necessitates several ghost cells to interpolate velocity !
771 * Check the difference between elem and faces ? and for interpolation of the velocity ?
772 */
773 constexpr int ft_ghost_cells = 4;
774 allocate_velocity(velocity_ft_, pb_ijk.get_domaine_ft(), ft_ghost_cells); // named at the end
775
776 kappa_ft_.allocate(pb_ijk.get_domaine_ft(), Domaine_IJK::ELEM, 2, "KAPPA_FT");
777 champs_compris_.ajoute_champ(kappa_ft_);
778
780 {
782
783 for (auto field : fields)
784 allocate_velocity(*field, dom_ijk, 1);
785
786 //auto fields_ft = { &terme_source_interfaces_ft_, &terme_repulsion_interfaces_ft_, &terme_abs_repulsion_interfaces_ft_ };
787 // for (auto field : fields_ft)
788 // allocate_velocity(*field, pb_ijk.get_domaine_ft(), 1);
789
790 allocate_velocity(terme_source_interfaces_ft_, pb_ijk.get_domaine_ft(), 1, "SOURCE_QDM_INTERF");
791 champs_compris_.ajoute_champ_vectoriel(terme_source_interfaces_ft_);
792 allocate_velocity(terme_repulsion_interfaces_ft_, pb_ijk.get_domaine_ft(), 1, "SHIELD_REPULSION");
793 champs_compris_.ajoute_champ_vectoriel(terme_repulsion_interfaces_ft_);
794 allocate_velocity(terme_abs_repulsion_interfaces_ft_, pb_ijk.get_domaine_ft(), 1, "SHIELD_REPULSION_ABS");
796 }
797
798 if ( sub_type(Schema_RK3_IJK, schema_temps_ijk()) )
799 {
800 Cerr << "Schema temps de type : RK3_FT" << finl;
801 allocate_velocity(RK3_F_velocity_, dom_ijk, 1);
802 }
803 else
804 Cerr << "Schema temps de type : Euler_Explicite" << finl;
805
808 velocity_convection_op_.initialize(dom_ijk);
809
810 // Economise la memoire si pas besoin
812 poisson_solver_.initialize(dom_ijk);
813
814 // Register champs compris
815 velocity_.nommer("VELOCITY");
816 velocity_.add_synonymous("VITESSE");
818 {
819 velocity_ft_.nommer("VELOCITY_FT");
820 velocity_ft_.add_synonymous("VITESSE_FT");
821 champs_compris_.ajoute_champ_vectoriel(velocity_ft_);
822 }
823 champs_compris_.ajoute_champ_vectoriel(velocity_);
824
825
826
827}
828
830{
831 // PROJECTION INITIALE
832 // Cette projection n'est pas utile en reprise.
833 // Elle sert uniquement a rendre le champ de vitesse initial a divergence nulle lorsque son expression est analytique.
835 {
837 {
838 Cerr << "Improved initial pressure" << finl;
842
843 // La pression n'est pas encore initialisee. elle est donc nulle.
844 // Avec cette option, on essaye une initialisation basee sur le champ de pression diphasique
845 // a l'equilibre, cad sans vitesse, ou a minima pour un champ a div(u)=0.
846
848 {
849 IJK_Field_vector3_double& coords = probleme_ijk().get_post().coords();
850
851 // Calcul du potentiel.
852 for (int dir = 0; dir < 3; dir++)
853 {
854 terme_source_interfaces_ft_[dir].data() = 0.;
855 terme_repulsion_interfaces_ft_[dir].data() = 0.;
856 terme_abs_repulsion_interfaces_ft_[dir].data() = 0.;
857 }
858 const double delta_rho = milieu_ijk().get_delta_rho();
860
861 assert(interfaces_->get_nb_bulles_reelles() == 1);
862 DoubleTab bounding_box;
863 interfaces_->calculer_bounding_box_bulles(bounding_box);
864 // Calcul la hauteur en x de la permiere bulle :
865 const double Dbx = bounding_box(0, 0, 1) - bounding_box(0, 0, 0);
866 const double kappa = 2. / (Dbx / 2.);
867
868 const int ni = pressure_.ni();
869 const int nj = pressure_.nj();
870 const int nk = pressure_.nk();
871
872 const auto& gravite = milieu_ijk().gravite().valeurs();
873 for (int k = 0; k < nk; k++)
874 for (int j = 0; j < nj; j++)
875 for (int i = 0; i < ni; i++)
876 {
877 double phi = gravite(0,0) * coords[0](i, j, k) + gravite(0,1) * coords[1](i, j, k) + gravite(0,2) * coords[2](i, j, k);
878 double potentiel_elem = milieu_ijk().sigma() * kappa - delta_rho * phi;
879 // La pression est hydrostatique, cad : pressure_ = P - rho g z
880 pressure_(i, j, k) = potentiel_elem * interfaces_->I(i, j, k); // - rho_field_(i,j,k) * phi;
881 }
882
883 // pressure gradient requires the "left" value in all directions:
884 pressure_.echange_espace_virtuel(1 /*, IJK_Field_double::EXCHANGE_GET_AT_LEFT_IJK*/);
885
886 // Mise a jour du champ de vitesse (avec dv = seulement le terme source)
887 d_velocity_[0].data() = 0.;
888 d_velocity_[1].data() = 0.;
889 d_velocity_[2].data() = 0.;
890
891 for (int dir = 0; dir < 3; dir++)
893
894 for (int dir = 0; dir < 3; dir++)
895 {
896 const int kmax = d_velocity_[dir].nk();
897 for (int k = 0; k < kmax; k++)
899 }
900
902 pressure_projection_with_inv_rho(inv_rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_,NoSym_);
903 else
904 pressure_projection_with_rho(rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_,NoSym_);
905 }
906 else
907 pressure_projection(velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_);
908
909 copy_field_values(pressure_ghost_cells_, pressure_);
910 }
912 {
913 Cerr << "*****************************************************************************\n"
914 << " Attention : projection du champ de vitesse initial sur div(u)=0\n"
915 << "*****************************************************************************" << finl;
916
918 {
920 pressure_projection_with_inv_rho(inv_rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_,NoSym_);
921 else
922 pressure_projection_with_rho(rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_,NoSym_);
923 }
924 else
925 pressure_projection(velocity_[0], velocity_[1], velocity_[2], pressure_, 1., pressure_rhs_, poisson_solver_);
926
927 pressure_.data() = 0.;
928 pressure_rhs_.data() = 0.;
929 }
930 }
931
932 // Projection initiale sur div(u)=0, si demande: (attention, ne pas le faire en reprise)
934 {
936 {
937 Cerr << " Warning: Possible incoherence des mots-cles\n"
938 << " ===========================================\n"
939 << "\n"
940 << "Avec correction_semi_locale_volume_bulle, la conservation du volume de la bulle repose entierement sur le fait que la divergence de la vitesse est numeriquement nulle en tout point.\n"
941 << "Il est suspect d'utiliser cette option avec disable_solveur_poisson.\n" << finl;
942 }
944 {
945 Cerr << " Warning: Possible incoherence des mots-cles\n"
946 << " ===========================================\n"
947 << "\n"
948 << "Avec correction_semi_locale_volume_bulle, la conservation du volume de la bulle repose entierement sur le fait que la divergence de la vitesse est numeriquement nulle en tout point.\n"
949 << "Pour securite, il est recommande d'utiliser avec cette option une projection initiale du champ de vitesse, garantissant cette propriete [mot-cle : projection_initiale].\n" << finl;
950 }
951 }
952 Cerr << "End of initial velocity projection" << finl;
953}
954
956{
957 projeter();
958
959 if (!probleme_ijk().domaine_ijk().get_periodic_flag(DIRECTION_K)) /* Apply BC */
960 force_zero_on_walls(velocity_[2]);
961
962 const double mu_l = milieu_ijk().get_mu_liquid(), rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour();
963
964 // Si calcul monophasique, on initialise correctement rho, mu, I une fois pour toute :
966 {
967 rho_field_.data() = rho_l;
968 rho_moyen_ = rho_l;
969 molecular_mu_.data() = mu_l;
971 }
972 else
973 {
974 Cerr << "Cas normal diphasique Probleme_FTD_IJK_base::run()" << finl;
976 const double indic_moyen = calculer_v_moyen(interfaces_->I());
977 rho_moyen_ = indic_moyen * rho_l + (1 - indic_moyen) * rho_v;
978 if (probleme_ijk().get_post().is_post_required("EXTERNAL_FORCE"))
979 for (int dir = 0; dir < 3; dir++)
981 }
982
983 return 1;
984}
985
987{
988 update_rho_v(); // Peut-etre pas toujours necessaire selon la formulation pour la convection?
989 for (int direction = 0; direction < 3; direction++)
990 store_rhov_moy_[direction] = calculer_v_moyen(rho_v_[direction]);
991}
992
994{
996 Cout << "forcage_.get_type_forcage() : " << forcage_.get_type_forcage() << finl;
997 if (forcage_.get_type_forcage() > 0)
998 {
999 const Domaine_IJK& gbz_splitting = velocity_[0].get_domaine();
1000 const Domaine_IJK& my_geom = velocity_[0].get_domaine();
1001
1002 const int my_ni = velocity_[0].ni();
1003 const int my_nj = velocity_[0].nj();
1004 const int my_nk = velocity_[0].nk();
1005 const int nproc_tot = Process::nproc();
1006 Cout << "BF compute_initial_chouippe" << finl;
1007 Cout << "ni : " << my_ni << " ,nj : " << my_nj << " ,nk : " << my_nk << finl;
1008 std::cout << "in initialise i_offset : " << gbz_splitting.get_offset_local(DIRECTION_I) << std::endl;
1009 std::cout << "Process::me()" << Process::me() << std::endl;
1010 forcage_.compute_initial_chouippe(nproc_tot, my_geom, my_ni, my_nj, my_nk, gbz_splitting, pb_ijk.nom_sauvegarde());
1011 // TODO (teo.boutin) move this by adding forcage_ to the tree of champs_compris
1012 champs_compris_.ajoute_champ_vectoriel(forcage_.get_force_ph2());
1013
1014 //statistics().create_custom_counter("m2",2,"TrioCFD");
1015 //statistics().begin_count("m2",statistics().get_last_opened_counter_level()+1);
1016 Cout << "AF compute_initial_chouippe" << finl;
1017 }
1018
1019 if (fichier_reprise_vitesse_ == "??") // si on ne fait pas une reprise on initialise V
1021 else
1023
1024 // Pour le check_stats_ ou pour travailler en increment de pression, il faut connaitre la pression initiale :
1026 {
1027 Cout << "Initialisation pression \nPini = " << expression_pression_initiale_ << finl;
1029 pressure_.echange_espace_virtuel(pressure_.ghost());
1030 }
1031
1032 /*
1033 * Compute mean rho_g using the indicator function
1034 */
1036 {
1039 const auto& gravite = milieu_ijk().gravite().valeurs();
1040 double indicator_sum = 0;
1041 double terme_source_acceleration_increment;
1042 const int ni = interfaces_->I().ni();
1043 const int nj = interfaces_->I().nj();
1044 const int nk = interfaces_->I().nk();
1045 const double rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour();
1046 for (int k = 0; k < nk; k++)
1047 for (int j = 0; j < nj; j++)
1048 for (int i = 0; i < ni; i++)
1049 {
1050 const double indic = interfaces_->I(i, j, k);
1051 indicator_sum += indic;
1052 terme_source_acceleration_increment = rho_l * indic + rho_v * (1 - indic);
1053 terme_source_acceleration_ += terme_source_acceleration_increment;
1054 }
1055 indicator_sum = Process::mp_sum(indicator_sum);
1057 terme_source_acceleration_ /= indicator_sum;
1059 terme_source_acceleration_ *= -gravite(0,0);
1060 terme_source_acceleration_z_ *= -gravite(0,2);
1061 Cout << "Calculation of force init due to gravity along x: mean(rho_g): " << terme_source_acceleration_ << finl;
1062 Cout << "Calculation of force init due to gravity along z: mean(rho_g): " << terme_source_acceleration_z_ << finl;
1063 }
1064
1065 // statistiques...
1067
1068 if (coef_immobilisation_ > 1e-16)
1069 {
1070 allocate_velocity(force_rappel_, pb_ijk.domaine_ijk(), 2, "EXTERNAL_FORCE");
1071 champs_compris_.ajoute_champ_vectoriel(force_rappel_);
1072 allocate_velocity(force_rappel_ft_, pb_ijk.get_domaine_ft(), 2);
1073 // A la reprise, c'est fait par le IJK_Interfaces::readOn
1074 if (interfaces_->get_flag_positions_reference() == 0) // (!reprise_)
1075 {
1076 Cerr << "Saving interfacial positions as references." << finl;
1077 interfaces_->set_positions_reference();
1078 }
1079 }
1080
1081 // Maj des grandeurs shear perio
1083 {
1085 redistribute_from_splitting_ft_elem_ghostz_min_.redistribute(interfaces_->I_ft(), I_ns_);
1086 redistribute_from_splitting_ft_elem_ghostz_max_.redistribute(interfaces_->I_ft(), I_ns_);
1087 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1088 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, rho_field_.nk() - 4);
1089 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1090 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, molecular_mu_.nk() - 4);
1091 if (use_inv_rho_)
1092 {
1093 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1094 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, inv_rho_field_.nk() - 4);
1095 }
1096 if (boundary_conditions_.get_correction_interp_monofluide() == 1)
1097 {
1098 interfaces_->calculer_kappa_ft(kappa_ft_);
1101 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmin_(I_ns_, kappa_ns_, milieu_ijk().sigma(), 0);
1102 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmax_(I_ns_, kappa_ns_, milieu_ijk().sigma(), pressure_.nk() - 4);
1103 }
1104 }
1105
1107}
1108
1110{
1112 {
1114 redistribute_from_splitting_ft_elem_ghostz_min_.redistribute(interfaces_->I_ft(), I_ns_);
1115 redistribute_from_splitting_ft_elem_ghostz_max_.redistribute(interfaces_->I_ft(), I_ns_);
1116 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1117 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, rho_field_.nk() - 4);
1118 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1119 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, molecular_mu_.nk() - 4);
1120 if (use_inv_rho_)
1121 {
1122 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
1123 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, inv_rho_field_.nk() - 4);
1124 }
1125 if (boundary_conditions_.get_correction_interp_monofluide() == 1)
1126 {
1127 interfaces_->calculer_kappa_ft(kappa_ft_);
1130 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmin_(I_ns_, kappa_ns_, milieu_ijk().sigma(), 0);
1131 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmax_(I_ns_, kappa_ns_, milieu_ijk().sigma(), pressure_.nk() - 4);
1132 }
1133 }
1134}
1135
1136void Navier_Stokes_FTD_IJK::redistribute_to_splitting_ft_elem(const IJK_Field_double& input_field, IJK_Field_double& output_field)
1137{
1138 redistribute_to_splitting_ft_elem_.redistribute(input_field, output_field);
1139}
1140
1141void Navier_Stokes_FTD_IJK::redistribute_from_splitting_ft_elem(const IJK_Field_double& input_field, IJK_Field_double& output_field)
1142{
1143 redistribute_from_splitting_ft_elem_.redistribute(input_field, output_field);
1144}
1145
1147{
1149 {
1150 // rho_face = 2*(rho_gauche*rho_droite)/(rho_gauche+rho_droite)
1151 // = 1./ (1/2 * (1/rho_g + 1/rho_d))
1152 // 1/rho_face est donc la moyenne geometrique de inv_rho.
1153 calculer_rho_harmonic_v(rho_field_, velocity_, rho_v_);
1154 }
1155 else
1156 calculer_rho_v(rho_field_, velocity_, rho_v_);
1157
1158 rho_v_[0].echange_espace_virtuel(rho_v_[0].ghost());
1159 rho_v_[1].echange_espace_virtuel(rho_v_[1].ghost());
1160 rho_v_[2].echange_espace_virtuel(rho_v_[2].ghost());
1161}
1162
1163void Navier_Stokes_FTD_IJK::calculer_terme_asservissement(double& ax, double& ay, double& az)
1164{
1165 // On trouve la vitesse moyenne de la phase vapeur pour la partie derivee du correcteur
1166
1167 update_rho_v();
1168 double v_moyx = calculer_v_moyen(velocity_[0]);
1169 double v_moyy = calculer_v_moyen(velocity_[1]);
1170 double v_moyz = calculer_v_moyen(velocity_[2]);
1171
1172 double rhov_moyx = calculer_v_moyen(rho_v_[DIRECTION_I]);
1173 double rhov_moyy = calculer_v_moyen(rho_v_[DIRECTION_J]);
1174 double rhov_moyz = calculer_v_moyen(rho_v_[DIRECTION_K]);
1175
1176 const Domaine_IJK& geom = velocity_[milieu_ijk().get_direction_gravite()].get_domaine();
1177 double Lz = geom.get_domain_length(DIRECTION_K);
1178 double Lx = geom.get_domain_length(DIRECTION_I);
1179 double Ly = geom.get_domain_length(DIRECTION_J);
1180
1181 double vol_dom = Lz * Lx * Ly;
1182 double alv = 0.;
1183 if (vol_bulle_monodisperse_ >= 0.)
1184 alv = interfaces_->get_nb_bulles_reelles() * vol_bulle_monodisperse_ / vol_dom;
1185 else
1186 alv = 1. - calculer_v_moyen(interfaces_->I());
1187
1188 const double drho = milieu_ijk().get_delta_rho(), rho_l = milieu_ijk().get_rho_liquid();
1189 double facv = 0.;
1190 if (std::fabs(alv * drho) > DMINFLOAT)
1191 {
1192 facv = 1. / (alv * drho);
1193 }
1194 double uvx = facv * (rho_l * v_moyx - rhov_moyx);
1195 double uvy = facv * (rho_l * v_moyy - rhov_moyy);
1196 double uvz = facv * (rho_l * v_moyz - rhov_moyz);
1197
1198 // On evalue la position de chaque bulles pour trouver le barycentre de la phase vapeur
1199
1200 ArrOfDouble volumes;
1201 DoubleTab centre_gravite;
1202
1203 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1204 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1205 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1206
1207 volumes.resize_array(nbulles_tot);
1208 volumes = 0.;
1209 centre_gravite.resize(nbulles_tot, 3);
1210 centre_gravite = 0.;
1211
1212 double centre_moyx = 0;
1213 double centre_moyy = 0;
1214 double centre_moyz = 0;
1215
1216 interfaces_->calculer_volume_bulles(volumes, centre_gravite);
1217
1218 for (int i = 0; i < nbulles_tot; i++)
1219 {
1220 centre_moyx += 1.0 * centre_gravite(i, 0) / nbulles_tot;
1221 centre_moyy += 1.0 * centre_gravite(i, 1) / nbulles_tot;
1222 centre_moyz += 1.0 * centre_gravite(i, 2) / nbulles_tot;
1223 }
1224
1225 ax = -Kp_ * (centre_moyx - Lx / 2) - Kd_ * uvx;
1226 ay = -Kp_ * (centre_moyy - Ly / 2) - Kd_ * uvy;
1227 az = -Kp_ * (centre_moyz - Lz / 2) - Kd_ * uvz;
1228}
1229
1231{
1232 const Domaine_IJK& dom = probleme_ijk().domaine_ijk();
1233
1234 for (int dir = 0; dir < 3; dir++)
1235 {
1236 const int imax = velocity_[dir].ni();
1237 const int jmax = velocity_[dir].nj();
1238 const int kmax = velocity_[dir].nk();
1239 const int ghost = velocity_[dir].ghost();
1240 const int last_global_k = dom.get_nb_items_global(Domaine_IJK::ELEM, 2);
1241
1242 for (int j = 0; j < jmax; j++)
1243 for (int i = 0; i < imax; i++)
1244 {
1245 if (dom.get_offset_local(2) == 0)
1246 {
1247 for (int k = -ghost; k < 0; k++)
1248 {
1249 double rho = 0.;
1250 double DU = 0.;
1251 if (dir == 0)
1252 {
1253 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i - 1, j, k));
1254 DU = boundary_conditions_.get_dU_perio();
1255 }
1256 else if (dir == 1)
1257 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i, j - 1, k));
1258 else if (dir == 2)
1259 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i, j, k - 1));
1260
1261 velocity_[dir](i, j, k) = rho_v_[dir](i, j, k) / rho - DU;
1262 }
1263 }
1264 if (dom.get_offset_local(2) + kmax == last_global_k)
1265 {
1266 for (int k = kmax; k < kmax + ghost; k++)
1267 {
1268 double rho = 0.;
1269 double DU = 0.;
1270 if (dir == 0)
1271 {
1272 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i - 1, j, k));
1273 DU = boundary_conditions_.get_dU_perio();
1274 }
1275 else if (dir == 1)
1276 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i, j - 1, k));
1277 else if (dir == 2)
1278 rho = 0.5 * (rho_field_(i, j, k) + rho_field_(i, j, k - 1));
1279
1280 velocity_[dir](i, j, k) = rho_v_[dir](i, j, k) / rho + DU;
1281 }
1282 }
1283 }
1284 }
1285}
1286
1287// Transfert du maillage ft vers ns de champs aux faces :
1296
1297
1298void Navier_Stokes_FTD_IJK::calculer_vitesses_bulle(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, DoubleTab& u_bulles_, DoubleTab& compteur_vBulles_)
1299{
1300 // On trouve la vitesse moyenne sur une surface d'épaisseur 1 maille au-dessus de chaque bulle de l'essaim
1301
1302 //update_rho_v();
1303
1304 const Domaine_IJK& geom = velocity_[0].get_domaine();
1305 const double Lz = geom.get_domain_length(DIRECTION_K);
1306 const double Lx = geom.get_domain_length(DIRECTION_I);
1307 const double Ly = geom.get_domain_length(DIRECTION_J);
1308 const int ni = vx.ni();
1309 const int nj = vx.nj();
1310 const int nk = vx.nk();
1311 const double dz = geom.get_constant_delta(DIRECTION_K);
1312 const double dx = geom.get_constant_delta(DIRECTION_I);
1313 const double dy = geom.get_constant_delta(DIRECTION_J);
1314
1315 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1316 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1317 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1318
1319 u_bulles_.resize(nbulles_tot, 3);
1320 u_bulles_ = 0.;
1321
1322 compteur_vBulles_.resize(nbulles_tot, 1);
1323 compteur_vBulles_ = 0.;
1324
1325 ArrOfDouble volumes;
1326 ArrOfDouble aspect_ratios;
1327 DoubleTab centre_gravite;
1328
1329 volumes.resize_array(nbulles_tot);
1330 volumes = 0.;
1331 aspect_ratios.resize_array(nbulles_tot);
1332 aspect_ratios = 0.;
1333 centre_gravite.resize(nbulles_tot, 3);
1334 centre_gravite = 0.;
1335
1336 double x_point = 0;
1337 double y_point = 0;
1338 double z_point = 0;
1339
1340 int i_point = 0;
1341 int j_point = 0;
1342 int k_point = 0;
1343
1344 int i_local = 0;
1345 int j_local = 0;
1346 int k_local = 0;
1347
1348 interfaces_->calculer_aspect_ratio(aspect_ratios);
1349 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
1350
1351 volumes.resize_array(nbulles_tot);
1352 aspect_ratios.resize_array(nbulles_tot);
1353 centre_gravite.resize(nbulles_tot, 3);
1354
1355 int klim = 0;
1356 double rayon = 0.;
1357
1358 double test = 0.;
1359
1360 for (int ib = 0; ib < nbulles_tot; ib++)
1361 {
1362 rayon = pow(3*volumes[ib]/(4.0*3.141592654),1.0/3.0);
1363 klim = static_cast<int>( (aspect_ratios[ib]*rayon)/dx*1.05 );
1364
1365 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
1366 {
1367 for (int k_beta = -klim; k_beta <= klim; k_beta++)
1368 {
1369 for (int k_alpha = -klim; k_alpha <= klim; k_alpha++)
1370 {
1371 test = 0.;
1372
1373 x_point = centre_gravite(ib,0) + k_beta*dx*1.0;
1374 y_point = centre_gravite(ib,1) + k_gamma*dx*1.0;
1375 z_point = centre_gravite(ib,2) + k_alpha*dx*1.0;
1376 //cout << k_gamma << " " << k_beta << endl;
1377 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
1378 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
1379
1380 if (z_point < 0)
1381 test = -1.0;
1382
1383 if (z_point >= Lz)
1384 test = 1.0;
1385
1386 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
1387 {
1388 if ( z_point >= Lz )
1389 {
1390 z_point -= Lz;
1391 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1392 }
1393 if ( z_point < 0 )
1394 {
1395 z_point += Lz;
1396 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1397 }
1398 if (y_point >=Ly)
1399 y_point -= Ly;
1400 if (y_point < 0)
1401 y_point += Ly;
1402
1403 if (x_point >= Lx)
1404 x_point -= Lx;
1405 if (x_point < 0)
1406 x_point += Lx;
1407 }
1408 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
1409
1410 i_point = static_cast<int>( x_point/dx );
1411 j_point = static_cast<int>( y_point/dy );
1412 k_point = static_cast<int>( z_point/dz );
1413
1414 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
1415 {
1416 i_local = i_point - geom.get_offset_local(0);
1417 j_local = j_point - geom.get_offset_local(1);
1418 k_local = k_point - geom.get_offset_local(2);
1419
1420 u_bulles_(ib,0) += (vx(i_local,j_local,k_local) + test*boundary_conditions_.get_dU_perio())*(1.0-interfaces_->I(i_local,j_local,k_local));
1421 u_bulles_(ib,1) += (vy(i_local,j_local,k_local))*(1.0-interfaces_->I(i_local,j_local,k_local));
1422 u_bulles_(ib,2) += (vz(i_local,j_local,k_local))*(1.0-interfaces_->I(i_local,j_local,k_local));
1423
1424 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
1425 compteur_vBulles_(ib,0) += (1.0-interfaces_->I(i_local,j_local,k_local));
1426 }
1427 }
1428 }
1429 }
1430 }
1431 mp_sum_for_each_item(u_bulles_);
1432 mp_sum_for_each_item(compteur_vBulles_);
1433 //Cerr << "volumes : " << volumes << finl;
1434 for (int i = 0; i < nbulles_tot; i++)
1435 {
1436 // const double x = 1./volumes[i];
1437 const double x = (compteur_vBulles_(i,0) == 0.) ? 0. : 1. / compteur_vBulles_(i,0);
1438 u_bulles_(i, 0) *= x;
1439 u_bulles_(i, 1) *= x;
1440 u_bulles_(i, 2) *= x;
1441 }
1442}
1443
1444
1445void Navier_Stokes_FTD_IJK::calculer_v_amont_bulle(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const IJK_Field_double& wx, const IJK_Field_double& wy, const IJK_Field_double& wz, DoubleTab& v_amont_, DoubleTab& w_amont_, const DoubleTab& d1_amont_, const DoubleTab& d2_amont_, const DoubleTab& d3_amont_, DoubleTab& compteur_)
1446{
1447 // On trouve la vitesse moyenne sur une surface d'épaisseur 1 maille au-dessus de chaque bulle de l'essaim
1448 cout << "v !!!!!!!!!!" << endl;
1449
1450 //update_rho_v();
1451
1452 const Domaine_IJK& geom = velocity_[0].get_domaine();
1453 const double Lz = geom.get_domain_length(DIRECTION_K);
1454 const double Lx = geom.get_domain_length(DIRECTION_I);
1455 const double Ly = geom.get_domain_length(DIRECTION_J);
1456 const int ni = vx.ni();
1457 const int nj = vx.nj();
1458 const int nk = vx.nk();
1459 const double dz = geom.get_constant_delta(DIRECTION_K);
1460 const double dx = geom.get_constant_delta(DIRECTION_I);
1461 const double dy = geom.get_constant_delta(DIRECTION_J);
1462
1463 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1464 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1465 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1466
1467 v_amont_.resize(nbulles_tot, 3);
1468 v_amont_ = 0.;
1469 w_amont_.resize(nbulles_tot, 3);
1470 w_amont_ = 0.;
1471 compteur_.resize(nbulles_tot, 1);
1472 compteur_ = 0.;
1473
1474 ArrOfDouble volumes;
1475 ArrOfDouble aspect_ratios;
1476 DoubleTab centre_gravite;
1477
1478 volumes.resize_array(nbulles_tot);
1479 volumes = 0.;
1480 aspect_ratios.resize_array(nbulles_tot);
1481 aspect_ratios = 0.;
1482 centre_gravite.resize(nbulles_tot, 3);
1483 centre_gravite = 0.;
1484
1485 double d1x = 0;
1486 double d1y = 0;
1487 double d1z = 0;
1488
1489 double d2x = 0;
1490 double d2y = 0;
1491 double d2z = 0;
1492
1493 double d3x = 0;
1494 double d3y = 0;
1495 double d3z = 0;
1496
1497 double x_point = 0;
1498 double y_point = 0;
1499 double z_point = 0;
1500
1501 int i_point = 0;
1502 int j_point = 0;
1503 int k_point = 0;
1504
1505 int i_local = 0;
1506 int j_local = 0;
1507 int k_local = 0;
1508
1509 interfaces_->calculer_aspect_ratio(aspect_ratios);
1510 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
1511
1512 volumes.resize_array(nbulles_tot);
1513 aspect_ratios.resize_array(nbulles_tot);
1514 centre_gravite.resize(nbulles_tot, 3);
1515
1516 int klim = 0;
1517 int klim2 = 0;
1518 double rayon = 0.;
1519
1520 double test = 0.;
1521
1522 for (int ib = 0; ib < nbulles_tot; ib++)
1523 {
1524 rayon = pow(3*volumes[ib]/(4.0*3.141592654),1.0/3.0);
1525 klim = static_cast<int>( (aspect_ratios[ib]*rayon)/dx*L_ );
1526
1527 d1x = d1_amont_(ib,0);
1528 d1y = d1_amont_(ib,1);
1529 d1z = d1_amont_(ib,2);
1530
1531 d2x = d2_amont_(ib,0);
1532 d2y = d2_amont_(ib,1);
1533 d2z = d2_amont_(ib,2);
1534
1535 d3x = d3_amont_(ib,0);
1536 d3y = d3_amont_(ib,1);
1537 d3z = d3_amont_(ib,2);
1538
1539 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
1540 {
1541 klim2 = static_cast<int>( sqrt(klim*klim - k_gamma*k_gamma) );
1542 for (int k_beta = -klim2; k_beta <= klim2; k_beta++)
1543 {
1544 for (int k_alpha = 0; k_alpha <= 2; k_alpha++)
1545 {
1546 test = 0.;
1547
1548 x_point = centre_gravite(ib,0) + (delta_ + k_alpha*dx) * d1x + (k_beta*d2x*1.0+k_gamma*d3x*1.0)*dx*1.0;
1549 y_point = centre_gravite(ib,1) + (delta_ + k_alpha*dx) * d1y + (k_beta*d2y*1.0+k_gamma*d3y*1.0)*dx*1.0;
1550 z_point = centre_gravite(ib,2) + (delta_ + k_alpha*dx) * d1z + (k_beta*d2z*1.0+k_gamma*d3z*1.0)*dx*1.0;
1551 //cout << k_gamma << " " << k_beta << endl;
1552 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
1553 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
1554
1555 if (z_point < 0)
1556 test = -1.0;
1557
1558 if (z_point >= Lz)
1559 test = 1.0;
1560
1561 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
1562 {
1563 if ( z_point >= Lz )
1564 {
1565 z_point -= Lz;
1566 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1567 }
1568 if ( z_point < 0 )
1569 {
1570 z_point += Lz;
1571 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1572 }
1573 if (y_point >=Ly)
1574 y_point -= Ly;
1575 if (y_point < 0)
1576 y_point += Ly;
1577
1578 if (x_point >= Lx)
1579 x_point -= Lx;
1580 if (x_point < 0)
1581 x_point += Lx;
1582 }
1583 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
1584
1585 i_point = static_cast<int>( x_point/dx );
1586 j_point = static_cast<int>( y_point/dy );
1587 k_point = static_cast<int>( z_point/dz );
1588
1589 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
1590 {
1591 i_local = i_point - geom.get_offset_local(0);
1592 j_local = j_point - geom.get_offset_local(1);
1593 k_local = k_point - geom.get_offset_local(2);
1594
1595 v_amont_(ib,0) += (vx(i_local,j_local,k_local) + test*boundary_conditions_.get_dU_perio());
1596 v_amont_(ib,1) += (vy(i_local,j_local,k_local));
1597 v_amont_(ib,2) += (vz(i_local,j_local,k_local));
1598
1599 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
1600 compteur_(ib,0) += 1;
1601
1602 w_amont_(ib,0) += wx(i_local,j_local,k_local);
1603 w_amont_(ib,1) += wy(i_local,j_local,k_local);
1604 w_amont_(ib,2) += wz(i_local,j_local,k_local);
1605 }
1606 }
1607 }
1608 }
1609 }
1610 mp_sum_for_each_item(v_amont_);
1611 mp_sum_for_each_item(w_amont_);
1612 mp_sum_for_each_item(compteur_);
1613 //Cerr << "volumes : " << volumes << finl;
1614 for (int i = 0; i < nbulles_tot; i++)
1615 {
1616 // const double x = 1./volumes[i];
1617 const double x = (compteur_(i,0) == 0.) ? 0. : 1. / compteur_(i,0);
1618 v_amont_(i, 0) *= x;
1619 v_amont_(i, 1) *= x;
1620 v_amont_(i, 2) *= x;
1621
1622 w_amont_(i, 0) *= x;
1623 w_amont_(i, 1) *= x;
1624 w_amont_(i, 2) *= x;
1625 }
1626}
1627
1628void Navier_Stokes_FTD_IJK::calculer_base_amont_bulle(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const DoubleTab& ubulles, DoubleTab& d1_amont_, DoubleTab& d2_amont_, DoubleTab& d3_amont_, DoubleTab& compteur_base_)
1629{
1630 // On trouve la vitesse moyenne sur une surface d'épaisseur 1 maille au-dessus de chaque bulle de l'essaim
1631 cout << "base !!!!!!!!!!" << endl;
1632 update_rho_v();
1633
1634 //cout << "TAILLE DU CHAMP VELOCITY : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << vx.ni() << endl;
1635
1636 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1637 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1638 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1639
1640 d1_amont_.resize(nbulles_tot, 3);
1641 d2_amont_.resize(nbulles_tot, 3);
1642 d3_amont_.resize(nbulles_tot, 3);
1643 compteur_base_.resize(nbulles_tot, 1);
1644 compteur_base_ = 0.;
1645
1646 DoubleTab v_amont_;
1647 DoubleTab w_amont_;
1648
1649 v_amont_.resize(nbulles_tot,3);
1650 v_amont_ = 0.;
1651 w_amont_.resize(nbulles_tot, 3);
1652 w_amont_ = 0.;
1653
1654 double d1x = 0.;
1655 double d1y = 0;
1656 double d1z = 0;
1657
1658 double d2x = 0;
1659 double d2y = 0.;
1660 double d2z = 0;
1661
1662 double d3x = 0;
1663 double d3y = 0;
1664 double d3z = 0.;
1665
1666 double normalisation = 1.;
1667
1668 for (int ib=0; ib < nbulles_tot; ib++)
1669 {
1670 d1_amont_(ib,0) = 1.0;
1671 d1_amont_(ib,1) = 0.;
1672 d1_amont_(ib,2) = 0.;
1673
1674 d2_amont_(ib,0) = 0.;
1675 d2_amont_(ib,1) = 1.0;
1676 d2_amont_(ib,2) = 0.;
1677
1678 d3_amont_(ib,0) = 0.;
1679 d3_amont_(ib,1) = 0.;
1680 d3_amont_(ib,2) = 1.0;
1681 }
1682
1683 calculer_v_amont_bulle(vx,vy,vz,vx,vy,vz,v_amont_,w_amont_,d1_amont_,d2_amont_,d3_amont_,compteur_base_);
1684
1685 compteur_base_ = 0.;
1686 d1_amont_ = 0.;
1687 d2_amont_ = 0.;
1688 d3_amont_ = 0.;
1689
1690 compteur_base_ = 0.;
1691
1692 for (int ib = 0; ib < nbulles_tot; ib++)
1693 {
1694 d1x = ubulles(ib,0)-v_amont_(ib,0);
1695 d1y = ubulles(ib,1)-v_amont_(ib,1);
1696 d1z = ubulles(ib,2)-v_amont_(ib,2);
1697 normalisation = sqrt(d1x*d1x + d1y*d1y + d1z*d1z)*1.0;
1698 d1x /= normalisation;
1699 d1y /= normalisation;
1700 d1z /= normalisation;
1701
1702 d2x = d1z;
1703 d2z = -d1x;
1704 normalisation = sqrt(d2x*d2x + d2y*d2y + d2z*d2z);
1705 d2x /= normalisation;
1706 d2z /= normalisation;
1707
1708 d3x = d1x*d1y;
1709 d3y = -(d1x*d1x + d1z*d1z);
1710 d3z = d1z*d1y;
1711 normalisation = sqrt(d3x*d3x + d3y*d3y + d3z*d3z);
1712 d3x /= normalisation;
1713 d3y /= normalisation;
1714 d3z /= normalisation;
1715
1716 d1_amont_(ib,0) += d1x;
1717 d1_amont_(ib,1) += d1y;
1718 d1_amont_(ib,2) += d1z;
1719
1720 d2_amont_(ib,0) += d2x;
1721 d2_amont_(ib,1) += d2y;
1722 d2_amont_(ib,2) += d2z;
1723
1724 d3_amont_(ib,0) += d3x;
1725 d3_amont_(ib,1) += d3y;
1726 d3_amont_(ib,2) += d3z;
1727
1728 compteur_base_(ib,0) += 1;
1729
1730 }
1731 mp_sum_for_each_item(d1_amont_);
1732 mp_sum_for_each_item(d2_amont_);
1733 mp_sum_for_each_item(d3_amont_);
1734 mp_sum_for_each_item(compteur_base_);
1735 //Cerr << "volumes : " << volumes << finl;
1736 for (int i = 0; i < nbulles_tot; i++)
1737 {
1738 // const double x = 1./volumes[i];
1739 const double x = (compteur_base_(i,0) == 0.) ? 0. : 1. / compteur_base_(i,0);
1740 d1_amont_(i, 0) *= x;
1741 d1_amont_(i, 1) *= x;
1742 d1_amont_(i, 2) *= x;
1743
1744 d2_amont_(i, 0) *= x;
1745 d2_amont_(i, 1) *= x;
1746 d2_amont_(i, 2) *= x;
1747
1748 d3_amont_(i, 0) *= x;
1749 d3_amont_(i, 1) *= x;
1750 d3_amont_(i, 2) *= x;
1751 }
1752}
1753
1754void Navier_Stokes_FTD_IJK::calculer_terme_S_x(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const IJK_Field_double& p, DoubleTab& S, const int nx)
1755{
1756
1757 //update_rho_v();
1758
1759 const Domaine_IJK& geom = velocity_[0].get_domaine();
1760 const double Lz = geom.get_domain_length(DIRECTION_K);
1761 const double Lx = geom.get_domain_length(DIRECTION_I);
1762 const double Ly = geom.get_domain_length(DIRECTION_J);
1763 const int ni = vx.ni();
1764 const int nj = vx.nj();
1765 const int nk = vx.nk();
1766 const double dz = geom.get_constant_delta(DIRECTION_K);
1767 const double dx = geom.get_constant_delta(DIRECTION_I);
1768 const double dy = geom.get_constant_delta(DIRECTION_J);
1769
1770 const double mu_l = milieu_ijk().get_mu_liquid();
1771
1772 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1773 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1774 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1775
1776 S.resize(nbulles_tot, 3);
1777 S = 0.;
1778
1779 ArrOfDouble volumes;
1780 DoubleTab centre_gravite;
1781
1782 volumes.resize_array(nbulles_tot);
1783 volumes = 0.;
1784 centre_gravite.resize(nbulles_tot, 3);
1785 centre_gravite = 0.;
1786
1787 double x_point = 0;
1788 double y_point = 0;
1789 double z_point = 0;
1790
1791 int i_point = 0;
1792 int j_point = 0;
1793 int k_point = 0;
1794
1795 int i_local = 0;
1796 int j_local = 0;
1797 int k_local = 0;
1798
1799 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
1800
1801 volumes.resize_array(nbulles_tot);
1802 centre_gravite.resize(nbulles_tot, 3);
1803
1804 int klim = static_cast<int>( L_boite_vol_controle_/2.0 / dz*1.0 );
1805
1806 for (int ib = 0; ib < nbulles_tot; ib++)
1807 {
1808 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
1809 {
1810 for (int k_beta = -klim; k_beta <= klim; k_beta++)
1811 {
1812 x_point = centre_gravite(ib,0) + L_boite_vol_controle_/2.0*nx;
1813 y_point = centre_gravite(ib,1) + k_beta*1.0*dy;
1814 z_point = centre_gravite(ib,2) + k_gamma*1.0*dz;
1815 //cout << k_gamma << " " << k_beta << endl;
1816 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
1817 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
1818
1819 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
1820 {
1821 if ( z_point >= Lz )
1822 {
1823 z_point -= Lz;
1824 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1825 }
1826 if ( z_point < 0 )
1827 {
1828 z_point += Lz;
1829 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1830 }
1831 if (y_point >=Ly)
1832 y_point -= Ly;
1833 if (y_point < 0)
1834 y_point += Ly;
1835
1836 if (x_point >= Lx)
1837 x_point -= Lx;
1838 if (x_point < 0)
1839 x_point += Lx;
1840 }
1841 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
1842
1843 i_point = static_cast<int>( x_point/dx );
1844 j_point = static_cast<int>( y_point/dy );
1845 k_point = static_cast<int>( z_point/dz );
1846
1847 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
1848 {
1849 i_local = i_point - geom.get_offset_local(0);
1850 j_local = j_point - geom.get_offset_local(1);
1851 k_local = k_point - geom.get_offset_local(2);
1852
1853 if (i_local-1 < 0)
1854 i_local += 1;
1855 if (j_local-1 < 0)
1856 j_local += 1;
1857 if (k_local-1 < 0)
1858 k_local += 1;
1859
1860 S(ib,0) += nx*( 2*mu_l*(vx(i_local,j_local,k_local)-vx(i_local-1,j_local,k_local))/dx - p(i_local,j_local,k_local) )*dy*dz;
1861 S(ib,1) += nx*( mu_l*( (vx(i_local,j_local,k_local)-vx(i_local,j_local-1,k_local))/dy + (vy(i_local,j_local,k_local)-vy(i_local-1,j_local,k_local))/dx) )*dy*dz;
1862 S(ib,2) += nx*( mu_l*( (vx(i_local,j_local,k_local)-vx(i_local,j_local,k_local-1))/dz + (vz(i_local,j_local,k_local)-vz(i_local-1,j_local,k_local))/dx) )*dy*dz;
1863 //cout << "DEBUG !!!!!!!!!!! " << nx*( ( (vx(i_local,j_local,k_local)-vx(i_local,j_local,k_local-1))/dz + (vz(i_local,j_local,k_local)-vz(i_local-1,j_local,k_local))/dx) ) << endl;;
1864 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
1865 }
1866 }
1867 }
1868 }
1870}
1871
1872void Navier_Stokes_FTD_IJK::calculer_terme_S_y(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const IJK_Field_double& p, DoubleTab& S, const int ny)
1873{
1874
1875 //update_rho_v();
1876
1877 const Domaine_IJK& geom = velocity_[0].get_domaine();
1878 const double Lz = geom.get_domain_length(DIRECTION_K);
1879 const double Lx = geom.get_domain_length(DIRECTION_I);
1880 const double Ly = geom.get_domain_length(DIRECTION_J);
1881 const int ni = vx.ni();
1882 const int nj = vx.nj();
1883 const int nk = vx.nk();
1884 const double dz = geom.get_constant_delta(DIRECTION_K);
1885 const double dx = geom.get_constant_delta(DIRECTION_I);
1886 const double dy = geom.get_constant_delta(DIRECTION_J);
1887
1888 const double mu_l = milieu_ijk().get_mu_liquid();
1889
1890 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
1891 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
1892 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
1893
1894 S.resize(nbulles_tot, 3);
1895 S = 0.;
1896
1897 ArrOfDouble volumes;
1898 DoubleTab centre_gravite;
1899
1900 volumes.resize_array(nbulles_tot);
1901 volumes = 0.;
1902 centre_gravite.resize(nbulles_tot, 3);
1903 centre_gravite = 0.;
1904
1905 double x_point = 0;
1906 double y_point = 0;
1907 double z_point = 0;
1908
1909 int i_point = 0;
1910 int j_point = 0;
1911 int k_point = 0;
1912
1913 int i_local = 0;
1914 int j_local = 0;
1915 int k_local = 0;
1916
1917 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
1918
1919 volumes.resize_array(nbulles_tot);
1920 centre_gravite.resize(nbulles_tot, 3);
1921
1922 int klim = static_cast<int>( L_boite_vol_controle_/2.0 / dx*1.0 );
1923
1924 for (int ib = 0; ib < nbulles_tot; ib++)
1925 {
1926 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
1927 {
1928 for (int k_beta = -klim; k_beta <= klim; k_beta++)
1929 {
1930 x_point = centre_gravite(ib,0) + k_beta*1.0*dx;
1931 y_point = centre_gravite(ib,1) + L_boite_vol_controle_/2.0*ny;
1932 z_point = centre_gravite(ib,2) + k_gamma*1.0*dz;
1933 //cout << k_gamma << " " << k_beta << endl;
1934 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
1935 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
1936
1937 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
1938 {
1939 if ( z_point >= Lz )
1940 {
1941 z_point -= Lz;
1942 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1943 }
1944 if ( z_point < 0 )
1945 {
1946 z_point += Lz;
1947 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
1948 }
1949 if (y_point >=Ly)
1950 y_point -= Ly;
1951 if (y_point < 0)
1952 y_point += Ly;
1953
1954 if (x_point >= Lx)
1955 x_point -= Lx;
1956 if (x_point < 0)
1957 x_point += Lx;
1958 }
1959 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
1960
1961 i_point = static_cast<int>( x_point/dx );
1962 j_point = static_cast<int>( y_point/dy );
1963 k_point = static_cast<int>( z_point/dz );
1964
1965 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
1966 {
1967 i_local = i_point - geom.get_offset_local(0);
1968 j_local = j_point - geom.get_offset_local(1);
1969 k_local = k_point - geom.get_offset_local(2);
1970
1971 if (i_local-1 < 0)
1972 i_local += 1;
1973 if (j_local-1 < 0)
1974 j_local += 1;
1975 if (k_local-1 < 0)
1976 k_local += 1;
1977
1978 S(ib,0) += ny*( mu_l*( (vy(i_local,j_local,k_local)-vy(i_local-1,j_local,k_local))/dx + (vx(i_local,j_local,k_local)-vx(i_local,j_local-1,k_local))/dy) )*dx*dz;
1979 S(ib,1) += ny*( 2*mu_l*(vy(i_local,j_local,k_local)-vy(i_local,j_local-1,k_local))/dy - p(i_local,j_local,k_local) )*dx*dz;
1980 S(ib,2) += ny*( mu_l*( (vy(i_local,j_local,k_local)-vy(i_local,j_local,k_local-1))/dz + (vz(i_local,j_local,k_local)-vz(i_local,j_local-1,k_local))/dy) )*dx*dz;
1981
1982 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
1983 }
1984 }
1985 }
1986 }
1988}
1989
1990void Navier_Stokes_FTD_IJK::calculer_terme_S_z(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const IJK_Field_double& p, DoubleTab& S, const int nz)
1991{
1992
1993 //update_rho_v();
1994
1995 const Domaine_IJK& geom = velocity_[0].get_domaine();
1996 const double Lz = geom.get_domain_length(DIRECTION_K);
1997 const double Lx = geom.get_domain_length(DIRECTION_I);
1998 const double Ly = geom.get_domain_length(DIRECTION_J);
1999 const int ni = vx.ni();
2000 const int nj = vx.nj();
2001 const int nk = vx.nk();
2002 const double dz = geom.get_constant_delta(DIRECTION_K);
2003 const double dx = geom.get_constant_delta(DIRECTION_I);
2004 const double dy = geom.get_constant_delta(DIRECTION_J);
2005
2006 const double mu_l = milieu_ijk().get_mu_liquid();
2007
2008 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
2009 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
2010 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
2011
2012 S.resize(nbulles_tot, 3);
2013 S = 0.;
2014
2015 ArrOfDouble volumes;
2016 DoubleTab centre_gravite;
2017
2018 volumes.resize_array(nbulles_tot);
2019 volumes = 0.;
2020 centre_gravite.resize(nbulles_tot, 3);
2021 centre_gravite = 0.;
2022
2023 double x_point = 0;
2024 double y_point = 0;
2025 double z_point = 0;
2026
2027 int i_point = 0;
2028 int j_point = 0;
2029 int k_point = 0;
2030
2031 int i_local = 0;
2032 int j_local = 0;
2033 int k_local = 0;
2034
2035 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
2036
2037 volumes.resize_array(nbulles_tot);
2038 centre_gravite.resize(nbulles_tot, 3);
2039
2040 int klim = static_cast<int>( L_boite_vol_controle_/2.0 / dx*1.0 );
2041
2042 for (int ib = 0; ib < nbulles_tot; ib++)
2043 {
2044 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
2045 {
2046 for (int k_beta = -klim; k_beta <= klim; k_beta++)
2047 {
2048 x_point = centre_gravite(ib,0) + k_beta*1.0*dx;
2049 y_point = centre_gravite(ib,1) + k_gamma*1.0*dy;
2050 z_point = centre_gravite(ib,2) + L_boite_vol_controle_/2.0*nz;
2051 //cout << k_gamma << " " << k_beta << endl;
2052 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
2053 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
2054
2055 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
2056 {
2057 if ( z_point >= Lz )
2058 {
2059 z_point -= Lz;
2060 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
2061 }
2062 if ( z_point < 0 )
2063 {
2064 z_point += Lz;
2065 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
2066 }
2067 if (y_point >=Ly)
2068 y_point -= Ly;
2069 if (y_point < 0)
2070 y_point += Ly;
2071
2072 if (x_point >= Lx)
2073 x_point -= Lx;
2074 if (x_point < 0)
2075 x_point += Lx;
2076 }
2077 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
2078
2079 i_point = static_cast<int>( x_point/dx );
2080 j_point = static_cast<int>( y_point/dy );
2081 k_point = static_cast<int>( z_point/dz );
2082
2083 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
2084 {
2085 i_local = i_point - geom.get_offset_local(0);
2086 j_local = j_point - geom.get_offset_local(1);
2087 k_local = k_point - geom.get_offset_local(2);
2088
2089 if (i_local-1 < 0)
2090 i_local += 1;
2091 if (j_local-1 < 0)
2092 j_local += 1;
2093 if (k_local-1 < 0)
2094 k_local += 1;
2095
2096 S(ib,0) += nz*( mu_l*( (vz(i_local,j_local,k_local)-vz(i_local-1,j_local,k_local))/dx + (vx(i_local,j_local,k_local)-vx(i_local,j_local,k_local-1))/dz) )*dx*dy;
2097 S(ib,1) += nz*( mu_l*( (vz(i_local,j_local,k_local)-vz(i_local,j_local-1,k_local))/dy + (vy(i_local,j_local,k_local)-vy(i_local,j_local,k_local-1))/dz) )*dx*dy;
2098 S(ib,2) += nz*( 2*mu_l*(vz(i_local,j_local,k_local)-vz(i_local,j_local,k_local-1))/dz - p(i_local,j_local,k_local) )*dx*dy;
2099
2100 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
2101 }
2102 }
2103 }
2104 }
2106}
2107
2108void Navier_Stokes_FTD_IJK::calculer_terme_volumique(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, const IJK_Field_double& rho_, const IJK_Field_double& indica_, DoubleTab& S)
2109{
2110
2111 //update_rho_v();
2112
2113 const Domaine_IJK& geom = velocity_[0].get_domaine();
2114 const double Lz = geom.get_domain_length(DIRECTION_K);
2115 const double Lx = geom.get_domain_length(DIRECTION_I);
2116 const double Ly = geom.get_domain_length(DIRECTION_J);
2117 const int ni = vx.ni();
2118 const int nj = vx.nj();
2119 const int nk = vx.nk();
2120 const double dz = geom.get_constant_delta(DIRECTION_K);
2121 const double dx = geom.get_constant_delta(DIRECTION_I);
2122 const double dy = geom.get_constant_delta(DIRECTION_J);
2123
2124 const int nbulles_reelles = interfaces_->get_nb_bulles_reelles();
2125 const int nbulles_ghost = interfaces_->get_nb_bulles_ghost();
2126 const int nbulles_tot = nbulles_reelles + nbulles_ghost;
2127
2128 S.resize(nbulles_tot, 3);
2129 S = 0.;
2130
2131 ArrOfDouble volumes;
2132 DoubleTab centre_gravite;
2133
2134 volumes.resize_array(nbulles_tot);
2135 volumes = 0.;
2136 centre_gravite.resize(nbulles_tot, 3);
2137 centre_gravite = 0.;
2138
2139 double x_point = 0;
2140 double y_point = 0;
2141 double z_point = 0;
2142
2143 int i_point = 0;
2144 int j_point = 0;
2145 int k_point = 0;
2146
2147 int i_local = 0;
2148 int j_local = 0;
2149 int k_local = 0;
2150
2151 interfaces_->calculer_volume_bulles(volumes,centre_gravite);
2152
2153 volumes.resize_array(nbulles_tot);
2154 centre_gravite.resize(nbulles_tot, 3);
2155
2156 int klim = static_cast<int>( L_boite_vol_controle_/2.0 / dx*1.0 );
2157
2158 for (int ib = 0; ib < nbulles_tot; ib++)
2159 {
2160 for (int k_gamma = -klim; k_gamma <= klim; k_gamma++)
2161 {
2162 for (int k_beta = -klim; k_beta <= klim; k_beta++)
2163 {
2164 for (int k_alpha = -klim; k_alpha <= klim; k_alpha++)
2165 {
2166 x_point = centre_gravite(ib,0) + k_beta*1.0*dx;
2167 y_point = centre_gravite(ib,1) + k_gamma*1.0*dy;
2168 z_point = centre_gravite(ib,2) + k_alpha*1.0*dz;
2169 //cout << k_gamma << " " << k_beta << endl;
2170 //cout << (x_point - centre_gravite(ib,0))/rayon*1.0 << (z_point - centre_gravite(ib,2))/rayon*1.0 << " " << (y_point - centre_gravite(ib,1))/rayon*1.0 << endl;
2171 //cout << "AVANT !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Ly << " " << z_point/Lz << endl;
2172
2173 while ( (z_point >= Lz) || (z_point < 0) || (y_point >= Ly) || (y_point < 0) || (x_point >= Lx) || (x_point < 0) )
2174 {
2175 if ( z_point >= Lz )
2176 {
2177 z_point -= Lz;
2178 x_point -= boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
2179 }
2180 if ( z_point < 0 )
2181 {
2182 z_point += Lz;
2183 x_point += boundary_conditions_.get_dU_perio()*(schema_temps_ijk().get_current_time() + boundary_conditions_.get_t0_shear());
2184 }
2185 if (y_point >=Ly)
2186 y_point -= Ly;
2187 if (y_point < 0)
2188 y_point += Ly;
2189
2190 if (x_point >= Lx)
2191 x_point -= Lx;
2192 if (x_point < 0)
2193 x_point += Lx;
2194 }
2195 //cout << "APRES !!!!!!!!!!!!! " << x_point/Lx << " " << y_point/Lz << " " << z_point/Lz << endl;
2196
2197 i_point = static_cast<int>( x_point/dx );
2198 j_point = static_cast<int>( y_point/dy );
2199 k_point = static_cast<int>( z_point/dz );
2200
2201 if ( (geom.get_offset_local(0) <= i_point) && (geom.get_offset_local(0)+ni > i_point) && (geom.get_offset_local(1) <= j_point) && (geom.get_offset_local(1)+nj > j_point) && (geom.get_offset_local(2) <= k_point) && (geom.get_offset_local(2)+nk > k_point) )
2202 {
2203 i_local = i_point - geom.get_offset_local(0);
2204 j_local = j_point - geom.get_offset_local(1);
2205 k_local = k_point - geom.get_offset_local(2);
2206
2207 if (i_local-1 < 0)
2208 i_local += 1;
2209 if (j_local-1 < 0)
2210 j_local += 1;
2211 if (k_local-1 < 0)
2212 k_local += 1;
2213
2214 S(ib,0) += rho_(i_local,j_local,k_local)*vx(i_local,j_local,k_local)*indica_(i_local,j_local,k_local)*dx*dy*dz;
2215 S(ib,1) += rho_(i_local,j_local,k_local)*vy(i_local,j_local,k_local)*indica_(i_local,j_local,k_local)*dx*dy*dz;
2216 S(ib,2) += rho_(i_local,j_local,k_local)*vz(i_local,j_local,k_local)*indica_(i_local,j_local,k_local)*dx*dy*dz;
2217
2218 //compteur_(ib,0) += interfaces_.I_ft(i_local,j_local,k_local);
2219 }
2220 }
2221 }
2222 }
2223 }
2225}
2226
2227void Navier_Stokes_FTD_IJK::calculer_vitesse_droite(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, double& vx_moy, double& vy_moy, double& vz_moy)
2228{
2229 /* Renvoie le vecteur vitesse moyen (spatial) en z = 0 */
2230 /* Ne fonctionne que pour des maillages uniformes */
2231 const Domaine_IJK& splitting = vx.get_domaine();
2232 const int ni = vx.ni();
2233 const int nj = vx.nj();
2234 const int nk = vx.nk();
2235 //const int nk = vx.nk();
2236 //double dz = splitting.get_constant_delta(DIRECTION_K);
2237 int z_index = splitting.get_local_slice_index(2);
2238 int z_index_max = splitting.get_nprocessor_per_direction(2) - 1;
2239 vx_moy = 0.;
2240 vy_moy = 0.;
2241 vz_moy = 0.;
2242 double alpha_l_moy = 0.;
2243
2244 if (z_index == z_index_max)
2245 {
2246 for (int i = 0; i < ni; i++)
2247 {
2248 for (int j = 0; j < nj; j++)
2249 {
2250 vx_moy += vx(i, j, nk - 1) * interfaces_->I(i, j, nk - 1);
2251 vy_moy += vy(i, j, nk - 1) * interfaces_->I(i, j, nk - 1);
2252 vz_moy += vz(i, j, nk - 1) * interfaces_->I(i, j, nk - 1);
2253 alpha_l_moy += interfaces_->I(i, j, nk - 1);
2254 }
2255 }
2256 }
2257 vx_moy = Process::mp_sum(vx_moy);
2258 vy_moy = Process::mp_sum(vy_moy);
2259 vz_moy = Process::mp_sum(vz_moy);
2260 alpha_l_moy = Process::mp_sum(alpha_l_moy);
2261
2262 vx_moy = vx_moy / alpha_l_moy;
2263 vy_moy = vy_moy / alpha_l_moy;
2264 vz_moy = vz_moy / alpha_l_moy;
2265
2266 return;
2267}
2268
2269void Navier_Stokes_FTD_IJK::calculer_vitesse_gauche(const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz, double& vx_moy, double& vy_moy, double& vz_moy)
2270{
2271 /* Renvoie le vecteur vitesse moyen (spatial) en z = 0 */
2272 /* Ne fonctionne que pour des maillages uniformes */
2273 const Domaine_IJK& splitting = vx.get_domaine();
2274 const int ni = vx.ni();
2275 const int nj = vx.nj();
2276 //const int nk = vx.nk();
2277 //double dz = splitting.get_constant_delta(DIRECTION_K);
2278 int z_index = splitting.get_local_slice_index(2);
2279 int z_index_min = 0;
2280 vx_moy = 0.;
2281 vy_moy = 0.;
2282 vz_moy = 0.;
2283 double alpha_l_moy = 0.;
2284
2285 if (z_index == z_index_min)
2286 {
2287 for (int i = 0; i < ni; i++)
2288 {
2289 for (int j = 0; j < nj; j++)
2290 {
2291 vx_moy += vx(i, j, 0) * interfaces_->I(i, j, 0);
2292 vy_moy += vy(i, j, 0) * interfaces_->I(i, j, 0);
2293 vz_moy += vz(i, j, 0) * interfaces_->I(i, j, 0);
2294 alpha_l_moy += interfaces_->I(i, j, 0);
2295 }
2296 }
2297 }
2298
2299 vx_moy = Process::mp_sum(vx_moy);
2300 vy_moy = Process::mp_sum(vy_moy);
2301 vz_moy = Process::mp_sum(vz_moy);
2302 alpha_l_moy = Process::mp_sum(alpha_l_moy);
2303
2304 vx_moy = vx_moy / alpha_l_moy;
2305 vy_moy = vy_moy / alpha_l_moy;
2306 vz_moy = vz_moy / alpha_l_moy;
2307 return;
2308}
2309
2310static double calculer_tau_wall(const IJK_Field_double& vx, const double mu_liquide)
2311{
2312 const int nj = vx.nj();
2313 const int ni = vx.ni();
2314 const Domaine_IJK& geom = vx.get_domaine();
2315 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
2316 // cast en double au cas ou on voudrait faire un maillage >2 milliards
2317 const double n_mailles_plan_xy = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1);
2318 const int kmin = vx.get_domaine().get_offset_local(DIRECTION_K);
2320 const int nktot = vx.get_domaine().get_nb_items_global(loc, DIRECTION_K);
2321 double tauw = 0.;
2322
2323#ifndef VARIABLE_DZ
2324 const double dz = geom.get_constant_delta(DIRECTION_K);
2325#else
2326 const ArrOfDouble& tab_dz=geom.get_delta(DIRECTION_K);
2327 // const int nz = geom.get_nb_elem_tot(DIRECTION_K);
2328 double dz = -1.; // invalid value
2329 // On prend le dz sur la paroi basse :
2330 if (kmin == 0)
2331 dz = tab_dz[0];
2332#endif
2333 if (kmin == 0)
2334 {
2335 for (int j = 0; j < nj; j++)
2336 for (int i = 0; i < ni; i++)
2337 tauw += vx(i, j, 0);
2338 }
2339 if (kmin + vx.nk() == nktot)
2340 {
2341 const int k = vx.nk() - 1;
2342 for (int j = 0; j < nj; j++)
2343 for (int i = 0; i < ni; i++)
2344 tauw += vx(i, j, k);
2345 }
2346
2347 // somme sur tous les processeurs.
2348 tauw = Process::mp_sum(tauw);
2349 // Il faut diviser par dz/2. et par 2*n_mailles_plan_xy
2350#ifdef VARIABLE_DZ
2351 // Pour definir un dz sur tous les procs, on recupere celui de la paroi basse
2352 // sur tous les procs, y compris ceux qui n'ont pas de mur, ou pas le mur gauche.
2353 dz = Process::mp_max(dz);
2354#endif
2355 tauw /= (dz * n_mailles_plan_xy);
2356 tauw *= mu_liquide;
2357 return tauw;
2358}
2359
2360// Inspiree de la methode d'IJK_Navier_Stokes_Tools :
2361static void runge_kutta3_update_for_float(const double dx, double& store, double& v, const int step, double dt_tot)
2362{
2363 const double coeff_a[3] = { 0., -5. / 9., -153. / 128. };
2364 // Fk[0] = 1; Fk[i+1] = Fk[i] * a[i+1] + 1
2365 const double coeff_Fk[3] = { 1., 4. / 9., 15. / 32. };
2366
2367 const double facteurF = coeff_a[step];
2368 const double intermediate_dt = compute_fractionnal_timestep_rk3(dt_tot, step);
2369 const double delta_t_divided_by_Fk = intermediate_dt / coeff_Fk[step];
2370 double x;
2371 switch(step)
2372 {
2373 case 0:
2374 x = dx;
2375 store = x;
2376 v += x * delta_t_divided_by_Fk;
2377 break;
2378 case 1:
2379 // general case, read and write F
2380 x = store * facteurF + dx;
2381 store = x;
2382 v += x * delta_t_divided_by_Fk;
2383 break;
2384 case 2:
2385 // do not write F
2386 x = store * facteurF + dx;
2387 v += x * delta_t_divided_by_Fk;
2388 break;
2389 default:
2390 Cerr << "Error in runge_kutta_update_for_float: wrong step" << finl;
2391 Process::exit();
2392 };
2393}
2394
2396{
2398 {
2399 if (apres)
2400 {
2402 for (int dir = 0; dir < 3; dir++)
2403 {
2405 u_euler_ap_rho_mu_ind_[dir] = calculer_v_moyen(velocity_[dir]);
2406 }
2407 }
2408 else /* avant */
2409 {
2411 for (int dir = 0; dir < 3; dir++)
2413 }
2414 }
2415}
2416
2418{
2419 if (coeff_evol_volume_ != 0.)
2420 {
2422 const int nb_reelles = interfaces_->get_nb_bulles_reelles();
2423 for (int ib = 0; ib < nb_reelles; ib++)
2425 }
2426}
2427
2428void Navier_Stokes_FTD_IJK::calculer_terme_source_acceleration(const double time, const double timestep, const int rk_step, const int dir)
2429{
2430 if (dir == 0 || dir == 1)
2431 calculer_terme_source_acceleration(velocity_[dir], time, timestep, rk_step);
2432 else
2433 calculer_terme_source_acceleration_z(velocity_[2], time, timestep, rk_step);
2434}
2435
2436void Navier_Stokes_FTD_IJK::calculer_terme_source_acceleration(IJK_Field_double& vx, const double time, const double timestep, const int rk_step)
2437{
2438 /*
2439 * Cette methode calcule la source de qdm a appliquer pour que les bulles soient
2440 * globalement fixes dans la direction de la gravite
2441 * o Si le parametre source_qdm_gr vaut 1, la correction a appliquer est :
2442 * vx = vx - moy^{xyz} (rho vx) - moy^{xyz} (rho vx_terminale) / moy^{xyz} (rho)
2443 * o Si le parametre source_qdm_gr vaut 0, la source est determinee par :
2444 * temre_force_init --> temre_source_acceleration et par
2445 * expression_derivee_force --> expression_derivee_acceleration
2446 * REMARQUE II : On peut envisager de faire une correction qui n'a pas besoin qu'on lui donne vx_terminale en
2447 * entree. C'est ce qui a ete explore, mais qui n'a pas aboutit.
2448 * */
2449 double new_time = time;
2450
2451 // S'il n'y a pas de derivee, la source est constante donc on peut sortir:
2453 return;
2454
2455 statistics().begin_count(STD_COUNTERS::source_terms,statistics().get_last_opened_counter_level()+1);
2456
2457 double v_moy = calculer_v_moyen(vx);
2458 update_rho_v();
2459 const int direction_gravite = milieu_ijk().get_direction_gravite();
2460
2461 // GAB, rotation : pas sur de mon coup la
2462 // double rhov_moy = calculer_v_moyen(rho_v_[DIRECTION_I]);
2463 double rhov_moy = calculer_v_moyen(rho_v_[direction_gravite]);
2464
2465 double moy_rappel = 0.;
2466 // GAB, rotation
2467 const Domaine_IJK& geom = velocity_[direction_gravite].get_domaine();
2468 double vol_dom = geom.get_domain_length(DIRECTION_I) * geom.get_domain_length(DIRECTION_J) * geom.get_domain_length(DIRECTION_K);
2469 if (coef_immobilisation_ > 1e-16)
2470 {
2471 // GAB, rotation, pas sur de mon coup
2472 // moy_rappel=calculer_v_moyen(force_rappel_[DIRECTION_I])*vol_dom;
2473 moy_rappel = calculer_v_moyen(force_rappel_[direction_gravite]) * vol_dom;
2474 }
2475
2476 const double rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour(), mu_l = milieu_ijk().get_mu_liquid();
2477 double tauw = calculer_tau_wall(vx, mu_l);
2478 double derivee_acceleration = 0.;
2479 double derivee_facteur_sv = 0.;
2480
2481 double alv = 0.;
2482 if (probleme_ijk().has_interface())
2483 {
2484 if (vol_bulle_monodisperse_ >= 0.)
2485 alv = interfaces_->get_nb_bulles_reelles() * vol_bulle_monodisperse_ / vol_dom;
2486 else
2487 alv = 1. - calculer_v_moyen(interfaces_->I());
2488 }
2490 {
2491 //
2492 double drho = rho_l - rho_v;
2493 double facv = 0., facl = 1.;
2494 if (std::fabs(alv * drho) > DMINFLOAT)
2495 {
2496 facv = 1. / (alv * drho);
2497 facl = 1. / ((1. - alv) * drho);
2498 }
2499 double ul = facl * (rhov_moy - rho_v * v_moy);
2500 double uv = facv * (rho_l * v_moy - rhov_moy);
2501
2502 // Mise a jour de l'acceleration
2503 parser_derivee_acceleration_.setVar("rappel_moyen", moy_rappel);
2505 parser_derivee_acceleration_.setVar("v_moyen", v_moy);
2506 parser_derivee_acceleration_.setVar("ur", uv - ul);
2507 parser_derivee_acceleration_.setVar("ul", ul);
2508 parser_derivee_acceleration_.setVar("uv", uv);
2509 parser_derivee_acceleration_.setVar("T", time);
2510 parser_derivee_acceleration_.setVar("rhov_moyen", rhov_moy);
2511 parser_derivee_acceleration_.setVar("tauw", tauw);
2512 // Pour utiliser rho_v il faudrait deplacer cette mise a jour a un endroit ou rho
2513 // est a jour en fonction de l'indicatrice
2514 // parser_derivee_acceleration_.setVar("rho_v_moyen", rho_v_moy);
2515 derivee_acceleration = parser_derivee_acceleration_.eval();
2516
2517 // Mise a jour de la source variable
2519 {
2520 parser_derivee_facteur_variable_source_.setVar("rappel_moyen", moy_rappel);
2522 parser_derivee_facteur_variable_source_.setVar("v_moyen", v_moy);
2524 parser_derivee_facteur_variable_source_.setVar("rhov_moyen", rhov_moy);
2525 parser_derivee_facteur_variable_source_.setVar("tauw", tauw);
2526 derivee_facteur_sv = parser_derivee_facteur_variable_source_.eval();
2527 } //
2528
2529 if (qdm_corrections_.is_type_gb())
2530 {
2531 // calcul de terme_source_acceleration_ et de terme_source_acceleration_
2532
2533 // ON NE VEUT PAS METTRE A JOUR TERME_SOURCE_ACCELERATION_ AVEC CETTE METHODE
2535 {
2536 terme_source_acceleration_ += derivee_acceleration * timestep;
2537 //terme_source_acceleration_ += 0;//derivee_acceleration * timestep;
2538 facteur_variable_source_ += derivee_facteur_sv * timestep;
2539 //facteur_variable_source_ += 0;//derivee_facteur_sv * timestep;
2540 new_time += timestep;
2541 }
2542 else if (sub_type(Schema_RK3_IJK, schema_temps_ijk()))
2543 {
2544 const double intermediate_dt = compute_fractionnal_timestep_rk3(timestep, rk_step);
2546 runge_kutta3_update_for_float(derivee_acceleration, rk3.get_store_RK3_source_acc(), terme_source_acceleration_, rk_step, timestep);
2547 Cout << "terme_source_acceleration_" << terme_source_acceleration_ << finl;
2548 //terme_source_acceleration_ += 0;
2549 runge_kutta3_update_for_float(derivee_facteur_sv, rk3.get_store_RK3_fac_sv(), facteur_variable_source_, rk_step, timestep);
2550 Cout << "facteur_variable_source_" << facteur_variable_source_ << finl;
2551 //facteur_variable_source_ += 0;
2552 new_time += intermediate_dt;
2553 }
2554 }
2555 else if (sub_type(Schema_RK3_IJK, schema_temps_ijk()))
2556 {
2557 const double intermediate_dt = compute_fractionnal_timestep_rk3(timestep/*total */, rk_step);
2559 runge_kutta3_update_for_float(derivee_acceleration, rk3.get_store_RK3_source_acc(), terme_source_acceleration_, rk_step, timestep/*total */);
2560
2561 runge_kutta3_update_for_float(derivee_facteur_sv, rk3.get_store_RK3_fac_sv(), facteur_variable_source_, rk_step, timestep/*total */);
2562 new_time += intermediate_dt;
2563 }
2564 }
2565 envoyer_broadcast(terme_source_acceleration_, 0);
2566
2567 // -----------------------------------------------------------
2568 // Force interface (:"force sigma") seloon x,y,z et u.Force_interface
2569 const Probleme_FTD_IJK_base& pb_ijk = probleme_ijk();
2570 double fs0(0), fs1(0), fs2(0), psn(0);
2572 {
2573 // FORCE INTERFACIALE : on veut un terme homogene a [rho.g]=[N.m^{-3}]
2574 // terme_source_interfaces_ns_ est homogene a [du/dt]=[m.s^{-2}]
2575 // -> in calculer_dv : "~ velocity_ += force_interf * dt ~"
2576 // --> force_interf a bien eu un mass_solver_with_rho plus haut
2577 fs0 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[0], 0));
2578 fs1 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[1], 1));
2579 fs2 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[2], 2));
2580 psn = calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, terme_source_interfaces_ns_)));
2581 }
2582 // energie cinetique (monophasique) et diphasique
2583 double uu(calculer_v_moyen(scalar_product(pb_ijk, velocity_, velocity_)));
2584 double uru(calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, velocity_))));
2585 // Force exterieur (:"force thi") selon x,y,z et acceleration_thi.acceleration_thi, force_thi.foce_thi, u.Force_THI
2586 double ft0(0), ft1(0), ft2(0), atat(0), ftft(0), ptn(0);
2587 if (forcage_.get_type_forcage() > 0)
2588 {
2589 // FORCE IMPOSEE : on veut un terme homogene a [rho.g]=[N.m^{-3}]
2590 // forcage_.get_force_ph2() est homogene a [du/dt]=[m.s^{-2}]
2591 // -> in compute_add_THI_force_sur_d_velocity : "~ d_velocity += forcage_.get_force_ph2() ~"
2592 ft0 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[0], 0));
2593 ft1 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[1], 1));
2594 ft2 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[2], 2));
2595 atat = calculer_v_moyen(scalar_product(pb_ijk, forcage_.get_force_ph2(), forcage_.get_force_ph2()));
2596 ftft = calculer_v_moyen(scalar_product(pb_ijk, scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2()), scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2())));
2597 ptn = calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2())));
2598 }
2599 // -----------------------------------------------------------
2600
2601 // Impression dans le fichier _acceleration.out
2603 {
2604 // GR : 07.01.22 : ce serai pas mal de mettre une condition if (tstep % dt_post_stats_acc_ == dt_post_stats_acc_ - 1 || stop)
2605 // pour alleger le dossier OUT. Voir avec GB et AB.
2606 // double ff=0.;
2607 int reset = (!pb_ijk.get_reprise()) && (schema_temps_ijk().get_tstep() == 0);
2608 SFichier fic =
2609 Ouvrir_fichier("_acceleration.out",
2610 "1.tstep\t2.time\t3.Vx\t4.rhoVx\t5.tauw\t6.da/dt\t7.NewT\t8.acceleration\t9.fac_var_source\t10.qdm_source\t11.vap_velocity_tmoy_\t12.liq_velocity_tmoy_\t13.qdm_patch_correction_[0]\t14.qdm_patch_correction_[1]\t15.qdm_patch_correction_[2]\t16.F_sigma_moyen[0]\t17.F_sigma_moyen[1]\t18.F_sigma_moyen[2]\t19.y.F_sigma\t20.u.u\t21.F_THI[0]\t22.F_THI[1]\t23.F_THI[2]\t24.A_THI.A_THI\t25.F_THI.F_THI\t26.u.F_THI\t27.u.rho.u",
2611 reset);
2612 // la derivee_acceleration n'est connue que sur le maitre
2613 fic << schema_temps_ijk().get_tstep() << " " << time << " " << v_moy << " " << rhov_moy << " " << tauw;
2614 fic << " " << derivee_acceleration << " " << new_time << " " << terme_source_acceleration_;
2615 fic << " " << facteur_variable_source_;
2616 fic << " " << 0.; //qdm_source_;
2617 fic << " " << vap_velocity_tmoy_;
2618 fic << " " << liq_velocity_tmoy_;
2619
2620 if (coef_immobilisation_ > 1e-16)
2621 fic << " " << moy_rappel;
2622
2623 for (int dir = 0; dir < 3; dir++)
2624 fic << " " << 0.; //qdm_patch_correction_[dir];
2625
2626 // Force interfaciale et puissance du travail des forces interfaciales
2627 // rho*terme_source_interfaces_ns_
2628 fic << " " << fs0; // F_sigma_moyen[0]
2629 fic << " " << fs1; // F_sigma_moyen[1]
2630 fic << " " << fs2; // F_sigma_moyen[2]
2631 // u.rho*terme_source_interfaces_ns_
2632 fic << " " << psn; // velocity.F_sigma
2633
2634 // Energie cinetique (double)
2635 // u.u (qui est aussi accessible par les .txt)
2636 fic << " " << uu;
2637
2638 // Force imposee et puissance du traveil de la force imposee
2639 // rho*F_THI
2640 fic << " " << ft0; // F_THI[0]
2641 fic << " " << ft1; // F_THI[1]
2642 fic << " " << ft2; // F_THI[2]
2643 fic << " " << atat; // A_THI.A_THI
2644 fic << " " << ftft; // F_THI.F_THI
2645 // u.rho*F_THI
2646 fic << " " << ptn; // velocity.F_THI
2647 // Energie cinetique en diphasiqeu (double)
2648 // u.rho.u (qui est aussi accessible par les .txt)
2649 fic << " " << uru;
2650
2651 fic << finl;
2652 fic.close();
2653 }
2654 statistics().end_count(STD_COUNTERS::source_terms);
2655}
2656
2657#ifdef COMPLEMENT_ANTI_DEVIATION_RESIDU
2658// left average - right average
2659static double calculer_wall_difference(const IJK_Field_double& vx)
2660{
2661 const int nj = vx.nj();
2662 const int ni = vx.ni();
2663 const Domaine_IJK& geom = vx.get_domaine();
2664 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
2665 // cast en double au cas ou on voudrait faire un maillage >2 milliards
2666 const double n_mailles_plan_xy = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1);
2667 const int kmin = vx.get_domaine().get_offset_local(DIRECTION_K);
2669 const int nktot = vx.get_domaine().get_nb_items_global(loc, DIRECTION_K);
2670
2671 double x = 0.;
2672 if (kmin == 0)
2673 {
2674 for (int j = 0; j < nj; j++)
2675 for (int i = 0; i < ni; i++)
2676 x += vx(i, j, 0);
2677 }
2678 if (kmin + vx.nk() == nktot)
2679 {
2680 const int k = vx.nk() - 1;
2681 for (int j = 0; j < nj; j++)
2682 for (int i = 0; i < ni; i++)
2683 x -= vx(i, j, k);
2684 }
2685
2686 // somme sur tous les processeurs.
2687 x = Process::mp_sum(x);
2688 // Il faut diviser par n_mailles_plan_xy
2689 x /= n_mailles_plan_xy;
2690 return x;
2691}
2692#endif
2693
2694
2695void Navier_Stokes_FTD_IJK::calculer_terme_source_acceleration_z(IJK_Field_double& vz, const double time, const double timestep, const int rk_step)
2696{
2697 /*
2698 * Cette methode calcule la source de qdm a appliquer pour que les bulles soient
2699 * globalement fixes dans la direction de la gravite
2700 * o Si le parametre source_qdm_gr vaut 1, la correction a appliquer est :
2701 * vx = vx - moy^{xyz} (rho vx) - moy^{xyz} (rho vx_terminale) / moy^{xyz} (rho)
2702 * o Si le parametre source_qdm_gr vaut 0, la source est determinee par :
2703 * temre_force_init --> temre_source_acceleration et par
2704 * expression_derivee_force --> expression_derivee_acceleration
2705 * REMARQUE II : On peut envisager de faire une correction qui n'a pas besoin qu'on lui donne vx_terminale en
2706 * entree. C'est ce qui a ete explore, mais qui n'a pas aboutit.
2707 * */
2708 double new_time = time;
2709
2710 // S'il n'y a pas de derivee, la source est constante donc on peut sortir:
2712 return;
2713
2714 statistics().begin_count(STD_COUNTERS::source_terms,statistics().get_last_opened_counter_level()+1);
2715
2716 double v_moy = calculer_v_moyen(vz);
2717 update_rho_v();
2718
2719 // GAB, rotation : pas sur de mon coup la
2720 // double rhov_moy = calculer_v_moyen(rho_v_[DIRECTION_I]);
2721 double rhov_moy = calculer_v_moyen(rho_v_[2]);
2722
2723 double moy_rappel = 0.;
2724 // GAB, rotation
2725 const Domaine_IJK& geom = velocity_[2].get_domaine();
2726 double vol_dom = geom.get_domain_length(DIRECTION_I) * geom.get_domain_length(DIRECTION_J) * geom.get_domain_length(DIRECTION_K);
2727 if (coef_immobilisation_ > 1e-16)
2728 {
2729 // GAB, rotation, pas sur de mon coup
2730 // moy_rappel=calculer_v_moyen(force_rappel_[DIRECTION_I])*vol_dom;
2731 moy_rappel = calculer_v_moyen(force_rappel_[2]) * vol_dom;
2732 }
2733
2734 const double rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour(), mu_l = milieu_ijk().get_mu_liquid();
2735 double tauw = calculer_tau_wall(vz, mu_l);
2736 double derivee_acceleration = 0.;
2737 double derivee_facteur_sv = 0.;
2738
2739 double alv = 0.;
2740 if (probleme_ijk().has_interface())
2741 {
2742 if (vol_bulle_monodisperse_ >= 0.)
2743 alv = interfaces_->get_nb_bulles_reelles() * vol_bulle_monodisperse_ / vol_dom;
2744 else
2745 alv = 1. - calculer_v_moyen(interfaces_->I());
2746 }
2748 {
2749 //
2750 double drho = rho_l - rho_v;
2751 double facv = 0., facl = 1.;
2752 if (std::fabs(alv * drho) > DMINFLOAT)
2753 {
2754 facv = 1. / (alv * drho);
2755 facl = 1. / ((1. - alv) * drho);
2756 }
2757 double ul = facl * (rhov_moy - rho_v * v_moy);
2758 double uv = facv * (rho_l * v_moy - rhov_moy);
2759
2760 // Mise a jour de l'acceleration
2761 parser_derivee_acceleration_.setVar("rappel_moyen", moy_rappel);
2763 parser_derivee_acceleration_.setVar("v_moyen", v_moy);
2764 parser_derivee_acceleration_.setVar("ur", uv - ul);
2765 parser_derivee_acceleration_.setVar("ul", ul);
2766 parser_derivee_acceleration_.setVar("uv", uv);
2767 parser_derivee_acceleration_.setVar("T", time);
2768 parser_derivee_acceleration_.setVar("rhov_moyen", rhov_moy);
2769 parser_derivee_acceleration_.setVar("tauw", tauw);
2770 // Pour utiliser rho_v il faudrait deplacer cette mise a jour a un endroit ou rho
2771 // est a jour en fonction de l'indicatrice
2772 // parser_derivee_acceleration_.setVar("rho_v_moyen", rho_v_moy);
2773 derivee_acceleration = parser_derivee_acceleration_.eval();
2774
2775 // Mise a jour de la source variable
2777 {
2778 parser_derivee_facteur_variable_source_.setVar("rappel_moyen", moy_rappel);
2780 parser_derivee_facteur_variable_source_.setVar("v_moyen", v_moy);
2782 parser_derivee_facteur_variable_source_.setVar("rhov_moyen", rhov_moy);
2783 parser_derivee_facteur_variable_source_.setVar("tauw", tauw);
2784 derivee_facteur_sv = parser_derivee_facteur_variable_source_.eval();
2785 } //
2786
2787 if (qdm_corrections_.is_type_gb())
2788 {
2789 // calcul de terme_source_acceleration_ et de terme_source_acceleration_
2790
2791 // ON NE VEUT PAS METTRE A JOUR TERME_SOURCE_ACCELERATION_ AVEC CETTE METHODE
2793 {
2794 terme_source_acceleration_z_ += derivee_acceleration * timestep;
2795 //terme_source_acceleration_ += 0;//derivee_acceleration * timestep;
2796 facteur_variable_source_ += derivee_facteur_sv * timestep;
2797 //facteur_variable_source_ += 0;//derivee_facteur_sv * timestep;
2798 new_time += timestep;
2799 }
2800 else if (sub_type(Schema_RK3_IJK, schema_temps_ijk()))
2801 {
2802 const double intermediate_dt = compute_fractionnal_timestep_rk3(timestep, rk_step);
2804 runge_kutta3_update_for_float(derivee_acceleration, rk3.get_store_RK3_source_acc(), terme_source_acceleration_z_, rk_step, timestep);
2805 Cout << "terme_source_acceleration_z" << terme_source_acceleration_z_ << finl;
2806 //terme_source_acceleration_ += 0;
2807 runge_kutta3_update_for_float(derivee_facteur_sv, rk3.get_store_RK3_fac_sv(), facteur_variable_source_, rk_step, timestep);
2808 Cout << "facteur_variable_source_z" << facteur_variable_source_ << finl;
2809 //facteur_variable_source_ += 0;
2810 new_time += intermediate_dt;
2811 }
2812 }
2813 else if (sub_type(Schema_RK3_IJK, schema_temps_ijk()))
2814 {
2815 const double intermediate_dt = compute_fractionnal_timestep_rk3(timestep/*total */, rk_step);
2817 runge_kutta3_update_for_float(derivee_acceleration, rk3.get_store_RK3_source_acc(), terme_source_acceleration_z_, rk_step, timestep/*total */);
2818
2819 runge_kutta3_update_for_float(derivee_facteur_sv, rk3.get_store_RK3_fac_sv(), facteur_variable_source_, rk_step, timestep/*total */);
2820 new_time += intermediate_dt;
2821 }
2822 }
2823 envoyer_broadcast(terme_source_acceleration_z_, 0);
2824
2825 // -----------------------------------------------------------
2826 // Force interface (:"force sigma") seloon x,y,z et u.Force_interface
2827 const Probleme_FTD_IJK_base& pb_ijk = probleme_ijk();
2828 double fs0(0), fs1(0), fs2(0), psn(0);
2830 {
2831 // FORCE INTERFACIALE : on veut un terme homogene a [rho.g]=[N.m^{-3}]
2832 // terme_source_interfaces_ns_ est homogene a [du/dt]=[m.s^{-2}]
2833 // -> in calculer_dv : "~ velocity_ += force_interf * dt ~"
2834 // --> force_interf a bien eu un mass_solver_with_rho plus haut
2835 fs0 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[0], 0));
2836 fs1 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[1], 1));
2837 fs2 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, terme_source_interfaces_ns_[2], 2));
2838 psn = calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, terme_source_interfaces_ns_)));
2839 }
2840 // energie cinetique (monophasique) et diphasique
2841 double uu(calculer_v_moyen(scalar_product(pb_ijk, velocity_, velocity_)));
2842 double uru(calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, velocity_))));
2843 // Force exterieur (:"force thi") selon x,y,z et acceleration_thi.acceleration_thi, force_thi.foce_thi, u.Force_THI
2844 double ft0(0), ft1(0), ft2(0), atat(0), ftft(0), ptn(0);
2845 if (forcage_.get_type_forcage() > 0)
2846 {
2847 // FORCE IMPOSEE : on veut un terme homogene a [rho.g]=[N.m^{-3}]
2848 // forcage_.get_force_ph2() est homogene a [du/dt]=[m.s^{-2}]
2849 // -> in compute_add_THI_force_sur_d_velocity : "~ d_velocity += forcage_.get_force_ph2() ~"
2850 ft0 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[0], 0));
2851 ft1 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[1], 1));
2852 ft2 = calculer_v_moyen(scalar_fields_product(pb_ijk, rho_field_, forcage_.get_force_ph2()[2], 2));
2853 atat = calculer_v_moyen(scalar_product(pb_ijk, forcage_.get_force_ph2(), forcage_.get_force_ph2()));
2854 ftft = calculer_v_moyen(scalar_product(pb_ijk, scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2()), scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2())));
2855 ptn = calculer_v_moyen(scalar_product(pb_ijk, velocity_, scalar_times_vector(pb_ijk, rho_field_, forcage_.get_force_ph2())));
2856 }
2857 // -----------------------------------------------------------
2858
2859 // Impression dans le fichier _acceleration.out
2861 {
2862 // GR : 07.01.22 : ce serai pas mal de mettre une condition if (tstep % dt_post_stats_acc_ == dt_post_stats_acc_ - 1 || stop)
2863 // pour alleger le dossier OUT. Voir avec GB et AB.
2864 // double ff=0.;
2865 int reset = (!pb_ijk.get_reprise()) && (schema_temps_ijk().get_tstep() == 0);
2866 SFichier fic =
2867 Ouvrir_fichier("_acceleration.out",
2868 "1.tstep\t2.time\t3.Vx\t4.rhoVx\t5.tauw\t6.da/dt\t7.NewT\t8.acceleration\t9.fac_var_source\t10.qdm_source\t11.vap_velocity_tmoy_\t12.liq_velocity_tmoy_\t13.qdm_patch_correction_[0]\t14.qdm_patch_correction_[1]\t15.qdm_patch_correction_[2]\t16.F_sigma_moyen[0]\t17.F_sigma_moyen[1]\t18.F_sigma_moyen[2]\t19.y.F_sigma\t20.u.u\t21.F_THI[0]\t22.F_THI[1]\t23.F_THI[2]\t24.A_THI.A_THI\t25.F_THI.F_THI\t26.u.F_THI\t27.u.rho.u",
2869 reset);
2870 // la derivee_acceleration n'est connue que sur le maitre
2871 fic << schema_temps_ijk().get_tstep() << " " << time << " " << v_moy << " " << rhov_moy << " " << tauw;
2872 fic << " " << derivee_acceleration << " " << new_time << " " << terme_source_acceleration_z_;
2873 fic << " " << facteur_variable_source_;
2874 fic << " " << 0.; //qdm_source_;
2875 fic << " " << vap_velocity_tmoy_;
2876 fic << " " << liq_velocity_tmoy_;
2877
2878 if (coef_immobilisation_ > 1e-16)
2879 fic << " " << moy_rappel;
2880
2881 for (int dir = 0; dir < 3; dir++)
2882 fic << " " << 0.; //qdm_patch_correction_[dir];
2883
2884 // Force interfaciale et puissance du travail des forces interfaciales
2885 // rho*terme_source_interfaces_ns_
2886 fic << " " << fs0; // F_sigma_moyen[0]
2887 fic << " " << fs1; // F_sigma_moyen[1]
2888 fic << " " << fs2; // F_sigma_moyen[2]
2889 // u.rho*terme_source_interfaces_ns_
2890 fic << " " << psn; // velocity.F_sigma
2891
2892 // Energie cinetique (double)
2893 // u.u (qui est aussi accessible par les .txt)
2894 fic << " " << uu;
2895
2896 // Force imposee et puissance du traveil de la force imposee
2897 // rho*F_THI
2898 fic << " " << ft0; // F_THI[0]
2899 fic << " " << ft1; // F_THI[1]
2900 fic << " " << ft2; // F_THI[2]
2901 fic << " " << atat; // A_THI.A_THI
2902 fic << " " << ftft; // F_THI.F_THI
2903 // u.rho*F_THI
2904 fic << " " << ptn; // velocity.F_THI
2905 // Energie cinetique en diphasiqeu (double)
2906 // u.rho.u (qui est aussi accessible par les .txt)
2907 fic << " " << uru;
2908
2909 fic << finl;
2910 fic.close();
2911 }
2912 statistics().end_count(STD_COUNTERS::source_terms);
2913}
2914
2915// force_tot est homogene a une force volumique (comparable a la source S), comme tout ce qu'on evalue ici.
2916// Attention, cette methode ne fait pas que des evaluations, elle calcule aussi terme_source_correction_x_ ou _y_
2918{
2919 // Toutes les interfaces etant fermees, on a donc la somme des forces
2920 // donnee par la poussee d'archimede : delta_rho * g * alpha
2921 const Probleme_FTD_IJK_base& pb_ijk = probleme_ijk();
2922 double vol_cell = 1., vol_NS = 1., vol_gaz = 0.;
2923 const Domaine_IJK& geom_NS = pb_ijk.get_domaine();
2924 for (int direction = 0; direction < 3; direction++)
2925 {
2926 vol_NS *= geom_NS.get_domain_length(direction);
2927 vol_cell *= geom_NS.get_constant_delta(direction);
2928 }
2929
2930 ArrOfDouble volume;
2931 DoubleTab position;
2932 const int nbulles = interfaces_->get_nb_bulles_reelles();
2933 // La methode calcule a present les volumes meme pour les bulles ghost.
2934 // Pour les enlever, il suffit simplement de reduire la taille du tableau :
2935 interfaces_->calculer_volume_bulles(volume, position);
2936 volume.resize_array(nbulles);
2937 position.resize(nbulles, 3);
2938 for (int ib = 0; ib < nbulles; ib++)
2939 vol_gaz += volume[ib];
2940
2941 update_rho_v();
2942 Vecteur3 force_tot, force_theo, rhov_moy, tauw;
2943 Vecteur3 acc, residu; // homogenes a d(rhou)/dt
2944#ifdef COMPLEMENT_ANTI_DEVIATION_RESIDU
2945 double moins_delta_Pwall_sur_h = 0.;
2946#endif
2947 tauw = 0.;
2948 // Flottaison opposee a la gravite :
2949 const double rho_l = milieu_ijk().get_rho_liquid(), rho_v = milieu_ijk().get_rho_vapour(), mu_l = milieu_ijk().get_mu_liquid();
2950
2951 const double drho_alpha = -(rho_l - rho_v) * vol_gaz / vol_NS;
2952 const double un_sur_h = 2. / geom_NS.get_domain_length(DIRECTION_K);
2953 double fractional_dt;
2954 const double timestep = schema_temps_ijk().get_timestep();
2955
2956 if (sub_type(Schema_RK3_IJK, schema_temps_ijk()))
2957 fractional_dt = compute_fractionnal_timestep_rk3(timestep /* total*/, rk_step);
2958 else
2959 // On suppose que c'est euler :
2960 fractional_dt = timestep;
2961
2962 // Convertir en des contributions volumiques (homogene au terme source) :
2963 for (int direction = 0; direction < 3; direction++)
2964 {
2965 if (direction != DIRECTION_K)
2966 {
2967 // Calcul du frottement moyen sur un mur (selon X ou Y)
2968 tauw[direction] = calculer_tau_wall(velocity_[direction], mu_l);
2969#ifdef COMPLEMENT_ANTI_DEVIATION_RESIDU
2970 }
2971 else
2972 {
2973 // On n'est pas certain qu'il (le gradient normal de Uz moyenne sur un mur)
2974 // soit nul en instantane. Pour verifier, on le calcule:
2975 tauw[direction] = calculer_tau_wall(velocity_[direction], mu_l);
2976 // La fonction calculer_tau_wall suppose que le champ de vitesse est a dz/2 du mur.
2977 // Pour la vitesse uz, il est en fait situe a dz. Donc il faut le doubler:
2978 tauw[direction] *= 2.;
2979 // Il y a aussi potentiellement une partie due a la pression en instantanne:
2980 // (dans la direction normale aux parois seulement)
2981 // +/-? (-Pw^+ + Pw^- ) / h :
2982 moins_delta_Pwall_sur_h = -calculer_wall_difference(pressure_) * un_sur_h;
2983#endif
2984 }
2985 force_tot[direction] = calculer_v_moyen(terme_source_interfaces_ns_[direction]) / vol_cell;
2986 if (interfaces_->is_terme_gravite_rhog())
2987 force_theo[direction] = 0.;
2988 else
2989 force_theo[direction] = drho_alpha * milieu_ijk().gravite().valeurs()(0, direction);
2990
2991 rhov_moy[direction] = calculer_v_moyen(rho_v_[direction]);
2992 acc[direction] = (rhov_moy[direction] - store_rhov_moy_[direction]) / fractional_dt;
2993 store_rhov_moy_[direction] = rhov_moy[direction];
2994 // Une partie de la force en x ou en z et la force en y sont des erreurs de discretisation,
2995 // que l'on peut corriger globalement :
2996 terme_source_correction_[direction] = force_theo[direction] - force_tot[direction];
2997 // Le frottement moyen doit etre divise par h pour etre rendu "volumique"
2998 // Il est oriente vers z- donc signe "-"
2999 tauw[direction] *= -un_sur_h;
3000 }
3001
3002 const int tstep = schema_temps_ijk().get_tstep();
3003
3004 if (tstep == 0)
3005 {
3006 // L'acceleration n'est pas valide car store_rhov_moy_^0 = rhov_moy^0 .. donc on ferait (0-0)/0...
3007 // Donc le residu est invalide.
3008 // Donc on ne l'ajoute pas a l'integrated_residu_, qui vaut 0 a ce moment la...
3009 residu = 0.;
3010 integrated_residu_ = 0.;
3011 }
3012 else
3013 {
3014 for (int dir = 0; dir < 3; dir++)
3015 {
3016 residu[dir] = acc[dir] - (force_tot[dir] + tauw[dir] + correction_force_[dir] * terme_source_correction_[dir]);
3017
3018 if (dir == 0)
3019 residu[dir] -= terme_source_acceleration_;
3020
3021 if (dir == 1)
3022 residu[dir] -= terme_source_acceleration_z_;
3023
3024 if (interfaces_->is_terme_gravite_rhog())
3025 residu[dir] = -(rho_l - (rho_l - rho_v) * vol_gaz / vol_NS) * milieu_ijk().gravite().valeurs()(0, dir);
3026
3027 integrated_residu_[dir] += residu[dir] * fractional_dt;
3028 }
3029 }
3030
3031 // Impression dans un fichier dedie :
3033 {
3034 int reset = (!pb_ijk.get_reprise()) && (tstep == 0);
3035 SFichier fic = Ouvrir_fichier("_bilan_qdm.out", "tstep\ttime\tFs_theo\tFtot\trhov\ttauw\tS\tacceleration\tres\tcumul_res\tCorrFs\nConvection\tDiffusion\tPression\n# Forces have 3 components.",
3036 reset, 20/*prec*/);
3037
3038 fic << tstep << " " << schema_temps_ijk().get_current_time() << " " << force_theo[0] << " " << force_theo[1] << " " << force_theo[2] << " ";
3039 fic << force_tot[0] << " " << force_tot[1] << " ";
3040 fic << force_tot[2] << " " << rhov_moy[0] << " " << rhov_moy[1] << " " << rhov_moy[2] << " " << tauw[0] << " ";
3041 fic << tauw[1] << " " << tauw[2] << " ";
3042 fic << terme_source_acceleration_ << " " << "0" << " " << terme_source_acceleration_z_ << " ";
3043 fic << acc[0] << " " << acc[1] << " " << acc[2] << " " << residu[0] << " " << residu[1] << " ";
3044 fic << residu[2] << " " << integrated_residu_[0] << " " << integrated_residu_[1] << " " << integrated_residu_[2] << " ";
3045 fic << terme_source_correction_[0] << " " << terme_source_correction_[1] << " " << terme_source_correction_[2] << " ";
3046 // GAB, qdm
3047 // fic << terme_interfaces[0] << " "
3048 // << terme_interfaces[1] << " "
3049 // << terme_interfaces[2] << " ";
3050 fic << terme_convection_[0] << " " << terme_convection_[1] << " " << terme_convection_[2] << " ";
3051 fic << terme_diffusion_[0] << " " << terme_diffusion_[1] << " " << terme_diffusion_[2] << " ";
3052 fic << terme_pression_[0] << " " << terme_pression_[1] << " " << terme_pression_[2] << " ";
3053 //
3054#ifdef COMPLEMENT_ANTI_DEVIATION_RESIDU
3055 fic << moins_delta_Pwall_sur_h << " ";
3056#endif
3057 fic << finl;
3058 fic.close();
3059 }
3060}
3061
3062// Mettre rk_step = -1 si schema temps different de rk3.
3063// /!\ rk_step = 0 signifie qu'on est en RK3, mais n'indique pas a quelle ss pas de temps de RK3 on se place !!!
3064void Navier_Stokes_FTD_IJK::calculer_dv(const double timestep, const double time, const int rk_step)
3065{
3066 // GAB : initialisation. On initialise que pour rk_step<=0, mais on pourrai initialiser a chaque ss pdt
3067 // Avec le post-traitement que je fais de mes termes, je dois les re-initialiser a chaque ss pdt,
3068 // si je ne les re-initialise pas alors je n'aurai pas leur valeur pour chaque avancement (apres je pourrai me passer de ce niveau de detail)
3069 // ==> Ce qui est certain c'est que je ne dois pas re initialiser ICI mes rho_u_... puisqu'ils sont
3070 // evalues EN DEHORS des boucles de RK3.
3071
3073 if (rk_step <= 0)
3074 {
3075 terme_convection_ = 0.;
3078 terme_diffusion_ = 0.;
3079 terme_interfaces_ = 0.;
3081 }
3082 // GAB
3083 // /!\ Valable que pour un domaine uniforme, j'ai vu des choses que je ne comprends pas la ou on defini volume aussi ...
3084 // on est dans variable dz et on ne prends pas en compte k dans le calcul du volume...
3085 double volume_cell_uniforme = 1.;
3086 for (int i = 0; i < 3; i++)
3087 volume_cell_uniforme *= pb_ijk.domaine_ijk().get_constant_delta(i);
3088 if (velocity_reset_)
3089 for (int dir = 0; dir < 3; dir++)
3090 velocity_[dir].data() = 0.; //Velocity reset for test
3091
3092// static Stat_Counter_Id calcul_dv_counter = statistiques().new_counter(2, "maj vitesse : calcul derivee vitesse");
3093// statistiques().begin_count(calcul_dv_counter);
3094 // Calcul d_velocity = convection
3095
3096 const double rho_l = milieu_ijk().get_rho_liquid();
3097
3099 {
3100 if (velocity_convection_op_.get_convection_op_option_rank() == non_conservative_simple)
3101 {
3103 // Multiplication par rho (on va rediviser a la fin)
3104 // (a partir de rho aux elements et dv aux faces)
3106 {
3107 // rho_face = 2*(rho_gauche*rho_droite)/(rho_gauche+rho_droite)
3108 // = 1./ (1/2 * (1/rho_g + 1/rho_d))
3109 // 1/rho_face est donc la moyenne geometrique de inv_rho.
3110 calculer_rho_harmonic_v(rho_field_, d_velocity_, d_velocity_);
3111 }
3112 else
3113 calculer_rho_v(rho_field_, d_velocity_, d_velocity_);
3114 }
3115 else if (velocity_convection_op_.get_convection_op_option_rank() == non_conservative_rhou)
3116 {
3117 update_rho_v();
3118
3119 rho_v_[0].echange_espace_virtuel(2);
3120 rho_v_[1].echange_espace_virtuel(2);
3121 rho_v_[2].echange_espace_virtuel(2);
3122
3123 // Non optimise car la methode calculer_avec_u_div_rhou inexistante.
3124 // Alors on initialise a 0 puis on fait ajouter :
3125 d_velocity_[0].data() = 0.;
3126 d_velocity_[1].data() = 0.;
3127 d_velocity_[2].data() = 0.;
3128 if (velocity_convection_op_.get_convection_op() != Nom("Centre4"))
3129 {
3130 velocity_convection_op_->ajouter_avec_u_div_rhou(rho_v_[0], rho_v_[1], rho_v_[2], // rhov_
3132 }
3133 }
3134 else if (velocity_convection_op_.get_convection_op_option_rank() == conservative)
3135 {
3136 update_rho_v();
3137
3138 rho_v_[0].echange_espace_virtuel(2);
3139 rho_v_[1].echange_espace_virtuel(2);
3140 rho_v_[2].echange_espace_virtuel(2);
3141
3143 }
3144 else
3145 {
3146 Cerr << "Unknown velocity convection type! " << finl;
3147 Process::exit();
3148 }
3149 pb_ijk.get_post().fill_op_conv();
3150 // GAB, qdm
3151
3152 // a priori homogene a int_{volume_cellule} (d rho v / dt) pour le moment
3153 // on divise le terme_convection par volume_cellule
3154 // Il ne faudrai pas un mass solveur sur mon terme de convection... avant de le moyenner meme ?
3155
3156 for (int dir = 0; dir < 3; dir++)
3157 {
3158 // if (rk_step==-1 || rk_step==0) // euler ou premier pdt de rk3
3159 // Pourquoi diviser par volume_cell_uniforme ?
3160 terme_convection_[dir] = calculer_v_moyen(d_velocity_[dir]) / volume_cell_uniforme;
3161
3163 {
3166 {
3167 for (int k = 0; k < d_velocity_[dir].nk(); k++)
3168 mass_solver_with_rho(terme_convection_mass_solver_[dir], rho_field_, pb_ijk.get_delta_z_local(), k);
3169 }
3170 else
3171 {
3172 for (int k = 0; k < d_velocity_[dir].nk(); k++)
3173 for (int j = 0; j < d_velocity_[dir].nj(); j++)
3174 for (int i = 0; i < d_velocity_[dir].ni(); i++)
3175 terme_convection_mass_solver_[dir](i, j, k) = terme_convection_mass_solver_[dir](i, j, k) / (rho_l * volume_cell_uniforme);
3176 }
3177
3179 }
3180 }
3181 }
3182 else
3183 {
3184 d_velocity_[0].data() = 0.;
3185 d_velocity_[1].data() = 0.;
3186 d_velocity_[2].data() = 0.;
3187 }
3188
3189 // Calcul diffusion
3191 {
3194 // GAB, qdm
3195 // a priori homogene a int_{volume_cellule} (d rho v / dt) pour le moment
3196 // mais on le divise par volume_cell_uniforme donc homogene a d rho v / dt maintenant
3197 // en diffusion "normale", on ajoute la diffusion plus tard
3198 for (int dir = 0; dir < 3; dir++)
3199 {
3200 // if (rk_step==-1 || rk_step==0) // revient a rk_step>0 // euler ou premier pdt de rk3
3201 terme_diffusion_[dir] = calculer_v_moyen(d_velocity_[dir]) / volume_cell_uniforme - terme_convection_[dir];
3203 {
3205 // terme_diffusion_mass_solver_ contient la diffusion et la convection
3207 {
3208 for (int k = 0; k < terme_diffusion_mass_solver_[dir].nk(); k++)
3209 {
3210 mass_solver_with_rho(terme_diffusion_mass_solver_[dir], rho_field_, pb_ijk.get_delta_z_local(), k);
3211
3212 // On retranche la convection
3213 for (int j = 0; j < terme_diffusion_mass_solver_[dir].nj(); j++)
3214 for (int i = 0; i < terme_diffusion_mass_solver_[dir].ni(); i++)
3216 }
3217 }
3218 else
3219 {
3220 // Dans le cas monophasique, rho_field_ vaut partout rho_liquide
3221 for (int k = 0; k < terme_diffusion_mass_solver_[dir].nk(); k++)
3222 for (int j = 0; j < terme_diffusion_mass_solver_[dir].nj(); j++)
3223 for (int i = 0; i < terme_diffusion_mass_solver_[dir].ni(); i++)
3224 {
3225 terme_diffusion_mass_solver_[dir](i, j, k) = terme_diffusion_mass_solver_[dir](i, j, k) / (rho_l * volume_cell_uniforme);
3227 }
3228 }
3229 // Moyenne sur le volume du domaine de simulation
3231 }
3232 }
3233 }
3234
3235 // GAB, qdm
3237 for (int i = 0; i < 3; i++)
3239
3240 // Calcul et ajout du grad(P^{n})*volume_cell (_entrelace?) :
3242 {
3243 // pressure gradient requires the "left" value in all directions:
3244 pressure_.echange_espace_virtuel(1 /*, IJK_Field_double::EXCHANGE_GET_AT_LEFT_IJK*/);
3245#ifndef VARIABLE_DZ
3246 double volume = 1.;
3247 for (int i = 0; i < 3; i++)
3248 volume *= pb_ijk.domaine_ijk().get_constant_delta(i);
3249#else
3250 Cerr << "This methods does not support variable DZ yet... Contact trust support. ";
3251 Process::exit();
3252 const double volume = get_channel_control_volume(dv, k, delta_z_local_);
3253#endif
3254 add_gradient_times_constant(pressure_, -volume /*constant*/, d_velocity_[0], d_velocity_[1], d_velocity_[2]);
3255 Cout << "BF add_gradient_times_constant" << finl;
3256 // GAB, qdm
3257 // En utilisation normale de la pression, elle n'est pas ajoutee ici
3259 {
3261 for (int dir_press = 0; dir_press < 3; dir_press++)
3262 terme_pression_in_ustar_[dir_press] = calculer_v_moyen(terme_pression_in_ustar_local_[dir_press]);
3263 Cout << "AF add_gradient_times_constant" << finl;
3264 }
3265 //
3266 }
3267
3268 const double sch_timestep = schema_temps_ijk().get_timestep();
3269 const int sch_tstep = schema_temps_ijk().get_tstep();
3270
3271 // Calcul du terme source aux interfaces pour l'ajouter a dv :
3272 // ATTENZIONE : Questa è una bugia. I termini di interfaccia vengono aggiunti direttamente a velocity_!
3274 {
3275 for (int dir = 0; dir < 3; dir++)
3276 {
3277 terme_source_interfaces_ft_[dir].data() = 0.;
3278 terme_repulsion_interfaces_ft_[dir].data() = 0.;
3279 terme_abs_repulsion_interfaces_ft_[dir].data() = 0.;
3280 }
3282
3283 // Avant le solveur de masse, il faut un terme homogene a \int_vol {rho v }
3285 {
3286 for (int dir = 0; dir < 3; dir++)
3287 {
3288 if ((rk_step == -1) || (refuse_patch_conservation_QdM_RK3_source_interf_))
3289 {
3290 // Avec le schema Euler, ou si on refuse le patch de conservation de la QdM en RK3 diphasique :
3292 }
3293 else
3294 {
3295 // On n'ajoute pas le terme source a d_velocity_...
3296 // On le prendra en compte directement dans velocity_.
3297 }
3298 }
3299
3300 for (int dir = 0; dir < 3; dir++)
3301 {
3303 // GAB, qdm : les forces d'interface sont directement ajoutees a velocity... aucun effet sur d_velocity normalement
3304 // Donc terme_interfaces_bf_mass_solver_bis est nul. C'EST A VERIFIER !!
3306 {
3308 terme_interfaces_bf_mass_solver_bis_[dir] = calculer_v_moyen(d_velocity_[dir]) / volume_cell_uniforme - terme_convection_[dir] - terme_diffusion_[dir];
3309 }
3310 }
3312 // Computing force_tot (Attention, il faut le faire avant d'appliquer le solver mass a terme_source_interfaces_ns_) :
3314 for (int dir = 0; dir < 3; dir++)
3315 {
3316 // On est en RK3 et on utilise le patch de conservation de la QdM (comportement par defaut du RK3)
3317 // Utilisation directe du terme source interf pour l'ajouter a velocity_.
3318 // On ne le met plus dans d_velocity_ car ce n'est pas conservatif globalement... (test quand sigm et drho)
3319 if (pb_ijk.get_post().get_liste_post_instantanes().contient_("REPULSION_FT") || pb_ijk.get_post().get_liste_post_instantanes().contient_("CELL_REPULSION_FT"))
3320 {
3322 }
3323 const int kmax = terme_source_interfaces_ns_[dir].nk();
3324 for (int k = 0; k < kmax; k++)
3325 {
3326 // division par le produit (volume * rho_face)
3328 {
3329 Cerr << "Je ne sais pas si inv_rho_field_ est a jour ici. A Verifier avant de l'activer." << finl;
3330 //calculer_rho_harmonic_v(rho_field_, d_velocity_, d_velocity_);
3331 mass_solver_with_inv_rho(terme_source_interfaces_ns_[dir], inv_rho_field_, pb_ijk.get_delta_z_local(), k);
3332 }
3333 else
3334 {
3335 // Division de terme_source_interfaces_ns_ par rho_field et par volume cellule
3336 //cout << " code Delta : "<<terme_repulsion_interfaces_ns_[0](6,9,10);
3337 //cout << " code Delta : "<<backup_terme_source_interfaces_ns_[0](6,9,10);
3338 //cout << " code Delta : "<<post_.get_rho_Ssigma()[2](6,11,11);
3339 //cout << endl;
3340 mass_solver_with_rho(terme_source_interfaces_ns_[dir], rho_field_, pb_ijk.get_delta_z_local(), k);
3341 //cout << " code Nabla : "<<terme_repulsion_interfaces_ns_[0](6,9,10);
3342 //cout << " code Nabla : "<<backup_terme_source_interfaces_ns_[0](6,9,10);
3343 //cout << " code Nabla : "<<post_.get_rho_Ssigma()[2](6,11,11);
3344 //cout << endl;
3345 //if (k==10)
3346 // {
3347 // cout << "code 2211 " << rho_field_(5,9,10) << " & " << rho_field_(6,9,10) << " & " << rho_field_(7,9,10)<<endl;
3348 // cout << "code Z,611 " << post_.get_rho_Ssigma()[2](6,11,11);
3349 // cout << ", code Z,611 " << backup_terme_source_interfaces_ns_[2](6,11,11);
3350 // cout << ", code Z,611 " << terme_source_interfaces_ns_[2](6,11,11)<<endl;
3351 // cout << "code X,6910 " << post_.get_rho_Ssigma()[0](6,9,10);
3352 // cout << ", code X,6910 " << backup_terme_source_interfaces_ns_[0](6,9,10);
3353 // cout << ", code X,6910 " << terme_source_interfaces_ns_[0](6,9,10)<<endl;
3354 // }
3355 if (pb_ijk.get_post().get_liste_post_instantanes().contient_("REPULSION_FT") || pb_ijk.get_post().get_liste_post_instantanes().contient_("CELL_REPULSION_FT"))
3356 {
3357 // Division de terme_repulsion_interfaces_ns_ par rho_field_ et par volume cellule
3358 mass_solver_with_rho(terme_repulsion_interfaces_ns_[dir], rho_field_, pb_ijk.get_delta_z_local(), k);
3359 //terme_repulsion_interfaces_ns_[0](6,9,10)=50;
3360 }
3361 // Egalite aux dimensions :
3362 // [terme_source_interfaces_ns_]=[terme_repulsion_interfaces_ns_]=[du/dt / Vcell] = m/s^2/m^3
3363 }
3364 if ((!refuse_patch_conservation_QdM_RK3_source_interf_) && (rk_step >= 0))
3365 {
3366 // puis
3367 // comme euler_explicit_update mais avec un pas de temps partiel :
3368 const double delta_t = compute_fractionnal_timestep_rk3(sch_timestep /* total*/, rk_step);
3369 const int imax = terme_source_interfaces_ns_[dir].ni();
3370 const int jmax = terme_source_interfaces_ns_[dir].nj();
3371 for (int j = 0; j < jmax; j++)
3372 for (int i = 0; i < imax; i++)
3373 {
3374 double x = terme_source_interfaces_ns_[dir](i, j, k);
3375 velocity_[dir](i, j, k) += x * delta_t;
3376 }
3377 }
3378 // On est dans une boucle sur les directions la, c ok
3379 // GAB, qdm ATTENTION on ne va ici que si on est en rk3
3382 }
3383 }
3384 }
3385 }
3386
3387 // On laisse l'ecriture de ce fichier de sortie A L'INTERIEUR de calculer_dv car on souhaite relever
3388 // la valeur des differents termes A CHAQUE sous-pas de temps du schema RK3. On peut en revanche,
3389
3391
3392 // Correcteur PID
3393
3394 ArrOfDouble acc_mrf;
3395 acc_mrf.resize_array(3);
3396 acc_mrf = 0.;
3397
3398 if (Kp_ != 0. || Kd_ != 0.)
3399 {
3400 double ax_PID;
3401 double ay_PID;
3402 double az_PID;
3403
3404 calculer_terme_asservissement(ax_PID, ay_PID, az_PID);
3405
3406 acc_mrf[0] = ax_PID;
3407 acc_mrf[1] = ay_PID;
3408 acc_mrf[2] = az_PID;
3409 }
3410
3411 for (int dir = 0; dir < 3; dir++)
3412 {
3413 // GAB question : pour quoi on cree dv, qu'est ce qui empeche de travailler sur d_velocity ???
3414 // -> Est ce que c'est uniquement parce qu'on va faire un certain nb d'operations dessus
3415 // et que manipuler dv est plus leger que de manipuler d_velocity ?
3416 IJK_Field_double& dv = d_velocity_[dir];
3417 const int kmax = d_velocity_[dir].nk();
3418 const int ni = dv.ni();
3419 const int nj = dv.nj();
3420 // terme source acceleration homogene a une force volumique (gradient de pression uniforme)
3421 // Si la correction est activee, on oppose la force_moy
3422 double force_volumique = correction_force_[dir] * terme_source_correction_[dir];
3423 // if (dir == DIRECTION_I)
3424 // {
3425 // force_volumique += terme_source_acceleration_;
3426 // }
3427 // GAB, rotation
3428 if (dir == 0)
3429 force_volumique += terme_source_acceleration_;
3430
3431 if (dir == 2)
3432 force_volumique += terme_source_acceleration_z_;
3433
3434#ifndef VARIABLE_DZ
3435 double volume = 1.;
3436 for (int i = 0; i < 3; i++)
3437 volume *= pb_ijk.domaine_ijk().get_constant_delta(i);
3438
3439 // GAB, qdm
3440 // dans d_velocity_moyen on a la contrib de interfaces, forces ajoutees
3441 terme_interfaces_conv_diff_mass_solver_[dir] = calculer_v_moyen(d_velocity_[dir]);
3442
3443 Cerr << "disable_diffusion_qdm_ : " << int(disable_diffusion_qdm_) << finl;
3444 Cerr << "diffusion_alternative_ : " << int(diffusion_alternative_) << finl;
3445 Cerr << "type_velocity_diffusion_form : " << velocity_diffusion_op_.get_diffusion_op_option() << finl;
3446 for (int k = 0; k < kmax; k++)
3447 {
3448 // #else
3449 // for (int k = 0; k < kmax; k++)
3450 // {
3451 // const double volume = get_channel_control_volume(dv, k, delta_z_local_);
3452 // }
3453 const double f = force_volumique * volume;
3454 if ((expression_variable_source_[0] != "??") || (expression_variable_source_[1] != "??") || (expression_variable_source_[2] != "??") || (expression_potential_phi_ != "??"))
3455 {
3456 for (int j = 0; j < nj; j++)
3457 for (int i = 0; i < ni; i++)
3458 dv(i, j, k) += facteur_variable_source_ * variable_source_[dir](i, j, k) * volume + f;
3459 }
3460 else
3461 {
3462 for (int j = 0; j < nj; j++)
3463 for (int i = 0; i < ni; i++)
3464 dv(i, j, k) += f;
3465 }
3466
3468 mass_solver_with_inv_rho(d_velocity_[dir], inv_rho_field_, pb_ijk.get_delta_z_local(), k);
3469 else
3470 mass_solver_with_rho(d_velocity_[dir], rho_field_, pb_ijk.get_delta_z_local(), k);
3471
3472 if (Kp_ != 0. || Kd_ != 0.)
3473 {
3474 for (int j = 0; j < nj; j++)
3475 for (int i = 0; i < ni; i++)
3476 dv(i, j, k) += acc_mrf[dir];
3477 }
3478
3479 // Terme source gravitaire en version simple "rho_g":
3480 // GAB : question a Guillaume : l 3235 -> "IJK_Field_double& dv = d_velocity_[dir];" , MAIS C'EST APRES
3481 // LA LIGNE 2865 ou d_velocity subi un calculer_rho_v.
3482 // donc dv est homogene a rho*v et donc a rho*g. Or 8 lignes plus bas on a dv(i,j,k) += g; !!!
3483 // il faut appliquer un mass_solver_with_rho a dv pour que l'operation soit homogene d'apres gr...
3484 // a moins que le mass_solver soit applique dans une des methodes...
3485 // mass_solver_with... est applique sur d_velocity_ juste au dessus de ce long commentaire. Donc d_velocity
3486 // est bien homogene a g, et ainsi (jespere) dv est bien homogene a g.
3487 if (pb_ijk.has_interface() && interfaces_->is_terme_gravite_rhog())
3488 {
3489 const double g = milieu_ijk().gravite().valeurs()(0, dir);
3490 for (int j = 0; j < nj; j++)
3491 for (int i = 0; i < ni; i++)
3492 dv(i, j, k) += g; // c'est rho*g qu'il faut pour GR, 18.08.2021
3493 }
3494
3496 {
3499 for (int dir2 = 0; dir2 < 3; dir2++)
3500 {
3501 const int kmax2 = d_velocity_[dir2].nk();
3502 const int imax = d_velocity_[dir2].ni();
3503 const int jmax = d_velocity_[dir2].nj();
3504 for (int k2 = 0; k2 < kmax2; k2++)
3505 for (int j = 0; j < jmax; j++)
3506 for (int i = 0; i < imax; i++)
3507 {
3508 // double laplacien_u = laplacien_velocity_[dir2](i,j,k2);
3509 // GAB, c'est assez dangereux de nommer nu une viscosite dynamique...
3510 // const double nu = molecular_mu_(i,j,k2) ; // On stocke nu dans mu dans ce cas.
3511 // GAB, qdm
3513 {
3514 terme_diffusion_local_[dir2](i, j, k2) = molecular_mu_(i, j, k2) * laplacien_velocity_[dir2](i, j, k2);
3515 // Cerr << "terme diffusion local" << terme_diffusion_local[dir2](i,j,k2) << finl;
3516 d_velocity_[dir2](i, j, k2) += terme_diffusion_local_[dir2](i, j, k2);
3517 // d_velocity_[dir2](i,j,k2) += nu * laplacien_u;
3518 }
3519 }
3520 // GAB, qdm
3521 d_velocity_[dir2].echange_espace_virtuel(d_velocity_[dir2].ghost());
3522 //
3523 }
3524 }
3525
3526 }
3527 // GAB, TODO bilan qdm
3528 // d_velocity_moyen_ap_mass_solver[dir] = calculer_v_moyen(d_velocity_[dir]);
3529 // dans d_velocity_conv_et_diff_moy on a que la contrib de convection et de diffusion
3530 // d_velocity_conv_et_diff_moy[dir] = calculer_v_moyen(d_velocity_conv_et_diff[dir])
3531
3532#endif
3533 // For the addition of the external forces to d_velocity_
3535 } // end of loop [dir].
3536 ///////////////////////////////////////////////////////
3537 // GAB, THI
3538 // MODIF GAB.. /!\ tstep : le numero d'iteration; timestep : le pas de temps, le dt
3539 // est-on au moment ou velocity_ contient la vitesse ou est-on au moment ou velocity_ contient la qdm ?
3540 if (forcage_.get_type_forcage() > 0) // && (rk_step==-1 || rk_step==0))
3541 {
3542 if (rk_step == -1)
3543 compute_add_THI_force_sur_d_velocity(velocity_, sch_tstep, sch_timestep, time, d_velocity_.get_domaine(), forcage_.get_facteur_forcage()); //, rk_step);
3544 else
3545 {
3546 const double intermediate_dt = compute_fractionnal_timestep_rk3(sch_timestep, rk_step);
3547 compute_add_THI_force_sur_d_velocity(velocity_, sch_tstep, intermediate_dt, time, d_velocity_.get_domaine(), forcage_.get_facteur_forcage()); //, rk_step);
3548 }
3549 }
3550 // verifier si mon terme de thi est bon en integrale
3551 ///////////////////////////////////////////////////////
3552 Cout << "G bilan qdm " << finl;
3555
3556 // Il est important de s'assurer a la fin que la derivee de la vitesse soit a zero sur les parois:
3557 if (!pb_ijk.domaine_ijk().get_periodic_flag(DIRECTION_K))
3558 force_zero_on_walls(d_velocity_[2]);
3559
3560// statistiques().end_count(calcul_dv_counter);
3561}
3562
3564{
3565 if (coef_immobilisation_ > 1e-16)
3566 {
3567 // maxValue n'avait pas le mp_max
3568 double integration_time = max_ijk(probleme_ijk().get_post().integrated_timescale());
3569 integration_time=std::max(1.,integration_time); // if integrated_timescale is missing, the value of integration will be -1.e30;
3570 // The trick is to set it to 1, as it is in fact numbers ot timesteps stored (see dirty code)
3571 interfaces_->compute_external_forces_(force_rappel_ft_, force_rappel_, velocity_,interfaces_->I(),interfaces_->I_ft(),
3572 coef_immobilisation_, schema_temps_ijk().get_tstep(), schema_temps_ijk().get_current_time(),
3574 integration_time, coef_mean_force_, coef_force_time_n_);
3575
3576 if (interfaces_->get_forcing_method())
3577 {
3578 // Si Parser
3579 const int kmax = d_velocity_[dir].nk();
3580 const int ni = d_velocity_[dir].ni();
3581 const int nj = d_velocity_[dir].nj();
3582 for (int k = 0; k < kmax; k++)
3583 for (int j = 0; j < nj; j++)
3584 for (int i = 0; i < ni; i++)
3585 d_velocity_[dir](i,j,k) += force_rappel_[dir](i,j,k);
3586 }
3587 else
3588 {
3589 // Si la force de rappel est calculee sans le parser (par la color function), elle est evaluee sur le FT.
3590 redistribute_from_splitting_ft_faces_[dir].redistribute_add(
3591 force_rappel_ft_[dir], d_velocity_[dir]);
3592 // Je pense qu'il faut la redistribuer pour le calcul de la force de rappel dans le terme expression_derivee_acceleration_
3593 redistribute_from_splitting_ft_faces_[dir].redistribute(
3594 force_rappel_ft_[dir], force_rappel_[dir]);
3595 }
3596 }
3597 return;
3598}
3599
3600
3602{
3603 // Ajout du terme source (force acceleration)
3604 // Solveur masse pour chaque composante du bilan de QdM
3605 const IJK_Field_vector3_double& grad_I_ns = probleme_ijk().get_post().get_grad_I_ns();
3606 for (int dir = 0; dir < 3; dir++)
3607 {
3608 // Si on est en presence d'une source analytique variable spatialement:
3609 if (expression_variable_source_[dir] != "??" && probleme_ijk().has_interface())
3610 set_field_data(variable_source_[dir], expression_variable_source_[dir], interfaces_->I(), grad_I_ns[dir], time);
3611 else if (expression_variable_source_[dir] != "??") // sans interface
3612 set_field_data(variable_source_[dir], expression_variable_source_[dir], grad_I_ns[dir], time);
3613 else if (expression_potential_phi_ != "??")
3614 {
3615 // Pour Remettre a zero la source:
3616 set_field_data(variable_source_[dir], Nom("0."), grad_I_ns[dir], time);
3617 }
3618 }
3619
3620 if (expression_potential_phi_ != "??")
3621 {
3622 set_field_data(potential_phi_, expression_potential_phi_, time);
3623 potential_phi_.echange_espace_virtuel(potential_phi_.ghost());
3624 add_gradient_times_constant(potential_phi_, 1.,variable_source_[0],variable_source_[1],variable_source_[2]);
3625 }
3626}
3627
3629{
3630 // GR : 07.01.22 : mettre une condition if (tstep % dt_post_stats_check_ == dt_post_stats_check_ - 1 || stop)
3631 // serai vraiment une bonne chose pour alleger les _check_....out... voir avec AB et GB.
3633 {
3635 {
3636 int reset_test = (probleme_ijk().get_reprise()) && ( schema_temps_ijk().get_tstep() == 0 );
3637
3638 // GAB, qdm RK3 : accurate_current_time_ = t0(1+ 1/4); t0(1+ 1/4 + 5/12); t0(1+ 1/4 + 5/12 + 1/3)
3639
3640 double accurate_current_time = 0.0;
3642 accurate_current_time = schema_temps_ijk().get_current_time();
3643 else if ( sub_type(Schema_Euler_explicite_IJK, schema_temps_ijk()) )
3644 accurate_current_time = ref_cast(Schema_RK3_IJK, schema_temps_ijk()).get_current_time_at_rk3_step();
3645
3646 SFichier fic_test=Ouvrir_fichier("_check_etapes_et_termes.out",
3647 "tstep\tcurrent_time\trk_step"
3648 "\trho_u_euler_av_prediction\trho_du_euler_ap_prediction"
3649 "\trho_u_euler_ap_projection\trho_du_euler_ap_projection"
3650 "\trho_u_euler_av_rho_mu_ind\trho_u_euler_ap_rho_mu_ind"
3651 "\tu_euler_ap_rho_mu_ind"
3652 "\ttemre_interfaces\tterme_convection\tterme_diffusion"
3653 "\tterme_pression_bis\tterme_pression_ter"
3654 "\tterme_interfaces_bf_mass_solver_bis\tterme_interfaces_bf_mass_solver\tterme_interfaces_bf_mass_solver"
3655 "\tpression_ap_proj"
3656 "\tdrho_u"
3657 "\tterme_moyen_convection_mass_solver"
3658 "\tterme_moyen_diffusion_mass_solver"
3659 "\n# Forces have 3 components.",
3660 reset_test, 20/*prec*/);
3661
3662
3663 // GAB, qdm
3664 Cout << "check etapes et termes" << finl;
3665 fic_test << schema_temps_ijk().get_tstep() << " " << accurate_current_time << " ";
3666 fic_test << rk_step << " ";
3667 // Inspection a gros grain
3668 fic_test << rho_u_euler_av_prediction_[0] << " "
3669 << rho_u_euler_av_prediction_[1] << " "
3670 << rho_u_euler_av_prediction_[2] << " "; // colone 5
3671 fic_test << rho_du_euler_ap_prediction_[0] << " "
3672 << rho_du_euler_ap_prediction_[1] << " "
3673 << rho_du_euler_ap_prediction_[2] << " ";
3674 fic_test << rho_u_euler_ap_projection_[0] << " "
3675 << rho_u_euler_ap_projection_[1] << " " // colonne 10
3676 << rho_u_euler_ap_projection_[2] << " ";
3677 fic_test << rho_du_euler_ap_projection_[0] << " "
3678 << rho_du_euler_ap_projection_[1] << " "
3679 << rho_du_euler_ap_projection_[2] << " ";
3680 fic_test << rho_u_euler_av_rho_mu_ind_[0] << " " // colonne 15
3681 << rho_u_euler_av_rho_mu_ind_[1] << " "
3682 << rho_u_euler_av_rho_mu_ind_[2] << " ";
3683 fic_test << rho_u_euler_ap_rho_mu_ind_[0] << " "
3684 << rho_u_euler_ap_rho_mu_ind_[1] << " "
3685 << rho_u_euler_ap_rho_mu_ind_[2] << " "; // colonne 20
3686 fic_test << u_euler_ap_rho_mu_ind_[0] << " "
3687 << u_euler_ap_rho_mu_ind_[1] << " "
3688 << u_euler_ap_rho_mu_ind_[2] << " "; // Dans l'etape de prediction, inspection terme a terme
3689 fic_test << terme_interfaces_[0] << " "
3690 << terme_interfaces_[1] << " " // colonne 25
3691 << terme_interfaces_[2] << " ";
3692 fic_test << terme_convection_[0] << " "
3693 << terme_convection_[1] << " "
3694 << terme_convection_[2] << " ";
3695 fic_test << terme_diffusion_[0] << " " // colonne 30
3696 << terme_diffusion_[1] << " "
3697 << terme_diffusion_[2] << " ";
3698 // Moyenne_spatiale{ grad(p) }
3699 fic_test << terme_pression_bis_[0] << " "
3700 << terme_pression_bis_[1] << " "
3701 << terme_pression_bis_[2] << " "; // colonne 35
3702 // Moyenne_spatiale{ 1/rho grad(p) }
3703 fic_test << terme_pression_ter_[0] << " "
3704 << terme_pression_ter_[1] << " "
3705 << terme_pression_ter_[2] << " ";
3706 // Inspection de l'effet du mass solver
3707 fic_test << terme_interfaces_bf_mass_solver_bis_[0] << " "
3708 << terme_interfaces_bf_mass_solver_bis_[1] << " " // colonne 40
3710 fic_test << terme_interfaces_bf_mass_solver_[0] << " "
3713 fic_test << terme_interfaces_af_mass_solver_[0] << " " // colonne 45 /!\ au 17.01.22 une coquille a ete corrigee : terme_interfaces_bf_mass_solver-> terme_interfaces_af_mass_solver
3716 fic_test << pression_ap_proj_ << " ";
3717 // On pourrai se passer de cette sortie et la creer uniquement dans python
3718 // ==> ( r^{n+1} - r^{n} ) * u^{n+1}
3720 << rho_u_euler_av_rho_mu_ind_[1]-rho_u_euler_ap_rho_mu_ind_[1] << " " // colonne 50
3722 fic_test << terme_moyen_convection_mass_solver_[0] << " "
3725 fic_test << terme_moyen_diffusion_mass_solver_[0] << " " // colonne 55
3728 fic_test << finl;
3729 fic_test.close();
3730 Cout << "check etapes et termes fini" << finl;
3731 }
3732 }
3733}
3734
3735// -----------------------------------------------------------------------------------
3736// FORCAGE EXTERIEUR, DEFINI DANS L'ESPACE SPECTRAL
3737void Navier_Stokes_FTD_IJK::compute_add_THI_force(const IJK_Field_vector3_double& vitesse, const int time_iteration, const double dt, //tstep, /!\ ce dt est faux, je ne sais pas pk mais en comparant sa valeur avec celle du dt_ev, je vois que c'est faux
3738 const double current_time, const Domaine_IJK& my_splitting)
3739{
3740
3741 statistics().create_custom_counter("m2",2,"TrioCFD");
3742 statistics().create_custom_counter("m3",2,"TrioCFD");
3743 statistics().begin_count("m2",statistics().get_last_opened_counter_level()+1);
3744 if (forcage_.get_forced_advection() == -1)
3745 {
3746 ArrOfDouble mean_u_liq;
3747 mean_u_liq.resize_array(3);
3748 for (int dir = 0; dir < 3; dir++)
3749 mean_u_liq[dir] = calculer_moyenne_de_phase_liq(vitesse[dir]);
3750 forcage_.update_advection_velocity(mean_u_liq);
3751 }
3752 if (forcage_.get_forced_advection() != 0)
3753 {
3754 Cout << "forced_advection" << forcage_.get_forced_advection() << finl;
3755 Cout << "BF : update_advection_length" << finl;
3756 forcage_.update_advection_length(dt);
3757 Cout << "AF : update_advection_length" << finl;
3758 }
3759 forcage_.compute_THI_force(time_iteration, dt, current_time, probleme_ijk().domaine_ijk());
3760
3761 statistics().end_count("m2");
3762 statistics().begin_count("m3",statistics().get_last_opened_counter_level()+1);
3763
3764 const IJK_Field_vector3_double& force = forcage_.get_force_ph2();
3765 for (int dir = 0; dir < 3; dir++)
3766 {
3767 // d_velocity_ est deja decoupe sur les differents procs; donc ni, nj, nk =! nb elem.
3768 const int kmax = d_velocity_[dir].nk();
3769 const int ni = d_velocity_[dir].ni();
3770 const int nj = d_velocity_[dir].nj();
3771
3772 for (int k = 0; k < kmax + 1; k++)
3773 for (int j = 0; j < nj + 1; j++)
3774 for (int i = 0; i < ni + 1; i++)
3775 {
3776 // GAB error : No continuous phase found ...
3777 // appeler mass_solver_with_rho si je veux div par rho*V (tant que je garde f localise aux faces)
3778 // double cell_mass = rho_field_(i,j,k)*my_geom.get_constant_delta(DIRECTION_I)*my_geom.get_constant_delta(DIRECTION_J)*my_geom.get_constant_delta(DIRECTION_K);
3779 const double inv_cell_mass = 1.; //my_geom.get_constant_delta(DIRECTION_I)*my_geom.get_constant_delta(DIRECTION_J)*my_geom.get_constant_delta(DIRECTION_K);
3780 //d_velocity_[dir](i,j,k) += force[dir](i,j,k)*inv_cell_mass;
3781 velocity_[dir](i, j, k) += force[dir](i, j, k) * inv_cell_mass * dt;
3782 }
3783 }
3784 statistics().end_count("m3");
3785}
3786
3787void Navier_Stokes_FTD_IJK::compute_add_THI_force_sur_d_velocity(const IJK_Field_vector3_double& vitesse, const int time_iteration, const double dt, //tstep, /!\ ce dt est faux, je ne sais pas pk mais en comparant sa valeur avec celle du dt_ev, je vois que c'est faux
3788 const double current_time, const Domaine_IJK& my_splitting, const int facteur)
3789{
3790// statistiques().begin_count(m2_counter_);
3791 if (forcage_.get_forced_advection() == -1)
3792 {
3793 /* Advection du champ de force par mean{u_l}^l */
3794 ArrOfDouble mean_u_liq;
3795 mean_u_liq.resize_array(3);
3796 for (int dir = 0; dir < 3; dir++)
3797 {
3798 // (22.02.22) FAUX : mean_u_liq[dir] contient alors alpha_liq*vitesse_liq[dir]
3799 // mean_u_liq[dir] = calculer_moyenne_de_phase_liq(vitesse_liq[dir]);
3800 // (22.02.22) JUSTE : mean_u liq[dir] contient bien vitesse_liq[dir]
3801 mean_u_liq[dir] = calculer_true_moyenne_de_phase_liq(vitesse[dir]);
3802 }
3803 forcage_.update_advection_velocity(mean_u_liq);
3804 }
3805 /* Advection du champ de force par advection_velocity_, donnee du jdd */
3806 if (forcage_.get_forced_advection() != 0)
3807 forcage_.update_advection_length(dt);
3808
3809 forcage_.compute_THI_force(time_iteration, dt, current_time, probleme_ijk().domaine_ijk());
3810// statistiques().end_count(m2_counter_);
3811//
3812// statistiques().begin_count(m3_counter_);
3813
3814 const IJK_Field_vector3_double& force = forcage_.get_force_ph2();
3815
3816 for (int dir = 0; dir < 3; dir++)
3817 {
3818 // d_velocity_ est deja decoupe sur les differents procs; donc ni, nj, nk =! nb elem.
3819 const int kmax = d_velocity_[dir].nk();
3820 const int ni = d_velocity_[dir].ni();
3821 const int nj = d_velocity_[dir].nj();
3822
3823 // La meme force appliquee partout
3824 if (facteur == 0)
3825 {
3826 for (int k = 0; k < kmax; k++)
3827 for (int j = 0; j < nj; j++)
3828 for (int i = 0; i < ni; i++)
3829 {
3830 // appeler mass_solver_with_rho si je veux div par rho*V (tant que je garde f localise aux faces)
3831 // double cell_mass = rho_field_(i,j,k)*my_geom.get_constant_delta(DIRECTION_I)*my_geom.get_constant_delta(DIRECTION_J)*my_geom.get_constant_delta(DIRECTION_K);
3832 //d_velocity_[dir](i,j,k) += force[dir](i,j,k)*inv_cell_mass;
3833 d_velocity_[dir](i, j, k) += force[dir](i, j, k);
3834 }
3835 }
3836 // Force active uniquement dans le liquide. Nulle dans le gaz
3837 else if (facteur == 1)
3838 {
3839 for (int k = 0; k < kmax; k++)
3840 for (int j = 0; j < nj; j++)
3841 for (int i = 0; i < ni; i++)
3842 {
3843 // appeler mass_solver_with_rho si je veux div par rho*V (tant que je garde f localise aux faces)
3844 // double cell_mass = rho_field_(i,j,k)*my_geom.get_constant_delta(DIRECTION_I)*my_geom.get_constant_delta(DIRECTION_J)*my_geom.get_constant_delta(DIRECTION_K);
3845 // indicatrice == 0 dans le gaz et 1 dans le liquide. ATTN : ~0.5 aux interfaces !!!
3846 d_velocity_[dir](i, j, k) += force[dir](i, j, k) * interfaces_->I(i, j, k);
3847 }
3848 }
3849 // Force ponderee par la masse volumique de la phase. Attention, il faut rester homogene a une vitesse
3850 else if (facteur == 2)
3851 {
3852 // S'assurer qu'on a bien calcule rho_moyen_
3853 for (int k = 0; k < kmax; k++)
3854 for (int j = 0; j < nj; j++)
3855 for (int i = 0; i < ni; i++)
3856 {
3857 // appeler mass_solver_with_rho si je veux div par rho*V (tant que je garde f localise aux faces)
3858 // double cell_mass = rho_field_(i,j,k)*my_geom.get_constant_delta(DIRECTION_I)*my_geom.get_constant_delta(DIRECTION_J)*my_geom.get_constant_delta(DIRECTION_K);
3859 d_velocity_[dir](i, j, k) += force[dir](i, j, k) * rho_field_(i, j, k) / rho_moyen_;
3860 }
3861 }
3862 d_velocity_[dir].echange_espace_virtuel(d_velocity_[dir].ghost());
3863 }
3864// statistiques().end_count(m3_counter_);
3865 Cout << "end of from_spect_to_phys_opti2_advection" << finl;
3866}
3867// -----------------------------------------------------------------------------------
3868
3870{
3871 /* Au 04.11.21 : Renvoi alpha_liq * vx_liq
3872 * */
3873 const Domaine_IJK& geom = vx.get_domaine();
3874 const int ni = vx.ni();
3875 const int nj = vx.nj();
3876 const int nk = vx.nk();
3877 double v_moy = 0.;
3878
3879#ifndef VARIABLE_DZ
3880 for (int k = 0; k < nk; k++)
3881 for (int j = 0; j < nj; j++)
3882 for (int i = 0; i < ni; i++)
3883 v_moy += vx(i, j, k) * interfaces_->I(i, j, k);
3884
3885 // somme sur tous les processeurs.
3886 v_moy = Process::mp_sum(v_moy);
3887 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
3888 // cast en double au cas ou on voudrait faire un maillage >2 milliards
3889 const double n_mailles_tot = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1) * geom.get_nb_elem_tot(2);
3890 v_moy /= n_mailles_tot;
3891#else
3892 const int offset = splitting.get_offset_local(DIRECTION_K);
3893 const ArrOfDouble& tab_dz=geom.get_delta(DIRECTION_K);
3894 for (int k = 0; k < nk; k++)
3895 {
3896 const double dz = tab_dz[k+offset];
3897 for (int j = 0; j < nj; j++)
3898 for (int i = 0; i < ni; i++)
3899 v_moy += vx(i,j,k)*dz;
3900 }
3901 // somme sur tous les processeurs.
3902 v_moy = Process::mp_sum(v_moy);
3903 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
3904 // cast en double au cas ou on voudrait faire un maillage >2 milliards
3905 const double n_mailles_xy = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1);
3906 v_moy /= (n_mailles_xy * geom.get_domain_length(DIRECTION_K) );
3907#endif
3908 return v_moy;
3909}
3910
3912{
3913 /*
3914 * Corrections to comply with the momentum budget
3915 * u_corrected = u - u_correction
3916 * u_corrected and u_corrrection are computed in the qdm_corrections_ object.
3917 * */
3918 double alpha_l = calculer_v_moyen(interfaces_->I());
3919 double rho_moyen = calculer_v_moyen(rho_field_);
3920 qdm_corrections_.set_rho_moyen_alpha_l(rho_moyen, alpha_l);
3921 qdm_corrections_.set_rho_liquide(milieu_ijk().get_rho_liquid());
3922 for (int dir = 0; dir < 3; dir++)
3923 {
3924 IJK_Field_double& vel = velocity_[dir];
3925 double rho_vel_moyen = calculer_v_moyen(rho_v_[dir]);
3926 qdm_corrections_.set_rho_vel_moyen(dir, rho_vel_moyen);
3927 Cout << "qdm_corrections_.get_need_for_vitesse_relative(" << dir << ")" << qdm_corrections_.get_need_for_vitesse_relative(dir) << finl;
3928 if (qdm_corrections_.get_need_for_vitesse_relative(dir))
3929 {
3931 qdm_corrections_.set_vitesse_relative(dir, vel_rel);
3932 }
3933 // TODO : Demander de l'aide a Guillaume :
3934 /* Pour moyenne glissante, je fais appel a des ArrOfDouble. En utilisation sequentielle, j'en
3935 * suis satisfait disons. En utilisation parallele, je ne sais pas vraiment comment sont gerees
3936 * mes listes. Sont-t-elles dupliquees ? Decoupees ? En tout cas la simu plante pour une liste
3937 * plus de 10 doubles, sur un maillage a 40^3 mailles, une seule bulle... */
3938 if (qdm_corrections_.get_need_to_compute_correction_value_one_direction(dir))
3939 qdm_corrections_.compute_correction_value_one_direction(dir);
3940 for (int k = 0; k < vel.nk(); ++k)
3941 for (int j = 0; j < vel.nj(); ++j)
3942 for (int i = 0; i < vel.ni(); ++i)
3943 {
3944 qdm_corrections_.compute_correct_velocity_one_direction(dir, vel(i, j, k));
3945 velocity_[dir](i, j, k) = qdm_corrections_.get_correct_velocitiy_one_direction(dir);
3946 }
3947 }
3948
3949 Cout << "AF : compute_and_add_qdm_corrections" << finl;
3950}
3951
3952// -----------------------------------------------------------------------------------
3953// CORRECTION DE QdM
3955{
3956 /* Au 04.11.21 : Renvoi vx_liq */
3957 double alpha_liq_vx_liq = calculer_moyenne_de_phase_liq(vx);
3958 double alpha_liq = calculer_v_moyen(interfaces_->I()); //en utilisant calculer_moyenne_de_phase_liq(indicatrice_ns_) on somme des chi^2 ce qui est genant aux mailles diphasiques
3959 return alpha_liq_vx_liq / alpha_liq;
3960}
3961
3963{
3964 /* Au 04.11.21 : Renvoi vx_vap */
3965 double alpha_vap_vx_vap = calculer_moyenne_de_phase_vap(vx);
3966 double alpha_vap = 1 - calculer_v_moyen(interfaces_->I()); //en utilisant 1-calculer_moyenne_de_phase_liq(indicatrice_ns_) on somme des chi^2 ce qui est genant aux mailles diphasiques
3967 return alpha_vap_vx_vap / alpha_vap;
3968}
3969
3971{
3972 /* Au 04.11.21 : Renvoi alpha_vap * vx_vap
3973 * */
3974 const Domaine_IJK& geom = vx.get_domaine();
3975 const int ni = vx.ni();
3976 const int nj = vx.nj();
3977 const int nk = vx.nk();
3978 double v_moy = 0.;
3979
3980#ifndef VARIABLE_DZ
3981 for (int k = 0; k < nk; k++)
3982 for (int j = 0; j < nj; j++)
3983 for (int i = 0; i < ni; i++)
3984 v_moy += vx(i, j, k) * (1 - interfaces_->I(i, j, k));
3985
3986 // somme sur tous les processeurs.
3987 v_moy = Process::mp_sum(v_moy);
3988 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
3989 // cast en double au cas ou on voudrait faire un maillage >2 milliards
3990 const double n_mailles_tot = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1) * geom.get_nb_elem_tot(2);
3991 v_moy /= n_mailles_tot;
3992#else
3993 const int offset = splitting.get_offset_local(DIRECTION_K);
3994 const ArrOfDouble& tab_dz=geom.get_delta(DIRECTION_K);
3995 for (int k = 0; k < nk; k++)
3996 {
3997 const double dz = tab_dz[k+offset];
3998 for (int j = 0; j < nj; j++)
3999 for (int i = 0; i < ni; i++)
4000 v_moy += vx(i,j,k)*dz;
4001 }
4002 // somme sur tous les processeurs.
4003 v_moy = Process::mp_sum(v_moy);
4004 // Maillage uniforme, il suffit donc de diviser par le nombre total de mailles:
4005 // cast en double au cas ou on voudrait faire un maillage >2 milliards
4006 const double n_mailles_xy = ((double) geom.get_nb_elem_tot(0)) * geom.get_nb_elem_tot(1);
4007 v_moy /= (n_mailles_xy * geom.get_domain_length(DIRECTION_K) );
4008#endif
4009 return v_moy;
4010}
4011
4012// Hard coded constant pressure gradient in i direction, add contribution in m/s*volume of control volume
4013void Navier_Stokes_FTD_IJK::terme_source_gravite(IJK_Field_double& dv, int k_index, int dir) const
4014{
4015 const double constant = milieu_ijk().gravite().valeurs()(0, dir);
4016 const int imax = dv.ni();
4017 const int jmax = dv.nj();
4018 for (int j = 0; j < jmax; j++)
4019 for (int i = 0; i < imax; i++)
4020 dv(i, j, k_index) += constant;
4021}
4022
4024{
4025 qdm_corrections_.set_time(schema_temps_ijk().get_current_time(), schema_temps_ijk().get_timestep(), schema_temps_ijk().get_tstep());
4026}
4027
4029{
4030 /* For monophasic corrections only */
4031 /*
4032 * Corrections to comply with the momentum budget
4033 * u_corrected = u - u_correction
4034 * u_corrected and u_corrrection are computed in the qdm_corrections_ object.
4035 * */
4036 double alpha_l = 1.; // calculer_v_moyen(interfaces_.I())
4037 double rho_moyen = milieu_ijk().get_rho_liquid(); // calculer_v_moyen(rho_field_)
4038 qdm_corrections_.set_rho_moyen_alpha_l(rho_moyen,alpha_l);
4039 qdm_corrections_.set_rho_liquide(milieu_ijk().get_rho_liquid());
4040 for (int dir=0; dir<3; dir++)
4041 {
4042 IJK_Field_double& vel = velocity_[dir];
4043 double rho_vel_moyen = calculer_v_moyen(rho_v_[dir]);
4044 qdm_corrections_.set_rho_vel_moyen(dir,rho_vel_moyen);
4045 Cout << "qdm_corrections_.get_need_for_vitesse_relative("<<dir<<")" << qdm_corrections_.get_need_for_vitesse_relative(dir)<< finl;
4046 if (qdm_corrections_.get_need_for_vitesse_relative(dir))
4047 {
4048 double vel_rel = calculer_true_moyenne_de_phase_liq(vel); // - calculer_true_moyenne_de_phase_vap(vel);
4049 qdm_corrections_.set_vitesse_relative(dir, vel_rel);
4050 }
4051 // TODO : Demander de l'aide a Guillaume :
4052 /* Pour moyenne glissante, je fais appel a des ArrOfDouble. En utilisation sequentielle, j'en
4053 * suis satisfait disons. En utilisation parallele, je ne sais pas vraiment comment sont gerees
4054 * mes listes. Sont-t-elles dupliquees ? Decoupees ? En tout cas la simu plante pour une liste
4055 * plus de 10 doubles, sur un maillage a 40^3 mailles, une seule bulle... */
4056 if (qdm_corrections_.get_need_to_compute_correction_value_one_direction(dir))
4057 qdm_corrections_.compute_correction_value_one_direction(dir);
4058 for (int k=0; k<vel.nk(); k++)
4059 for (int j=0; j<vel.nj(); j++)
4060 for (int i=0; i<vel.ni(); i++)
4061 {
4062 qdm_corrections_.compute_correct_velocity_one_direction(dir, vel(i,j,k));
4063 velocity_[dir](i,j,k) = qdm_corrections_.get_correct_velocitiy_one_direction(dir);
4064 }
4065 }
4066 Cout << "AF : compute_and_add_qdm_corrections_monophasic" << finl;
4067}
4068
4069static int decoder_numero_bulle(const int code)
4070{
4071 const int num_bulle = code >>6;
4072 return num_bulle;
4073}
4074
4075void Navier_Stokes_FTD_IJK::compute_var_volume_par_bulle(ArrOfDouble& var_volume_par_bulle)
4076{
4077 if (vol_bulles_.size_array() > 0.)
4078 {
4079 ArrOfDouble volume_reel;
4080 DoubleTab position;
4081 interfaces_->calculer_volume_bulles(volume_reel, position);
4082 const int nb_reelles = interfaces_->get_nb_bulles_reelles();
4083 for (int ib = 0; ib < nb_reelles; ib++)
4084 var_volume_par_bulle[ib] = volume_reel[ib] - vol_bulles_[ib];
4085 // Pour les ghost : on retrouve leur vrai numero pour savoir quel est leur volume...
4086 for (int i = 0; i < interfaces_->get_nb_bulles_ghost(0 /* no print*/); i++)
4087 {
4088 const int ighost = interfaces_->ghost_compo_converter(i);
4089 const int ibulle_reelle = decoder_numero_bulle(-ighost);
4090 // Cerr << " aaaa " << i << " " << ighost << " " << ibulle_reelle << finl;
4091 var_volume_par_bulle[nb_reelles + i] = volume_reel[nb_reelles+ i] - vol_bulles_[ibulle_reelle];
4092 }
4093 }
4094 else
4095 {
4096 // Initialisation de vol_bulles_ a la valeur initiale du volume des bulles, dans le cas ou il n'est pas specifie dans le jeu de donnees.
4097 // Note : uniquement dans le cas de la correction_semi_locale du volume, pour ne pas impacter les cas tests
4099 {
4100 ArrOfDouble volume_reel;
4101 DoubleTab position;
4102 interfaces_->calculer_volume_bulles(volume_reel, position);
4103 const int nb_reelles = interfaces_->get_nb_bulles_reelles();
4104 vol_bulles_.resize_array(nb_reelles);
4105 for (int ib = 0; ib < nb_reelles; ib++)
4106 {
4107 var_volume_par_bulle[ib] = 0.;
4108 vol_bulles_[ib] = volume_reel[ib];
4109 }
4110 // Pour les ghost : on retrouve leur vrai numero pour savoir quel est leur volume...
4111 for (int i = 0; i < interfaces_->get_nb_bulles_ghost(0 /* no print*/); i++)
4112 {
4113 const int ighost = interfaces_->ghost_compo_converter(i);
4114 const int ibulle_reelle = decoder_numero_bulle(-ighost);
4115 // Cerr << " aaaa " << i << " " << ighost << " " << ibulle_reelle << finl;
4116 var_volume_par_bulle[nb_reelles + i] = 0.;
4117 vol_bulles_[ibulle_reelle] = volume_reel[nb_reelles+ i];
4118 }
4119 }
4120 }
4121}
4122
4124{
4125 // Impression dans le fichier qdm_correction.out
4126 if ( sub_type(Schema_RK3_IJK, schema_temps_ijk()) ) // && (rk3_sub_step!=0)
4127 Cout << "in write_qdm_corrections_information, rk_step = " << ref_cast(Schema_RK3_IJK, schema_temps_ijk()).get_rk_step() << finl;
4128
4129 Vecteur3 qdm_cible = qdm_corrections_.get_correction_values();
4130 Vecteur3 velocity_correction = qdm_corrections_.get_velocity_corrections();
4131 Vecteur3 rho_vel;
4132 for (int dir=0; dir<3; ++dir) rho_vel[dir] = calculer_v_moyen(scalar_fields_product(probleme_ijk(), rho_field_,velocity_[dir],dir));
4133
4135 {
4136 int reset = (!probleme_ijk().get_reprise()) && (schema_temps_ijk().get_tstep()==0);
4137 SFichier fic=Ouvrir_fichier("_qdm_correction.out",
4138 "1.iteration\t2.time\t3.qdm_cible[0]\t4.qdm_cible[1]\t5.qdm_cible[2]\t6.velocity_correction[0]\t7.velocity_correction[1]\t8.velocity_correction[2]\t9.qdm[0]\t10.qdm[1]\t11.qdm[2]",
4139 reset);
4140 // temps
4141 fic << schema_temps_ijk().get_tstep() << " ";
4142 fic << schema_temps_ijk().get_current_time() << " ";
4143 // CIBLE CONSTANE : qdm_cible = al.rl.u_cible
4144 fic << qdm_cible[0] << " ";
4145 fic << qdm_cible[1] << " ";
4146 fic << qdm_cible[2] << " ";
4147 // velocity_correction = (<r.u> - qdm_cible) / <r>
4148 fic << velocity_correction[0] << " ";
4149 fic << velocity_correction[1] << " ";
4150 fic << velocity_correction[2] << " ";
4151 // <r.u>
4152 fic << rho_vel[0] << " ";
4153 fic << rho_vel[1] << " ";
4154 fic << rho_vel[2] << " ";
4155 fic<<finl;
4156 fic.close();
4157 // << finl;
4158 }
4159}
4160
4161// GAB, qdm : construction du terme de pression pour le bilan de qdm. Je trouve ea plus logique de bouger cette fonction dans
4162// IJK_Navier_Stokes_tool, mais etant donne qu'elle se trouve dans IJK_kernel, je ne sais pas trop si c'est propre que j'y touche
4163// voir avec Guillaume ce qu'il en dit.
4164// inspire de : void IJK_FT_Post::calculer_gradient_indicatrice_et_pression(const IJK_Field_double& indic)
4165Vecteur3 Navier_Stokes_FTD_IJK::calculer_inv_rho_grad_p_moyen(const IJK_Field_double& rho, const IJK_Field_double& pression)
4166{
4167 IJK_Field_vector3_double champ;
4168 allocate_velocity(champ, probleme_ijk().domaine_ijk(), 1);
4169 Vecteur3 resu;
4170
4171 // Remise a zero :
4172 for (int dir = 0; dir < 3; dir++)
4173 {
4174 champ[dir].data() = 0.;
4175 // je ne sais pas a quoi ca sert, mais il est appele avant add_gradient_times_constant_over_rho dans IJK_NS_tool
4176 champ[dir].echange_espace_virtuel(1);
4177 }
4178 add_gradient_times_constant_over_rho(pression, rho, 1. /*constant*/, champ[0], champ[1], champ[2]);
4179 for (int dir = 0; dir < 3; dir++)
4180 {
4181 // Je ne sais pas e quoi cette ligne sert. elle est dans calculer_gradient_indicatrice_et_pression, alors je copie
4182 champ[dir].echange_espace_virtuel(1);
4183 }
4184 // calculer_rho_v(inv_rho, champ, inv_rho_champ);
4185 for (int dir = 0; dir < 3; dir++)
4186 resu[dir] = calculer_v_moyen(champ[dir]);
4187
4188 return resu;
4189}
4190
4192{
4193 IJK_Field_vector3_double champ;
4194 allocate_velocity(champ, probleme_ijk().domaine_ijk(), 1);
4195 Vecteur3 resu;
4196
4197 // Remise a zero :
4198 for (int dir = 0; dir < 3; dir++)
4199 {
4200 champ[dir].data() = 0.;
4201 // je ne sais pas a quoi ca sert, mais il est appele avant add_gradient_times_constant_over_rho dans IJK_NS_tool
4202 champ[dir].echange_espace_virtuel(1);
4203 }
4204 add_gradient_times_constant(pression, 1. /*constant*/, champ[0], champ[1], champ[2]);
4205 for (int dir = 0; dir < 3; dir++)
4206 {
4207 // Je ne sais pas e quoi cette ligne sert. elle est dans calculer_gradient_indicatrice_et_pression, alors je copie
4208 champ[dir].echange_espace_virtuel(1);
4209 }
4210 for (int dir = 0; dir < 3; dir++)
4211 resu[dir] = calculer_v_moyen(champ[dir]);
4212
4213 return resu;
4214}
4215
4217{
4218 /*
4219 * Calcule Moyenne_spatiale{ 1/rho * grad(p) }
4220 * */
4221 IJK_Field_vector3_double champ;
4222 allocate_velocity(champ, probleme_ijk().domaine_ijk(), 1);
4223 Vecteur3 resu;
4224
4225 // Remise a zero :
4226 for (int dir = 0; dir < 3; dir++)
4227 {
4228 champ[dir].data() = 0.;
4229 // je ne sais pas a quoi ca sert, mais il est appele avant add_gradient_times_constant_over_rho dans IJK_NS_tool
4230 champ[dir].echange_espace_virtuel(1);
4231 }
4232 add_gradient_times_constant_over_rho(pression, rho_field_, 1. /*constant*/, champ[0], champ[1], champ[2]);
4233 for (int dir = 0; dir < 3; dir++)
4234 {
4235 // Je ne sais pas e quoi cette ligne sert. elle est dans calculer_gradient_indicatrice_et_pression, alors je copie
4236 champ[dir].echange_espace_virtuel(1);
4237 }
4238 for (int dir = 0; dir < 3; dir++)
4239 resu[dir] = calculer_v_moyen(champ[dir]);
4240
4241 return resu;
4242}
4243
4244void Navier_Stokes_FTD_IJK::euler_explicit_update(const IJK_Field_double& dv, IJK_Field_double& v, const int k_layer) const
4245{
4246 const double delta_t = schema_temps_ijk().get_timestep();
4247 const int imax = v.ni();
4248 const int jmax = v.nj();
4249 for (int j = 0; j < jmax; j++)
4250 for (int i = 0; i < imax; i++)
4251 {
4252 double x = dv(i, j, k_layer);
4253 v(i, j, k_layer) += x * delta_t;
4254 }
4255}
4256
4258{
4259 if (boundary_conditions_.get_correction_conserv_qdm() == 2)
4260 {
4261 update_rho_v();
4262 rho_field_.echange_espace_virtuel(rho_field_.ghost());
4264 }
4265 else
4266 {
4267 // Protection to make sure that even without the activation of the flag check_divergence_, the EV of velocity is correctly field.
4268 // This protection MAY be necessary if convection uses ghost velocity (but I'm not sure it actually does)
4269 velocity_[0].echange_espace_virtuel(2);
4270 velocity_[1].echange_espace_virtuel(2);
4271 velocity_[2].echange_espace_virtuel(2);
4272 }
4273
4274 if (with_p)
4275 pressure_.echange_espace_virtuel(1);
4276}
4277
4278void Navier_Stokes_FTD_IJK::rk3_sub_step(const int rk_step, const double total_timestep, const double fractionnal_timestep, const double time)
4279{
4280 if (!frozen_velocity_)
4281 {
4283
4284 // GAB TODO : voir dans euler_explicite ce qu'on a dit qu'on ferai pour voir
4285 // si le calculer_dv s'est bien passe
4286 Cout << "rk3ss: rk_step " << rk_step << finl;
4287 calculer_dv(total_timestep, time, rk_step);
4288 //
4289#ifdef PROJECTION_DE_LINCREMENT_DV
4290 // ajout du gradient de pression a dv
4292 {
4294 pressure_projection_with_rho(rho_field_, d_velocity_[0], d_velocity_[1], d_velocity_[2],
4295 d_pressure_,1. , pressure_rhs_, check_divergence_, poisson_solver_,NoSym_);
4296 else
4297 pressure_projection_with_rho(rho_field_, d_velocity_[0], d_velocity_[1], d_velocity_[2],
4298 pressure_,1. , pressure_rhs_, check_divergence_, poisson_solver_,NoSym_);
4299 }
4300#else
4301#endif
4302
4303 // Mise a jour du champ de vitesse (etape de projection GAB, 28/06/21 : c'est la prediction, pas la projection non ?)
4304 for (int dir = 0; dir < 3; dir++)
4305 {
4306 const int kmax = d_velocity_[dir].nk();
4307 for (int k = 0; k < kmax; k++)
4308 runge_kutta3_update(d_velocity_[dir], RK3_F_velocity_[dir], velocity_[dir], rk_step, k, total_timestep);
4309 }
4310
4311#ifdef PROJECTION_DE_LINCREMENT_DV
4312 // Mise a jour du champ de pression
4314 {
4315 const int kmax = pressure_.nk();
4316 for (int k = 0; k < kmax; k++)
4317 runge_kutta3_update(d_pressure_ /* increment */,
4318 RK3_F_pressure_ /* intermediate storage */,
4319 pressure_ /* variable to update */, rk_step, k, total_timestep);
4320 }
4321#else
4322#endif
4323
4324 // Conditions en entree
4325 if (vitesse_entree_ > -1e20)
4327
4328 // Forcage de la vitesse en amont de la bulle :
4329 if (vitesse_upstream_ > -1e20)
4330 {
4332 {
4333
4334 double vx;
4335 double vy;
4336 double vz;
4337
4338 calculer_vitesse_gauche(velocity_[0], velocity_[1], velocity_[2], vx, vy, vz);
4339
4340 force_upstream_velocity_shear_perio(velocity_[0], velocity_[1], velocity_[2], vitesse_upstream_, interfaces_, nb_diam_upstream_, boundary_conditions_, nb_diam_ortho_shear_perio_, vx, vy,
4341 vz, epaisseur_maille_);
4342 }
4343 else
4344 force_upstream_velocity(velocity_[0], velocity_[1], velocity_[2], vitesse_upstream_, interfaces_, nb_diam_upstream_, upstream_dir_, milieu_ijk().get_direction_gravite(),
4346 }
4347 } // end of if ! frozen_velocity
4348 //static Stat_Counter_Id projection_counter_ = statistiques().new_counter(0, "projection");
4349#ifdef PROJECTION_DE_LINCREMENT_DV
4350 if (0)
4351#else
4353#endif
4354 {
4355 //statistiques().begin_count(projection_counter_);
4357 {
4358 Cerr << "L'option include_pressure_gradient_in_ustar n'est pas encore implementee en RK3." << finl;
4359 Process::exit();
4360 }
4361
4363 {
4364 Cerr << "Methode incremental pour le grad(P)" << finl;
4365 Cerr << " Option codee uniquement pour le sch_euler... Tester et implementer si besoiN. " << finl;
4366 Process::exit();
4367 }
4368 // OPTION A SELECTIONNE DANS LE CAS DUN SHEAR PERIO POUR EVITER LES PBMS D INTERPOLATION DE RHO AU NIVEAU DU BORD PERIO_Z
4370 pressure_projection_with_inv_rho(inv_rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, fractionnal_timestep, pressure_rhs_, poisson_solver_,NoSym_);
4371 else
4372 {
4373#ifdef PROJECTION_DE_LINCREMENT_DV
4374 // On l'a fait avant pour etre sur qu'elle soit bien dans la derivee stockee...
4375#else
4376 pressure_projection_with_rho(rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, fractionnal_timestep, pressure_rhs_, poisson_solver_,NoSym_);
4377
4378 // GAB TODO : cest a peu pres ici qu'il faudra travailler pour recuperer le
4379 // terme de pression
4380#endif
4381 // GAB TODO : checker si le passage de rho_n a rho_n+1 est bon
4382 // chercher ca pour l'etape de deplacement de rho : maj_indicatrice_rho_mu
4383 }
4384
4385 // GAB, qdm : on recupere ici le terme grad(p),
4387 // GAB, qdm : on recupere ici le terme de pression (1/rho * grad(p))
4389 pression_ap_proj_ += calculer_v_moyen(pressure_);
4390
4391 //statistiques().end_count(projection_counter_);
4392 }
4393
4394// if (Process::je_suis_maitre())
4395// {
4396// Cout << "Timings diff=" << statistics().get_last_time(diffusion_counter_) << " conv=" << statistiques().last_time(convection_counter_);
4397// Cout << " src=" << statistics().last_time(source_counter_) << finl;
4398// }
4399}
4400
4401void Navier_Stokes_FTD_IJK::euler_time_step(ArrOfDouble& var_volume_par_bulle)
4402{
4403 if (!frozen_velocity_)
4404 {
4406
4407 // GAB, qdm
4409 {
4411 for (int dir = 0; dir < 3; dir++)
4413 }
4414
4415 // GAB, remarque : calculer dv calcule dv, MAIS NE L'APPLIQUE PAS au champ de vitesse !!!
4416 // l'increment de vitesse est ajoute au champ de vitesse avec euler_explicit_update
4417 calculer_dv(schema_temps_ijk().get_timestep(), schema_temps_ijk().get_current_time(), -1 /*rk_step = -1 pour sch euler... */);
4418 // GAB, qdm calculer_dv ne fait que l'etape de prediction)
4420 {
4422 for (int dir = 0; dir < 3; dir++)
4424 }
4425#ifdef PROJECTION_DE_LINCREMENT_DV
4426 // ajout du gradient de pression a dv
4428 {
4430 {
4431 pressure_projection_with_rho(rho_field_, d_velocity_[0], d_velocity_[1], d_velocity_[2],
4432 pressure_, 1., pressure_rhs_, check_divergence_, poisson_solver_,NoSym_);
4433 // GAB --> C'est plutot ici que l(on ajoute le terme_pression !!)
4434 }
4435 else
4436 {
4437 pressure_projection_with_rho(rho_field_, d_velocity_[0], d_velocity_[1], d_velocity_[2],
4438 d_pressure_, 1., pressure_rhs_, check_divergence_, poisson_solver_,NoSym_);
4439
4440 // Then update the pressure field :
4441 const int kmax = pressure_.nk();
4442 for (int k = 0; k < kmax; k++)
4444 }
4445 }
4446#endif
4447 // Mise a jour du champ de vitesse (etape de projection et de prediction)
4448 for (int dir = 0; dir < 3; dir++)
4449 {
4450 const int kmax = d_velocity_[dir].nk();
4451 for (int k = 0; k < kmax; k++)
4452 {
4453 // GAB, question : d_velocity est issu de calculer_dv. Il manque pas l'appliquation de l'operateur de divergence avant d'appliquer d_velocity e velocity ?
4454 // il manque au moins la multiplication par les surfaces je pense -> NON, lis bien les etapes de convection et de diffusion.
4456 }
4457 }
4458
4459 // GAB, qdm : cree le rho_n * v_n+1
4461 {
4463 for (int dir = 0; dir < 3; dir++)
4465 }
4466
4468 {
4470 for (int dir = 0; dir < 3; dir++)
4472 }
4473
4474 // Conditions en entree
4475 if (vitesse_entree_ > -1e20)
4477
4478 // Forcage de la vitesse en amont de la bulle :
4479 if (vitesse_upstream_ > -1e20)
4480 {
4482 {
4483 if (expression_vitesse_upstream_ != "??")
4484 {
4485 std::string expr(expression_vitesse_upstream_);
4486 Parser parser;
4487 parser.setString(expr);
4488 parser.setNbVar((int) 1);
4489 parser.addVar("t");
4490 parser.parseString();
4491 parser.setVar((int) 0, schema_temps_ijk().get_current_time() - schema_temps_ijk().get_modified_time_ini());
4492 vitesse_upstream_ = parser.eval();
4493 }
4494 }
4495 else
4496 {
4497 int dir = 0;
4498 if (upstream_dir_ == -1)
4499 {
4501 if (dir == -1)
4502 dir = 0;
4503 }
4504 const DoubleTab& rising_vector = interfaces_->get_ijk_compo_connex().get_rising_vectors();
4505 const double velocity_magnitude = interfaces_->get_ijk_compo_connex().get_rising_velocities()[0];
4506 const Vecteur3& velocity_vector = interfaces_->get_ijk_compo_connex().get_rising_velocity_overall();
4507 velocity_bubble_new_ = velocity_vector[dir]; // * rising_vector[dir];
4508 if (schema_temps_ijk().get_tstep() == 0)
4509 {
4510 if (velocity_bubble_old_ < -1e20)
4512 else
4514 if (vitesse_upstream_reprise_ < -1e20)
4516 else
4518 }
4519 const double delta_velocity = velocity_bubble_scope_ + velocity_bubble_new_;
4520 const double ddelta_velocity = (velocity_bubble_new_ - velocity_bubble_old_) / schema_temps_ijk().get_timestep();
4521 if (schema_temps_ijk().get_tstep() % 100)
4523
4528 Cerr << "Velocity bubble (old): " << velocity_bubble_old_ << finl;
4530 Cerr << "Velocity upstream: " << vitesse_upstream_ << finl;
4531 Cerr << "Velocity bubble (new): " << velocity_bubble_new_ << finl;
4532 Cerr << "Velocity magnitude: " << velocity_magnitude << finl;
4533 Cerr << "Velocity dir upstream: " << rising_vector(0, dir) << finl;
4534 }
4536 Cerr << "Force upstream velocity" << finl;
4537
4539 {
4540 double vx;
4541 double vy;
4542 double vz;
4543
4544 calculer_vitesse_gauche(velocity_[0], velocity_[1], velocity_[2], vx, vy, vz);
4545
4546 force_upstream_velocity_shear_perio(velocity_[0], velocity_[1], velocity_[2], vitesse_upstream_, interfaces_.valeur(), nb_diam_upstream_, boundary_conditions_,
4548 }
4549 else
4550 force_upstream_velocity(velocity_[0], velocity_[1], velocity_[2], vitesse_upstream_, interfaces_.valeur(), nb_diam_upstream_, upstream_dir_, milieu_ijk().get_direction_gravite(),
4552
4553 }
4554 } // end of if ! frozen_velocity
4555 // static Stat_Counter_Id projection_counter_ = statistiques().new_counter(0, "projection");
4556#ifdef PROJECTION_DE_LINCREMENT_DV
4557 if (0)
4558#else
4560#endif
4561 {
4562 // statistiques().begin_count(projection_counter_);
4564 {
4565 Cerr << "Methode incrementale pour le grad(P)" << finl;
4566 Cerr << "Initialisation du d_pressure_ conservee depuis le pas de temps precedent... " << finl;
4567 Cerr << "Ce n'est probablement pas optimal. QQ idees dans les sources si divergence . " << finl;
4568 // Que vaut d_pressure ?
4569 // Important car c'est l'initialisation du solveur...
4570
4571 // 1. raz :
4572 // d_pressure_.data() = 0.; // raz...
4573 // 2. dp = - timestep_ * (potentiel_elem - delta_rho * phi) * u . grad(I)
4574 // (sigma_ * courbure) on a ustar a dispo, par u^n.
4575 // 3. dp = - timestep_ * u . grad(P^n)
4576 // ici, on a ustar dispo, plus u^n.
4577 // Si on veut tester avec u^n (c mieux je pense), il faut initialiser dp
4578 // juste avant l'euler_explicit_update
4580 {
4581 pressure_projection_with_inv_rho(inv_rho_field_, velocity_[0], velocity_[1], velocity_[2], d_pressure_, schema_temps_ijk().get_timestep(), pressure_rhs_, poisson_solver_,NoSym_);
4582 }
4583 else
4584 {
4585#ifdef PROJECTION_DE_LINCREMENT_DV
4586 // On l'a fait avant pour etre sur qu'elle soit bien dans la derivee stockee...
4587#else
4588 pressure_projection_with_rho(rho_field_, velocity_[0], velocity_[1], velocity_[2], d_pressure_, schema_temps_ijk().get_timestep(), pressure_rhs_, poisson_solver_,NoSym_);
4589#endif
4590 }
4591
4592 // Mise a jour de la pression :
4593 for (int dir = 0; dir < 3; dir++)
4594 {
4595 const int kmax = pressure_.nk();
4596 for (int k = 0; k < kmax; k++)
4598 }
4599
4600 Cerr << " Un exit pour voir avec gdb... " << finl;
4601 Cerr << " Si ca fonctionne, faire le meme en RK3... " << finl;
4602 // Process::exit();
4603 }
4604 else
4605 {
4607 pressure_projection_with_inv_rho(inv_rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, schema_temps_ijk().get_timestep(), pressure_rhs_, poisson_solver_,NoSym_);
4608 else
4609 {
4610#ifdef PROJECTION_DE_LINCREMENT_DV
4611#else
4612 pressure_projection_with_rho(rho_field_, velocity_[0], velocity_[1], velocity_[2], pressure_, schema_temps_ijk().get_timestep(), pressure_rhs_, poisson_solver_,NoSym_);
4613#endif
4614 }
4615 }
4617 {
4618 // GAB, qdm : recuperons le temre de pression (1/rho * grad(p)) si on fait le bilan en u (ca a du sens meme?)
4619 // grap(p) si on fait le bilan de qdm
4620 // terme_pression_bis = calculer_inv_rho_grad_p_moyen(rho_field_, pressure_);
4622 // GAB, qdm : recuperons le terme de pression (1/rho * grad(p))
4624 pression_ap_proj_ = calculer_v_moyen(pressure_);
4625 }
4626 }
4627
4628 Cerr << "Copy pressure on extended field for probes" << finl;
4629 copy_field_values(pressure_ghost_cells_, pressure_);
4630
4631// Cout << "Timings diff=" << statistiques().last_time(diffusion_counter_) << " conv=" << statistiques().last_time(convection_counter_);
4632// Cout << " src=" << statistiques().last_time(source_counter_) << finl;
4633}
4634
4636{
4637 // CORRECTION DE QUANTITE DE MOUVEMENT : Correction de QdM : permet de controler la QdM globale, dans chaque direction
4638 if (!(qdm_corrections_.is_type_none()))
4639 {
4643 else
4645 }
4646 else
4647 {
4648 Cout << "qdm_corrections_.is_type_none() : " << qdm_corrections_.is_type_none() << finl;
4649 Cout << "terme_source_acceleration_" << terme_source_acceleration_ << finl;
4650 Cout << "terme_source_acceleration_z" << terme_source_acceleration_z_ << finl;
4651 }
4652
4653 if (qdm_corrections_.write_me())
4655}
4656
4657// TODO FIXME DANS DOMAINE
4659{
4660 const Domaine_IJK& dom_ijk = probleme_ijk().domaine_ijk();
4661 const Domaine_IJK& dom_ft = probleme_ijk().get_domaine_ft();
4662
4663 for (int dir = 0; dir < 3; dir++)
4664 {
4665 VECT(IntTab) map(3);
4667 const int n_ext = dom_ijk.ft_extension();
4668
4669 for (int dir2 = 0; dir2 < 3; dir2++)
4670 {
4671 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4672 if (n_ext == 0 || !dom_ijk.get_periodic_flag(dir2))
4673 {
4674 map[dir2].resize(1,3);
4675 map[dir2](0,0) = 0;// source index
4676 map[dir2](0,1) = 0;// dest index
4677 map[dir2](0,2) = n;// size
4678 }
4679 else
4680 {
4681 map[dir2].resize(3,3);
4682 // copy NS field to central domaine of extended field
4683 map[dir2](0,0) = 0;
4684 map[dir2](0,1) = n_ext;
4685 map[dir2](0,2) = n;
4686 // copy right part of NS field to left part of extended field
4687 map[dir2](1,0) = n - n_ext;
4688 map[dir2](1,1) = 0;
4689 map[dir2](1,2) = n_ext;
4690 // copy left part of NS field to right of extended field
4691 map[dir2](2,0) = 0;
4692 map[dir2](2,1) = n + n_ext;
4693 map[dir2](2,2) = n_ext;
4694 }
4695 }
4696 redistribute_to_splitting_ft_faces_[dir].initialize(dom_ijk, dom_ft, loc, map);
4697
4698 for (int dir2 = 0; dir2 < 3; dir2++)
4699 {
4700 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4701 if (n_ext == 0 || !dom_ijk.get_periodic_flag(dir2))
4702 {
4703 map[dir2].resize(1,3);
4704 map[dir2](0,0) = 0;
4705 map[dir2](0,1) = 0;
4706 map[dir2](0,2) = n;
4707 }
4708 else
4709 {
4710 map[dir2].resize(1,3);
4711 // When copying back from extended splitting, ignore extended data, take only central part
4712 map[dir2](0,0) = n_ext; // source index
4713 map[dir2](0,1) = 0; // dest index
4714 map[dir2](0,2) = n; // size
4715 }
4716 }
4717 redistribute_from_splitting_ft_faces_[dir].initialize(dom_ft, dom_ijk, loc, map);
4718 }
4719
4720 // Pour les elements:
4721 {
4722 VECT(IntTab) map(3);
4724 const int n_ext = dom_ijk.ft_extension();
4725
4726 for (int dir2 = 0; dir2 < 3; dir2++)
4727 {
4728 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4729 if (n_ext == 0 || !dom_ijk.get_periodic_flag(dir2))
4730 {
4731 map[dir2].resize(1,3);
4732 map[dir2](0,0) = 0;// source index
4733 map[dir2](0,1) = 0;// dest index
4734 map[dir2](0,2) = n;// size
4735 }
4736 else
4737 {
4738 map[dir2].resize(3,3);
4739 // copy NS field to central domaine of extended field
4740 map[dir2](0,0) = 0;
4741 map[dir2](0,1) = n_ext;
4742 map[dir2](0,2) = n;
4743 // copy right part of NS field to left part of extended field
4744 map[dir2](1,0) = n - n_ext;
4745 map[dir2](1,1) = 0;
4746 map[dir2](1,2) = n_ext;
4747 // copy left part of NS field to right of extended field
4748 map[dir2](2,0) = 0;
4749 map[dir2](2,1) = n + n_ext;
4750 map[dir2](2,2) = n_ext;
4751 }
4752 }
4753 redistribute_to_splitting_ft_elem_.initialize(dom_ijk, dom_ft, loc, map);
4754
4755
4756 for (int dir2 = 0; dir2 < 3; dir2++)
4757 {
4758 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4759 if (n_ext == 0 || !dom_ijk.get_periodic_flag(dir2))
4760 {
4761 map[dir2].resize(1,3);
4762 map[dir2](0,0) = 0;
4763 map[dir2](0,1) = 0;
4764 map[dir2](0,2) = n;
4765 }
4766 else
4767 {
4768 map[dir2].resize(1,3);
4769 // When copying back from extended splitting, ignore extended data, take only central part
4770 map[dir2](0,0) = n_ext; // source index
4771 map[dir2](0,1) = 0; // dest index
4772 map[dir2](0,2) = n; // size
4773 }
4774 }
4775 redistribute_from_splitting_ft_elem_.initialize(dom_ft, dom_ijk, loc, map);
4776
4777 for (int dir2 = 0; dir2 < 3; dir2++)
4778 {
4779 const int ghost_a_redistribute = 2 ;
4780 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4781 if(dir2==2)
4782 {
4783 // on ne redistribue les ghost que sur z pour le shear perio
4784 map[dir2].resize(1,3);
4785 // envoyer les rangees -2, -1, 0, 1 dans 0, 1, 2, 3
4786 map[dir2](0,0) = n_ext-ghost_a_redistribute; // source index
4787 map[dir2](0,1) = 0; // dest index
4788 map[dir2](0,2) = ghost_a_redistribute*2; // size
4789 }
4790 else
4791 {
4792 map[dir2].resize(1,3);
4793 map[dir2](0,0) = n_ext; // source index
4794 map[dir2](0,1) = 0; // dest index
4795 map[dir2](0,2) = n; // size
4796 }
4797
4798 }
4799 redistribute_from_splitting_ft_elem_ghostz_min_.initialize(dom_ft,dom_ijk, loc, map);
4800
4801 for (int dir2 = 0; dir2 < 3; dir2++)
4802 {
4803 const int ghost_a_redistribute = 2 ;
4804 const int n = dom_ijk.get_nb_items_global(loc, dir2);
4805 const int n_ft = dom_ft.get_nb_items_global(loc, dir2);
4806 if(dir2==2)
4807 {
4808 // on ne redistribue les ghost que sur z pour le shear perio
4809 map[dir2].resize(1,3);
4810 // envoyer les rangees n-2, n-1, n, n+1 dans 4, 5, 6, 7
4811 map[dir2](0,0) = n_ft - n_ext - ghost_a_redistribute; // source index
4812 map[dir2](0,1) = n - 2*ghost_a_redistribute; // dest index
4813 map[dir2](0,2) = ghost_a_redistribute*2; // size
4814 }
4815 else
4816 {
4817 map[dir2].resize(1,3);
4818 map[dir2](0,0) = n_ext; // source index
4819 map[dir2](0,1) = 0; // dest index
4820 map[dir2](0,2) = n; // size
4821 }
4822
4823 }
4824 redistribute_from_splitting_ft_elem_ghostz_max_.initialize(dom_ft, dom_ijk, loc, map);
4825 }
4826}
4827
4828// Calcule vitesse_ft (etendue) a partir du champ de vitesse.
4830{
4832 const Domaine_IJK& dom_ijk = pb_ijk.domaine_ijk();
4833
4834 for (int dir = 0; dir < 3; dir++)
4835 redistribute_to_splitting_ft_faces_[dir].redistribute(velocity_[dir], velocity_ft_[dir]);
4836
4838 {
4839 // after redistribute, velocity in ft domain must be shifted by the shear
4840 velocity_ft_[0].redistribute_with_shear_domain_ft(velocity_[0], boundary_conditions_.get_dU_perio(boundary_conditions_.get_resolution_u_prime_()), dom_ijk.ft_extension());
4841 velocity_ft_[1].redistribute_with_shear_domain_ft(velocity_[1], 0., dom_ijk.ft_extension());
4842 velocity_ft_[2].redistribute_with_shear_domain_ft(velocity_[2], 0., dom_ijk.ft_extension());
4843 }
4844
4845 for (int dir = 0; dir < 3; dir++)
4846 velocity_ft_[dir].echange_espace_virtuel(velocity_ft_[dir].ghost());
4847}
4848
4849// Nouvelle version ou le transport se fait avec les ghost...
4850void Navier_Stokes_FTD_IJK::deplacer_interfaces_rk3(const double timestep, const int rk_step, ArrOfDouble& var_volume_par_bulle)
4851{
4853
4854 // Calculer vitesse_ft (etendue) a partir du champ de vitesse.
4855// static Stat_Counter_Id deplacement_interf_counter_ = statistiques().new_counter(1, "Deplacement de l'interface");
4856// statistiques().begin_count(deplacement_interf_counter_);
4857
4859
4860 // On conserve les duplicatas que l'on transporte comme le reste.
4861 // Normalement, transporter_maillage gere aussi les duplicatas...
4863 {
4864 interfaces_->calculer_vecteurs_de_deplacement_rigide(vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_);
4865
4867 timestep/* total meme si RK3*/, var_volume_par_bulle, rk_step);
4868
4870
4872 var_volume_par_bulle, rk_step, schema_temps_ijk().get_current_time());
4873
4875
4876 interfaces_->transporter_maillage_rigide(timestep, vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_, rk_step);
4877 }
4878 else
4879 {
4880 interfaces_->calculer_vecteurs_de_deplacement_rigide(vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_);
4881
4883 timestep/* total meme si RK3*/, var_volume_par_bulle, rk_step);
4884
4886 var_volume_par_bulle, rk_step, schema_temps_ijk().get_current_time());
4887 }
4888
4889// statistiques().end_count(deplacement_interf_counter_);
4890 // On verra a la fin du pas de temps si certaines bulles reeles sont trop proche du bord
4891 // du domaine etendu. Pour l'instant, dans les sous dt, on ne les transferts pas.
4892
4893 // On a conserve les duplicatas donc pas besoin de les re-creer...
4894 // On calcule l'indicatrice du prochain pas de temps (qui correspond aux interfaces qu'on vient de deplacer.
4895 pb_ijk.update_indicator_field();
4896
4898}
4899
4900
4902{
4904 {
4905 redistribute_from_splitting_ft_elem_ghostz_min_.redistribute(interfaces_->I_ft(), I_ns_);
4906 redistribute_from_splitting_ft_elem_ghostz_max_.redistribute(interfaces_->I_ft(), I_ns_);
4907 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
4908 rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, rho_field_.nk() - 4);
4909 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
4910 molecular_mu_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, molecular_mu_.nk() - 4);
4911 if (use_inv_rho_)
4912 {
4913 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmin_(I_ns_, 0);
4914 inv_rho_field_.get_shear_BC_helpler().set_indicatrice_ghost_zmax_(I_ns_, inv_rho_field_.nk() - 4);
4915 }
4916 if (boundary_conditions_.get_correction_interp_monofluide() == 1)
4917 {
4918 interfaces_->calculer_kappa_ft(kappa_ft_);
4921 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmin_(I_ns_, kappa_ns_, milieu_ijk().sigma(), 0);
4922 pressure_.get_shear_BC_helpler().set_I_sig_kappa_zmax_(I_ns_, kappa_ns_, milieu_ijk().sigma(), pressure_.nk() - 4);
4923 }
4924 }
4925}
4926
4927void Navier_Stokes_FTD_IJK::deplacer_interfaces(const double timestep, const int rk_step, ArrOfDouble& var_volume_par_bulle, const int first_step_interface_smoothing)
4928{
4929 /*
4930 * TODO: Advect with zero velocity at the beggining of the simulation to use the remeshing algo
4931 */
4933
4935 {
4936 interfaces_->calculer_vecteurs_de_deplacement_rigide(vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_, first_step_interface_smoothing);
4937
4939 timestep/* total meme si RK3*/, var_volume_par_bulle, rk_step, first_step_interface_smoothing);
4940
4942
4944 var_volume_par_bulle, rk_step, schema_temps_ijk().get_current_time());
4945
4947
4948 interfaces_->transporter_maillage_rigide(timestep, vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_, rk_step, first_step_interface_smoothing);
4949 }
4950 else
4951 {
4952 // Note : Pour ne pas alterer les cas tests, on supprime
4953 // les duplicatas avant le transport dans ce cas. Si on ne supprime pas
4954 // les duplicatas, cela fonctionne aussi, mais le resultat des cas tests est un peu different.
4955 // Dans ce cadre, pour que l'indicatrice intermediaire puisse etre calculee,
4956 // il faut dupliquer les bulles aux frontieres periodiques ; puis supprimer
4957 // ces bulles pour realiser le remailage de l'interface ; puis les dupliquer a nouveau pour calculer l'indicatrice finale.
4958 interfaces_->supprimer_duplicata_bulles();
4959
4960 interfaces_->calculer_vecteurs_de_deplacement_rigide(vitesses_translation_bulles_, mean_bubble_rotation_vector_, centre_gravite_bulles_, first_step_interface_smoothing);
4961
4963 timestep/* total meme si RK3*/, var_volume_par_bulle, rk_step, first_step_interface_smoothing);
4964
4966 var_volume_par_bulle, rk_step, schema_temps_ijk().get_current_time());
4967
4968 interfaces_->transferer_bulle_perio();
4969 interfaces_->creer_duplicata_bulles();
4970 }
4971}
4972
4973void Navier_Stokes_FTD_IJK::sauvegarder_equation(const Nom& lataname, SFichier& fichier) const
4974{
4975 fichier << " tinit " << schema_temps_ijk().get_current_time() << "\n"
4976 << " terme_acceleration_init " << terme_source_acceleration_ << "\n"
4977 << " terme_acceleration_init_z " << terme_source_acceleration_z_ << "\n"
4978 // GAB : qdm_source. Les valeurs des attributs utiles pour le calcul de source_qdm_gr sont
4979 // ecrits dans la reprise. Ils sont ecrits avec des mots-clefs qui n'ont pas vocation a
4980 // etre dans un jdd. Ces mots doivent se trouver uniquement dans des fichiers sauv.
4981 << " reprise_vap_velocity_tmoy " << vap_velocity_tmoy_ << "\n"
4982 << " reprise_liq_velocity_tmoy " << liq_velocity_tmoy_ << "\n"
4983 << " fichier_reprise_vitesse " << basename(lataname) << "\n";
4984 fichier << " timestep_reprise_vitesse 1" << "\n";
4985 if (probleme_ijk().has_interface())
4986 fichier << " interfaces " << interfaces_.valeur() << "\n";
4987 fichier << " forcage " << forcage_ << "\n"
4988 << " corrections_qdm " << qdm_corrections_;
4989
4990 fichier << "velocity_bubble_old " << velocity_bubble_old_ << "\n";
4991 fichier << "vitesse_upstream_reprise " << vitesse_upstream_reprise_ << "\n";
4992}
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
void set_extension_from_bulle_param(double vol_bulle, double diam_bulle)
int get_offset_local(int direction) const
Returns the local offset in requested direction.
int get_nb_elem_local(int direction) const
Returns the number of elements owned by this processor in the given direction.
bool get_periodic_flag(int direction) const
Method returns true if periodic in this direction.
double get_domain_length(int direction) const
Returns the length of the entire domain in requested direction.
int get_nprocessor_per_direction(int direction) const
Returns the number of slices in the given direction.
int ft_extension() const
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.
int get_nb_items_global(Localisation loc, int direction) const
Returns the number of local items (on this processor) for the given localisation in the requested dir...
int get_nb_elem_tot(int direction) const
Returns the total (global) number of mesh cells in requested direction.
int get_local_slice_index(int direction) const
Returns the position of the local subdomain in the requested direction.
Localisation
Localisation sub class.
Definition Domaine_IJK.h:53
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....
const Nom & le_nom() const override
Renvoie le nom de l'equation.
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
Domaine_IJK::Localisation get_localisation() const
const Domaine_IJK & get_domaine() const
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
virtual const Champ_Don_base & gravite() const
Renvoie la gravite du milieu si elle a ete associe provoque une erreur sinon.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
int contient_(const char *const ch) const
Definition Motcle.cpp:333
FixedVector< Redistribute_Field, 3 > redistribute_to_splitting_ft_faces_
Vecteur3 calculer_grad_p_moyen(const IJK_Field_double &pression)
bool has_champ(const Motcle &nom) const override
IJK_Field_vector3_double force_rappel_ft_
IJK_Field_vector3_double rho_u_euler_av_rho_mu_ind_champ_
Fluide_Diphasique_IJK & milieu_ijk()
double calculer_true_moyenne_de_phase_vap(const IJK_Field_double &vx)
void initialise_velocity_from_file(const Nom &fichier_reprise_vitesse)
void calculer_terme_source_acceleration(IJK_Field_double &vx, const double time, const double timestep, const int rk_step)
IJK_Field_vector3_double rho_u_euler_ap_projection_champ_
Redistribute_Field redistribute_from_splitting_ft_elem_ghostz_min_
IJK_Field_vector3_double terme_repulsion_interfaces_ft_
void maj_indicatrice_rho_mu(const bool parcourir=true)
IJK_Field_vector3_double velocity_
Probleme_FTD_IJK_base & probleme_ijk()
IJK_Field_vector3_double terme_pression_in_ustar_local_
IJK_Field_vector3_double variable_source_
IJK_Field_vector3_double terme_diffusion_mass_solver_
const IJK_Field_double & get_IJK_field(const Motcle &nom) override
Boundary_Conditions boundary_conditions_
FixedVector< Redistribute_Field, 3 > redistribute_from_splitting_ft_faces_
IJK_Field_vector3_double rho_u_euler_av_prediction_champ_
IJK_Field_vector3_double terme_repulsion_interfaces_ns_
Multigrille_Adrien poisson_solver_
IJK_Field_vector3_double terme_source_interfaces_ns_
void rk3_sub_step(const int rk_step, const double total_timestep, const double fractionnal_timestep, const double time)
void calculer_terme_volumique(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const IJK_Field_double &rho_, const IJK_Field_double &indica_, DoubleTab &S)
IJK_Field_vector3_double rho_v_
IJK_Field_vector3_double RK3_F_velocity_
bool has_champ_vectoriel(const Motcle &nom) const override
void get_noms_champs_postraitables(Noms &noms, Option opt=NONE) const override
void sauvegarder_equation(const Nom &, SFichier &) const
IJK_Field_vector3_double terme_pression_local_
void compute_add_external_forces(const int dir)
IJK_Field_double pressure_ghost_cells_
Redistribute_Field redistribute_from_splitting_ft_elem_ghostz_max_
IJK_Field_vector3_double velocity_ft_
const Milieu_base & milieu() const override
IJK_Field_vector3_double force_rappel_
IJK_Field_vector3_double terme_abs_repulsion_interfaces_ns_
double calculer_true_moyenne_de_phase_liq(const IJK_Field_double &vx)
void deplacer_interfaces(const double timestep, const int rk_step, ArrOfDouble &var_volume_par_bulle, const int first_step_interface_smoothing)
void euler_explicit_update(const IJK_Field_double &dv, IJK_Field_double &v, const int k_layer) const
void calculer_vitesse_gauche(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, double &vx_moy, double &vy_moy, double &vz_moy)
Vecteur3 calculer_grad_p_over_rho_moyen(const IJK_Field_double &pression)
void calculer_terme_asservissement(double &ax, double &ay, double &az)
void completer() override
Complete la construction (initialisation) des objets associes a l'equation.
void calculer_v_amont_bulle(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const IJK_Field_double &wx, const IJK_Field_double &wy, const IJK_Field_double &wz, DoubleTab &v_amont_, DoubleTab &w_amont_, const DoubleTab &d1_amont_, const DoubleTab &d2_amont_, const DoubleTab &d3_amont_, DoubleTab &compteur_)
IJK_Field_vector3_double terme_abs_repulsion_interfaces_ft_
IJK_Field_vector3_double rho_du_euler_ap_prediction_champ_
double calculer_moyenne_de_phase_liq(const IJK_Field_double &vx)
Schema_Temps_IJK_base & schema_temps_ijk()
Operateur_IJK_faces_diff velocity_diffusion_op_
IJK_Field_vector3_double terme_source_interfaces_ft_
void initialise_velocity_using_expression(const Noms &expression_vitesse_initiale)
Vecteur3 calculer_inv_rho_grad_p_moyen(const IJK_Field_double &inv_rho, const IJK_Field_double &pression)
void compute_add_THI_force_sur_d_velocity(const IJK_Field_vector3_double &vitesse, const int time_iteration, const double dt, const double current_time, const Domaine_IJK &my_splitting, const int facteur)
Redistribute_Field redistribute_to_splitting_ft_elem_
void calculer_terme_S_z(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const IJK_Field_double &p, DoubleTab &S, const int nz)
const IJK_Field_vector3_double & get_IJK_field_vector(const Motcle &nom) override
IJK_Field_vector3_double backup_terme_source_interfaces_ns_
Redistribute_Field redistribute_from_splitting_ft_elem_
void deplacer_interfaces_rk3(const double timestep, const int rk_step, ArrOfDouble &var_volume_par_bulle)
void compute_var_volume_par_bulle(ArrOfDouble &var_volume_par_bulle)
void compute_add_THI_force(const IJK_Field_vector3_double &vitesse, const int time_iteration, const double dt, const double current_time, const Domaine_IJK &my_splitting)
IJK_Field_vector3_double rho_du_euler_ap_projection_champ_
void euler_time_step(ArrOfDouble &var_volume_par_bulle)
IJK_Field_vector3_double terme_diffusion_local_
void calculer_terme_source_acceleration_z(IJK_Field_double &vz, const double time, const double timestep, const int rk_step)
void compute_correction_for_momentum_balance(const int rk_step)
IJK_Field_vector3_double d_velocity_
void calculer_dv(const double timestep, const double time, const int rk_step)
void associer_pb_base(const Probleme_base &) override
S'associe au Probleme passe en parametre.
double calculer_moyenne_de_phase_vap(const IJK_Field_double &vx)
void update_v_or_rhov(bool with_p=false)
void terme_source_gravite(IJK_Field_double &dv, int k_index, int dir) const
void calculer_terme_S_y(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const IJK_Field_double &p, DoubleTab &S, const int ny)
void associer_milieu_base(const Milieu_base &) override
IJK_Field_vector3_double terme_convection_mass_solver_
void write_check_etapes_et_termes(const int rk_step)
IJK_Field_vector3_double zero_field_ft_
Champs_compris_IJK champs_compris_
void redistribute_from_splitting_ft_elem(const IJK_Field_double &input_field, IJK_Field_double &output_field)
void fill_variable_source_and_potential_phi(const double time)
IJK_Field_vector3_double rho_u_euler_ap_rho_mu_ind_champ_
IJK_Field_vector3_double psi_velocity_
void redistribute_to_splitting_ft_elem(const IJK_Field_double &input_field, IJK_Field_double &output_field)
void calculer_vitesse_droite(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, double &vx_moy, double &vy_moy, double &vz_moy)
int preparer_calcul() override
Tout ce qui ne depend pas des autres problemes eventuels.
IJK_Field_vector3_double d_v_diff_et_conv_
IJK_Field_vector3_double laplacien_velocity_
Operateur_IJK_faces_conv velocity_convection_op_
void calculer_terme_S_x(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const IJK_Field_double &p, DoubleTab &S, const int nx)
void calculer_vitesses_bulle(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, DoubleTab &u_bulles_, DoubleTab &compteur_vBulles_)
IJK_Field_vector3_double backup_terme_source_interfaces_ft_
void test_etapes_et_bilan_rho_u_euler(bool apres)
static void Fill_postprocessable_fields(std::vector< FieldInfo_t > &chps)
void set_param(Param &titi) const override
void calculer_base_amont_bulle(const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, const DoubleTab &ubulles, DoubleTab &d1_amont_, DoubleTab &d2_amont_, DoubleTab &d3_amont_, DoubleTab &compteur_base_)
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
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 bool DISABLE_DIPHASIQUE
Definition Option_IJK.h:26
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
Representation des donnees de la classe Parser.
Definition Parser.h:39
void addVar(const char *)
Definition Parser.cpp:565
virtual void setNbVar(int nvar)
Definition Parser.cpp:116
void setVar(const char *sv, double val)
Definition Parser.h:73
double eval()
Definition Parser.h:68
void setString(const std::string &s)
Definition Parser.h:102
virtual void parseString()
Definition Parser.cpp:124
IJK_Field_vector3_double & coords()
Motcles get_liste_post_instantanes() const
void fill_surface_force(IJK_Field_vector3_double &the_field_you_know)
IJK_Field_vector3_double & get_grad_I_ns()
void initialise_stats(Domaine_IJK &splitting, ArrOfDouble &vol_bulles, const double vol_bulle_monodisperse)
const Domaine_IJK & domaine_ijk() const
const Nom & nom_sauvegarde() const
const Postprocessing_IJK & get_post() const
ArrOfDouble_with_ghost & get_delta_z_local()
const Domaine_IJK & get_domaine_ft() const
const Domaine_IJK & get_domaine() 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
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
static double mp_max(double)
Definition Process.cpp:376
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
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
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
Explicit Euler scheme for IJK setups.
double & get_store_RK3_fac_sv()
double & get_store_RK3_source_acc()
Classe de base des flux de sortie.
Definition Sortie.h:52
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469