TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Postprocessing_IJK.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, 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 <Check_espace_virtuel.h>
17#include <Postprocessing_IJK.h>
18#include <Schema_Euler_explicite_IJK.h>
19#include <IJK_Navier_Stokes_tools.h>
20#include <Probleme_FTD_IJK_base.h>
21#include <IJK_Thermal_cut_cell.h>
22#include <IJK_Field_vector.h>
23#include <IJK_Lata_writer.h>
24#include <Schema_RK3_IJK.h>
25#include <Domaine_IJK.h>
26#include <IJK_Interfaces.h>
27#include <Option_IJK.h>
28
29Implemente_instanciable_sans_constructeur(Postprocessing_IJK, "Postprocessing_IJK", Postraitement_ft_lata);
30
31// list of fields that may be postprocessed
32std::vector<Postprocessing_IJK::FieldInfo_t> Postprocessing_IJK::champs_postraitables_ = {};
33
34
35namespace
36{
37// Could not find it elsewhere but surely must already exist?
38inline Entity str_to_entity(const Motcle& loc)
39{
40 if (loc == "ELEM") return Entity::ELEMENT;
41 if (loc == "SOM") return Entity::NODE;
42 if (loc == "FACES") return Entity::FACE;
43
44 Cerr << "Invalid localisation for field postprocessing : '" << loc << "' !!" << finl;
46 return Entity::ELEMENT; // for compilers
47}
48
49inline Nom entity_to_str(const Entity& e)
50{
51 if (e == Entity::ELEMENT) return "ELEM";
52 if (e == Entity::NODE) return "SOM";
53 if (e == Entity::FACE) return "FACES";
54 return "??";
55}
56
57inline int extract_component(const Nom& fld_name)
58{
59 const std::vector<std::string> compos = {"_X", "_Y", "_Z"};
60 std::string s = fld_name.getString();
61 std::string end = s.substr(s.size()-2, 2);
62 auto it = std::find(compos.begin(), compos.end(), end);
63 if(it == compos.end())
64 {
65 Cerr << "ERROR: field name '" << fld_name << "' does not end with a component name (_X, _Y or _Z)!! Should not happend?" << finl;
67 }
68 return (int)std::distance(compos.begin(), it);
69}
70
71}
72
73Postprocessing_IJK::Postprocessing_IJK()
74{
75 groups_statistiques_FT_.dimensionner(0);
76}
77
78Sortie& Postprocessing_IJK::printOn(Sortie& os) const { return os; }
79
81{
82 // temporarily set here, need to find a better place
83 // (or just add them as a trustvect rather than naming individual coords)
84 // or create a wrapper class than has the wanted syntax and overloads []
85 // Expression_Ana_3 : public Objet_U_With_Params
86 // Expression_Ana_6 : public Objet_U_With_Params
87 // with param.ajouter("x", exp) etc
88 expression_vitesse_analytique_.dimensionner_force(3);
89 expression_dvitesse_analytique_.dimensionner_force(3);
90 expression_gradP_analytique_.dimensionner_force(3);
91 expression_gradU_analytique_.dimensionner_force(3);
92 expression_gradV_analytique_.dimensionner_force(3);
93 expression_gradW_analytique_.dimensionner_force(3);
94 expression_grad2P_analytique_.dimensionner_force(6);
95 expression_grad2U_analytique_.dimensionner_force(6);
96 expression_grad2V_analytique_.dimensionner_force(6);
97 expression_grad2W_analytique_.dimensionner_force(6);
99}
100
102{
103 ref_ijk_ft_ = ijk_ft;
104 statistiques_FT_.associer_probleme(ijk_ft);
105 interfaces_ = ref_ijk_ft_->get_interface();
106 pressure_ = ref_ijk_ft_->eq_ns().pressure_;
107 velocity_ = ref_ijk_ft_->eq_ns().velocity_;
108 bk_tsi_ns_ = ref_ijk_ft_->eq_ns().backup_terme_source_interfaces_ns_;
109 d_velocity_ = ref_ijk_ft_->eq_ns().d_velocity_;
110
111 if (ref_ijk_ft_->has_thermals())
112 thermals_ = ref_ijk_ft_->get_ijk_thermals();
113}
114
116{
118
119 param.ajouter("nb_pas_dt_post_thermals_probes", &nb_pas_dt_post_thermals_probes_);
120 param.ajouter("nb_pas_dt_post_stats_bulles", &nb_pas_dt_post_stats_bulles_);
121 param.ajouter("nb_pas_dt_post_stats_plans", &nb_pas_dt_post_stats_plans_);
122 param.ajouter("nb_pas_dt_post_stats_cisaillement", &nb_pas_dt_post_stats_cisaillement_);
123 param.ajouter("nb_pas_dt_post_stats_mrf", &nb_pas_dt_post_stats_mrf_);
124 param.ajouter("nb_pas_dt_post_stats_amont", &nb_pas_dt_post_stats_amont_);
125 param.ajouter("nb_pas_dt_post_stats_fh", &nb_pas_dt_post_stats_fh_);
126
127 param.ajouter("time_interval_post_", &time_interval_post_);
128 param.ajouter("time_interval_post_thermals_probes", &time_interval_post_thermals_probes_);
129 param.ajouter("time_interval_post_stats_bulles", &time_interval_post_stats_bulles_);
130 param.ajouter("time_interval_post_stats_plans", &time_interval_post_stats_plans_);
131 param.ajouter("time_interval_post_stats_cisaillement", &time_interval_post_stats_cisaillement_);
132 param.ajouter("time_interval_post_stats_mrf", &time_interval_post_stats_mrf_);
133
134 param.ajouter("champs_a_postraiter", &liste_post_instantanes_);
135
136 param.ajouter_flag("check_stats", &check_stats_);
137 param.ajouter_flag("postraiter_sous_pas_de_temps", &postraiter_sous_pas_de_temps_);
138 // Pour reconstruire au post-traitement la grandeur du/dt, on peut choisir de relever u^{dt_post} et u^{dt_post+1} :
139 param.ajouter_flag("post_par_paires", &post_par_paires_);
140
141 param.ajouter("expression_vx_ana", &expression_vitesse_analytique_[0]);
142 param.ajouter("expression_vy_ana", &expression_vitesse_analytique_[1]);
143 param.ajouter("expression_vz_ana", &expression_vitesse_analytique_[2]);
144
145 param.ajouter("expression_dvx_ana", &expression_dvitesse_analytique_[0]);
146 param.ajouter("expression_dvy_ana", &expression_dvitesse_analytique_[1]);
147 param.ajouter("expression_dvz_ana", &expression_dvitesse_analytique_[2]);
148 param.ajouter("expression_p_ana", &expression_pression_analytique_);
149
150 param.ajouter("expression_dPdx_ana", &expression_gradP_analytique_[0]);
151 param.ajouter("expression_dPdy_ana", &expression_gradP_analytique_[1]);
152 param.ajouter("expression_dPdz_ana", &expression_gradP_analytique_[2]);
153
154 param.ajouter("expression_dUdx_ana", &expression_gradU_analytique_[0]);
155 param.ajouter("expression_dUdy_ana", &expression_gradU_analytique_[1]);
156 param.ajouter("expression_dUdz_ana", &expression_gradU_analytique_[2]);
157
158 param.ajouter("expression_dVdx_ana", &expression_gradV_analytique_[0]);
159 param.ajouter("expression_dVdy_ana", &expression_gradV_analytique_[1]);
160 param.ajouter("expression_dVdz_ana", &expression_gradV_analytique_[2]);
161
162 param.ajouter("expression_dWdx_ana", &expression_gradW_analytique_[0]);
163 param.ajouter("expression_dWdy_ana", &expression_gradW_analytique_[1]);
164 param.ajouter("expression_dWdz_ana", &expression_gradW_analytique_[2]);
165
166 // Pour les seconds gradients :
167 param.ajouter("expression_ddPdxdx_ana", &expression_grad2P_analytique_[0]);
168 param.ajouter("expression_ddPdydy_ana", &expression_grad2P_analytique_[1]);
169 param.ajouter("expression_ddPdzdz_ana", &expression_grad2P_analytique_[2]);
170 param.ajouter("expression_ddPdxdy_ana", &expression_grad2P_analytique_[3]);
171 param.ajouter("expression_ddPdxdz_ana", &expression_grad2P_analytique_[4]);
172 param.ajouter("expression_ddPdydz_ana", &expression_grad2P_analytique_[5]);
173 // And for velocities :
174 param.ajouter("expression_ddUdxdx_ana", &expression_grad2U_analytique_[0]);
175 param.ajouter("expression_ddUdydy_ana", &expression_grad2U_analytique_[1]);
176 param.ajouter("expression_ddUdzdz_ana", &expression_grad2U_analytique_[2]);
177 param.ajouter("expression_ddUdxdy_ana", &expression_grad2U_analytique_[3]);
178 param.ajouter("expression_ddUdxdz_ana", &expression_grad2U_analytique_[4]);
179 param.ajouter("expression_ddUdydz_ana", &expression_grad2U_analytique_[5]);
180
181 param.ajouter("expression_ddVdxdx_ana", &expression_grad2V_analytique_[0]);
182 param.ajouter("expression_ddVdydy_ana", &expression_grad2V_analytique_[1]);
183 param.ajouter("expression_ddVdzdz_ana", &expression_grad2V_analytique_[2]);
184 param.ajouter("expression_ddVdxdy_ana", &expression_grad2V_analytique_[3]);
185 param.ajouter("expression_ddVdxdz_ana", &expression_grad2V_analytique_[4]);
186 param.ajouter("expression_ddVdydz_ana", &expression_grad2V_analytique_[5]);
187
188 param.ajouter("expression_ddWdxdx_ana", &expression_grad2W_analytique_[0]);
189 param.ajouter("expression_ddWdydy_ana", &expression_grad2W_analytique_[1]);
190 param.ajouter("expression_ddWdzdz_ana", &expression_grad2W_analytique_[2]);
191 param.ajouter("expression_ddWdxdy_ana", &expression_grad2W_analytique_[3]);
192 param.ajouter("expression_ddWdxdz_ana", &expression_grad2W_analytique_[4]);
193 param.ajouter("expression_ddWdydz_ana", &expression_grad2W_analytique_[5]);
194
195 param.ajouter("t_debut_statistiques", &t_debut_statistiques_);
196
197 // mots clés pour la reprise de stats
198 param.ajouter_flag("reset_reprise_integrated", &reset_reprise_integrated_);
199}
200
202{
203 Motcle motlu;
204 is >> motlu;
205
207 Cerr << "Post-processing for the interface of IJK_interfaces object named: '" << motlu << "'" << finl;
208
209 // Check valid interface equation name:
210 Motcle interf_nam;
211 for (int i=0; i < mon_probleme->nombre_d_equations(); i++)
212 {
213 const Equation_base& eb = mon_probleme->equation(i);
214 if (motlu == eb.le_nom() && eb.que_suis_je() == "IJK_Interfaces")
215 interf_nam = eb.le_nom();
216 }
217
218 if (motlu != interf_nam)
219 {
220 Cerr << "ERROR: the requested interface equation '" << motlu << "' is not available for post-processing!!!" << finl;
222 }
223
224 is >> motlu;
225 if (motlu != "{")
226 {
227 Cerr << "ERROR: Postprocessing_IJK::lire_entete_bloc_interface()\n";
228 Cerr << " { was expected after the keyword interfaces\n";
229 Cerr << " We found '" << motlu << "'" << finl;
231 }
232}
233
234void Postprocessing_IJK::register_one_field(const Motcle& fld_nam, const Motcle& reqloc_s)
235{
236 Entity reqloc = str_to_entity(reqloc_s);
237 noms_champs_a_post_.add(fld_nam);
238
239 Motcle true_field_name = fld_nam;
240
241 // IJK_Thermals gives a list of possible prefixes. The field names are appended with _index when added to champs_compris by individual thermal equations
242 // Because of that, we have to get the prefix from the field name asked
243 const std::string& str = fld_nam.getString();
244 std::string key ("_");
245 std::size_t found = str.rfind(key);
246 if (found!=std::string::npos)
247 {
248 Nom var = Nom(str.substr(0,found));
249 found++;
250 try
251 {
252 // this may raise exception if field name did not finish with integer. Then we go to catch block below
253 std::stoi(str.substr(found));
254 // Cerr << "field was suffixed with an integer: " << fld_nam<<finl;
255 // if field was ending with integer, check that the prefix is known by ijk thermals
256 std::vector<FieldInfo_t> prefix_thermals;
258 for (const auto& f : prefix_thermals)
259 {
260 Nom prefix = std::get<0>(f);
261 if (prefix == var)
262 {
263 // if we found a matching prefix, we know that the field location must be defined by the prefix
264 true_field_name=prefix;
265 Cerr << " For IJK_thermals: postpro field name '" << fld_nam << "' matched with prefix " << true_field_name << " defined in IJK_thermals::Fill_postprocessable_fields " << finl;
266
267 // then we must add an entry to champs_postraitables_ so that the field can be found
268 std::vector<FieldInfo_t> c = {{ fld_nam, std::get<1>(f), std::get<2>(f), std::get<3>(f)}};
269 champs_postraitables_.insert(champs_postraitables_.end(), c.begin(), c.end());
270 }
271 }
272 }
273 catch ( const std::invalid_argument& )
274 {
275 // in that case, everything is fine, field name should be treated as normal (not from thermals)
276 // Cerr << "field was not suffixed with an integer: " << fld_nam<<finl;
277 }
278 }
279
280 for (const auto& f : champs_postraitables_)
281 {
282 // Prepare entries in storage map (some of them might not be used for example when postprocessing
283 // an unknown directly):
284 // Teo Boutin: moved here because sometime a post may depend on another.
285 // Then some fields in the map may not be prepared
286 // For example: if CURL is asked in post but not CRITERE_Q, we try in alloc_fields to allocate scalar_post_fields_.at("CRITERE_Q") which was not pre initialized.
287 // now we pre fill for every post processable field. Probably there is a better solution
288 Motcle nom2 = std::get<0>(f);
289 if ((get<2>(f) == Nature_du_champ::scalaire) && (!scalar_post_fields_.count(nom2)))
290 {
291 scalar_post_fields_[nom2] = IJK_Field_double();
292 }
293 if((get<2>(f) == Nature_du_champ::vectoriel) && (!vect_post_fields_.count(nom2)))
294 {
295 vect_post_fields_[nom2] = IJK_Field_vector3_double();
296 }
297 }
298
299
300 // Lookup the field in champs_postraitables_
301 int idx = 0;
302 for (const auto& f : champs_postraitables_)
303 {
304 Motcle nom2 = std::get<0>(f);
305 Entity loc2 = std::get<1>(f);
306
307 bool want_interp = (reqloc == Entity::ELEMENT && loc2 == Entity::FACE);
308 if(nom2 == fld_nam
309 && (reqloc == loc2 || want_interp)) // allow FACE to ELEMENT interpolation
310 {
311 // If already there, error:
312 FieldIndex_t k = {idx, want_interp};
313 if (std::find(field_post_idx_.begin(), field_post_idx_.end(), k) != field_post_idx_.end())
314 {
315 Cerr << "ERROR: field '" << fld_nam << "' at localisation '"<< reqloc_s <<"' duplicated in list of fields to be postprocessed!!" << finl;
317 }
318 field_post_idx_.push_back(k);
319 list_post_required_.push_back(fld_nam);
320 break;
321 }
322
323 idx++;
324 }
325
326 if (idx == (int)champs_postraitables_.size())
327 {
328 Cerr << "ERROR: field '" << fld_nam << "' at localisation '"<< reqloc_s <<"' is not available for postprocessing!!" << finl;
330 }
331}
332
333/** Override. Called from base class.
334 */
335void Postprocessing_IJK::register_interface_field(const Motcle& nom_champ, const Motcle& loc_lu)
336{
337 Entity e = str_to_entity(loc_lu);
338
339 // Check the field is indeed on the interface:
340 std::vector<FieldInfo_t> flds;
342 bool ok=false;
343 for (const auto& f : flds)
344 {
345 Motcle nom2 = get<0>(f);
346 Entity loc2 = get<1>(f);
347 bool isOnInterface = get<3>(f); // must check that it is truly on interface, as IJK_Interfaces also defines eulerian fields
348 if(isOnInterface && nom2 == nom_champ && e == loc2)
349 {
350 ok = true;
351 break;
352 }
353 }
354 if(!ok)
355 {
356 Cerr << "ERROR: on the interface, field '" << nom_champ << "' at localisation '"<< loc_lu <<"' is not available for postprocessing!!" << finl;
358 }
359 // Everything ok, we register the field for post:
360 register_one_field(nom_champ, loc_lu);
361 interface_post_required_ = true;
362}
363
364/** Override to have a simpler logic than base class. We really want to retrieve names + location.
365 */
367{
368 Motcle accolade_fermee("}"), motlu;
369
370 is >> motlu;
371
372 while (motlu != accolade_fermee)
373 {
374 Motcle loc;
375 is >> loc;
376 register_one_field(motlu, loc);
377 is >> motlu;
378 }
379
380 return 1;
381}
382
383/** Initialise lata file and various other stuff
384 */
386{
387 if(!nom_fich_.finit_par(".lata"))
388 nom_fich_ = nom_fich_ + Nom(".lata");
389
390 // Post_processing field allocations:
391 alloc_fields();
393
394 // Integrated field initialisation
395 init_integrated_and_ana(ref_ijk_ft_->get_reprise());
396
398
400
402}
403
404/**
405 * Write the master lata file and prepare statistics and other stuff
406 */
408{
409 const Nom& lata_name = nom_fich_;
410 const double current_time = ref_ijk_ft_->schema_temps_ijk().get_current_time();
411 dumplata_header(lata_name);
412 dumplata_add_geometry(lata_name, velocity_.valeur()[0]);
413 dumplata_add_geometry(lata_name, ref_ijk_ft_->eq_ns().velocity_ft_[0]);
414
415 // Calcul des moyennes spatiales sur la condition initiale:
416 if (is_stats_plans_activated() && current_time >= t_debut_statistiques_)
417 {
418 // FA AT 16/07/2013 pensent que necessaire pour le calcul des derivees dans statistiques_.update_stat_k(...)
419 // Je ne sais pas si c'est utile, mais j'assure...
420 velocity_.valeur()[0].echange_espace_virtuel(2 /*, IJK_Field_ST::EXCHANGE_GET_AT_RIGHT_I*/);
421 velocity_.valeur()[1].echange_espace_virtuel(2 /*, IJK_Field_ST::EXCHANGE_GET_AT_RIGHT_J*/);
422 velocity_.valeur()[2].echange_espace_virtuel(2 /*, IJK_Field_ST::EXCHANGE_GET_AT_RIGHT_K*/);
423 pressure_->echange_espace_virtuel(1);
424
425 // C'est update_stat_ft qui gere s'il y a plusieurs groupes
426 // pour faire la vraie indicatrice + les groupes
427 update_stat_ft(0.);
428 }
429}
430
432{
433 // Take care of fields and probes - new mode
435
436// // Take care of fields - OLD MODE:
437// {
438// Schema_Temps_IJK_base& sch = ref_ijk_ft_->schema_temps_ijk();
439// Cout << "BF posttraiter_champs_instantanes " << sch.get_current_time() << " " << sch.get_tstep() << finl;
440// posttraiter_champs_instantanes(nom_fich_, sch.get_current_time(), sch.get_tstep());
441// if (ref_ijk_ft_->has_thermals())
442// ref_ijk_ft_->get_ijk_thermals().thermal_subresolution_outputs(); // for thermal counters
443// Cout << "AF posttraiter_champs_instantanes" << finl;
444// }
445
446 // Thermal part
447 postraiter_thermals(forcer);
448
449 // Statistics (bubbles, etc.)
450 postraiter_stats(forcer);
451
452 // Probes update -
453 // TODO : not necessary? done in base class?
454 Schema_Temps_IJK_base& sch = ref_ijk_ft_->schema_temps_ijk();
455 double current_time = sch.get_current_time(),
456 timestep = sch.get_timestep();
457 les_sondes_.mettre_a_jour(current_time, timestep);
458}
459
460/** Override. Write the interface mesh if present, and the integer field 'COMPO_CONNEXE' on it.
461 */
463{
464 if(!interface_post_required_ || !ref_ijk_ft_->has_interface())
465 return 1;
466 Schema_Temps_IJK_base& sch = ref_ijk_ft_->schema_temps_ijk();
467 int latastep = sch.get_tstep();
468 const IJK_Interfaces& interf = ref_ijk_ft_->get_interface();
469 interf.dumplata_ft_mesh(nom_fich_.getChar(), "INTERFACES", latastep);
470
471 // Writing systematically COMPO_CONNEXE, the only integer field:
472 const ArrOfInt& comp_c = ref_ijk_ft_->get_interface().maillage_ft_ijk().compo_connexe_facettes();
473 dumplata_ft_field(nom_fich_, "INTERFACES", "COMPO_CONNEXE", "ELEM", comp_c, latastep);
474
475 return 1;
476}
477
478static inline bool check_loc_compat(Entity requested_loc, Domaine_IJK::Localisation loc_ijk, bool want_interp)
479{
480 using LocIJK = Domaine_IJK::Localisation;
481 if (requested_loc == Entity::ELEMENT && loc_ijk == LocIJK::ELEM)
482 return true;
483 if (requested_loc == Entity::NODE && loc_ijk == LocIJK::NODES)
484 return true;
485 if ((loc_ijk == LocIJK::FACES_I || loc_ijk == LocIJK::FACES_J || loc_ijk == LocIJK::FACES_K))
486 {
487 if(requested_loc == Entity::FACE) return true;
488 if(requested_loc == Entity::ELEMENT) // natural localisation is face, user wants interpolation to ELEM - OK
489 {
490 assert(want_interp);
491 return true;
492 }
493 }
494 return false;
495}
496
497/*! Override from 'Postraitement' since the logic is simpler here
498 */
500{
501 int latastep = ref_ijk_ft_->schema_temps_ijk().get_tstep();
502
503 // Write out a new time in the lata:
504 dumplata_newtime(nom_fich_, ref_ijk_ft_->schema_temps_ijk().get_current_time());
505
506 // Write INTERFACES if there:
508
509 // Dump requested fields:
510 for (const FieldIndex_t& v : field_post_idx_)
511 {
512 int idx = get<0>(v);
513 bool want_interpolation = get<1>(v);
514 const FieldInfo_t& fld_info = champs_postraitables_[idx];
515 Motcle fld_nam = get<0>(fld_info);
516 Entity fld_loc = get<1>(fld_info); // the natural localisation of field
517 Nature_du_champ nat = get<2>(fld_info);
518 bool is_on_interf = get<3>(fld_info);
519
520 if (!ref_ijk_ft_->has_champ(fld_nam) && !ref_ijk_ft_->has_champ_vectoriel(fld_nam) )
521 {
522 Cerr << finl << "ERROR Field '" << fld_nam << "' is not available for postprocessing!" << finl << finl;
523 Cerr << "(Fields currently available are : " << finl;
524 Noms ns;
525 ref_ijk_ft_->get_noms_champs_postraitables(ns, Option::DESCRIPTION);
526 for (const auto& n: ns) Cerr << n << " ";
527 Cerr << ")" << finl;
529 }
530
531 if (nat == Nature_du_champ::scalaire)
532 {
533 const IJK_Field_double* fld = &(ref_ijk_ft_->get_IJK_field(fld_nam));
534 assert(fld->nature_du_champ() == Nature_du_champ::scalaire);
535
536 if (is_on_interf) // for now, loc validity is not checked for interf fields ...
537 dumplata_ft_field(nom_fich_, "INTERFACES", fld_nam, entity_to_str(fld_loc), fld->data(), latastep);
538 else
539 {
540 if (!check_loc_compat(fld_loc, fld->get_localisation(), want_interpolation))
541 {
542 Cerr << "ERROR Field '" << fld_nam << "' is available for postprocessing, but NOT at localisation '" << entity_to_str(fld_loc) << "'!" << finl;
544 }
545 if(want_interpolation)
546 {
547 // First time we interpolate - needs to allocate storage:
548 if (post_projected_field_.get_ptr(0) == nullptr)
549 allocate_cell_vector(post_projected_field_, domaine_ijk_, 0);
550 // Identify the correct component to use for temp storage (we could have had separate temporary members for
551 // component interpolation, but I don't think this would have made the below any better/shorter ...):
552 int compo_num = extract_component(fld_nam);
553 interpolate_to_center_compo(post_projected_field_[compo_num], *fld);
554 post_projected_field_[compo_num].dumplata_scalar(nom_fich_, latastep);
555 }
556 else
557 fld->dumplata_scalar(nom_fich_, latastep);
558 }
559 }
560 else if (nat == Nature_du_champ::vectoriel)
561 {
562 if(is_on_interf)
563 {
564 Cerr << "ERROR: post-processing of vectorial field on the interface not implemented (here '" << fld_nam << "') !" << finl;
566 }
567
568 const IJK_Field_vector3_double& fld = ref_ijk_ft_->get_IJK_field_vector(fld_nam);
569 const Entity loc = fld.localisation();
570 assert(fld.nature_du_champ() == Nature_du_champ::vectoriel);
571 if (loc == Entity::ELEMENT && fld_loc == Entity::FACE)
572 {
573 Cerr << "ERROR Field '" << fld_nam << "' is available for postprocessing on '" << entity_to_str(loc) << "' and can not be projected to '" << entity_to_str(fld_loc) << "'" << finl;
575 }
576 if (want_interpolation) // needs interpolation
577 {
578 assert(loc == Entity::FACE && fld_loc == Entity::FACE);
579 // First time we interpolate - needs to allocate storage:
580 if (post_projected_field_.get_ptr(0) == nullptr)
581 allocate_cell_vector(post_projected_field_, domaine_ijk_, 0);
582 // TODO: pour ABN from GB : problem avec le const ! -> faire un ref_cast_non_const tout moche?
583 // for (int dir2 = 0; dir2 < 3; dir2++)
584 // fld[dir2].echange_espace_virtuel(fld[dir2].ghost());
585 /* Exit in error if the virtual spaces of the distributed array are not up to date */
586 // for (int dir2 = 0; dir2 < 3; dir2++) assert(check_espace_virtuel_vect(fld[dir2]));
587 interpolate_to_center(post_projected_field_, fld);
588 dumplata_cellvector(nom_fich_,Nom("CELL_") + fld_nam, post_projected_field_, latastep);
589 }
590 if(fld_loc != loc) // Incompatible localisations, not interpolation possible
591 {
592 Cerr << "ERROR Field '" << fld_nam << "' is available for postprocessing, but NOT at localisation '" << entity_to_str(fld_loc) << "' !" << finl;
594 }
595
596 switch(loc)
597 {
598 case Entity::NODE:
599 Process::exit("ERROR: post-processing vectorial field on NODES not implemented!");
600 break;
601 case Entity::ELEMENT:
602 dumplata_cellvector(nom_fich_, fld_nam, fld, latastep);
603 break;
604 case Entity::FACE:
605 dumplata_vector(nom_fich_, fld_nam, fld[0], fld[1], fld[2], latastep);
606 break;
607 default:
608 Process::exit("ERROR: Unexpected error!");
609 }
610 } // if(nat == vectoriel)
611 else // nat == Nature_du_champ::multi_scalaire
612 Process::exit("ERROR: no multiscalar support!!");
613 }
614 return 1;
615}
616
618{
619 domaine_ijk_ = dom_ijk;
620 domaine_ft_ = dom_ft;
621 statistiques_FT_.associer_domaine(dom_ijk);
622}
623
625{
626 Navier_Stokes_FTD_IJK& ns = ref_ijk_ft_->eq_ns();
627
628
629 // En reprise, il se peut que le champ ne soit pas dans la liste des posts, mais qu'on l'ait quand meme.
630 // Dans ce cas, on choisi de le lire, remplir le field et le re-sauvegarder a la fin (on n'en a rien fait de plus entre temps...)
631 if (
633 || is_post_required("INDICATRICE_PERTURBE")
634 || ((reprise) && ((ns.fichier_reprise_vitesse_ != "??"))) // TODO teo boutin: read from fichier_reprise_interface maybe ??
635 )
636 {
637 indicatrice_non_perturbe_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "INDICATRICE_PERTURBE");
639 fill_indic(ref_ijk_ft_->get_reprise());
640 }
641
642 // pour relire les champs de temps integres:
643 if (is_post_required("INTEGRATED_TIMESCALE"))
644 {
645 integrated_timescale_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "INTEGRATED_TIMESCALE");
647 if ((reprise) && (!reset_reprise_integrated_))
648 {
649 if (ns.fichier_reprise_vitesse_ == "??")
650 {
651 Cerr << "fichier_reprise_vitesse_ should be specified in the restart file in Navier_Stokes_FTD_IJK object" << endl;
653 }
654 const int timestep_reprise_integrated_timescale_ = 1;
655 const Nom& geom_name = integrated_timescale_.get_domaine().le_nom();
656
657 if (!lata_has_field(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_timescale_, geom_name, "INTEGRATED_TIMESCALE"))
658 {
659 Cerr << "fichier_reprise_vitesse_ " << ns.fichier_reprise_vitesse_ << " does not contain field INTEGRATED_TIMESCALE to restart statistics. You may specify the flag reset_reprise_integrated in postprocessing to reset statistics" << endl;
661 }
662 lire_dans_lata(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_timescale_, geom_name, "INTEGRATED_TIMESCALE", integrated_timescale_); // fonction qui lit un champ a partir d'un lata .
663 }
664 else
665 {
666 integrated_timescale_.data() = 0.;
667 // Question GB pour Antoine : c'est une precaution pour pas qu'il vaille 0 au debut?
668 // Mais du coup, on le compte deux fois...
669 update_integral_indicatrice(interfaces_->In(), 1. /* Should be the integration timestep */, integrated_timescale_);
670 }
671 }
672
673 // Pour relire les champs de vitesse et pression integres :
674 if ((( ns.coef_immobilisation_ > 1e-16) && is_stats_plans_activated()) || is_post_required("INTEGRATED_VELOCITY"))
675 {
676 allocate_velocity(integrated_velocity_, domaine_ijk_, 2, "INTEGRATED_VELOCITY");
677 champs_compris_.ajoute_champ_vectoriel(integrated_velocity_);
678 }
679 if (is_post_required("INTEGRATED_VELOCITY"))
680 {
681 if ((reprise) && (!reset_reprise_integrated_))
682 {
683 if (ns.fichier_reprise_vitesse_ == "??")
684 {
685 Cerr << "fichier_reprise_vitesse_ should be specified in the restart file in Navier_Stokes_FTD_IJK object" << endl;
687 }
688 const int timestep_reprise_integrated_velocity_ = 1;
689 const Nom& geom_name = velocity_.valeur()[0].get_domaine().le_nom();
690
691 if (!lata_has_field(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_velocity_, geom_name, "INTEGRATED_VELOCITY"))
692 {
693 Cerr << "fichier_reprise_vitesse_ " << ns.fichier_reprise_vitesse_ << " does not contain field INTEGRATED_VELOCITY to restart statistics. You may specify the flag reset_reprise_integrated in postprocessing to reset statistics" << endl;
695 }
696
697 cout << "Lecture vitesse integree initiale dans fichier " << ns.fichier_reprise_vitesse_ << " timestep= " << timestep_reprise_integrated_velocity_ << endl;
698 lire_dans_lata(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_velocity_, geom_name, "INTEGRATED_VELOCITY", integrated_velocity_[0], integrated_velocity_[1],
699 integrated_velocity_[2]); // fonction qui lit un champ a partir d'un lata .
700 }
701 else
702 {
703 for (int i = 0; i < 3; i++)
704 integrated_velocity_[i].data() = 0.;
705 velocity_.valeur()[0].echange_espace_virtuel(velocity_.valeur()[0].ghost());
706 velocity_.valeur()[1].echange_espace_virtuel(velocity_.valeur()[1].ghost());
707 velocity_.valeur()[2].echange_espace_virtuel(velocity_.valeur()[2].ghost());
708
709 update_integral_velocity(velocity_, integrated_velocity_, interfaces_->In(), integrated_timescale_);
710
711 }
712 }
713
714 if ((( ns.coef_immobilisation_ > 1e-16) && is_stats_plans_activated()) || is_post_required("INTEGRATED_PRESSURE"))
715 {
716 integrated_pressure_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "INTEGRATED_PRESSURE");
718 }
719
720 if (is_post_required("INTEGRATED_PRESSURE"))
721 {
722 if ((reprise) && (!reset_reprise_integrated_))
723 {
724 if (ns.fichier_reprise_vitesse_ == "??")
725 {
726 Cerr << "fichier_reprise_vitesse_ should be specified in the restart file in Navier_Stokes_FTD_IJK object" << endl;
728 }
729 const int timestep_reprise_integrated_pressure_ = 1;
730 const Nom& geom_name = pressure_->get_domaine().le_nom();
731
732 if (!lata_has_field(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_pressure_, geom_name, "INTEGRATED_PRESSURE"))
733 {
734 Cerr << "fichier_reprise_vitesse_ " << ns.fichier_reprise_vitesse_ << " does not contain field INTEGRATED_PRESSURE to restart statistics. You may specify the flag reset_reprise_integrated in postprocessing to reset statistics" << endl;
736 }
737 cout << "Lecture pression integree initiale dans fichier " << ns.fichier_reprise_vitesse_ << " timestep= " << timestep_reprise_integrated_pressure_ << endl;
738 lire_dans_lata(ns.fichier_reprise_vitesse_, timestep_reprise_integrated_pressure_, geom_name, "INTEGRATED_PRESSURE", integrated_pressure_); // fonction qui lit un champ a partir d'un lata .
739
740 }
741 else
742 {
743 integrated_pressure_.data() = 0.;
744
745 // Le champ de pression initial ne vaut-il pas forcemment 0?
746 update_integral_pressure(pressure_, integrated_pressure_, interfaces_->In(), integrated_timescale_);
747
748 }
749 }
750
751 // Pour le post-traitement de lambda2 - ALREADY DONE IN alloc_fields() !!!
752// if (liste_post_instantanes_.contient_("LAMBDA2"))
753// {
754//// lambda2_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
755// dudy_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
756// dvdx_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
757// dwdy_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
758// }
759
760 // Pour le check_stats_ :
761 if (check_stats_)
762 {
763 Cout << "Initialisation champs analytiques (derivee P)" << "\ndPdx = " << expression_gradP_analytique_[0] << "\ndPdy = " << expression_gradP_analytique_[1] << "\ndPdz = "
764 << expression_gradP_analytique_[2] << finl;
765
766 Cout << "Initialisation champs analytiques (derivee U)" << "\ndUdx = " << expression_gradU_analytique_[0] << "\ndUdy = " << expression_gradU_analytique_[1] << "\ndUdz = "
767 << expression_gradU_analytique_[2] << finl;
768
769 Cout << "Initialisation champs analytiques (derivee V)" << "\ndVdx = " << expression_gradV_analytique_[0] << "\ndVdy = " << expression_gradV_analytique_[1] << "\ndVdz = "
770 << expression_gradV_analytique_[2] << finl;
771
772 Cout << "Initialisation champs analytiques (derivee W)" << "\ndWdx = " << expression_gradW_analytique_[0] << "\ndWdy = " << expression_gradW_analytique_[1] << "\ndWdz = "
773 << expression_gradW_analytique_[2] << finl;
774
775 Cout << "Initialisation champs analytiques (derivees secondes P) " << "\nddPdxdx = " << expression_grad2P_analytique_[0] << "\nddPdydy = " << expression_grad2P_analytique_[1] << "\nddPdzdz = "
777 Cout << "\nddPdxdy = " << expression_grad2P_analytique_[3] << "\nddPdxdz = " << expression_grad2P_analytique_[4] << "\nddPdydz = " << expression_grad2P_analytique_[5] << finl;
778
779 Cout << "Initialisation champs analytiques (derivees secondes U) " << "\nddUdxdx = " << expression_grad2U_analytique_[0] << "\nddUdydy = " << expression_grad2U_analytique_[1] << "\nddUdzdz = "
781 Cout << "\nddUdxdy = " << expression_grad2U_analytique_[3] << "\nddUdxdz = " << expression_grad2U_analytique_[4] << "\nddUdydz = " << expression_grad2U_analytique_[5] << finl;
782
783 Cout << "Initialisation champs analytiques (derivees secondes V) " << "\nddVdxdx = " << expression_grad2V_analytique_[0] << "\nddVdydy = " << expression_grad2V_analytique_[1] << "\nddVdzdz = "
785 Cout << "\nddVdxdy = " << expression_grad2V_analytique_[3] << "\nddVdxdz = " << expression_grad2V_analytique_[4] << "\nddVdydz = " << expression_grad2V_analytique_[5] << finl;
786
787 Cout << "Initialisation champs analytiques (derivees secondes W) " << "\nddWdxdx = " << expression_grad2W_analytique_[0] << "\nddWdydy = " << expression_grad2W_analytique_[1] << "\nddWdzdz = "
789 Cout << "\nddWdxdy = " << expression_grad2W_analytique_[3] << "\nddWdxdz = " << expression_grad2W_analytique_[4] << "\nddWdydz = " << expression_grad2W_analytique_[5] << finl;
790
791 // Le remplissage des set_field est fait par l'objet Statistiques au moment de l'appel a get_IJK_...
792 }
793}
794
796{
797 // Meme if que pour l'allocation.
798 // On ne fait le calcul/remplissage du champ que dans un deuxieme temps car on
799 // n'avait pas les interfaces avant (lors de l'init)
800 if (((ref_ijk_ft_->eq_ns().coef_immobilisation_ > 1e-16) && is_stats_plans_activated()) || is_post_required("INDICATRICE_PERTURBE")
801 || (reprise && (fichier_reprise_indicatrice_non_perturbe_ != "??")))
802 {
804 }
805}
806
807void Postprocessing_IJK::initialise_stats(Domaine_IJK& splitting, ArrOfDouble& vol_bulles, const double vol_bulle_monodisperse)
808{
809 cout << "Initialisation des statistiques. T_debut_statistiques=" << t_debut_statistiques_ << endl;
810 statistiques_FT_.initialize(ref_ijk_ft_, splitting, check_stats_);
811 // Si on utilise un seul groupe et qu'on impose un volume unique a toutes les bulles,
812 if (vol_bulle_monodisperse >= 0.)
813 {
814 // on redimensionne le tableau a nb bulles reelles'
815 vol_bulles.resize_array(interfaces_->get_nb_bulles_reelles());
816 vol_bulles = vol_bulle_monodisperse;
817 }
818 // S'il n'y a pas qu'un group, on s'occupe des objets stats pour chaque group:
819 const int nb_groups = interfaces_->nb_groups();
820 if (nb_groups > 1)
821 {
822 groups_statistiques_FT_.dimensionner(nb_groups);
823 for (int igroup = 0; igroup < nb_groups; igroup++)
824 groups_statistiques_FT_[igroup].initialize(ref_ijk_ft_, splitting, check_stats_);
825 }
826}
827
829{
830 // Est-il deja rempli et stocke?
831 // Si on n'est pas en reprise de calcul, le fichier "fichier_reprise_indicatrice_non_perturbe_" est forcement a "??"
833 {
834 const int timestep_reprise_indicatrice_non_perturbe = 1; // 1 ou 0 est le premier? attention au get_db ou latadb...
835 cout << "Lecture indicatrice non perturbee dans fichier " << fichier_reprise_indicatrice_non_perturbe_ << " timestep= " << timestep_reprise_indicatrice_non_perturbe << endl;
836 const Nom& geom_name = indicatrice_non_perturbe_.get_domaine().le_nom();
837 lire_dans_lata(fichier_reprise_indicatrice_non_perturbe_, timestep_reprise_indicatrice_non_perturbe, geom_name, "INDICATRICE_PERTURBE", indicatrice_non_perturbe_); // fonction qui lit un champ a partir d'un lata .
838 }
839 else if (
840 (( ref_ijk_ft_->eq_ns().coef_immobilisation_ > 1e-16) && is_stats_plans_activated())
841 || is_post_required("INDICATRICE_PERTURBE")
842 )
843 {
844
845 // Sinon, on le calcule une fois pour toute (cas bulles fixe = le champ ne varie pas en temps...)
846 ArrOfDouble volume_reel;
847 DoubleTab position;
848 interfaces_->calculer_volume_bulles(volume_reel, position);
849 interfaces_->compute_indicatrice_non_perturbe(indicatrice_non_perturbe_, ref_ijk_ft_->get_interface().I(), volume_reel, position);
850 supprimer_chevauchement(indicatrice_non_perturbe_);
851 }
852}
853
854void Postprocessing_IJK::posttraiter_champs_instantanes(const char *lata_name, double current_time, int time_iteration)
855{
856 throw; // THIS METHOD SHOULD NOT BE CALLED ANYMORE
857}
858
859// 2020.03.12. CHOIX : Meme en disable_diphasique, on fait appel a la classe fille stats FT
861{
863 {
864 Nom n("");
865 // post-traitement des stats diphasiques :
866 // (si calcul monophasique, on devrait avoir chi=1)
867 for (int flag_valeur_instantanee = 0; flag_valeur_instantanee < 2; flag_valeur_instantanee++)
868 {
870 n = "monophasique_";
871 else
872 n = "diphasique_";
873
874 if (flag_valeur_instantanee == 0)
875 n += "statistiques_";
876 else
877 n += "moyenne_spatiale_";
878
879 n += Nom(current_time);
880 if ((flag_valeur_instantanee) || (statistiques_FT_.t_integration() > 0.))
881 {
882 SFichier f(n + Nom(".txt"));
883 f.setf(ios::scientific); // precision pour allez chercher les 4 ordres
884 f.precision(15);
885 statistiques_FT_.postraiter(f, flag_valeur_instantanee /* flag pour ecrire la moyenne instantanee ou la moyenne */);
886 statistiques_FT_.postraiter_thermique(current_time); /* moyenne instantanee et temporelle */
887
888 // S'il n'y a pas qu'un group, on posttraite les objets stats pour chaque group:
889 if ((!Option_IJK::DISABLE_DIPHASIQUE) && (interfaces_->nb_groups() > 1))
890 {
891 for (int igroup = 0; igroup < interfaces_->nb_groups(); igroup++)
892 {
893 SFichier figroup(n + Nom("_grp") + Nom(igroup) + Nom(".txt"));
894 figroup.setf(ios::scientific);
895 figroup.precision(15);
896 groups_statistiques_FT_[igroup].postraiter(figroup, flag_valeur_instantanee /* flag pour ecrire la moyenne instantanee ou la moyenne */);
897 if (flag_valeur_instantanee == 1)
898 groups_statistiques_FT_[igroup].postraiter_thermique(current_time); /* moyenne instantanee et temporelle */
899 }
900 }
901 }
902 }
903 statistiques_FT_.postraiter_thermique(current_time); /* moyenne instantanee et temporelle */
904 }
905
906}
907
908// Le nom du fichier est base sur le nom du cas...
909// Si reset!=0, on efface le fichier avant d'ecrire, sinon on ajoute...
910void Postprocessing_IJK::ecrire_statistiques_bulles(int reset, const Nom& nom_cas, const double current_time) const
911{
913 return;
914
915 const DoubleTab& gravite = ref_ijk_ft_->milieu_ijk().gravite().valeurs();
916 ArrOfDouble volume;
917 DoubleTab position;
918 ArrOfDouble surface;
919 ArrOfDouble aspect_ratio;
920 ArrOfDouble surfactant;
921 ArrOfDouble surfactant_min;
922 ArrOfDouble surfactant_max;
923 const int nbulles = interfaces_->get_nb_bulles_reelles();
924 DoubleTab hauteurs_bulles(nbulles, 3);
925 DoubleTab bounding_box;
926 interfaces_->calculer_bounding_box_bulles(bounding_box);
927 for (int ib = 0; ib < nbulles; ib++)
928 for (int dir = 0; dir < 3; dir++)
929 hauteurs_bulles(ib, dir) = bounding_box(ib, dir, 1) - bounding_box(ib, dir, 0);
930
931 // La methode calcule a present les surfaces meme pour les bulles ghost.
932 // Pour les enlever, il suffit simplement de reduire la taille du tableau :
933 interfaces_->calculer_surface_bulles(surface);
934 surface.resize_array(nbulles);
935
936 // La methode calcule a present les volumes meme pour les bulles ghost.
937 // Pour les enlever, il suffit simplement de reduire la taille du tableau :
938 interfaces_->calculer_volume_bulles(volume, position);
939 interfaces_->calculer_aspect_ratio(aspect_ratio);
940 interfaces_->calculer_surfactant(surfactant, surfactant_min, surfactant_max);
941 volume.resize_array(nbulles);
942 position.resize(nbulles, 3);
943
944 DoubleTab poussee;
945 interfaces_->calculer_poussee_bulles(gravite, poussee);
946
947 if(ref_ijk_ft_->has_thermals())
948 const_cast<Postprocessing_IJK*>(this)->thermals_->ecrire_statistiques_bulles(reset, nom_cas, current_time, surface);
949
951 {
952 char s[1000];
953 const char *nomcas = nom_cas;
954 SFichier fic;
955 const int n = position.dimension(0);
956 IOS_OPEN_MODE mode = (reset) ? ios::out : ios::app;
957
958 auto write_func_tab = [&](const char * fnam, const DoubleTab& tab, int col)
959 {
960 snprintf(s, 1000, fnam, nomcas);
961 fic.ouvrir(s, mode);
962 snprintf(s, 1000, "%.16e ", current_time);
963 fic << s;
964 for (int i = 0; i < n; i++)
965 {
966 snprintf(s, 1000, "%.16e ", tab(i, col));
967 fic << s;
968 }
969 fic << endl;
970 fic.close();
971 };
972
973 auto write_func_arr = [&](const char * fnam, const ArrOfDouble& tab)
974 {
975 snprintf(s, 1000, fnam, nomcas);
976 fic.ouvrir(s, mode);
977 snprintf(s, 1000, "%.16e ", current_time);
978 fic << s;
979 for (int i = 0; i < n; i++)
980 {
981 snprintf(s, 1000, "%.16e ", tab[i]);
982 fic << s;
983 }
984 fic << endl;
985 fic.close();
986 };
987
988 write_func_tab("%s_bulles_pousseex.out", poussee, 0);
989 write_func_tab("%s_bulles_hx.out", hauteurs_bulles,0);
990 write_func_tab("%s_bulles_hy.out", hauteurs_bulles,1);
991 write_func_tab("%s_bulles_hz.out", hauteurs_bulles,2);
992
993 write_func_tab("%s_bulles_centre_x.out", position, 0);
994 write_func_tab("%s_bulles_centre_y.out", position, 1);
995 write_func_tab("%s_bulles_centre_z.out", position, 2);
996
997 write_func_arr("%s_bulles_surface.out", surface);
998 write_func_arr("%s_bulles_volume.out", volume);
999 write_func_arr("%s_bulles_aspect_ratio.out", aspect_ratio);
1000 write_func_arr("%s_bulles_volume.out", volume);
1001
1002 if (!interfaces_->maillage_ft_ijk().Surfactant_facettes().get_disable_surfactant())
1003 {
1004 write_func_arr("%s_bulles_surfactant.out", surfactant);
1005 write_func_arr("%s_bulles_surfactant_min.out", surfactant_min);
1006 write_func_arr("%s_bulles_surfactant_max.out", surfactant_max);
1007 }
1008 if (interfaces_->follow_colors())
1009 {
1010 const ArrOfInt& colors = interfaces_->get_colors();
1011 snprintf(s, 1000, "%s_bulles_colors.out", nomcas);
1012 fic.ouvrir(s, mode);
1013 snprintf(s, 1000, "%.16e ", current_time);
1014 fic << s;
1015 for (int i = 0; i < n; i++)
1016 {
1017 snprintf(s, 1000, "%d ", (int) colors[i]);
1018 fic << s;
1019 }
1020 fic << endl;
1021 fic.close();
1022 }
1023 }
1024}
1025
1026void Postprocessing_IJK::ecrire_statistiques_cisaillement(int reset, const Nom& nom_cas, const double current_time) const
1027{
1029 return;
1030
1031
1032 double v_x_droite;
1033 double v_y_droite;
1034 double v_z_droite;
1035
1036 double v_x_gauche;
1037 double v_y_gauche;
1038 double v_z_gauche;
1039
1040 Navier_Stokes_FTD_IJK& ns = const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns();
1041 ns.calculer_vitesse_gauche(velocity_.valeur()[0],velocity_.valeur()[1],velocity_.valeur()[2],v_x_gauche,v_y_gauche,v_z_gauche);
1042 ns.calculer_vitesse_droite(velocity_.valeur()[0],velocity_.valeur()[1],velocity_.valeur()[2],v_x_droite,v_y_droite,v_z_droite);
1043
1045 {
1046 char s[1000];
1047 const char *nomcas = nom_cas;
1048 SFichier fic;
1049 IOS_OPEN_MODE mode = (reset) ? ios::out : ios::app;
1050
1051 snprintf(s, 1000, "%s_cisaillement.out", nomcas);
1052 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1053 fic.ouvrir(s, mode);
1054
1055 for (const auto v: {current_time, v_x_droite, v_y_droite, v_z_droite, v_x_gauche, v_y_gauche, v_z_gauche})
1056 {
1057 snprintf(s, 1000, "%.16e ", v);
1058 fic << s;
1059 }
1060
1061 fic << endl;
1062 fic.close();
1063 }
1064
1065}
1066
1067void Postprocessing_IJK::ecrire_statistiques_mrf(int reset, const Nom& nom_cas, const double current_time) const
1068{
1070 return;
1071
1072 double ax_PID, ay_PID, az_PID;
1073
1074 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_asservissement(ax_PID,ay_PID,az_PID);
1075
1077 {
1078 char s[1000];
1079 const char *nomcas = nom_cas;
1080 SFichier fic;
1081 IOS_OPEN_MODE mode = (reset) ? ios::out : ios::app;
1082
1083 snprintf(s, 1000, "%s_mrf.out", nomcas);
1084 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1085 fic.ouvrir(s, mode);
1086 for (const auto v: {current_time, ax_PID, ay_PID, az_PID})
1087 {
1088 snprintf(s, 1000, "%.16e ", v);
1089 fic << s;
1090 }
1091 fic << endl;
1092 fic.close();
1093 }
1094}
1095
1096
1097void Postprocessing_IJK::ecrire_statistiques_amont(int reset, const Nom& nom_cas, const double current_time)
1098{
1100 return;
1101
1102 ArrOfDouble volume;
1103 DoubleTab position;
1104 const int nbulles = interfaces_->get_nb_bulles_reelles();
1105
1106 // La methode calcule a present les volumes meme pour les bulles ghost.
1107 // Pour les enlever, il suffit simplement de reduire la taille du tableau :
1108 interfaces_->calculer_volume_bulles(volume, position);
1109 volume.resize_array(nbulles);
1110 position.resize(nbulles, 3);
1111
1112 DoubleTab d1;
1113 DoubleTab d2;
1114 DoubleTab d3;
1115 DoubleTab v_amont;
1116 DoubleTab u_bulles;
1117 DoubleTab w_amont;
1118 DoubleTab compteur;
1119 DoubleTab compteur_base;
1120 DoubleTab compteur_bulles;
1121
1122 //const IJK_Field_vector3_double& curl = vect_post_fields_.at("CURL");
1123
1124 /*const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_vitesses_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],u_bulles,compteur_bulles);
1125 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_base_amont_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],u_bulles,d1,d2,d3,compteur_base);
1126 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_v_amont_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],curl[0],curl[1],curl[2],v_amont,w_amont,d1,d2,d3,compteur);
1127 */
1128 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_vitesses_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],u_bulles,compteur_bulles);
1129 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_base_amont_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],u_bulles,d1,d2,d3,compteur_base);
1130 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_v_amont_bulle(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2],v_amont,w_amont,d1,d2,d3,compteur);
1131
1132
1133 d1.resize(nbulles, 3);
1134 d2.resize(nbulles, 3);
1135 d3.resize(nbulles, 3);
1136 cout << "Vecteur 1 : " << d1(0,0) << " " << d1(0,1) << " " << d1(0,2) << endl;
1137 cout << "Vecteur 2 : " << d2(0,0) << " " << d2(0,1) << " " << d2(0,2) << endl;
1138 cout << "Vecteur 3 : " << d3(0,0) << " " << d3(0,1) << " " << d3(0,2) << endl;
1139 v_amont.resize(nbulles, 3);
1140 w_amont.resize(nbulles, 3);
1141 compteur.resize(nbulles, 1);
1142
1143 u_bulles.resize(nbulles, 3);
1144
1146 {
1147 char s[1000];
1148 const char *nomcas = nom_cas;
1149 SFichier fic;
1150 const int n = position.dimension(0);
1151 IOS_OPEN_MODE mode = (reset) ? ios::out : ios::app;
1152
1153 snprintf(s, 1000, "%s_bulles_ux.out", nomcas);
1154 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1155 fic.ouvrir(s, mode);
1156 snprintf(s, 1000, "%.16e ", current_time);
1157 fic << s;
1158 for (int i = 0; i < n; i++)
1159 {
1160 snprintf(s, 1000, "%.16e ", u_bulles(i, 0));
1161 fic << s;
1162 }
1163 fic << endl;
1164 fic.close();
1165
1166 snprintf(s, 1000, "%s_bulles_uy.out", nomcas);
1167 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1168 fic.ouvrir(s, mode);
1169 snprintf(s, 1000, "%.16e ", current_time);
1170 fic << s;
1171 for (int i = 0; i < n; i++)
1172 {
1173 snprintf(s, 1000, "%.16e ", u_bulles(i, 1));
1174 fic << s;
1175 }
1176 fic << endl;
1177 fic.close();
1178
1179 snprintf(s, 1000, "%s_bulles_uz.out", nomcas);
1180 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1181 fic.ouvrir(s, mode);
1182 snprintf(s, 1000, "%.16e ", current_time);
1183 fic << s;
1184 for (int i = 0; i < n; i++)
1185 {
1186 snprintf(s, 1000, "%.16e ", u_bulles(i, 2));
1187 fic << s;
1188 }
1189 fic << endl;
1190 fic.close();
1191
1192 snprintf(s, 1000, "%s_bulles_vx_amont.out", nomcas);
1193 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1194 fic.ouvrir(s, mode);
1195 snprintf(s, 1000, "%.16e ", current_time);
1196 fic << s;
1197 for (int i = 0; i < n; i++)
1198 {
1199 snprintf(s, 1000, "%.16e ", v_amont(i, 0));
1200 fic << s;
1201 }
1202 fic << endl;
1203 fic.close();
1204
1205 snprintf(s, 1000, "%s_bulles_vy_amont.out", nomcas);
1206 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1207 fic.ouvrir(s, mode);
1208 snprintf(s, 1000, "%.16e ", current_time);
1209 fic << s;
1210 for (int i = 0; i < n; i++)
1211 {
1212 snprintf(s, 1000, "%.16e ", v_amont(i, 1));
1213 fic << s;
1214 }
1215 fic << endl;
1216 fic.close();
1217
1218 snprintf(s, 1000, "%s_bulles_vz_amont.out", nomcas);
1219 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1220 fic.ouvrir(s, mode);
1221 snprintf(s, 1000, "%.16e ", current_time);
1222 fic << s;
1223 for (int i = 0; i < n; i++)
1224 {
1225 snprintf(s, 1000, "%.16e ", v_amont(i, 2));
1226 fic << s;
1227 }
1228 fic << endl;
1229 fic.close();
1230
1231 snprintf(s, 1000, "%s_bulles_wx_amont.out", nomcas);
1232 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1233 fic.ouvrir(s, mode);
1234 snprintf(s, 1000, "%.16e ", current_time);
1235 fic << s;
1236 for (int i = 0; i < n; i++)
1237 {
1238 snprintf(s, 1000, "%.16e ", w_amont(i, 0));
1239 fic << s;
1240 }
1241 fic << endl;
1242 fic.close();
1243
1244 snprintf(s, 1000, "%s_bulles_wy_amont.out", nomcas);
1245 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1246 fic.ouvrir(s, mode);
1247 snprintf(s, 1000, "%.16e ", current_time);
1248 fic << s;
1249 for (int i = 0; i < n; i++)
1250 {
1251 snprintf(s, 1000, "%.16e ", w_amont(i, 1));
1252 fic << s;
1253 }
1254 fic << endl;
1255 fic.close();
1256
1257 snprintf(s, 1000, "%s_bulles_wz_amont.out", nomcas);
1258 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1259 fic.ouvrir(s, mode);
1260 snprintf(s, 1000, "%.16e ", current_time);
1261 fic << s;
1262 for (int i = 0; i < n; i++)
1263 {
1264 snprintf(s, 1000, "%.16e ", w_amont(i, 2));
1265 fic << s;
1266 }
1267 fic << endl;
1268 fic.close();
1269 }
1270
1271}
1272
1273void Postprocessing_IJK::ecrire_statistiques_fh(int reset, const Nom& nom_cas, const double current_time) const
1274{
1276 return;
1277
1278 ArrOfDouble volume;
1279 DoubleTab position;
1280 const int nbulles = interfaces_->get_nb_bulles_reelles();
1281
1282 // La methode calcule a present les volumes meme pour les bulles ghost.
1283 // Pour les enlever, il suffit simplement de reduire la taille du tableau :
1284 interfaces_->calculer_volume_bulles(volume, position);
1285 volume.resize_array(nbulles);
1286 position.resize(nbulles, 3);
1287
1288 DoubleTab S_surfacePX;
1289 DoubleTab S_surfaceMX;
1290 DoubleTab S_surfacePY;
1291 DoubleTab S_surfaceMY;
1292 DoubleTab S_surfacePZ;
1293 DoubleTab S_surfaceMZ;
1294 DoubleTab S_volumique;
1295
1296 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_x(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfacePX, 1);
1297 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_x(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfaceMX, -1);
1298 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_y(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfacePY, 1);
1299 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_y(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfaceMY, -1);
1300 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_z(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfacePZ, 1);
1301 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_S_z(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], pressure_, S_surfaceMZ, -1);
1302 const_cast<Postprocessing_IJK*>(this)->ref_ijk_ft_->eq_ns().calculer_terme_volumique(ref_ijk_ft_->eq_ns().velocity_[0],ref_ijk_ft_->eq_ns().velocity_[1],ref_ijk_ft_->eq_ns().velocity_[2], ref_ijk_ft_->eq_ns().rho_field_, interfaces_->In(), S_volumique);
1303
1304 S_surfacePX.resize(nbulles, 3);
1305 S_surfaceMX.resize(nbulles, 3);
1306 S_surfacePY.resize(nbulles, 3);
1307 S_surfaceMY.resize(nbulles, 3);
1308 S_surfacePZ.resize(nbulles, 3);
1309 S_surfaceMZ.resize(nbulles, 3);
1310 S_volumique.resize(nbulles, 3);
1311
1313 {
1314 char s[1000];
1315 const char *nomcas = nom_cas;
1316 SFichier fic;
1317 const int n = position.dimension(0);
1318 IOS_OPEN_MODE mode = (reset) ? ios::out : ios::app;
1319
1320 snprintf(s, 1000, "%s_bulles_FX.out", nomcas);
1321 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1322 fic.ouvrir(s, mode);
1323 snprintf(s, 1000, "%.16e ", current_time);
1324 fic << s;
1325 for (int i = 0; i < n; i++)
1326 {
1327 snprintf(s, 1000, "%.16e ", S_surfacePX(i, 0) + S_surfaceMX(i, 0) + S_surfacePY(i, 0) + S_surfaceMY(i, 0) + S_surfacePZ(i, 0) + S_surfaceMZ(i, 0));
1328 fic << s;
1329 }
1330 fic << endl;
1331 fic.close();
1332
1333 snprintf(s, 1000, "%s_bulles_FY.out", nomcas);
1334 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1335 fic.ouvrir(s, mode);
1336 snprintf(s, 1000, "%.16e ", current_time);
1337 fic << s;
1338 for (int i = 0; i < n; i++)
1339 {
1340 snprintf(s, 1000, "%.16e ", S_surfacePX(i, 1) + S_surfaceMX(i, 1) + S_surfacePY(i, 1) + S_surfaceMY(i, 1) + S_surfacePZ(i, 1) + S_surfaceMZ(i, 1));
1341 fic << s;
1342 }
1343 fic << endl;
1344 fic.close();
1345
1346 snprintf(s, 1000, "%s_bulles_FZ.out", nomcas);
1347 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1348 fic.ouvrir(s, mode);
1349 snprintf(s, 1000, "%.16e ", current_time);
1350 fic << s;
1351 for (int i = 0; i < n; i++)
1352 {
1353 snprintf(s, 1000, "%.16e ", S_surfacePX(i, 2) + S_surfaceMX(i, 2) + S_surfacePY(i, 2) + S_surfaceMY(i, 2) + S_surfacePZ(i, 2) + S_surfaceMZ(i, 2));
1354 fic << s;
1355 }
1356 fic << endl;
1357 fic.close();
1358
1359 snprintf(s, 1000, "%s_bulles_VX.out", nomcas);
1360 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1361 fic.ouvrir(s, mode);
1362 snprintf(s, 1000, "%.16e ", current_time);
1363 fic << s;
1364 for (int i = 0; i < n; i++)
1365 {
1366 snprintf(s, 1000, "%.16e ", S_volumique(i, 0));
1367 fic << s;
1368 }
1369 fic << endl;
1370 fic.close();
1371
1372 snprintf(s, 1000, "%s_bulles_VY.out", nomcas);
1373 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1374 fic.ouvrir(s, mode);
1375 snprintf(s, 1000, "%.16e ", current_time);
1376 fic << s;
1377 for (int i = 0; i < n; i++)
1378 {
1379 snprintf(s, 1000, "%.16e ", S_volumique(i, 1));
1380 fic << s;
1381 }
1382 fic << endl;
1383 fic.close();
1384
1385 snprintf(s, 1000, "%s_bulles_VZ.out", nomcas);
1386 // Cerr << "Ecriture des donnees par bulles: fichier " << s << endl;
1387 fic.ouvrir(s, mode);
1388 snprintf(s, 1000, "%.16e ", current_time);
1389 fic << s;
1390 for (int i = 0; i < n; i++)
1391 {
1392 snprintf(s, 1000, "%.16e ", S_volumique(i, 2));
1393 fic << s;
1394 }
1395 fic << endl;
1396 fic.close();
1397 }
1398
1399}
1400
1401
1402/** Methode qui met a jour l'indicatrice, les termes de repulsion
1403 * ainsi que les termes interfaciaux : ai, kappa*ai, n(aux cellules)
1404 *
1405 * Par definition, mettre igroup a -1 pour inclure toutes les bulles
1406 * Dans ce cas, la methode met a jour l'ev de l'indicatrice au lieu de celui de interfaces_.groups_indicatrice_n_ns()[igroup]
1407 *
1408 * Attention: de nombreux tableaux sont modifies par cette methode en sortie.
1409 * Ils peuvent etre des tableaux de travail. Si on veut qu'il soient correctent
1410 * pour la suite, il faut faire l'appel avec les champs globaux (incluant tous
1411 * les groupes a la fin). Sinon, les champs en ai, normale ou grad_I ne contiendront qu'un groupe.
1412 */
1414{
1415 Navier_Stokes_FTD_IJK& ns = ref_ijk_ft_->eq_ns();
1416 //ArrOfDouble volume;
1417 //DoubleTab position;
1418 //interfaces_.calculer_volume_bulles(volume, position);
1419// static Stat_Counter_Id updtstat_counter_ = statistiques().new_counter(2, "update statistiques");
1420// statistiques().begin_count(updtstat_counter_);
1422 {
1423 // Calcul du champ grad_P_ est fait dans update_stat
1424 statistiques_FT_.update_stat(ref_ijk_ft_, dt);
1425 return;
1426 }
1427 int nb_groups = interfaces_->nb_groups();
1428 // Boucle debute a -1 pour faire l'indicatrice globale.
1429 // S'il n'y a pas de groupes de bulles (monophasique ou monodisperse), on passe exactement une fois dans la boucle
1430 if (nb_groups == 1)
1431 nb_groups = 0; // Quand il n'y a qu'un groupe, on ne posttraite pas les choses pour ce groupe unique puisque c'est identique au cas global
1432 for (int igroup = -1; igroup < nb_groups; igroup++)
1433 {
1434 if (is_post_required("AIRE_INTERF"))
1435 {
1436 IJK_Field_double& ai_ft = scalar_post_fields_.at("AIRE_INTERF");
1437 interfaces_->calculer_normales_et_aires_interfaciales(ai_ft, kappa_ai_ft_, normale_cell_ft_, igroup);
1438 // Puis les redistribue sur le ns :
1442 }
1443 // (pas besoin d'echange EV car ils n'ont pas de ghost).
1444
1445 // Calcul du gradient de l'indicatrice et de vitesse :
1446 if (igroup == -1)
1447 {
1448 // interfaces_.In().echange_espace_virtuel(1);
1449 // Calcul des champs grad_I_ns_
1450 calculer_gradient_indicatrice(interfaces_->In());
1451 ns.transfer_ft_to_ns(); // pour remplir : terme_repulsion_interfaces_ft_ et terme_abs_repulsion_interfaces_ft_
1452 // Calcul des champs grad_I_ns_, terme_repulsion_interfaces_ns_, terme_abs_repulsion_interfaces_ns_
1453 // a partir de interfaces_.In(), et terme_*_ft_
1454 statistiques_FT_.update_stat(ref_ijk_ft_, dt);
1455 }
1456 else
1457 {
1458 // interfaces_.groups_indicatrice_n_ns()[igroup].echange_espace_virtuel(1);
1459 // Calcul des champs grad_I_ns_, terme_repulsion_interfaces_ns_, terme_abs_repulsion_interfaces_ns_
1460 // a partir de interfaces_.In(), et terme_*_ft_
1461 calculer_gradient_indicatrice(interfaces_->groups_indicatrice_n_ns()[igroup]);
1462 ns.transfer_ft_to_ns();
1463 groups_statistiques_FT_[igroup].update_stat(ref_ijk_ft_, dt);
1464 }
1465 }
1466// statistiques().end_count(updtstat_counter_);
1467}
1468
1469// Calcul du lambda2 a partir du gradient.
1470// A optimiser simplement en mutualisant avec la methode d'update_stats.
1471// Et en ne faisant le calcul que si besoin, cad si les champs de gradient ne sont pas a jour...
1472void Postprocessing_IJK::update_gradU_lambda2(const bool need_lambda2)
1473{
1474 IJK_Field_double& lambda2 = scalar_post_fields_.at("LAMBDA2");
1475 // TODO : Clean theses : dudx_ and vectorise with what's in statistiques ... gradU[2]
1476 if (need_lambda2)
1477 compute_and_store_gradU_cell(velocity_.valeur()[0], velocity_.valeur()[1], velocity_.valeur()[2],
1478 /* Et les champs en sortie */
1479 dudx_, dvdy_, dwdx_, dudz_, dvdz_, dwdz_, 1 /* yes compute_all */,
1480 dudy_, dvdx_, dwdy_, lambda2);
1481 statistiques_FT_.compute_and_store_gradU_cell(velocity_.valeur()[0], velocity_.valeur()[1], velocity_.valeur()[2]);
1482}
1483
1485{
1486 IJK_Field_vector3_double& rot = vect_post_fields_.at("CURL");
1487 IJK_Field_double& critere_Q = scalar_post_fields_.at("CRITERE_Q");
1488 //IJK_Field_double& lambda2 = scalar_post_fields_.at("LAMBDA2");
1489
1490 const IJK_Field_vector3_double& gradU=statistiques_FT_.get_IJK_field_vector("dUd");
1491 const IJK_Field_vector3_double& gradV=statistiques_FT_.get_IJK_field_vector("dVd");
1492 const IJK_Field_vector3_double& gradW=statistiques_FT_.get_IJK_field_vector("dWd");
1493 const IJK_Field_double& dudx = gradU[0];
1494 const IJK_Field_double& dudy = gradU[1];
1495 const IJK_Field_double& dudz = gradU[2];
1496 const IJK_Field_double& dvdx = gradV[0];
1497 const IJK_Field_double& dvdy = gradV[1];
1498 const IJK_Field_double& dvdz = gradV[2];
1499 const IJK_Field_double& dwdx = gradW[0];
1500 const IJK_Field_double& dwdy = gradW[1];
1501 const IJK_Field_double& dwdz = gradW[2];
1503 // Nombre local de mailles en K
1504 const int kmax = critere_Q.nk();
1505 const int imax = critere_Q.ni();
1506 const int jmax = critere_Q.nj();
1507 for (int k = 0; k < kmax; k++)
1508 for (int j = 0; j < jmax; j++)
1509 for (int i = 0; i < imax; i++)
1510 {
1511 rot[0](i, j, k) = dwdy(i, j, k) - dvdz(i, j, k);
1512 rot[1](i, j, k) = dudz(i, j, k) - dwdx(i, j, k);
1513 rot[2](i, j, k) = dvdx(i, j, k) - dudy(i, j, k);
1514 // Calcul du critere Q selon (Jeong & Hussain 1995)
1515 critere_Q(i, j, k) = -0.5
1516 * (dudx(i, j, k) * dudx(i, j, k)
1517 + 2. * dudy(i, j, k) * dvdx(i, j, k)
1518 + 2. * dudz(i, j, k) * dwdx(i, j, k)
1519 + dvdy(i, j, k) * dvdy(i, j, k)
1520 + 2. * dvdz(i, j, k) * dwdy(i, j, k)
1521 + dwdz(i, j, k) * dwdz(i, j, k));
1522 }
1523}
1524
1525/** Was the field of name 'nom' requested for postprocessing?
1526 */
1528{
1529 return (std::find(list_post_required_.begin(), list_post_required_.end(), nom) != list_post_required_.end());
1530}
1531
1532// Pour qu'un champ vectoriel puisse etre interpole a l'element, il faut qu'il ait au moins 1 ghost.
1533void Postprocessing_IJK::Fill_postprocessable_fields(std::vector<FieldInfo_t>& chps)
1534{
1535 std::vector<FieldInfo_t> c =
1536 {
1537 // Name / Localisation (elem, face, ...) / Nature (scalare, vector) / Located on interface?
1538
1539 { "CURL", Entity::ELEMENT, Nature_du_champ::vectoriel, false },
1540 { "CRITERE_Q", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1541 { "NUM_COMPO", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1542 { "FORCE_PH", Entity::FACE, Nature_du_champ::vectoriel, false },
1543 { "COORDS", Entity::FACE, Nature_du_champ::vectoriel, false },
1544 { "LAMBDA2", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1545
1546 { "VELOCITY_ANA", Entity::FACE, Nature_du_champ::vectoriel, false },
1547 { "ECART_ANA", Entity::FACE, Nature_du_champ::vectoriel, false },
1548 { "PRESSURE_ANA", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1549 { "ECART_P_ANA", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1550 { "D_VELOCITY_ANA", Entity::FACE, Nature_du_champ::vectoriel, false },
1551
1552 { "D_VELOCITY", Entity::FACE, Nature_du_champ::vectoriel, false },
1553 { "OP_CONV", Entity::FACE, Nature_du_champ::vectoriel, false },
1554 { "D_PRESSURE", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1555 { "MU", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1556 { "RHO", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1557 { "INDICATRICE_NS", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1558
1559 // A faire sauter avec le travail de William:
1560 { "INDICATRICE_FT", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1561 { "GRAD_INDICATRICE_FT", Entity::FACE, Nature_du_champ::vectoriel, false },
1562 { "REBUILT_INDICATRICE_FT", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1563 { "GROUPS_FT", Entity::ELEMENT, Nature_du_champ::vectoriel, false },
1564
1565 // Dans NS :
1566 // { "SOURCE_QDM_INTERF", Entity::FACE, Nature_du_champ::vectoriel, false },
1567 // { "SHIELD_REPULSION", Entity::FACE, Nature_du_champ::vectoriel, false },
1568 { "RHO_SOURCE_QDM_INTERF", Entity::FACE, Nature_du_champ::vectoriel, false },
1569 { "RHO_SOURCE_QDM_INTERF", Entity::ELEMENT, Nature_du_champ::vectoriel, false },
1570 { "BK_SOURCE_QDM_INTERF", Entity::FACE, Nature_du_champ::vectoriel, false },
1571
1572 { "AIRE_INTERF", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1573 { "COURBURE_AIRE_INTERF", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1574 { "NORMALE_EULER", Entity::ELEMENT, Nature_du_champ::vectoriel, false },
1575 { "PRESSURE_LIQ", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1576 { "PRESSURE_VAP", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1577 { "GROUPS", Entity::ELEMENT, Nature_du_champ::vectoriel, false },
1578 { "SURFACE_VAPEUR_PAR_FACE", Entity::FACE, Nature_du_champ::vectoriel, false },
1579 { "BARYCENTRE_VAPEUR_PAR_FACE", Entity::FACE, Nature_du_champ::vectoriel, false },
1580
1581 { "VARIABLE_SOURCE", Entity::FACE, Nature_du_champ::vectoriel, false },
1582 { "INTEGRATED_VELOCITY", Entity::FACE, Nature_du_champ::vectoriel, false },
1583 { "INTEGRATED_PRESSURE", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1584 { "INDICATRICE_PERTURBE", Entity::ELEMENT, Nature_du_champ::scalaire, false },
1585 { "INTEGRATED_TIMESCALE", Entity::ELEMENT, Nature_du_champ::scalaire, false }
1586 };
1587
1588 chps.insert(chps.end(), c.begin(), c.end());
1589}
1590
1592{
1593 statistiques_FT_.get_noms_champs_postraitables(noms, opt);
1594 for (const auto& n : champs_compris_.liste_noms_compris())
1595 noms.add(n);
1596 for (const auto& n : champs_compris_.liste_noms_compris_vectoriel())
1597 noms.add(n);
1598}
1600{
1601 if (statistiques_FT_.has_champ(nom))
1602 {
1603 return true;
1604 }
1605 return champs_compris_.has_champ(nom);
1606}
1608{
1609 if (statistiques_FT_.has_champ_vectoriel(nom))
1610 {
1611 return true;
1612 }
1613 return champs_compris_.has_champ_vectoriel(nom);
1614}
1615/** Retrieve requested field for postprocessing, potentially updating it.
1616 */
1617const IJK_Field_double& Postprocessing_IJK::get_IJK_field(const Motcle& nom)
1618{
1619
1620 if (statistiques_FT_.has_champ(nom))
1621 {
1622 return statistiques_FT_.get_IJK_field(nom);
1623 }
1624
1625 if (!has_champ(nom))
1626 {
1627 Cerr << "ERROR in Postprocessing_IJK::get_IJK_field : " << finl;
1628 Cerr << "Requested field '" << nom << "' is not recognized by Postprocessing_IJK::get_IJK_field()." << finl;
1629 throw;
1630 }
1631
1632 double current_time = ref_ijk_ft_->schema_temps_ijk().get_current_time();
1633
1634 // TODO pas optimal :
1635 if (nom == "LAMBDA2")
1637 if (nom == "CRITERE_Q")
1639
1640 if (nom == "NUM_COMPO")
1641 {
1642 IJK_Field_double& num_compo_ft = scalar_post_fields_.at("NUM_COMPO");
1643 const int ni = num_compo_ft.ni(), nj = num_compo_ft.nj(), nk = num_compo_ft.nk();
1644 const IntVect& num_compo = interfaces_->get_num_compo();
1645 for (int k = 0; k < nk; k++)
1646 for (int j = 0; j < nj; j++)
1647 for (int i = 0; i < ni; i++)
1648 {
1649 const int num_elem = domaine_ft_->convert_ijk_cell_to_packed(i, j, k);
1650 num_compo_ft(i, j, k) = num_compo[num_elem];
1651 }
1652 }
1653
1654 if (nom == "AIRE_INTERF")
1655 {
1656 IJK_Field_double& ai_ft = scalar_post_fields_.at("AIRE_INTERF");
1657 interfaces_->calculer_aire_interfaciale(ai_ft);
1658 }
1659 if (nom == "PRESSURE_ANA")
1660 {
1661 set_field_data(scalar_post_fields_.at("PRESSURE_ANA"), expression_pression_analytique_, current_time);
1662 }
1663 if (nom == "ECART_P_ANA")
1664 {
1665 auto& pressure_ana=scalar_post_fields_.at("PRESSURE_ANA");
1666 double ct = current_time;
1667 if ( sub_type(Schema_Euler_explicite_IJK, ref_ijk_ft_->schema_temps_ijk()) )
1668 {
1669 ct -= ref_ijk_ft_->schema_temps_ijk().get_timestep();
1670 }
1671 else if ( sub_type(Schema_RK3_IJK, ref_ijk_ft_->schema_temps_ijk()) )
1672 {
1673 Schema_RK3_IJK& rk3 = ref_cast(Schema_RK3_IJK, ref_ijk_ft_->schema_temps_ijk());
1674 Cerr << "rkstep " << rk3.get_rk_step() << finl;
1675 int rk_step_before = rk3.get_rk_step();
1676 if ((rk_step_before == 0) || (rk_step_before == 3))
1677 rk_step_before = 2;
1678 else if (rk_step_before == 1)
1679 rk_step_before = 0;
1680 else
1681 /* ici, c'est rk_step_before=2 */
1682 rk_step_before = 1;
1683 Cerr << "rkstep_before " << rk_step_before << finl;
1684 const double intermediate_dt = compute_fractionnal_timestep_rk3(rk3.get_timestep(), rk_step_before);
1685 ct -= intermediate_dt;
1686 }
1687 else
1688 {
1689 Cerr << "To do for other time scheme" << endl;
1690 }
1691 Cerr << "GB: ERROR P FIELD " << ct;
1692 double err = 0.;
1693 set_field_data(pressure_ana, expression_pression_analytique_, ct);
1694 const int ni = pressure_->ni();
1695 const int nj = pressure_->nj();
1696 const int nk = pressure_->nk();
1697 const trustIdType ntot = Process::mp_sum(ni * nj * nk);
1698 // La pression est definie a une constante pres:
1699 const double cst_press = pressure_ana(0, 0, 0) - pressure_.valeur()(0, 0, 0);
1700 for (int k = 0; k < nk; k++)
1701 for (int j = 0; j < nj; j++)
1702 for (int i = 0; i < ni; i++)
1703 {
1704 const double val = pressure_ana(i, j, k) - pressure_.valeur()(i, j, k) - cst_press;
1705 ecart_p_ana_(i, j, k) = val;
1706 err += val * val;
1707 }
1708 err = Process::mp_sum(err);
1709 err = sqrt(err / static_cast<double>(ntot));
1710 Cerr << " " << err;
1712 {
1713 Process::Journal() << "Postprocessing_IJK::posttraiter_champs_instantanes : OWN_PTR(Champ_base) ECART_P_ANA sur ce proc (ni,nj,nk,ntot):" << " " << ni << " " << nj << " " << nk << " " << ntot << finl;
1714 }
1715 ecart_p_ana_.echange_espace_virtuel(ecart_p_ana_.ghost());
1716 Cerr << finl;
1717 }
1718
1719 return champs_compris_.get_champ(nom);
1720
1721 // if (nom.debute_par("dU"))
1722 // {
1723 // const IJK_Field_vector3_double& gradU = statistiques_FT_.get_IJK_field_vector("gradU");
1724 // if (nom == "DUDX")
1725 // return gradU[0];
1726 // if (nom == "DUDY")
1727 // return gradU[1];
1728 // if (nom == "DUDZ")
1729 // return gradU[2];
1730 // }
1731 // if (nom.debute_par("dV"))
1732 // {
1733 // const IJK_Field_vector3_double& gradV = statistiques_FT_.get_IJK_field_vector("gradV");
1734 // if (nom == "DVDX")
1735 // return gradV[0];
1736 // if (nom == "DVDY")
1737 // return gradV[1];
1738 // if (nom == "DVDZ")
1739 // return gradV[2];
1740 // }
1741 // if (nom.debute_par("dW"))
1742 // {
1743 // const IJK_Field_vector3_double& gradW = statistiques_FT_.get_IJK_field_vector("gradW");
1744 // if (nom == "DWDX")
1745 // return gradW[0];
1746 // if (nom == "DWDY")
1747 // return gradW[1];
1748 // if (nom == "DWDZ")
1749 // return gradW[2];
1750 // }
1751 //
1752 // //
1753 // // if (Option_IJK::DISABLE_DIPHASIQUE)
1754 // {
1755 // if (nom == "VELOCITY_ANA_X")
1756 // return velocity_ana_[0];
1757 // if (nom == "VELOCITY_ANA_Y")
1758 // return velocity_ana_[1];
1759 // if (nom == "VELOCITY_ANA_Z")
1760 // return velocity_ana_[2];
1761 // if (nom == "ECART_ANA_X")
1762 // return ecart_ana_[0];
1763 // if (nom == "ECART_ANA_Y")
1764 // return ecart_ana_[1];
1765 // if (nom == "ECART_ANA_Z")
1766 // return ecart_ana_[2];
1767 // }
1768 //
1769 // const int idx_wanted = convert_suffix_to_int(nom);
1770 // const Nom field_name = nom.getPrefix(Nom("_") + Nom(idx_wanted));
1771 // Cerr << "In get_IJK_field by name : " << nom << " read as : (" << field_name << " ; " << idx_wanted << ")" << finl;
1772 //
1773 //// Remplir la liste de tous les possibles :
1774 // Motcles liste_champs_thermiques_possibles;
1775 // posttraiter_tous_champs_thermique(liste_champs_thermiques_possibles, 0);
1776 // int rang = liste_champs_thermiques_possibles.rang(field_name);
1777 // if (rang == -1)
1778 // {
1779 // Cerr << field_name << " not found as possible for field name. Should be in the list: " << liste_champs_thermiques_possibles << finl;
1780 // Process::exit();
1781 // }
1782 //
1783
1784
1785
1786}
1787
1788const IJK_Field_vector3_double& Postprocessing_IJK::get_IJK_field_vector(const Motcle& nom)
1789{
1790 if (nom == "CURL")
1792
1793 if (statistiques_FT_.has_champ_vectoriel(nom))
1794 {
1795 return statistiques_FT_.get_IJK_field_vector(nom);
1796 }
1797 if (!has_champ_vectoriel(nom))
1798 {
1799 Cerr << "ERROR in Postprocessing_IJK::get_IJK_field_vector : " << finl;
1800 Cerr << "Requested field '" << nom << "' is not recognized by Postprocessing_IJK::get_IJK_field_vector()." << finl;
1801 throw;
1802 }
1803
1804 double current_time = ref_ijk_ft_->schema_temps_ijk().get_current_time();
1805
1806 if (nom == "VELOCITY_ANA")
1807 {
1808 for (int i = 0; i < 3; i++)
1809 set_field_data(velocity_ana_[i], expression_vitesse_analytique_[i], current_time);
1810 }
1811 if (nom == "ECART_ANA")
1812 {
1813 Cerr << "GB: ERROR FIELD " << current_time;
1814 for (int dir = 0; dir < 3; dir++)
1815 {
1816 double err = 0.;
1817 set_field_data(velocity_ana_[dir], expression_vitesse_analytique_[dir], current_time);
1818 const int ni = ref_ijk_ft_->eq_ns().velocity_[dir].ni();
1819 const int nj = ref_ijk_ft_->eq_ns().velocity_[dir].nj();
1820 const int nk = ref_ijk_ft_->eq_ns().velocity_[dir].nk();
1821 const double ntot = Process::mp_sum_as_double(ni * nj * nk);
1822 for (int k = 0; k < nk; k++)
1823 for (int j = 0; j < nj; j++)
1824 for (int i = 0; i < ni; i++)
1825 {
1826 const double val = velocity_ana_[dir](i, j, k) - ref_ijk_ft_->eq_ns().velocity_[dir](i, j, k);
1827 ecart_ana_[dir](i, j, k) = val;
1828 err += val * val;
1829 }
1830 err = Process::mp_sum(err);
1831 err = sqrt(err / ntot);
1832 Cerr << " " << err;
1834 {
1835 Process::Journal() << "Postprocessing_IJK::posttraiter_champs_instantanes : OWN_PTR(Champ_base) ECART_ANA sur ce proc (ni,nj,nk,ntot):" << " " << ni << " " << nj << " " << nk << " " << ntot << finl;
1836 }
1837 }
1838 Cerr << finl;
1839 }
1840
1841 if (nom == "INTEGRATED_VELOCITY")
1842 {
1843 update_integral_velocity(velocity_, integrated_velocity_, interfaces_->In(), integrated_timescale_);
1844 }
1845 if (nom == "INTEGRATED_PRESSURE")
1846 {
1847 update_integral_pressure(pressure_, integrated_pressure_, interfaces_->In(), integrated_timescale_);
1848 }
1849 if (nom == "INTEGRATED_TIMESCALE")
1850 {
1851 update_integral_indicatrice(interfaces_->In(), 1. /* Should be the integration timestep */, integrated_timescale_);
1852 }
1853 if (nom == "INDICATRICE_PERTURBE")
1854 {
1855 //Faut-il faire un update_...( indicatrice_non_perturbe_) avant?
1856 }
1857
1858
1859
1860 return champs_compris_.get_champ_vectoriel(nom);
1861}
1862
1863const int& Postprocessing_IJK::get_IJK_flag(const Nom& nom) const
1864{
1865 Cerr << "Erreur dans Postprocessing_IJK::get_IJK_variable : " << "Variable demandee : " << nom << " Liste des variables possibles : " << finl;
1866 Process::exit();
1867 throw;
1868}
1869
1871{
1872 if (is_post_required("INTEGRATED_VELOCITY"))
1873 dumplata_vector(lata_name, "INTEGRATED_VELOCITY", integrated_velocity_[0], integrated_velocity_[1], integrated_velocity_[2], 0);
1874
1875 if (is_post_required("INTEGRATED_PRESSURE"))
1876 dumplata_scalar(lata_name, "INTEGRATED_PRESSURE", integrated_pressure_, 0);
1877
1878 if (is_post_required("INDICATRICE_PERTURBE"))
1879 dumplata_scalar(lata_name, "INDICATRICE_PERTURBE", indicatrice_non_perturbe_, 0);
1880
1881 if (is_post_required("INTEGRATED_TIMESCALE"))
1882 dumplata_scalar(lata_name, "INTEGRATED_TIMESCALE", integrated_timescale_, 0);
1883}
1884
1885void Postprocessing_IJK::sauvegarder_post_maitre(const Nom& lata_name, SFichier& fichier) const
1886{
1887
1888 if (statistiques_FT_.t_integration() > 0.)
1889 {
1890 Cerr << "All bubbles : " << endl;
1891 fichier << " statistiques_FT " << statistiques_FT_;
1892 // S'il y a plusieurs groups, on s'occupe des objets stats pour chaque group:
1893 // (en ecrivant directement le vecteur d'objets)
1894 if (interfaces_->nb_groups() > 1)
1895 {
1896 Cerr << "Group by group :" << endl;
1897 fichier << " groups_statistiques_FT " << groups_statistiques_FT_;
1898 }
1899 }
1900}
1901
1903{
1904 param.ajouter("statistiques_FT", &statistiques_FT_);
1905 param.ajouter("groups_statistiques_FT", &groups_statistiques_FT_);
1906}
1907
1908
1910{
1911 if (liste_post_instantanes_.contient_("OP_CONV"))
1912 for (int i = 0; i < 3; i++)
1913 op_conv_[i].data() = d_velocity_.valeur()[i].data();
1914
1915 if (liste_post_instantanes_.contient_("CELL_OP_CONV"))
1916 interpolate_to_center(cell_op_conv_,d_velocity_);
1917}
1918
1919void Postprocessing_IJK::fill_surface_force(IJK_Field_vector3_double& the_field_you_know)
1920{
1921 double volume = 1.;
1922 for (int i = 0; i < 3; i++)
1923 volume *= domaine_ijk_->get_constant_delta(i);
1924
1925 if (is_post_required("RHO_SOURCE_QDM_INTERF"))
1926 {
1927 IJK_Field_vector3_double& rho_Ssigma = vect_post_fields_.at("RHO_SOURCE_QDM_INTERF");
1928 for (int dir = 0; dir < 3; dir++)
1929 {
1930 IJK_Field_double& source = ref_ijk_ft_->eq_ns().terme_source_interfaces_ns_[dir];
1931 for (int k = 0; k < source.nk(); k++)
1932 for (int j = 0; j < source.nj(); j++)
1933 for (int i = 0; i < source.ni(); i++)
1934 rho_Ssigma[dir](i,j,k) = source(i,j,k)/volume;
1935 }
1936 }
1937
1938 // TODO : probablement inutile nouvelle syntaxe
1939 if (liste_post_instantanes_.contient_("CELL_RHO_SOURCE_QDM_INTERF"))
1940 {
1941 interpolate_to_center(cell_rho_Ssigma_,ref_ijk_ft_->eq_ns().terme_source_interfaces_ns_);
1942 for (int dir = 0; dir < 3; dir++)
1943 {
1944 IJK_Field_double& source = cell_rho_Ssigma_[dir];
1945 for (int k = 0; k < source.nk(); k++)
1946 for (int j = 0; j < source.nj(); j++)
1947 for (int i = 0; i < source.ni(); i++)
1948 cell_rho_Ssigma_[dir](i,j,k) = source(i,j,k)/volume;
1949 }
1950 }
1951}
1952
1953// Calcul du gradient de l'indicatrice et de pression :
1954// Attention, il faut que la pression et l'indicatrice soient a jour
1955// dans leur espaces virtuels avant d'appeler cette methode
1956// Methode qui calcule des champs grad_I_ns_,
1957// a partir de pressure_ et indicatrice_ns__
1958void Postprocessing_IJK::calculer_gradient_indicatrice(const IJK_Field_double& indic)
1959{
1960 // Remise a zero :
1961 for (int dir = 0; dir < 3; dir++)
1962 {
1963 grad_I_ns_[dir].data() = 0.;
1964 }
1965
1966 // From IJK_Navier_Stokes_Tools.cpp
1967 // interfaces_.In().echange_espace_virtuel(1);
1968 add_gradient_times_constant(indic, 1. /*Constante multiplicative*/, grad_I_ns_[DIRECTION_I], grad_I_ns_[DIRECTION_J], grad_I_ns_[DIRECTION_K]);
1969
1970 for (int dir = 0; dir < 3; dir++)
1971 {
1972 grad_I_ns_[dir].echange_espace_virtuel(1);
1973 }
1974}
1975
1977{
1978 rebuilt_indic_.allocate(domaine_ft_, Domaine_IJK::ELEM, 0);
1980 {
1981 IJK_Field_double& ai_ft = scalar_post_fields_.at("AIRE_INTERF");
1982 ai_ft.allocate(domaine_ft_, Domaine_IJK::ELEM, 0, "AIRE_INTERF");
1983 champs_compris_.ajoute_champ(ai_ft);
1984 }
1985 // Pour les stats, on calcule kappa*ai :
1987 {
1988 kappa_ai_ft_.allocate(domaine_ft_, Domaine_IJK::ELEM, 0);
1989 kappa_ai_ns_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
1990 ai_ns_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0);
1991 allocate_cell_vector(normale_cell_ns_, domaine_ijk_, 0);
1992 }
1993
1994 // For the pressure field extension:
1996 && ((is_post_required("PRESSURE_LIQ")) || (is_post_required("PRESSURE_VAP")) || is_stats_plans_activated()))
1997 {
1999 pressure_ft_.allocate(domaine_ft_, Domaine_IJK::ELEM, 5);
2000 extended_pl_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "PRESSURE_LIQ");
2001 champs_compris_.ajoute_champ(extended_pl_);
2002 extended_pv_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "PRESSURE_VAP");
2003 champs_compris_.ajoute_champ(extended_pv_);
2004 extended_pl_ft_.allocate(domaine_ft_, Domaine_IJK::ELEM, 0);
2005 extended_pv_ft_.allocate(domaine_ft_, Domaine_IJK::ELEM, 0);
2006 }
2007 else
2009
2010 // Allocation du champ de normale aux cellules :
2011 if (!Option_IJK::DISABLE_DIPHASIQUE && ((is_post_required("NORMALE_INTERF")) || (is_post_required("PRESSURE_LIQ")) // Je ne suis pas sur que ce soit necessaire. Seulement si on l'utilise dans le calcul de p_ext
2012 || (is_post_required("PRESSURE_VAP")) // Je ne suis pas sur que ce soit necessaire.
2014 {
2015 allocate_cell_vector(normale_cell_ft_, domaine_ft_, 0);
2016 }
2017
2018
2019 if (is_post_required("NUM_COMPO"))
2020 {
2021 IJK_Field_double& num_c = scalar_post_fields_.at("NUM_COMPO");
2022 num_c.allocate(domaine_ft_, Domaine_IJK::ELEM, 0, "NUM_COMPO");
2023 champs_compris_.ajoute_champ(num_c);
2024 }
2025
2026 if (is_post_required("VELOCITY_ANA") or is_post_required("ECART_ANA") )
2027 {
2028 allocate_velocity(velocity_ana_, domaine_ijk_, 1, "VELOCITY_ANA");
2029 champs_compris_.ajoute_champ_vectoriel(velocity_ana_);
2030 }
2031
2032 if (is_post_required("ECART_ANA"))
2033 {
2034 allocate_velocity(ecart_ana_, domaine_ijk_, 1, "ECART_ANA");
2035 champs_compris_.ajoute_champ_vectoriel(ecart_ana_);
2036 }
2037
2038 if (is_post_required("PRESSURE_ANA") or is_post_required("ECART_P_ANA") )
2039 {
2040 scalar_post_fields_.at("PRESSURE_ANA").allocate(domaine_ijk_, Domaine_IJK::ELEM, 1, "PRESSURE_ANA");
2041 champs_compris_.ajoute_champ(scalar_post_fields_.at("PRESSURE_ANA"));
2042 }
2043
2044 if (is_post_required("ECART_P_ANA"))
2045 {
2046 ecart_p_ana_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1, "ECART_P_ANA");
2047 champs_compris_.ajoute_champ(ecart_p_ana_);
2048 }
2049
2050
2051
2052 // Allocation des champs derivee de vitesse :
2053 if (is_post_required("LAMBDA2")|| is_post_required("CRITERE_Q") || is_post_required("CURL"))
2054 {
2055 dudx_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2056 dudy_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2057 dudz_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2058 dvdx_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2059 dvdy_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2060 dvdz_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2061 dwdx_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2062 dwdy_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2063 dwdz_.allocate(domaine_ijk_, Domaine_IJK::ELEM, 1);
2064 if (is_post_required("LAMBDA2"))
2065 {
2066 scalar_post_fields_.at("LAMBDA2").allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "LAMBDA2");
2067 champs_compris_.ajoute_champ(scalar_post_fields_.at("LAMBDA2"));
2068 }
2069 if (is_post_required("CRITERE_Q") || is_post_required("CURL"))
2070 {
2071 scalar_post_fields_.at("CRITERE_Q").allocate(domaine_ijk_, Domaine_IJK::ELEM, 0, "CRITERE_Q");
2072 champs_compris_.ajoute_champ(scalar_post_fields_.at("CRITERE_Q"));
2073 // Le rotationnel, aux elems aussi :
2074 allocate_cell_vector(vect_post_fields_.at("CURL"), domaine_ijk_, 0, "CURL");
2075 champs_compris_.ajoute_champ_vectoriel(vect_post_fields_.at("CURL"));
2076 }
2077 }
2078
2079 if (interfaces_->nb_groups() > 1)
2080 {
2081 // On alloue un tableau assez grand pour contenir tous les groupes.
2082 if (interfaces_->nb_groups() > 3)
2083 {
2084 Cerr << "More than 3 groups are planned, but the allocated fields has only 3 components" << endl;
2085 Process::exit();
2086 }
2087 // TODO AYM: allocate fait dans IJK_Interfaces a l init
2088 // allocate_cell_vector(interfaces_.groups_indicatrice_n_ns(),splitting_, 1); // Besoin d'un ghost pour le calcul du grad
2089 // allocate_cell_vector(interfaces_.groups_indicatrice_n_ft(),splitting_ft_, 1); // peut-etre qu'un ghost=0 suffit et fonctionne pour le redistribute.
2090 }
2091
2092 // Pour verification des stats :
2093 if (check_stats_)
2094 {
2095 // Le gradient de pression aux faces : (il est deja alloue par defaut)
2096 // allocate_velocity(gradP_, splitting_, 1);
2097 // Le gradient de vitesse aux elems : (il est stocke, seulement si besoin, dans l'objet statistiques_FT_)
2098 // allocate_cell_vector(dUd_, splitting_, 1);
2099 // allocate_cell_vector(dVd_, splitting_, 1);
2100 // allocate_cell_vector(dWd_, splitting_, 1);
2101 // Et leurs solutions analytiques sans ghost :
2102 allocate_velocity(ana_gradP_, domaine_ijk_, 1);
2103 allocate_cell_vector(ana_dUd_, domaine_ijk_, 0);
2104 allocate_cell_vector(ana_dVd_, domaine_ijk_, 0);
2105 allocate_cell_vector(ana_dWd_, domaine_ijk_, 0);
2106 // Pour les deriv secondes :
2107 allocate_cell_vector(ana_grad2Pi_, domaine_ijk_, 0);
2108 allocate_cell_vector(ana_grad2Pc_, domaine_ijk_, 0);
2109 // And for velocities components :
2110 allocate_cell_vector(ana_grad2Ui_, domaine_ijk_, 0);
2111 allocate_cell_vector(ana_grad2Uc_, domaine_ijk_, 0);
2112 allocate_cell_vector(ana_grad2Vi_, domaine_ijk_, 0);
2113 allocate_cell_vector(ana_grad2Vc_, domaine_ijk_, 0);
2114 allocate_cell_vector(ana_grad2Wi_, domaine_ijk_, 0);
2115 allocate_cell_vector(ana_grad2Wc_, domaine_ijk_, 0);
2116 }
2117
2118
2119}
2120
2122{
2123 bool flag_variable_source = ref_ijk_ft_->eq_ns().get_flag_variable_source();
2124 // Le mot cle TOUS n'a pas encore ete compris comme tel.
2125 if ((liste_post_instantanes_.contient_("GRAD_INDICATRICE_FT")) || (liste_post_instantanes_.contient_("TOUS")))
2126 allocate_velocity(grad_I_ft_, domaine_ft_, 2);
2127
2128 if (liste_post_instantanes_.contient_("D_VELOCITY_ANA"))
2129 allocate_velocity(d_velocity_ana_, domaine_ijk_, 1);
2130 if (liste_post_instantanes_.contient_("OP_CONV"))
2131 {
2132 allocate_velocity(op_conv_, domaine_ijk_, ref_ijk_ft_->eq_ns().d_velocity_[0].ghost()); // Il y a 1 ghost chez d_velocity_
2133 // On veut qqch d'aligne pour copier les data() l'un dans l'autre
2134 }
2135 if (liste_post_instantanes_.contient_("CELL_OP_CONV"))
2136 {
2137 allocate_cell_vector(cell_op_conv_, domaine_ijk_, ref_ijk_ft_->eq_ns().d_velocity_[0].ghost()); // Il y a 1 ghost chez d_velocity_
2138 // On veut qqch d'aligne pour copier les data() l'un dans l'autre
2139 }
2140
2141 if (is_post_required("RHO_SOURCE_QDM_INTERF"))
2142 {
2143 IJK_Field_vector3_double& rho_Ssigma = vect_post_fields_.at("RHO_SOURCE_QDM_INTERF");
2144 allocate_velocity(rho_Ssigma, domaine_ijk_, 1, "RHO_SOURCE_QDM_INTERF");
2145 champs_compris_.ajoute_champ_vectoriel(rho_Ssigma);
2146 // TODO : probablement inutile maintenant:
2147 allocate_cell_vector(cell_rho_Ssigma_, domaine_ijk_, 0);
2148 }
2149
2150 // Pour le calcul des statistiques diphasiques :
2151 // (si le t_debut_stat a ete initialise... Sinon, on ne va pas les calculer au cours de ce calcul)
2152 if (is_stats_plans_activated() || flag_variable_source)
2153 {
2154 allocate_velocity(grad_I_ns_, domaine_ijk_, 1);
2155 }
2156}
2157
2159{
2160 if ((imp) || (liste_post_instantanes_.contient_("COORDS")))
2161 {
2162 Noms noms_coords; // on attend trois expressions
2163 noms_coords.dimensionner_force(3);
2164 noms_coords[0] = "X";
2165 noms_coords[1] = "Y";
2166 noms_coords[2] = "Z";
2167 allocate_velocity(coords_, domaine_ijk_, 1);
2168 for (int i = 0; i < 3; i++)
2169 {
2170 // Cette methode parcours ni(), nj() et nk() et donc pas les ghost...
2171 set_field_data(coords_[i], noms_coords[i]);
2172 }
2173 }
2174}
2175
2176void Postprocessing_IJK::postraiter_thermals(bool stop)
2177{
2178 if (ref_ijk_ft_->has_thermals())
2179 thermals_->set_first_step_thermals_post(first_step_thermals_post_);
2180
2181 // TODO review this:
2182
2183// if (ref_ijk_ft_->has_thermals())
2184// if (stop || first_step_thermals_post_
2185// || (nb_pas_dt_post_thermals_probes_ >= 0 && tstep_sauv % nb_pas_dt_post_thermals_probes_ == nb_pas_dt_post_thermals_probes_ - 1)
2186// || (std::floor((current_time-timestep)/time_interval_post_thermals_probes_) < std::floor(current_time/time_interval_post_thermals_probes_)))
2187// {
2188// Cout << "tstep : " << tstep << finl;
2189// thermals_->thermal_subresolution_outputs(nb_pas_dt_post_thermals_probes_);
2190// }
2191}
2192
2197
2198// Warning: this one looking at t_debut_statistiques_ too
2203
2208
2213
2218
2223
2224
2225void Postprocessing_IJK::postraiter_stats(bool stop)
2226{
2227 Schema_Temps_IJK_base& sch = ref_ijk_ft_->schema_temps_ijk();
2228 int tstep = sch.get_tstep(),
2229 tstep_init = sch.get_tstep_init();
2230 double current_time = sch.get_current_time(),
2231 timestep = sch.get_timestep();
2232 const Nom& nom_cas = nom_du_cas();
2233
2234 const int tstep_sauv = tstep + tstep_init;
2235
2236 // Helper function, indicating for a given nb_pas_dt_XXX if post for this XXX category should be triggered:
2237 auto should_post = [&](int nb_pas_dt, double time_interv)
2238 {
2239 if (stop
2240 || (nb_pas_dt >= 0 && tstep_sauv % nb_pas_dt == nb_pas_dt - 1)
2241 || (std::floor((current_time-timestep)/time_interv) < std::floor(current_time/time_interv)))
2242 return true;
2243 return false;
2244 };
2245
2247 ecrire_statistiques_bulles(0, nom_cas, current_time);
2249 posttraiter_statistiques_plans(current_time);
2251 ecrire_statistiques_cisaillement(0, nom_cas, current_time);
2253 ecrire_statistiques_mrf(0, nom_cas, current_time);
2255 ecrire_statistiques_amont(0, nom_cas, current_time);
2257 ecrire_statistiques_fh(0, nom_cas, current_time);
2258}
2259
2260// NEW INTERPOLATING FUNCTION TO AVOID EULERIAN POINTS LYING IN THE BUBBLES OR ON THE INTERFACE
2261static void ijk_interpolate_implementation_bis(const IJK_Field_double& field, const DoubleTab& coordinates, ArrOfDouble& result, int skip_unknown_points, double value_for_bad_points,
2262 const IJK_Field_double& indic)
2263{
2264 const int ghost = field.ghost();
2265 const int ni = field.ni();
2266 const int nj = field.nj();
2267 const int nk = field.nk();
2268 const Domaine_IJK& geom = field.get_domaine();
2269 const double dx = geom.get_constant_delta(DIRECTION_I);
2270 const double dy = geom.get_constant_delta(DIRECTION_J);
2271 const double dz = geom.get_constant_delta(DIRECTION_K);
2272 const Domaine_IJK::Localisation loc = field.get_localisation();
2273 double origin_x = geom.get_origin(DIRECTION_I) + ((loc == Domaine_IJK::FACES_J || loc == Domaine_IJK::FACES_K || loc == Domaine_IJK::ELEM) ? (dx * 0.5) : 0.);
2274 double origin_y = geom.get_origin(DIRECTION_J) + ((loc == Domaine_IJK::FACES_K || loc == Domaine_IJK::FACES_I || loc == Domaine_IJK::ELEM) ? (dy * 0.5) : 0.);
2275 double origin_z = geom.get_origin(DIRECTION_K) + ((loc == Domaine_IJK::FACES_I || loc == Domaine_IJK::FACES_J || loc == Domaine_IJK::ELEM) ? (dz * 0.5) : 0.);
2276 const int nb_coords = coordinates.dimension(0);
2277 const int gh = indic.ghost();
2278 result.resize_array(nb_coords);
2279 for (int idx = 0; idx < nb_coords; idx++)
2280 {
2281 const double x = coordinates(idx, 0); // coordinate of the point where the interpolation is needed
2282 const double y = coordinates(idx, 1);
2283 const double z = coordinates(idx, 2);
2284 const double x2 = (x - origin_x) / dx;
2285 const double y2 = (y - origin_y) / dy;
2286 const double z2 = (z - origin_z) / dz;
2287 const int index_i = (int) (floor(x2)) - geom.get_offset_local(DIRECTION_I); //index of the closest cell center is this defined only in the single processor?
2288 const int index_j = (int) (floor(y2)) - geom.get_offset_local(DIRECTION_J);
2289 const int index_k = (int) (floor(z2)) - geom.get_offset_local(DIRECTION_K);
2290 const int index_kp1 = index_k + 1;
2291 const double xfact = x2 - floor(x2); // non-dimension distance inside the cell where the interpolation is requested
2292 const double yfact = y2 - floor(y2);
2293 const double zfact = z2 - floor(z2);
2294
2295 // Compute the phase indicator function in all the eulerian points involved in the interpolation
2296 double c_1 = 0.;
2297 double c_2 = 0.;
2298 double c_3 = 0.;
2299 double c_4 = 0.;
2300 double c_5 = 0.;
2301 double c_6 = 0.;
2302 double c_7 = 0.;
2303 double c_8 = 0.;
2304 //The following loop is used to take into account the non-periodic condition along the z-axis
2305 // if the index of the point is outside the wall the cell is considered as vapor, therefore putting an invalid value
2306 if (!geom.get_periodic_flag(DIRECTION_K))
2307 // In this case the two domains (FT and NS) are equal in the z direction
2308 {
2309 const int kmin = geom.get_offset_local(DIRECTION_K);
2310 const int nktot = geom.get_nb_items_global(loc, DIRECTION_K);
2311 //Serial calculation
2312 if (nktot == nk)
2313 {
2314 if ((kmin == 0) || (kmin + nk == nktot)) //The conditions on walls may be imposed at the same time since there is no misunderstanding on the indices
2315 {
2316 // The phase indicator function is correctly evaluated only inside the domain of the single processor
2317 // otherwise its value remains equal to 0, leading to ad invalid value for the interpolation
2318 if (index_k >= 0 && index_k < nk && index_kp1 >= 0 && index_kp1 < nk && index_i >= 0 && index_i < ni && index_j >= 0 && index_j < nj)
2319 {
2320 c_1 = indic(index_i, index_j, index_k);
2321 if (index_i != ni - 1)
2322 c_2 = indic(index_i + 1, index_j, index_k);
2323 if (index_j != nj - 1)
2324 c_3 = indic(index_i, index_j + 1, index_k);
2325 if (index_i != ni - 1 && index_j != nj - 1)
2326 c_4 = indic(index_i + 1, index_j + 1, index_k);
2327
2328 c_5 = indic(index_i, index_j, index_kp1);
2329 if (index_i != ni - 1)
2330 c_6 = indic(index_i + 1, index_j, index_kp1);
2331 if (index_j != nj - 1)
2332 c_7 = indic(index_i, index_j + 1, index_kp1);
2333 if (index_i != ni - 1 && index_j != nj - 1)
2334 c_8 = indic(index_i + 1, index_j + 1, index_kp1);
2335 }
2336 }
2337 }
2338 //Parallel calculation
2339 //NB The following procedure does not fit for one processor
2340 //since the first condition assigns a value to the point outside the right wall which should be invalid
2341 //THE LOOP SHOULD BE IMPROVED
2342 //The two walls are addressed separately since they are elaborated by two different processors.
2343 else
2344 {
2345 if (kmin == 0) //on the left wall
2346 {
2347 if (index_k >= 0 && index_kp1 >= 0 && index_i >= -gh && index_i < ni + gh && index_j >= -gh && index_j < nj + gh && index_kp1 < nk && index_k < nk)
2348 {
2349 c_1 = indic(index_i, index_j, index_k);
2350 if (index_i != ni + gh - 1)
2351 c_2 = indic(index_i + 1, index_j, index_k);
2352 if (index_j != nj + gh - 1)
2353 c_3 = indic(index_i, index_j + 1, index_k);
2354 if (index_i != ni + gh - 1 && index_j != nj + gh - 1)
2355 c_4 = indic(index_i + 1, index_j + 1, index_k);
2356
2357 c_5 = indic(index_i, index_j, index_kp1);
2358 if (index_i != ni + gh - 1)
2359 c_6 = indic(index_i + 1, index_j, index_kp1);
2360 if (index_j != nj + gh - 1)
2361 c_7 = indic(index_i, index_j + 1, index_kp1);
2362 if (index_i != ni + gh - 1 && index_j != nj + gh - 1)
2363 c_8 = indic(index_i + 1, index_j + 1, index_kp1);
2364 }
2365 }
2366 else if (kmin + nk == nktot) // on the right wall
2367 {
2368 if (index_k < nk && index_kp1 < nk && index_i >= -gh && index_i < ni + gh && index_j >= -gh && index_j < nj + gh && index_kp1 >= 0 && index_k >= 0)
2369 {
2370 //Process::Journal() << "Proc: " << Process::me() << " i,j,k: "
2371 // << index_i << " " << index_j << " " << index_k << endl;
2372 c_1 = indic(index_i, index_j, index_k);
2373 if (index_i != ni + gh - 1)
2374 c_2 = indic(index_i + 1, index_j, index_k);
2375 if (index_j != nj + gh - 1)
2376 c_3 = indic(index_i, index_j + 1, index_k);
2377 if (index_i != ni + gh - 1 && index_j != nj + gh - 1)
2378 c_4 = indic(index_i + 1, index_j + 1, index_k);
2379
2380 c_5 = indic(index_i, index_j, index_kp1);
2381 if (index_i != ni + gh - 1)
2382 c_6 = indic(index_i + 1, index_j, index_kp1);
2383 if (index_j != nj + gh - 1)
2384 c_7 = indic(index_i, index_j + 1, index_kp1);
2385 if (index_i != ni + gh - 1 && index_j != nj + gh - 1)
2386 c_8 = indic(index_i + 1, index_j + 1, index_kp1);
2387 }
2388 }
2389 else // points in processor not treating walls
2390 {
2391 if (index_k < nk + gh && index_kp1 < nk + gh && index_i >= -gh && index_i < ni + gh && index_j >= -gh && index_j < nj + gh && index_kp1 >= -gh && index_k >= -gh)
2392 {
2393 c_1 = indic(index_i, index_j, index_k);
2394 if (index_i < ni + gh - 1)
2395 c_2 = indic(index_i + 1, index_j, index_k);
2396 if (index_j < nj + gh - 1)
2397 c_3 = indic(index_i, index_j + 1, index_k);
2398 if (index_i < ni + gh - 1 && index_j < nj + gh - 1)
2399 c_4 = indic(index_i + 1, index_j + 1, index_k);
2400
2401 c_5 = indic(index_i, index_j, index_kp1);
2402 if (index_i < ni + gh - 1)
2403 c_6 = indic(index_i + 1, index_j, index_kp1);
2404 if (index_j < nj + gh - 1)
2405 c_7 = indic(index_i, index_j + 1, index_kp1);
2406 if (index_i < ni + gh - 1 && index_j < nj + gh - 1)
2407 c_8 = indic(index_i + 1, index_j + 1, index_kp1);
2408 }
2409 }
2410 }
2411 }
2412
2413 else // ghost cells may be interrogated when the direction is periodic
2414 {
2415 if (index_k < nk + gh && index_kp1 < nk + gh && index_i >= -gh && index_i < ni + gh && index_j >= -gh && index_j < nj + gh && index_kp1 >= -gh && index_k >= -gh)
2416 {
2417 c_1 = indic(index_i, index_j, index_k);
2418 if (index_i < ni + gh - 1)
2419 c_2 = indic(index_i + 1, index_j, index_k);
2420 if (index_j < nj + gh - 1)
2421 c_3 = indic(index_i, index_j + 1, index_k);
2422 if (index_i < ni + gh - 1 && index_j < nj + gh - 1)
2423 c_4 = indic(index_i + 1, index_j + 1, index_k);
2424
2425 c_5 = indic(index_i, index_j, index_kp1);
2426 if (index_i < ni + gh - 1)
2427 c_6 = indic(index_i + 1, index_j, index_kp1);
2428 if (index_j < nj + gh - 1)
2429 c_7 = indic(index_i, index_j + 1, index_kp1);
2430 if (index_i < ni + gh - 1 && index_j < nj + gh - 1)
2431 c_8 = indic(index_i + 1, index_j + 1, index_kp1);
2432 }
2433 }
2434
2435 // Where at least of the points used in the interpolation is outside the liquid phase (at the interface or in the vapor phase)
2436 // the invalid value is assigned by the interpolation function
2437 bool ok_2 = (c_1 + c_2 + c_3 + c_4 + c_5 + c_6 + c_7 + c_8 >= 7.99);
2438
2439// is point in the domain ? (ghost cells ok...)
2440 bool ok = (index_i >= -ghost && index_i < ni + ghost - 1) && (index_j >= -ghost && index_j < nj + ghost - 1) && (index_k >= -ghost && index_k < nk + ghost - 1);
2441 if (!ok or !ok_2)
2442 {
2443 if (skip_unknown_points)
2444 {
2445 result[idx] = value_for_bad_points;
2446 continue; // go to next point
2447 }
2448 else
2449 {
2450 // Error!
2451 Cerr << "Error in ijk_interpolate_implementation: request interpolation of point " << x << " " << y << " " << z << " which is outside of the domain on processor " << Process::me()
2452 << finl;
2453 Process::exit();
2454 }
2455 }
2456
2457 double r = (((1. - xfact) * field(index_i, index_j, index_k) + xfact * field(index_i + 1, index_j, index_k)) * (1. - yfact)
2458 + ((1. - xfact) * field(index_i, index_j + 1, index_k) + xfact * field(index_i + 1, index_j + 1, index_k)) * (yfact)) * (1. - zfact)
2459 + (((1. - xfact) * field(index_i, index_j, index_kp1) + xfact * field(index_i + 1, index_j, index_kp1)) * (1. - yfact)
2460 + ((1. - xfact) * field(index_i, index_j + 1, index_kp1) + xfact * field(index_i + 1, index_j + 1, index_kp1)) * (yfact)) * (zfact);
2461 result[idx] = r;
2462 }
2463}
2464void ijk_interpolate_skip_unknown_points_bis(const IJK_Field_double& field, const DoubleTab& coordinates, ArrOfDouble& result, const double value_for_bad_points, const IJK_Field_double& indic)
2465{
2466 ijk_interpolate_implementation_bis(field, coordinates, result, 1 /* yes:skip unknown points */, value_for_bad_points, indic);
2467}
2468
2469// Here begins the computation of the extended pressure fields
2470// ALL the calculations are performed on the extended domain (FT) and the final field is the redistributed on the physical one (Navier-Stokes)
2472{
2474 return; // Leave the function if the extended fields are not necessary...
2475
2476 Navier_Stokes_FTD_IJK& ns = ref_ijk_ft_->eq_ns();
2477 // The following calculation is defined on the extended domain ft
2478 const Domaine_IJK& split_ft = domaine_ft_;
2479 const int ni = split_ft.get_nb_elem_local(DIRECTION_I);
2480 const int nj = split_ft.get_nb_elem_local(DIRECTION_J);
2481 const int nk = split_ft.get_nb_elem_local(DIRECTION_K);
2482 const double dx = split_ft.get_constant_delta(DIRECTION_I);
2483 const double dy = split_ft.get_constant_delta(DIRECTION_J);
2484 const double dz = split_ft.get_constant_delta(DIRECTION_K);
2485 int nbsom = 0;
2486 // ArrOfInt liste_composantes_connexes_dans_element;
2487 DoubleTab positions_liq(2 * nbsom, 3); // Table of coordinates where interpolation needs to be computed
2488 DoubleTab positions_vap(2 * nbsom, 3);
2489 IntTab crossed_cells(nbsom, 3); // Table to store i,j,k of cells crossed by the interface.
2490
2491 //pressure field has to be extended from ns to ft
2493 pressure_ft_.echange_espace_virtuel(pressure_ft_.ghost()); // 5 ghost cells needed to avoid invalid points in the vapor phase
2494 //dP_ft_.echange_espace_virtuel(gradP_ft_.ghost());
2495
2496 //initialisation
2497
2498 // The other points of the domain ( the one outside the crossed cells are still equal to original value of pressure)
2499 // This generates the discontinuities seen in Visit
2502 //for (int dir = 0; dir < 3; dir++)
2503 // {
2504 // dP_ft_[dir].data() = 0.;
2505 //}
2506
2507 int errcount_pext = 0;
2508 // i,j,k are the indices if the cells in the extended domain, for each processor
2509 for (int k = 0; k < nk; k++)
2510 for (int j = 0; j < nj; j++)
2511 for (int i = 0; i < ni; i++)
2512 {
2513 if ((interfaces_->In_ft()(i, j, k) > 1.e-6) && (1. - interfaces_->In_ft()(i, j, k) > 1.e-6))
2514 {
2515 Vecteur3 bary_facettes_dans_elem;
2516 Vecteur3 normale;
2517 double norm = 1.;
2518 double dist = 0.;
2519 for (int c = 0; c < 3; c++)
2520 {
2521 normale[c] = interfaces_->get_norm_par_compo_itfc_in_cell_ft()[c](i, j, k);
2522 bary_facettes_dans_elem[c] = interfaces_->get_bary_par_compo_itfc_in_cell_ft()[c](i, j, k);
2523 }
2524 norm = sqrt(normale[0] * normale[0] + normale[1] * normale[1] + normale[2] * normale[2]);
2525 //if (norm<0.95)
2526 // Process::Journal() << "[WARNING-NORM] " << "Indicatrice[" << i <<"," << j << "," << k << "] = " << interfaces_.In_ft()(i,j,k)
2527 // << " norm= " << norm << finl;
2528 // }
2529 if (norm < 1.e-8)
2530 {
2531 // Process::Journal() << " nb_compo_traversantes " << nb_compo_traversantes << finl;
2532 Process::Journal() << "Indicatrice[" << i << "," << j << "," << k << "] = " << interfaces_->In_ft()(i, j, k) << finl;
2533 Process::Journal() << "[WARNING-Extended-pressure] on Proc. " << Process::me() << "Floating Point Exception is barely avoided (" << " normale " << normale[0] << " " << normale[1]
2534 << " " << normale[2] << " )" << finl;
2535 Process::Journal() << " But we have no distance to extrapolate the pressure" << finl;
2536 dist = 1.52 * sqrt(dx * dx + dy * dy + dz * dz) / 3.;
2537 if (interfaces_->In_ft()(i, j, k) * (1 - interfaces_->In_ft()(i, j, k)) > 1.e-6)
2538 {
2539 Process::Journal() << "[WARNING-Extended-pressure] " << "Indicatrice[" << i << "," << j << "," << k << "] = " << interfaces_->In_ft()(i, j, k) << finl;
2540 if (interfaces_->In_ft()(i, j, k) > 0.99)
2541 {
2542 Process::Journal() << "[WARNING-Extended-pressure] " << "Pressure_ft_ will be kept as an extension for p_liq pressure_[" << i << "," << j << "," << k << "] = "
2543 << pressure_ft_(i, j, k) << finl;
2544 extended_pv_ft_(i, j, k) = 1.e20;
2545 }
2546 else
2547 {
2548 Process::Journal() << "[WARNING-Extended-pressure] " << "Pressure_ft_ will be kept as an extension for p_vap pressure_[" << i << "," << j << "," << k << "] = "
2549 << pressure_ft_(i, j, k) << finl;
2550 extended_pl_ft_(i, j, k) = 1.e20;
2551 }
2552 continue; // This cell is not added to crossed cells.
2553 }
2554 else
2555 {
2556 // We still need a unit normal
2557 for (int dir = 0; dir < 3; dir++)
2558 if (normale[dir] != 0)
2559 normale[dir] = (normale[dir] > 0.) ? 1.0 : -1.0;
2560
2561 norm = sqrt(normale[0] * normale[0] + normale[1] * normale[1] + normale[2] * normale[2]);
2562 if (std::fabs(norm) < 1.e-10)
2563 {
2564 Process::Journal() << "[WARNING-Extended-pressure] ||normal|| < 1.e-10" << finl;
2565 }
2566 }
2567 }
2568
2569 if (std::fabs(norm) < 1.e-10)
2570 {
2571 Process::Journal() << "[WARNING-Extended-pressure] Even with precaution, the normal truely is zero in compute_extended_pressures()... " << finl;
2572 Cerr << "We ignore the extrapolation and keep the local value... (hopefully rare enough)" << finl;
2573 dist = 0.;
2574 errcount_pext++;
2575 }
2576 else
2577 {
2578 dist = 1.52 * (std::fabs(dx * normale[0]) + std::fabs(dy * normale[1]) + std::fabs(dz * normale[2])) / norm;
2579 // 2020.04.15 : GB correction for non-isotropic meshes and closer extrapolation points:
2580 // The previous version was looking very far away in the direction where the mesh is fine (dz in channel flows).
2581 // Then, a lot of ghost would be required.
2582 // This new version still goes to the same value of dist when nx=1 or when nz=1, but is sin between
2583 // double eps = 1.e-20;
2584 // dist = 1.52*std::min(min(dx/(std::fabs(normale[0])+eps),dy/(std::fabs(normale[1])+eps)),dz/(std::fabs(normale[2])+eps));
2585 }
2586
2587 nbsom++;
2588 crossed_cells.resize(nbsom, 3, RESIZE_OPTIONS::COPY_INIT);
2589 positions_liq.resize(2 * nbsom, 3, RESIZE_OPTIONS::COPY_INIT);
2590 positions_vap.resize(2 * nbsom, 3, RESIZE_OPTIONS::COPY_INIT);
2591
2592 crossed_cells(nbsom - 1, 0) = i;
2593 crossed_cells(nbsom - 1, 1) = j;
2594 crossed_cells(nbsom - 1, 2) = k;
2595
2596 for (int dir = 0; dir < 3; dir++)
2597 {
2598 // Four image points are calculated, two on each side of the interface
2599 //liquid phase
2600 positions_liq(2 * nbsom - 2, dir) = bary_facettes_dans_elem[dir] + dist * normale[dir]; // 1st point to be done...
2601 positions_liq(2 * nbsom - 1, dir) = bary_facettes_dans_elem[dir] + 2 * dist * normale[dir]; // 2nd point to be done...
2602 //vapor_phase
2603 positions_vap(2 * nbsom - 2, dir) = bary_facettes_dans_elem[dir] - dist * normale[dir]; // 1st point to be done...
2604 positions_vap(2 * nbsom - 1, dir) = bary_facettes_dans_elem[dir] - 2 * dist * normale[dir]; // 2nd point to be done...
2605 }
2606 }
2607 }
2608
2609
2610
2611 errcount_pext = static_cast<int>(Process::mp_sum(errcount_pext));
2612 if (Process::je_suis_maitre() && errcount_pext)
2613 Cerr << "[WARNING-Extended-pressure] Error Count = " << errcount_pext << endl;
2614
2615 // Interpolation on the image points
2616 // All the quantities are evaluated on the extended domain, both the pressure field, both the image points coordinates
2617
2618 ArrOfDouble p_interp_liq(2 * nbsom);
2619 ArrOfDouble p_interp_vap(2 * nbsom);
2620 ijk_interpolate_skip_unknown_points(pressure_ft_, positions_vap, p_interp_vap, 1.e5 /*value for unknown points*/);
2621 ijk_interpolate_skip_unknown_points_bis(pressure_ft_, positions_liq, p_interp_liq, 1.e5 /* value for unknown points */, interfaces_->In_ft());
2622
2623 // Extrapolation in the eulerian cells crossed by the interface
2624 int inval_pl_count = 0.;
2625 int inval_pv_count = 0.;
2626 for (int icell = 0; icell < nbsom; icell++)
2627 {
2628 const int i = crossed_cells(icell, 0);
2629 const int j = crossed_cells(icell, 1);
2630 const int k = crossed_cells(icell, 2);
2631 // const int nb_compo_traversantes = interfaces_.compute_list_compo_connex_in_element(mesh, elem, liste_composantes_connexes_dans_element);
2632 const int nb_compo_traversantes = interfaces_->nb_compo_traversantes(i, j, k);
2633 if (nb_compo_traversantes != 1)
2634 {
2635 extended_pv_ft_(i, j, k) = 1.e20;
2636 inval_pv_count++;
2637 }
2638 else
2639 {
2640 extended_pv_ft_(i, j, k) = 2 * p_interp_vap[2 * icell] - 1 * p_interp_vap[2 * icell + 1];
2641 }
2642
2643 //for(int dir=0; dir<3; dir++)
2644 if (p_interp_liq[2 * icell + 1] == 1.e5)
2645 {
2646 if (p_interp_liq[2 * icell] == 1.e5) //May changing the order affect the result??
2647 {
2648 extended_pl_ft_(i, j, k) = 1.e20;
2649 inval_pl_count++;
2650 //dP_ft_[dir](i,j,k) = 1.e20
2651 }
2652 else
2653 {
2654 extended_pl_ft_(i, j, k) = p_interp_liq[2 * icell];
2655 //dP_ft_[dir](i,j,k) = 1.e20
2656 }
2657 }
2658 else
2659 {
2660 if (p_interp_liq[2 * icell] != 1.e5)
2661 {
2662 extended_pl_ft_(i, j, k) = 2 * p_interp_liq[2 * icell] - 1 * p_interp_liq[2 * icell + 1];
2663 //dP_ft_[dir](i,j,k) = (p_interp_liq(2*icell) - 1*p_interp_liq(2*icell+1))*normale[dir]/dist;
2664 }
2665 else
2666 {
2667 extended_pl_ft_(i, j, k) = p_interp_liq[2 * icell + 1];
2668 //dP_ft_[dir](i,j,k) = 1.e20
2669 }
2670 }
2671 }
2672
2673 inval_pl_count = static_cast<int>(Process::mp_sum(inval_pl_count));
2674 inval_pv_count = static_cast<int>(Process::mp_sum(inval_pv_count));
2675 if (Process::je_suis_maitre() && inval_pl_count)
2676 Cerr << "[WARNING-Extended-pressure] Invalid p_l cells Count = " << inval_pl_count << endl;
2677 if (Process::je_suis_maitre() && inval_pv_count)
2678 Cerr << "[WARNING-Extended-pressure] Invalid p_v cells Count = " << inval_pv_count << endl;
2679
2680 // The previous evaluated extended pressure has to be recomputed on the real NS domain
2683 //ref_ijk_ft_.redistribute_from_splitting_ft_elem_.redistribute(dP_ft, dP_);
2684
2685 extended_pl_.echange_espace_virtuel(extended_pl_.ghost());
2686 extended_pv_.echange_espace_virtuel(extended_pv_.ghost());
2687}
2688
2689// Methode appelee lorsqu'on a mis "TOUS" dans la liste des champs a postraiter.
2690// Elle ajoute a la liste tous les noms de champs postraitables par IJK_Interfaces
2691
2693{
2694 liste.add("TEMPERATURE");
2695 liste.add("CP");
2696 liste.add("LAMBDA");
2697 liste.add("TEMPERATURE_ANA");
2698 liste.add("ECART_T_ANA");
2699 liste.add("DIV_LAMBDA_GRAD_T_VOLUME");
2700 liste.add("SOURCE_TEMPERATURE");
2701 liste.add("TEMPERATURE_ADIM_BULLES");
2702 liste.add("TEMPERATURE_PHYSIQUE_T");
2703 liste.add("TEMPERATURE_ADIMENSIONNELLE_THETA");
2704 liste.add("SOURCE_TEMPERATURE_ANA");
2705 liste.add("ECART_SOURCE_TEMPERATURE_ANA");
2706 liste.add("GRAD_T");
2707 liste.add("GRAD_T0");
2708 liste.add("GRAD_T1");
2709 liste.add("GRAD_T2");
2710 liste.add("T_RUST");
2711 liste.add("DIV_RHO_CP_T_V");
2712
2713}
2714
2715// Methode appelee lorsqu'on a mis "TOUS" dans la liste des champs a postraiter.
2716// Elle ajoute a la liste tous les noms de champs postraitables par IJK_Interfaces
2718{
2719 liste.add("TEMPERATURE");
2720 liste.add("CP");
2721 liste.add("LAMBDA");
2722 liste.add("TEMPERATURE_ANA");
2723 liste.add("ECART_T_ANA");
2724 liste.add("DIV_LAMBDA_GRAD_T_VOLUME");
2725 liste.add("SOURCE_TEMPERATURE");
2726 liste.add("TEMPERATURE_ADIM_BULLES");
2727 liste.add("TEMPERATURE_PHYSIQUE_T");
2728 liste.add("TEMPERATURE_ADIMENSIONNELLE_THETA");
2729 liste.add("SOURCE_TEMPERATURE_ANA");
2730 liste.add("ECART_SOURCE_TEMPERATURE_ANA");
2731 liste.add("GRAD_T");
2732 liste.add("GRAD_T0");
2733 liste.add("GRAD_T1");
2734 liste.add("GRAD_T2");
2735 liste.add("T_RUST");
2736 liste.add("DIV_RHO_CP_T_V");
2737}
2738
2739// local utilitary functions for the method Postprocessing_IJK::get_max_timestep_for_post
2740namespace
2741{
2742
2743// returns remainder of division between real numbers
2744double modulo(double dividend, double divisor)
2745{
2746 return ((std::floor(dividend/divisor) + 1)*divisor - dividend);
2747}
2748
2749// Note : the (1+1e-12) safety factor ensures that the simulation reaches the target.
2750// Otherwise, the simulation time might fall just below the target due to numerical errors, not triggering the desired post.
2751// If you happen to miss an interval, you may adjust the factor to a higher value
2752void add_max_timestep(std::vector<double>& timesteps, double current_time, double interval)
2753{
2754 if (interval>0 && (modulo(current_time, interval) != 0))
2755 timesteps.push_back(modulo(current_time, interval)*(1+1e-12));
2756
2757}
2758
2759}
2760
2761/// @brief Compute the max possible timestep to use during the next iteration
2762/// in order to not skip a time interval for postpro
2763/// @param current_time
2764/// @return max time step acceptable in order to land on a time for requirede post
2765double Postprocessing_IJK::get_max_timestep_for_post(double current_time) const
2766{
2767
2768 std::vector<double> timesteps;
2769 timesteps.push_back(DMAXFLOAT);
2770 add_max_timestep(timesteps, current_time, time_interval_post_);
2771 add_max_timestep(timesteps, current_time, time_interval_post_thermals_probes_);
2772 add_max_timestep(timesteps, current_time, time_interval_post_stats_bulles_);
2773 add_max_timestep(timesteps, current_time, time_interval_post_stats_plans_);
2774 add_max_timestep(timesteps, current_time, time_interval_post_stats_cisaillement_);
2775 add_max_timestep(timesteps, current_time, time_interval_post_stats_mrf_);
2776 add_max_timestep(timesteps, current_time, time_interval_post_stats_amont_);
2777 add_max_timestep(timesteps, current_time, time_interval_post_stats_fh_);
2778
2779 double min=*std::min_element(timesteps.begin(),timesteps.end());
2780 assert(min>0);
2781 return min;
2782
2783}
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
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_constant_delta(int direction) const
Returns the size of cells in a direction.
double get_origin(int direction) const
Returns the coordinate of the first node (global) of the mesh in the 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...
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.
virtual Nature_du_champ nature_du_champ() const
Definition Field_base.h:77
void allocate(const Domaine_IJK &d, Domaine_IJK::Localisation l, int ghost_size, int additional_k_layers=0, int nb_compo=1, const Nom &name=Nom(), bool external_storage=false, int monofluide=0, double rov=0., double rol=0., int use_inv_rho_in_pressure_solver=0)
Domaine_IJK::Localisation get_localisation() const
virtual void dumplata_scalar(const char *filename, int step) const
const Domaine_IJK & get_domaine() const
Entity & localisation()
: class IJK_Interfaces
static void Fill_postprocessable_fields(std::vector< FieldInfo_t > &chps)
void dumplata_ft_mesh(const char *filename, const char *meshname, int step) const
static void Fill_postprocessable_fields(std::vector< FieldInfo_t > &chps)
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
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)
Redistribute_Field redistribute_to_splitting_ft_elem_
Redistribute_Field redistribute_from_splitting_ft_elem_
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)
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
const Nom & le_nom() const override
Renvoie *this;.
Definition Nom.cpp:563
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
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
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
bool is_stats_bulles_activated() const
IJK_Field_vector3_double ana_grad2Pc_
IJK_Field_vector3_double ana_dUd_
void init_integrated_and_ana(bool reprise)
IJK_Field_double extended_pl_ft_
void ecrire_statistiques_fh(int reset, const Nom &nom_cas, const double current_time) const
IJK_Field_double ai_ns_
void calculer_gradient_indicatrice(const IJK_Field_double &indic)
IJK_Field_double integrated_timescale_
IJK_Field_double dvdz_
void ecrire_statistiques_mrf(int reset, const Nom &nom_cas, const double current_time) const
void ecrire_statistiques_cisaillement(int reset, const Nom &nom_cas, const double current_time) const
IJK_Field_double dudy_
IJK_Field_vector3_double ana_gradP_
bool is_post_required(const Motcle &nom) const
std::map< Motcle, IJK_Field_vector3_double > vect_post_fields_
std::map< Motcle, IJK_Field_double > scalar_post_fields_
void improved_initial_pressure_guess(bool imp)
IJK_Field_double rebuilt_indic_
IJK_Field_vector3_double normale_cell_ft_
void ecrire_statistiques_amont(int reset, const Nom &nom_cas, const double current_time)
void sauvegarder_post(const Nom &lata_name)
const IJK_Field_double & get_IJK_field(const Motcle &nom) override
IJK_Field_double dvdy_
IJK_Field_vector3_double d_velocity_ana_
IJK_Field_double kappa_ai_ns_
static void Fill_postprocessable_fields(std::vector< FieldInfo_t > &chps)
double time_interval_post_thermals_probes_
bool is_stats_amont_activated() const
const IJK_Field_vector3_double & get_IJK_field_vector(const Motcle &nom) override
void update_gradU_lambda2(const bool need_lambda2=false)
IJK_Field_double kappa_ai_ft_
void ecrire_statistiques_bulles(int reset, const Nom &nom_cas, const double current_time) const
Champs_compris_IJK champs_compris_
the actual fields registered and managed by the post-processing part (=all the extra fields,...
std::vector< FieldIndex_t > field_post_idx_
IJK_Field_double integrated_pressure_
IJK_Field_vector3_double ana_dVd_
std::pair< int, bool > FieldIndex_t
IJK_Field_vector3_double velocity_ana_
IJK_Field_double extended_pv_
IJK_Field_vector3_double ana_grad2Ui_
IJK_Field_double dvdx_
bool is_stats_mrf_activated() const
IJK_Field_double dudz_
bool is_stats_plans_activated() const
IJK_Field_double ecart_p_ana_
void associer_probleme(const Probleme_FTD_IJK_base &)
IJK_Field_vector3_double ana_grad2Pi_
static std::vector< FieldInfo_t > champs_postraitables_
list of fields that can be potentially postprocessed
void fill_surface_force(IJK_Field_vector3_double &the_field_you_know)
IJK_Field_vector3_double grad_I_ft_
int write_extra_mesh() override
double time_interval_post_stats_cisaillement_
IJK_Field_vector3_double ana_grad2Wc_
IJK_Field_double extended_pv_ft_
IJK_Field_double dudx_
void postraiter(int forcer) override
void update_stat_ft(const double dt)
IJK_Field_vector3_double cell_rho_Ssigma_
IJK_Field_double dwdx_
void posttraiter_tous_champs_thermique(Motcles &liste, const int idx) const
void set_param(Param &param) const override
int lire_champs_a_postraiter(Entree &is, bool expect_acco) override
IJK_Field_double indicatrice_non_perturbe_
IJK_Field_vector3_double ana_dWd_
IJK_Field_vector3_double ana_grad2Vc_
void sauvegarder_post_maitre(const Nom &lata_name, SFichier &fichier) const
IJK_Field_double dwdz_
IJK_Field_vector3_double integrated_velocity_
IJK_Field_vector3_double cell_op_conv_
void fill_indic(bool reprise=0)
IJK_Field_vector3_double ana_grad2Uc_
void get_noms_champs_postraitables(Noms &noms, Option opt=NONE) const
bool is_stats_cisaillement_activated() const
int postraiter_champs() override
void posttraiter_champs_instantanes(const char *lata_name, double time, int time_iteration)
IJK_Field_double pressure_ft_
void associer_domaines(Domaine_IJK &dom_ijk, Domaine_IJK &dom_ft)
bool has_champ_vectoriel(const Motcle &nom) const override
IJK_Field_vector3_double coords_
double get_max_timestep_for_post(double current_time) const
Compute the max possible timestep to use during the next iteration in order to not skip a time interv...
void register_one_field(const Motcle &fld_nam, const Motcle &loc)
void reprendre_post(Param &param)
Champs_compris_IJK_interface::FieldInfo_t FieldInfo_t
IJK_Field_double dwdy_
void register_interface_field(const Motcle &nom_champ, const Motcle &loc) override
IJK_Field_vector3_double ecart_ana_
IJK_Field_vector3_double op_conv_
IJK_Field_vector3_double grad_I_ns_
IJK_Field_vector3_double normale_cell_ns_
void posttraiter_statistiques_plans(double time)
const int & get_IJK_flag(const Nom &nom) const
IJK_Field_double extended_pl_
void initialise_stats(Domaine_IJK &splitting, ArrOfDouble &vol_bulles, const double vol_bulle_monodisperse)
std::vector< Motcle > list_post_required_
Statistiques_dns_ijk_FT statistiques_FT_
IJK_Field_vector3_double ana_grad2Wi_
void lire_entete_bloc_interface(Entree &is) override
bool has_champ(const Motcle &nom) const override
void posttraiter_tous_champs_energie(Motcles &liste, const int idx) const
IJK_Field_vector3_double ana_grad2Vi_
void set_param(Param &param) const override
void completer_sondes() override
void postraiter(int forcer) override
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static double mp_sum_as_double(int v)
Definition Process.h:99
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
void redistribute(const IJK_Field_double &input_field, IJK_Field_double &output_field)
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.
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
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
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133