TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Convection_Diffusion_Temperature_FT_Disc.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#include <Convection_Diffusion_Temperature_FT_Disc.h>
16#include <Transport_Interfaces_FT_Disc.h>
17#include <Domaine_VF.h>
18#include <Discretisation_base.h>
19#include <Probleme_FT_Disc_gen.h>
20#include <Fluide_Diphasique.h>
21#include <Fluide_Incompressible.h>
22#include <Domaine.h>
23#include <Sous_Domaine.h>
24#include <Param.h>
25#include <Champ_Uniforme.h>
26#include <Echange_impose_base.h>
27#include <Echange_contact_VDF_FT_Disc.h>
28#include <Domaine_Cl_VDF.h>
29#include <Neumann_paroi.h>
30#include <Neumann_paroi_adiabatique.h>
31#include <SChaine.h>
32#include <Entree.h>
33#include <EChaine.h>
34#include <Interprete_bloc.h>
35#include <Domaine_VDF.h>
36#include <Perf_counters.h>
37#include <TRUST_Ref.h>
38#include <Parametre_implicite.h>
39#include <Dirichlet_paroi_fixe.h>
40#include <Dirichlet_paroi_defilante.h>
41
42static const double TSAT_CONSTANTE = 0.;
43
44Implemente_instanciable_sans_constructeur(Convection_Diffusion_Temperature_FT_Disc,"Convection_Diffusion_Temperature_FT_Disc",Convection_Diffusion_Temperature);
45
47{
48 phase_ = -1;
49 correction_courbure_ordre_=0; // Par defaut, pas de prise en compte de la courbure pour corriger le champ etendu delta_vitesse
50 correction_gradt_ordre_=1; // Par defaut, temperature gradient is computed in ordre 1
51 stencil_width_ = 8; //GB : Valeur par defaut de stencil_width_
52 temp_moy_ini_ = 0.; //GB : Valeur par defaut de la temperature moyenne initiale
53 nom_sous_domaine_ = "unknown_sous_domaine"; //GB : Valeur par defaut de la sous-domaine de moyenne
54 prescribed_mpoint_ = -1.e30;
55 mixed_elems_.resize_array(0);
56 lost_fluxes_.resize_array(0);
57 derivee_energy_.resize_array(0);
58 mixed_elems_diffu_.resize_array(0);
59 lost_fluxes_diffu_.resize_array(0);
60 mixed_elems_conv_.resize_array(0);
61 lost_fluxes_conv_.resize_array(0);
62}
63
65{
67}
68/*! @brief cf Convection_Diffusion_std::readOn(Entree&).
69 *
70 */
72{
73 // Ne pas faire assert(fluide non nul)
75 solveur_masse->set_name_of_coefficient_temporel("rho_cp_comme_T");
76 Nom num=inconnue().le_nom(); // On prevoir le cas d'equation de scalaires passifs
77 num.suffix("temperature_thermique");
78 Nom nom="Convection_chaleur";
79 nom+=num;
80 terme_convectif.set_fichier(nom);
81 terme_convectif.set_description((Nom)"Convective heat transfer rate=Integral(-rho*cp*T*u*ndS) [W] if SI units used");
82 nom="Diffusion_chaleur";
83 nom+=num;
84 terme_diffusif.set_fichier(nom);
85 terme_diffusif.set_description((Nom)"Conduction heat transfer rate=Integral(lambda*grad(T)*ndS) [W] if SI units used");
86
87 // If keyword correction_mpoint_diff_conv_energy_ has not been read, the table should be properly set:
88 if (correction_mpoint_diff_conv_energy_.size_array() != 3)
89 {
90 Cerr << "We account for no energy correction!!" << finl;
95 }
96 return is;
97}
98
100{
102 param.ajouter("phase",&phase_);
103 param.ajouter_condition("(value_of_phase_eq_0)_or_(value_of_phase_eq_1)","phase must be set to 0 or 1");
104 param.ajouter("stencil_width",&stencil_width_);
105 param.ajouter("correction_courbure_ordre", &correction_courbure_ordre_);
106 param.ajouter("correction_gradt_ordre", &correction_gradt_ordre_);
107 param.ajouter_non_std("equation_interface",(this),Param::REQUIRED);
108 param.ajouter_non_std("maintien_temperature",(this));
109 param.ajouter_non_std("equation_navier_stokes",(this),Param::REQUIRED);
110 param.ajouter_non_std("prescribed_mpoint", (this));
111 param.ajouter("correction_mpoint_diff_conv_energy", &correction_mpoint_diff_conv_energy_);
112 param.ajouter_flag("divergence_free_velocity_extension", &divergence_free_velocity_extension_);
113 param.ajouter_flag("explicit_u_NS", &explicit_u_NS_); // X_D_ADD_P rien Flag to force a really explicit scheme
114 param.ajouter_non_std("solveur_pression_fictive",(this),Param::OPTIONAL);
115 param.ajouter("bc_opening_pressure",&name_bc_opening_pressure_,Param::OPTIONAL);
116 param.ajouter_flag("reinjection_tcl", &reinjection_);
117 param.ajouter("tempC", &tempC_);
118 param.ajouter("Rc_inject", &Rc_inject_);
119 param.ajouter("thetaC", &thetaC_);
120 param.ajouter("Rc_GridN", &Rc_GridN_);
121}
122
124{
125 if (mot=="equation_interface")
126 {
127 const Probleme_FT_Disc_gen& pb = ref_cast(Probleme_FT_Disc_gen,probleme());
128 Motcle nom_eq;
129 is >> nom_eq;
131 Cerr << " Interface equation for the temperature convection diffusion equation :"
132 << nom_eq << finl;
133 ref_eq_interface_ = pb.equation_interfaces(nom_eq);
134 return 1;
135 }
136 else if (mot=="solveur_pression_fictive")
137 {
139 Cerr << "Reading and typing of fictitious pressure solver (for velocity extension) : " << finl;
140 is >> solveur_pression_;
141 Cerr<<"Fake Pressure solver type : "<<solveur_pression_->que_suis_je()<< finl;
142 solveur_pression_.nommer("solveur_pression_fictive");
143 return 1;
144 }
145 else if (mot=="diffusion")
146 {
147 if (je_suis_maitre())
148 Cerr << " "<< que_suis_je() <<"::lire diffusivite" << finl;
149 // Need phase to know which diffusivity to use:
150 if (phase_ < 0)
151 {
152 barrier();
153 Cerr << " Error: phase must be specified before diffusion" << finl;
155 }
157 return 1;
158 }
159 else if (mot=="convection")
160 {
161 if (je_suis_maitre())
162 Cerr << " "<< que_suis_je() <<"::lire convection" << finl;
163 if (!ref_eq_ns_)
164 {
165 barrier();
166 Cerr << " Error: equation_navier_stokes must be specified before convection" << finl;
168 }
170 return 1;
171 }
172 else if (mot=="maintien_temperature")
173 {
174 if (je_suis_maitre())
175 Cerr << " Equation_Concentration_FT::lire maintien_temperature" << finl;
177 is >> nom_sous_domaine_;
178 is >> temp_moy_ini_;
179 return 1;
180 }
181 else if (mot=="prescribed_mpoint")
182 {
183 if (je_suis_maitre())
184 Cerr << que_suis_je() <<"::lire prescribed_mpoint" << finl;
185 is_prescribed_mpoint_ = true; // set flag to true.
186 is >> prescribed_mpoint_;
187 return 1;
188 }
189 else if (mot=="equation_navier_stokes")
190 {
191 const Probleme_FT_Disc_gen& pb = ref_cast(Probleme_FT_Disc_gen,probleme());
192 Motcle nom_eq;
193 is >> nom_eq;
195 Cerr << " Navier_stokes equation for the temperature convection diffusion equation :"
196 << nom_eq << finl;
197 const Navier_Stokes_std& ns = pb.equation_hydraulique(nom_eq);
198 ref_eq_ns_ = ns;
199 return 1;
200 }
201 else
203}
204
206{
207 // return ref_eq_ns_->vitesse();
208 // GB 2019.03.07 (code lost between 2022.02.16 and 2023.06.20!!)
209 // We will go through all the effort of creating a continous velocity from the unknown of NS!
210 // We might as well use it! ;-)
211 return vitesse_convection_;
212}
213
217
222
226
227static void extrapolate(const Domaine_VF& domaine_vf,
228 const DoubleTab& interfacial_area,
229 const int stencil_width,
230 const DoubleTab& distance,
231 DoubleTab& field)
232{
233 const double invalid_test = -1.e30;
234 const IntTab& elem_faces = domaine_vf.elem_faces();
235 const IntTab& faces_elem = domaine_vf.face_voisins();
236 const int nb_faces_elem = elem_faces.dimension(1);
237 const int nb_elem = elem_faces.dimension(0);
238 DoubleTab field_old;
239 // n_iterations = stencil_width is the minimum to get a propagation of information from the interface to the border
240 // of the extrapolation. But doing more will lead to smoother values... And it probably costs close to nothing
241 const double n_iterations = 5*stencil_width;
242 for (int iteration = 0; iteration < n_iterations; iteration++)
243 {
244 // Copy the old field value as we do not want to use the current iteration values.
245 field_old = field;
246 // La valeur sur un element est la moyenne des valeurs sur les elements voisins
247 for (int i_elem = 0; i_elem < nb_elem; i_elem++)
248 {
249 // Do not touch field in interfacial cells.
250 // Iterate on other values.
251 const double d = distance[i_elem];
252 if (( d > invalid_test) && (interfacial_area[i_elem]<DMINFLOAT))
253 {
254 double somme = 0.;
255 double coeff = 0.;
256 for (int i_face = 0; i_face < nb_faces_elem; i_face++)
257 {
258 const int face = elem_faces(i_elem, i_face);
259 const int voisin = faces_elem(face, 0) + faces_elem(face, 1) - i_elem;
260 if (voisin >= 0)
261 {
262 // Not a boundary...
263 double mp = field_old[voisin];
264 const double dvois = distance[voisin];
265 if (dvois > invalid_test)
266 {
267 // Give more weight in the smoothing to values closer to the interface:
268 if (fabs(dvois)<DMINFLOAT)
269 {
270 Cerr << "distance is very much at zero whereas interfacial_area is zero too... Pathological case to be looked into closely. " << finl;
271 Cerr << "Is it from a Break-up or coalescence? " << finl;
272 Cerr << "see Convection_Diffusion_Temperature_FT_Disc and static void extrapolate" << finl;
273 Cerr << "Contact TRUST support." << finl;
275 }
276 const double inv_d2 = 1./(dvois*dvois);
277 somme += mp*inv_d2;
278 coeff+=inv_d2;
279 }
280 }
281 }
282 if (coeff > 0.)
283 field[i_elem] = somme / coeff;
284 }
285 }
287 }
288}
289
290static void extrapoler_dans_phase(DoubleTab& gradient,
291 const DoubleTab& indicatrice,
292 const Domaine_VF& domaine_vf,
293 const double invalid_test,
294 const double indic_phase, const int nb_iter)
295{
296 DoubleTab gradient_old;
297 for (int iteration = 0; iteration < nb_iter; iteration++)
298 {
299 // Copie de la valeur du gradient: on ne veut pas utiliser les valeurs
300 // calculees lors de l'iteration courante
301 gradient_old = gradient;
302 // La valeur sur un element est la moyenne des valeurs sur les elements voisins
303 for (int i_elem = 0; i_elem < domaine_vf.elem_faces().dimension(0); i_elem++)
304 {
305 if (indicatrice[i_elem] != indic_phase)
306 {
307 // Ne pas toucher au gradient de la phase "phase".
308 // Iterer sur les autres valeurs.
309 double somme = 0.;
310 int coeff = 0;
311 for (int i_face = 0; i_face < domaine_vf.elem_faces().dimension(1); i_face++)
312 {
313 const int face = domaine_vf.elem_faces(i_elem, i_face);
314 const int voisin = domaine_vf.face_voisins(face, 0) + domaine_vf.face_voisins(face, 1) - i_elem;
315 if (voisin >= 0)
316 {
317 // Not a boundary...
318 const double grad = gradient_old[voisin];
319 if (grad > invalid_test)
320 {
321 somme += grad;
322 coeff++;
323 }
324 }
325 }
326 if (coeff > 0)
327 gradient[i_elem] = somme / coeff;
328 }
329 }
330 gradient.echange_espace_virtuel();
331 }
332}
333// A partir des valeurs du "champ" dans la phase "phase", calcule
334// les valeurs du "champ" dans un voisinage d'epaisseur "stencil_width"
335// en extrapolant lineairement et en supposant que la valeur a l'interface
336// vaut "interfacial_value".
337static void extrapoler_champ_elem(const Domaine_VF& domaine_vf,
338 const DoubleTab& indicatrice,
339 const DoubleTab& distance_interface,
340 const DoubleTab& normale_interface,
341 const DoubleTab& champ_div_n,
342 const int correction_gradt_ordre_,
343 const int phase,
344 const int stencil_width,
345 const double interfacial_value,
346 DoubleTab& champ,
347 DoubleTab& gradient,
348 const double temps)
349{
350 const IntTab& elem_faces = domaine_vf.elem_faces();
351 //const IntTab& faces_elem = domaine_vf.face_voisins();
352 const int nb_faces_elem = elem_faces.dimension(1);
353 const int nb_elem = elem_faces.dimension(0);
354
355 const DoubleTab& centre_gravite_elem = domaine_vf.xp();
356 const DoubleTab& centre_gravite_face = domaine_vf.xv();
357 const double invalid_test = -1.e30;
358 const double invalid_value = -2.e30;
359 // Calcul de la composante normale du gradient du champ:
360 // gradient normal = (champ - valeur_interface) / distance.
361 assert(gradient.dimension(0) == distance_interface.dimension(0));
362 gradient = invalid_value;
363 const double indic_phase = (phase == 0) ? 0. : 1.;
364 int i_elem;
365 int err_count = 0;
366 for (i_elem = 0; i_elem < nb_elem; i_elem++)
367 {
368 double d = distance_interface[i_elem];
369 if (indicatrice[i_elem] == indic_phase && d > invalid_test)
370 {
371
372 // Test pour remedier a une eventuelle erreur de calcul de la
373 // fonction distance dans les mailles voisines des mailles traversees
374 // par l'interface. On sait que la distance est superieure a delta_x/2
375 // A faire: calculer distance_min = delta_x/2
376 // if (std::fabs(d) < distance_min) {
377 // d = (d>0) ? distance_min : -distance_min;
378 // err_count++;
379 // }
380
381 // Test pour savoir si la distance a l'interface est bien inferieure
382 // au rayon du cercle inscrit a l'element
383 // Si c'est le cas, on remplace la distance par plus ou moins ce rayon
384 // suivant la phase dans laquelle se situe l'element
385 double dist_elem_face_min = 1e30;
386 for (int face_loc=0; face_loc<nb_faces_elem; face_loc++)
387 {
388 double dist_elem_face = 0;
389 const int face_glob = elem_faces(i_elem,face_loc);
390 for (int i_dim=0; i_dim<Objet_U::dimension; i_dim++)
391 {
392 double centre_elem_i = centre_gravite_elem(i_elem,i_dim);
393 double centre_face_i = centre_gravite_face(face_glob,i_dim);
394 dist_elem_face += (centre_elem_i-centre_face_i)*(centre_elem_i-centre_face_i);
395 }
396 dist_elem_face = sqrt(dist_elem_face);
397 dist_elem_face_min = (dist_elem_face < dist_elem_face_min) ? dist_elem_face : dist_elem_face_min;
398 }
399
400 // Codage initial valable uniquement pour une discretisation VDF
401 // double dx = domaine_vf.volumes(i_elem)/domaine_vf.face_surfaces(elem_faces(i_elem,0));
402 // double dy = domaine_vf.volumes(i_elem)/domaine_vf.face_surfaces(elem_faces(i_elem,1));
403 // double dz = domaine_vf.volumes(i_elem)/domaine_vf.face_surfaces(elem_faces(i_elem,2));
404 // double dist_elem_face_min = ( ((dx<dy) ? dx : dy)<dz ? ((dx<dy) ? dx : dy) : dz )/2;
405
406 // Si la distance entre le centre de l'element et l'interface est plus petite
407 // que la plus petite distance entre le centre de l'element et le centre de ses faces
408 // on ecrase la valeur de la distance a l'interface qui est manifestement fausse.
409 // On choisit par defaut la plus petite distance entre le centre de l'element et le
410 // centre de ses faces. Le signe de la distance est determine en fonction de la phase
411 // de l'element (la distance etant fausse, son signe a toutes les chances de l'etre
412 // aussi).
413 if (std::fabs(d) < dist_elem_face_min)
414 {
415 Cerr << "Time = " << temps << "; extrapoler_champ_elem: distance lower than dx/2" << finl;
416 Cerr << " Element position:" << finl;
417 for (int i_dim=0; i_dim<Objet_U::dimension; i_dim++)
418 {
419 Cerr << " x(" << i_dim << ") = " << centre_gravite_elem(i_elem,i_dim) << finl;
420 }
421
422 d = (phase == 0) ? -dist_elem_face_min : dist_elem_face_min;
423
424 err_count++;
425 }
426 const double v = champ[i_elem];
427 // Ceci est le gradient evalue a une distance d/2 de l'interface
428 // (difference finie centree)
429 const double grad = (v - interfacial_value) / d;
430 // Correction du gradient pour trouver la valeur a l'interface :
431 // on suppose que le transfert est stationnaire, et flux normal
432 // a l'interface.
433 const double div_n = champ_div_n[i_elem];
434
435 switch (correction_gradt_ordre_)
436 {
437 case 0:
438 // Pas de prise en compte de la correction en courbure
439 gradient[i_elem] = grad;
440 break;
441 case 1:
442 // note that div_n and k are in opposite sign
443 gradient[i_elem] = grad * (1. - (-div_n) * d / 2.);
444 break;
445 case 2:
446 // Prise en compte de la correction en courbure a l'ordre 2
447 gradient[i_elem] = grad * (1. - (-div_n) * d / 2. + (-div_n) * (-div_n) * d * d / 6.);
448 break;
449 default:
450 Cerr << "Error for the method Convection_Diffusion_Temperature_FT_Disc::extrapoler_champ_elem correction_gradt_ordre_" << finl;
452 }
453 }
454 }
455 if (err_count)
456 Cerr << "extrapoler_champ_elem: errcount=" << err_count << finl;
457 gradient.echange_espace_virtuel();
458 // On etale ce gradient par continuite sur une epaisseur de "stencil_value"
459 // Les iterations de cet algorithme convergent vers une sorte de laplacien=0
460 // avec condition aux limites de Dirichlet sur les elements de la phase "phase".
461 extrapoler_dans_phase(gradient, indicatrice, domaine_vf, invalid_test, indic_phase, stencil_width/* nb_iter*/ );
462
463 // 2023. Pour la vitesse de convection extrapolee, on reextrapole dans l'autre phase :
464 const double autre_phase = 1.-indic_phase;
465 extrapoler_dans_phase(gradient, indicatrice, domaine_vf, invalid_test, autre_phase, stencil_width/* nb_iter*/ );
466
467 // On calcule la valeur extrapolee:
468 for (i_elem = 0; i_elem < nb_elem; i_elem++)
469 {
470 const double d = distance_interface[i_elem];
471 const double grad = gradient[i_elem];
472 if (indicatrice[i_elem] != indic_phase
473 && d > invalid_test
474 && grad > invalid_test)
475 {
476 // Extrapolation parabolique tenant compte de la courbure de l'interface :
477 const double div_n = champ_div_n[i_elem];
478 champ[i_elem] = d * grad * (1. - 0.5 * div_n * d) + interfacial_value;
479 // TODO: Assess Higher order Taylor series by the inclusion of a new parameter in the datafile. (Formulae below to be checked)
480 // champ[i_elem] = 0.5 * d * grad * (1. - 0.5 * div_n * d) + interfacial_value; // multiplied by 0.5 (may be it was missing...we have to check)
481 // champ[i_elem] = d * grad * (1. - 0.5 * div_n * d + div_n * div_n * d * d / 6.) + interfacial_value;
482 }
483 }
484 champ.echange_espace_virtuel();
485}
486
487/*! @brief met a jour le champ grad_t en fonction du champ inconnue.
488 *
489 * Attention, l'inconnue est modifiee (on etend le champ de temperature dans la phase
490 * opposee.
491 *
492 */
494{
495 Transport_Interfaces_FT_Disc& eq_interface_ = ref_eq_interface_.valeur();
496 const DoubleTab& indicatrice = eq_interface_.get_indicatrice().valeurs();
497 const DoubleTab& distance_interface = eq_interface_.get_distance_interface().valeurs();
498 const DoubleTab& normale_interface = eq_interface_.get_normale_interface().valeurs();
499 //GB : Augmenter la constante de l'epaisseur
500 //GB : const int stencil_width = 8;
501 const int stencil_width = stencil_width_;
502 const double interfacial_value = TSAT_CONSTANTE;
503
504 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
505
506 const double temps = schema_temps().temps_courant();
507
508 // Extrapolation lineaire de la temperature des mailles diphasiques a partir
509 // de la temperature des mailles de la "phase".
510 DoubleTab& temperature = inconnue().valeurs();
511
512 Navier_Stokes_FT_Disc& eq_navier_stokes = ref_cast(Navier_Stokes_FT_Disc, ref_eq_ns_.valeur());
513 const DoubleTab& div_n = eq_navier_stokes.calculer_div_normale_interface().valeurs();
514
515 extrapoler_champ_elem(domaine_vf, indicatrice, distance_interface, normale_interface, div_n,
517 phase_, stencil_width, interfacial_value,
518 temperature,
519 grad_t_->valeurs(),
520 temps);
521}
522
527
529{
530 const double invalid_test = -1.e25;
532
534 {
535 mpoint.valeurs() = prescribed_mpoint_;
536 return;
537 }
538 mpoint.valeurs() = grad_t_->valeurs();
539
540 DoubleTab& val = mpoint.valeurs();
541 const int n = val.size();
542 for (int i = 0; i < n; i++)
543 if (val[i] < invalid_test)
544 val[i] = 0;
545
546 const double k = fluide_dipha_->fluide_phase(phase_).conductivite().valeurs()(0,0);
547 const double L = fluide_dipha_->chaleur_latente();
548 // L est la chaleur latente de changement de phase pour passer de
549 // la phase 0 a la phase 1.
550 double f = k / L;
551 // Si on est dans la phase 0 et que L > 0, on doit avoir mpoint positif pour
552 // gradient(T) scalaire n negatif.
553 if (phase_ == 0)
554 f = -f;
555
556 mpoint.valeurs() *= f;
557
558 // Pour deverminage : on impose une variation de mpoint lineaire en z
559 //const Domaine_VF & domaine_vf = ref_cast(Domaine_VF, domaine_dis());
560 //for (int i = 0; i < n ; i++)
561 // mpoint.valeurs()[i] = 500./8957.*(1.+0.1*(domaine_vf.xp()(i,3)-0.0005)/0.001);
562
563
564 // Here, it is too early to correct the table mpoint.valeurs() because it has not been used yet to build the extended velocities.
565 // If we were correcting it here with the TCL contribution, we would generate tangential artificial delta_u velocities that are not desired.
566 // Consequently, the TCL effect will be explicitely applied to secmem2 and mpoint will be explicitely corrected too (but later,
567 // just before post-processing in fact).
568
570}
571
572// The list mixed_elems_ contains elems several times (once per operator conv/diff, once per face to a pure phase_ neighbour)
573// (that is four times in most of 2D cells when convection+diffusion are applied)
574// We reduce the list to unique occurences of elements.
575static void collect_into_unique_occurence(ArrOfInt& mixed_elems, ArrOfDouble& lost_fluxes)
576{
577 const int nb_elem_with_duplicates = mixed_elems.size_array();
578 int nb_elem = 0;
579 // Cerr << "Algo may be optimized? It is in NxN = " << nb_elem_with_duplicates << " x "
580 // << nb_elem_with_duplicates << " = " << nb_elem_with_duplicates*nb_elem_with_duplicates <<finl;
581 for (int i=0; i<nb_elem_with_duplicates; i++)
582 {
583 const int elemi = mixed_elems[i];
584 // Have we seen this element already?
585 int j=0;
586 for(j=0; j<i; j++)
587 {
588 const int elemj = mixed_elems[j];
589 if (elemi == elemj)
590 {
591 // yes, then we hit the "continue" in the next if and the loop continues with the next element
592 break;
593 }
594 }
595 if (j!=i)
596 continue;
597
598 // Here, we are with a new element that will remain in the list (may be moved to the position nb_elem)
599 lost_fluxes[nb_elem] = lost_fluxes[i]; // We store the first lost_flux for this elem
600 for (j=i+1; j<nb_elem_with_duplicates; j++)
601 {
602 const int elemj = mixed_elems[j];
603 if (elemi == elemj)
604 {
605 lost_fluxes[nb_elem] += lost_fluxes[j]; // and pile-up others...
606 }
607 }
608 mixed_elems[nb_elem] = elemi;
609 nb_elem++;
610 }
611 lost_fluxes.resize_array(nb_elem);
612 mixed_elems.resize_array(nb_elem);
613}
614
616{
617 Cerr << "Work in progress and widly incorrect. " << finl;
618 Cerr << "Wait and see for further improvements. Exit" << finl;
620 if (inconnue().nb_valeurs_temporelles() == 1)
621 {
622 Cerr << "You need at least 2 positions to the wheel... Contact TRUST support. " << finl;
624 }
625 Transport_Interfaces_FT_Disc& eq_interface_ = ref_eq_interface_.valeur();
626 //const Champ_base& ch_indic = ref_cast(Champ_Inc,eq_interface_.get_indicatrice());
627 //const DoubleTab& indicatrice = ch_indic.valeurs();
628 const DoubleTab& indicatrice = eq_interface_.inconnue().valeurs();
629 const DoubleTab& indicatrice_passe = eq_interface_.inconnue().passe();
630 const double& dt = schema_temps().pas_de_temps();
631 //const DoubleTab& indicatrice_passe = ch_indic.passe();
632 DoubleTab& temperature = inconnue().valeurs();
633 const DoubleTab& temperature_passe = inconnue().passe();
634 const double rhocp = fluide_dipha_->fluide_phase(phase_).masse_volumique().valeurs()(0,0)
635 * fluide_dipha_->fluide_phase(phase_).capacite_calorifique().valeurs()(0,0);
636
637 const int nb_elem = mixed_elems_.size_array();
638 //assert(mixed_elems_diffu_.size_array()==nb_elem);
639 //assert(mixed_elems_conv_.size_array()==nb_elem); // all lists should now have the same size. Or maybe not due to BC?
640 // But still, mixed_elems_ should be the longest and the other should be included
641 derivee_energy_.resize_array(nb_elem);
642 for(int i=0; i<nb_elem; i++)
643 {
644 const int elemi = mixed_elems_[i];
645 derivee_energy_[i] = (temperature[elemi] * indicatrice[elemi] - temperature_passe[elemi] * indicatrice_passe[elemi])* rhocp;
646 }
647
648 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, ref_eq_ns_.valeur());
649 const double Lvap = fluide_dipha_->chaleur_latente();
650 const DoubleVect& volume = ref_cast(Domaine_VF, domaine_dis()).volumes();
651 DoubleTab& mp = mpoint_->valeurs();
652 const DoubleTab& ai = ns.get_interfacial_area();
653 const double temps = schema_temps().temps_courant();
654 {
655 double total_flux_lost = 0.;
656 double total_derivee_energy = 0.;
657 double mpai_tot = 0.;
658 double mp_sum_before = 0.;
659 double int_ai_before = 0.;
660 for (int nd=0 ; nd<nb_elem ; nd++)
661 {
662 const int elembe = mixed_elems_[nd];
663 int_ai_before += ai[elembe];
664 // Cerr << " elembe= " << elembe << finl;
665 // total_flux_lost -= lost_fluxes_(nd)*rhocp; // multiplied by rhocp (vp) // "-" because depends on convention (GB)
666 total_flux_lost -= lost_fluxes_(nd); // in the present TRUST version it should not be multiplied by rhocp
667 total_derivee_energy += derivee_energy_(nd)*volume[nd];
668 mpai_tot += mp[elembe]*ai[elembe]*Lvap;// multiplied by Lvap (vp)
669 mp_sum_before += mp[elembe]*ai[elembe];
670 }
671 if (int_ai_before>DMINFLOAT)
672 {
673 const double mean_mp_before = mp_sum_before/int_ai_before;
674 Cerr << " mp_sum_before= " << mp_sum_before << " mean_mp_before= " << mean_mp_before << " time= " << temps << finl;
675 }
676 total_flux_lost = mp_sum(total_flux_lost);
677 mpai_tot = mp_sum(mpai_tot);
678 total_derivee_energy = mp_sum(total_derivee_energy)/dt;
679 Cerr << "[Basic-Mixed-cells-Energy-Balance] Time= " << temps << " nb_elems= " << nb_elem
680 << " phi(positive if towards mixed cells)= " << total_flux_lost
681 << " mp*ai*Lvap= " << mpai_tot
682 << " dE/dt= " << total_derivee_energy
683 << " imbalance= " << total_derivee_energy-total_flux_lost+mpai_tot << finl;
684 }
685
686 // Energy balance correction. Loop on mixed elems only :
687 const int option=-1; // To disable that
688 {
689 const int account_for_diff = correction_mpoint_diff_conv_energy_[0];
690 const int account_for_conv = correction_mpoint_diff_conv_energy_[1];
691 const int account_for_mixed_cell_energy = correction_mpoint_diff_conv_energy_[2];
692 double int_dmp_ai = 0.; // The integral over the interface of delta_mp
693 double int_ai = 0.; // The interface area
694 double int_mp_ai = 0.;
695 for(int i=0; i<nb_elem; i++)
696 {
697 const int elem = mixed_elems_[i];
698 // The convention is that phi_lost is viewed from the liquid side point-of-view.
699 // (negative for evap as it's leaving the pure liquid)
700 // So when we consider mixed cells, the incoming flux is "-phi_lost"
701 const double phi_in_mixed_cell = lost_fluxes_[i];
702 double phi_conv_lost_by_mixed_cell = 0.;
703 double phi_diffu_added_to_mixed_cell = 0.;
704 if (mixed_elems_diffu_[i] != elem)
705 {
706 Cerr << "Search for a solution? What case is it? diffu, BC? " << finl;
708 }
709 else
710 {
711 phi_diffu_added_to_mixed_cell = lost_fluxes_diffu_[i];
712 // Cerr << " lost-flux-diff= " << phi_diffu_added_to_mixed_cell << " at-time= " << temps << " in-elem= " << elem << finl;
713 }
714 if (i>=mixed_elems_conv_.size_array() || mixed_elems_conv_[i] != elem)
715 {
716 phi_conv_lost_by_mixed_cell =0.;
717 int j=0;
718 for (j=0; j<mixed_elems_conv_.size_array(); j++)
719 {
720 if (mixed_elems_conv_[j] == elem)
721 {
722 phi_conv_lost_by_mixed_cell = lost_fluxes_conv_[j];
723 break;
724 }
725 }
726 if (j==mixed_elems_conv_.size_array())
727 {
728 Cerr << "conv. The end of the list is reached, "
729 << "mixed_elems_["<< i<<"]= " << elem << " was not found in mixed_elem_conv_"<< finl;
730 Cerr << "mixed_elems_conv_= " << mixed_elems_conv_ << finl;
731 Cerr << "mixed_elems_= " << mixed_elems_ << finl;
732 Cerr << "WE ASSUME IT IS BECAUSE IT IS A BC? any solution? WE IGNORE IT"<< finl;
733 // Process::exit();
734 }
735
736 }
737 else
738 {
739 phi_conv_lost_by_mixed_cell = lost_fluxes_conv_[i];
740 // Cerr << " lost-flux-conv= " << phi_conv_lost_by_mixed_cell << " at-time= " << temps << " in-elem= " << elem << finl;
741 }
742
743 double VdrhocpT_dt = 0.;
744 if (account_for_mixed_cell_energy)
745 {
746 VdrhocpT_dt=(rhocp*volume[elem])*(temperature[elem] * indicatrice[elem] - temperature_passe[elem] * indicatrice_passe[elem])/dt;
747 // Cerr << "temp_current= " << temperature[elem] << " temp_previous= " << temperature_passe[elem] << finl;
748 }
749
750 if (option ==1)
751 {
752 // OPtion 1 : Correction of T
753 const double value_before = temperature[elem];
754 temperature[elem] = 1/indicatrice[elem] * (temperature_passe[elem] * indicatrice_passe[elem] + dt/(rhocp*volume[elem])*(mp[elem]*ai[elem]*Lvap - phi_in_mixed_cell*rhocp));
755 // multiplied phi_lost by rhocp (vp)
756 Cerr << "[Delta-T-due-to-Energy-correction] elem "<< elem <<" Tnew-Tuncorrected " << temperature[elem]-value_before << finl;
757 //
758 const double tmp = (temperature[elem] * indicatrice[elem] - temperature_passe[elem] * indicatrice_passe[elem])* rhocp;
759 if (derivee_energy_[i] != tmp)
760 {
761 Cerr << "New derivee_energy after correction (before/after) : ( "<< derivee_energy_[i] <<" / " << tmp << " )." << finl;
762 derivee_energy_[i] = tmp;
763 }
764 }
765 else if (option ==2)
766 {
767 // Option 2 : Correction of mp: local corrections in all mixed cells
768 if (ai[elem]>DMINFLOAT)
769 {
770 const double old_mp = mp[elem];
771
772 double delta_mp = 0. ;
773 if (account_for_diff)
774 {
775 delta_mp += (1/(ai[elem]*Lvap))*((mp[elem]*ai[elem]*Lvap + phi_diffu_added_to_mixed_cell)); // for Stefan it is negative sign before phi_difu_...
776 // (we need to make it uniform so that it works for all with the same sign convention....may depend on the normal)
777 Cerr << " delta-mp-diff= " << delta_mp << finl;
778 }
779 if (account_for_conv)
780 {
781 // To be checked :
782 // - the minus sign?
783 // - what surface should we use? ai or Sface?
784 // - The interpolation of T to the face?
785 // double Tface = temperature[elem];
786 // double rhov = fluide_dipha_->fluide_phase(1-phase_).masse_volumique()(0,0);
787
788 delta_mp += (1/(ai[elem]*Lvap))*(-phi_conv_lost_by_mixed_cell);
789 // delta_mp += (1/(ai[elem]*Lvap))*(-(mp[elem]*ai[elem]*rhocp/rhov*Tface - phi_conv_lost_by_mixed_cell));
790 Cerr << " delta-mp-conv= " << delta_mp << finl;
791 }
792 if (account_for_mixed_cell_energy)
793 delta_mp += (1/(ai[elem]*Lvap))*(VdrhocpT_dt);
794 // divided by Lvap (now consistent in units-vp) and multiplied phi_lost by rhocp
795 mp[elem] +=delta_mp;
796 Cerr << " delta_mp= " << delta_mp << " old_mp= " << old_mp << " new_mp= " << mp[elem] << finl;
797 if (fabs(old_mp)>DMINFLOAT)
798 Cerr << "relative correction of mp at time "<< temps << " elem= " << elem << " delta= " <<delta_mp/old_mp*100. << "%." <<finl;
799 }
800 }
801 else if (option==3)
802 {
803 // Option 3 : Global Correction of mp:
804 if ((ai[elem]>DMINFLOAT) and (temps>DMINFLOAT))
805 {
806 int_ai += ai[elem];
807 int_mp_ai += mp[elem]*ai[elem];
808 // Cerr << " area-elem= " << ai[elem] << " temps= " << temps << finl;
809 // Before we had : const double tmp = (1/(Lvap))*(VdrhocpT_dt-(mp[elem]*ai[elem]*Lvap - phi_in_mixed_cell*rhocp));
810
811 double delta_mp = 0. ;
812 if (account_for_diff)
813 {
814 // delta_mp += (1/(ai[elem]*Lvap))*(-(mp[elem]*ai[elem]*Lvap - phi_diffu_added_to_mixed_cell));
815 delta_mp += (-1/Lvap)*((mp[elem]*ai[elem]*Lvap - phi_diffu_added_to_mixed_cell));// for Stefan it is negative sign before phi_difu_...
816 // (we need to make it uniform so that it works for all with the same sign convention....may depend on the normal)
817 // delta_mp += mp[elem]*ai[elem] + (1/Lvap)*(phi_diffu_added_to_mixed_cell);
818 // Cerr << " mpaiL= " << mp[elem]*ai[elem]*Lvap << " phi_diff= " << phi_diffu_added_to_mixed_cell << finl;
819 // Cerr << " delta-mp-diff= " << delta_mp << finl;
820 }
821
822 if (account_for_conv)
823 {
824 // To be checked :
825 // - the minus sign?
826 // - what surface should we use? ai or Sface?
827 // - The interpolation of T to the face?
828 // double Tface = temperature[elem];
829 // double rhov = fluide_dipha_->fluide_phase(1-phase_).masse_volumique()(0,0);
830
831 // delta_mp += (1/(ai[elem]*Lvap))*(-(mp[elem]*ai[elem]*rhocp/rhov*Tface - phi_conv_lost_by_mixed_cell));
832 // delta_mp += (1/(ai[elem]*Lvap))*((mp[elem]*ai[elem]*rhocp/rhov*Tface - phi_conv_lost_by_mixed_cell));
833 // delta_mp += (1/Lvap)*(mp[elem]*ai[elem]*rhocp/rhov*Tface);
834 // Cerr << " conv-new= " << (1/Lvap)*(mp[elem]*ai[elem]*rhocp/rhov*Tface) << finl;
835 delta_mp += (-1/Lvap)*(phi_conv_lost_by_mixed_cell);
836 // Cerr << " conv-new= " << phi_conv_lost_by_mixed_cell << " in elem= " << elem << finl;
837 // Cerr << " delta-mp-conv= " << delta_mp << finl;
838 }
839 if (account_for_mixed_cell_energy)
840 {
841 delta_mp += (1/Lvap)*(VdrhocpT_dt);
842// Cerr << " delta-mp-energy= " << (1/Lvap)*(VdrhocpT_dt) << finl;
843 }
844 int_dmp_ai += delta_mp;
845// Cerr << " delta-mp-tot= " << int_dmp_ai << " time= " << temps << finl;
846 }
847 }
848 // End of options
849 }
850 if ((option==3) and (int_ai>DMINFLOAT))
851 // if ((option==3))
852 {
853 const double mean_dmp = int_dmp_ai/int_ai;
854 const double mean_mp = int_mp_ai/int_ai;
855 double rel= 0.;
856 if (fabs(mean_mp)>DMINFLOAT)
857 rel=mean_dmp/mean_mp*100.;
858 Cerr << "correction of mp at time "<< temps << " mean_mp= " << mean_mp << " relative= " << rel << "%." <<finl;
859 /* Bad correction:
860 *
861 for(int i=0; i<nb_elem; i++)
862 {
863 const int elem = mixed_elems_[i];
864 mp[elem] +=mean_dmp;
865 Cerr << " newmp= " << mp[elem] << finl;
866 }*/
867 // New correction truely based on AI:
868 // (to be in perfect agreement with the condition (on untouched variables) used later for the extrapolation:
869 /* for(int i=0; i<nb_elem; i++)
870 {
871 const int elem = mixed_elems_[i];
872 if ((ai[elem]>DMINFLOAT) and (temps>DMINFLOAT))
873 mp[elem] +=mean_dmp;
874 } */
875
876 // GB 18/10/2020. Application of the correction EVERYWHERE:
877 mp +=mean_dmp;
878 }
879
880 double total_flux_lost = 0.;
881 double total_derivee_energy = 0.;
882 double mpai_tot = 0.;
883// double mp_tot = 0.;
884 for (int nd=0 ; nd<nb_elem ; nd++)
885 {
886 total_flux_lost -= lost_fluxes_(nd)*rhocp; // multiplied by rhocp (vp) // "-" because depends on convention (GB)
887 total_derivee_energy += derivee_energy_(nd)*volume[nd];
888 const int elem = mixed_elems_[nd];
889 mpai_tot += mp[elem]*ai[elem]*Lvap; // multiplied by Lvap (vp)
890 // mp_tot += mp[elem];
891 }
892 if ((option==3) and (int_ai>DMINFLOAT))
893 {
894 const double mean_mp_corr = mpai_tot/(int_ai*Lvap);
895 Cerr << " mean_mp_corr= " << mean_mp_corr << " time= " << temps << finl;
896 }
897 total_flux_lost = mp_sum(total_flux_lost);
898 mpai_tot = mp_sum(mpai_tot);
899 total_derivee_energy = mp_sum(total_derivee_energy)/dt;
900 Cerr << "[Corrected-balance] Time= " << temps << " nb_elems= " << nb_elem
901 << " phi(positive if towards mixed cells)= " << total_flux_lost
902 << " mp*ai*Lvap= " << mpai_tot
903 << " dE/dt= " << total_derivee_energy
904 << " imbalance= " << total_derivee_energy-total_flux_lost+mpai_tot << finl;
905 }
906
907 // If mpoint has been modified in interfacial cells (mixed cells). We want to extend it back into both phases
908 // using the same procedure
909 if ((option==0) or (option==3) or (option==2))
910 {
911 double mmax = 0.;
912 const int n = ai.size_array();
913 for(int i=0; i<n; i++)
914 {
915 if ((ai[i]>DMINFLOAT) && (fabs(mp[i])>mmax))
916 {
917 mmax =fabs(mp[i]);
918 }
919 }
920 mmax = Process::mp_max(mmax);
921 // Cerr << "[Maximum-mp] Time= " << temps << " max(abs(mp))= " << mmax << finl;
922 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
923 const DoubleTab& distance_interface = eq_interface_.get_distance_interface().valeurs();
924 extrapolate(domaine_vf, ai, stencil_width_, distance_interface, mp);
925 }
926}
927
928// With this approach, calculer_delta_u_interface is not called,
929// so the velocity should be extended.
930// Fills the field : vitesse_convection_
932{
933 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, ref_eq_ns_.valeur());
934 // vitesse_convection_->valeurs() = (bool)(explicit_u_NS_) ? ns.inconnue()->valeurs() : ns.inconnue()->futur();
935
936 const DoubleTab& val_vitesse_ns = explicit_u_NS_ ? ns.inconnue().valeurs() : ns.inconnue().futur();
937
939 vitesse_convection_->valeurs() += val_vitesse_ns;
940
941 // Projection of the convective field :
942 //SolveurSys solveur_pression(ns.get_solveur_pression());
943 OWN_PTR(Solveur_Masse_base) solveur_masse_fictitious(ns.solv_masse()); // Copy the operator to change the coeff
944 solveur_masse_fictitious->set_name_of_coefficient_temporel("no_coeff");
945
946 //On utilise un operateur de divergence temporaire et pas celui porte par l equation
947 //pour ne pas modifier les flux_bords_ rempli au cours de ...::mettre_a_jour
948 Operateur_Div div_tmp;
949 div_tmp.associer_eqn(ns);// It's slightly tricky but associating it to (*this) is not OK, because we want to apply it to a velocity.
950 // As delta_u is not the unknown of this equation (no more than vitesse_convection_), we resort to ns to
951 // make it work. Basically, it also means that delta_u gets the BC from u_ns?
952 // Problem with div_tmp.typer() that get the type of equation to make a type.
953 // Hence, it will see a conv/diff equation for a scalar... and will type div_tmp badly (not for a vector velocity field!)
954 // Instead we associer_eqn to ns
955 div_tmp.typer();
956 Cerr << "[Conv_diff_FT_Disc] div_tmp recieved the type " << div_tmp.type() << finl;
957 Cerr << "[Conv_diff_FT_Disc] div_tmp que suis je " << div_tmp.que_suis_je() << finl;
958 if (0)
959 {
960 Equation_base& eqn=ref_eq_ns_.valeur();
961 Nom inut;
962 Nom nom_type=eqn.discretisation().get_name_of_type_for(ns.que_suis_je(),inut,ns);
963 // const Probleme_FT_Disc_gen& pb = ref_cast(Probleme_FT_Disc_gen,probleme());
964 // ref_cast
965 // OWN_PTR(Operateur_Div_base)::typer(nom_type);
966 Cerr << "[Conv_diff_FT_Disc] Velocity correction. Construction of the divergence operator type : " << nom_type << finl;
967 // Cerr << valeur().que_suis_je() << finl ;
968 }
969
970 div_tmp.l_op_base().associer_eqn(ns);//*this);
971 //div_tmp.typer();
972 div_tmp->completer();
973 // En VDF, la methode 'completer()' est surchargee et fait
974 // 1. Operateur_base::completer();
975 // 2. iter.completer_();
976 // donc si on fait juste :
977 // div_tmp.l_op_base().associer(domaine_dis(), zcl_fictitious_, vitesse_convection_);
978 // On rate l'etape 2 qui a ete faite avec le completer plus haut...
979
980 // WARNING : Si on prend les cl de l'ope de pression pour cette divergence, il y a une vitesse sur les sorties de NS
981 // qui se trouve face a des conditions limites de symetrie dans zcl_fictitious...
982 // Du coup, ca fait un gros div! Ce n'est pas ce qu'on veut.
983 // PAR CONTRE, pour le calcul du gradient ci-dessous, c'est bien les cl de zcl_fictitious qu'on veut,
984 // sinon, sortie libre va mettre un grad(P).n non nul au bord!!
985 // DONC EN CONCLUSION, ON VEUT UN MIX!
986 //
987
988 // RHS for this pressure solveur : div(delta_u)
989 // We need to create a table sized as temperature to store the rhs :
990 DoubleTab& secmem = divergence_delta_U->valeurs();
991 //secmem.copy(inconnue().valeurs(), RESIZE_OPTIONS::NOCOPY_NOINIT);
992 div_tmp->calculer(vitesse_convection_->valeurs(),secmem);
993
994 // On ne conserve que la divergence des elements proches de l'interface, et supprime quand la distance est invalide
995 if (0) // Cela pourrait etre utile si on construisait le saut de vitesse delta u_0 mais
996 // cela semble presenter que peu d'interet...
997 {
998 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
999 const IntTab& face_voisins = domaine_vf.face_voisins();
1000 const IntTab& elem_faces = domaine_vf.elem_faces();
1001 const int nb_elem = secmem.size_array();
1002 const int nb_faces_elem = elem_faces.dimension(1);
1003 const Transport_Interfaces_FT_Disc& eq_transport = ref_eq_interface_.valeur();
1004 // Distance a l'interface discretisee aux elements:
1005 const DoubleTab& distance = eq_transport.get_distance_interface().valeurs();
1006 // const int nb_elem = secmem2.dimension(0);
1007 for (int elem = 0; elem < nb_elem; elem++)
1008 {
1009 const double dist = distance(elem);
1010 int i_face = -1;
1011 if (dist < -1e20)
1012 {
1013 // Distance invalide: on est loin de l'interface
1014 // invalide ou voisin invalide, on supprime la div :
1015 secmem(elem) = 0.;
1016 }
1017 else
1018 {
1019 // Y a-t-il un voisin pour lequel la distance est invalide
1020 for (i_face = 0; i_face < nb_faces_elem; i_face++)
1021 {
1022 const int face = elem_faces(elem, i_face);
1023 const int voisin = face_voisins(face, 0) + face_voisins(face, 1) - elem;
1024 if (voisin >= 0)
1025 {
1026 const double d = distance(voisin);
1027 if (d < -1e20)
1028 {
1029 // invalide ou voisin invalide, on supprime la div :
1030 secmem(elem) = 0.;
1031 break; // Un voisin invalide
1032 }
1033 }
1034 }
1035 }
1036 }
1037 }
1038 // Correction du second membre d'apres les conditions aux limites :
1039 assembleur_pression_->modifier_secmem(secmem);
1040 // Ajout pour la sauvegarde au premier pas de temps si reprise
1041 la_pression->changer_temps(schema_temps().temps_courant());
1042
1043 // Resolution du systeme en pression : calcul de la_pression
1044 solveur_pression_.resoudre_systeme(matrice_pression_.valeur(),
1045 secmem,
1046 la_pression->valeurs()
1047 );
1048 assembleur_pression_->modifier_solution(la_pression->valeurs());
1049 // Calcul d(u)/dt = vpoint + 1/rho*grad(P)
1050
1051 DoubleTab& gradP = gradient_pression_->valeurs();
1052 // Can I re-use a gradient from NS?
1053 Operateur_Grad gradient_tmp;
1054 gradient_tmp.associer_eqn(ns);//*this);
1055 gradient_tmp.typer();
1056 gradient_tmp.l_op_base().associer_eqn(ns);//*this);
1057 gradient_tmp->completer();
1058 // It is important to associate the gradient to the good BC via zcl,
1059 // Otherwise a normal gradient appears at the outlet.
1060 gradient_tmp.l_op_base().associer(domaine_dis(), zcl_fictitious_, vitesse_convection_); // Quel champ inco pour le gradP? A quoi sert-elle?
1061 gradient_tmp.calculer(la_pression->valeurs(), gradP);
1062 // I don't wanna divide by rho_face :
1063 solveur_masse_fictitious->appliquer(gradP); // divide by cell_volume
1064
1065 // Correction of vitesse : "+=" seems the good sign, though I don't understand why...
1066 {
1067 int i, j;
1068 DoubleTab& vc = vitesse_convection_->valeurs();
1069 const int n = vc.dimension(0);
1070 if (vc.nb_dim() == 1)
1071 {
1072 // VDF
1073 for (i = 0; i < n; i++)
1074 vc(i) += gradP(i);
1075 }
1076 else
1077 {
1078 //VEF
1079 const int m = vc.dimension(1);
1080 for (i = 0; i < n; i++)
1081 for (j = 0; j < m; j++)
1082 vc(i,j) += gradP(i,j);
1083 }
1085 }
1086
1087}
1089{
1090 // We start the timestep by computing :
1091 // STEP 1. Extend velocity and temperature (via calculer_grad_t which does a linear extrapolation
1092 // from the values within "phase_")
1093 statistics().create_custom_counter("calculer_mpoint",3,"FrontTracking");
1094 statistics().begin_count("calculer_mpoint",statistics().get_last_opened_counter_level()+1);
1096 statistics().end_count("calculer_mpoint");
1097
1098 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, ref_eq_ns_.valeur());
1099 // Emptying lists for new timestep.
1100 mixed_elems_.resize_array(0);
1101 lost_fluxes_.resize_array(0);
1102
1103 // STEP 2. Compute the continuous extension of velocity from phase_ into the other.
1104 // This velocity will be usefull for the convection operator.
1105 // Now, the step calculer_delta_u_interface calls get_mpoint instead of
1106 // calculer_mpoint (which used to in turns call: calculer_grad_t)
1107 // Therefore, it is important to have called explicitely the temperature
1108 // extension before at the begining of the function.
1109 statistics().create_custom_counter("extend_ui",3,"FrontTracking");
1110 statistics().begin_count("extend_ui", statistics().get_last_opened_counter_level()+1);
1111 const Champ_Inc_base& vitesse_ns = ns.inconnue();
1113 {
1114 // Here, we are in faire_un_pas_de_temps_eqn_base() between avancer and reculer()
1115 // We are not in mettre_a_jour(). valeurs() has u^n; futur() is u^(n+1)
1116 const DoubleTab& val_vitesse_ns = explicit_u_NS_ ? vitesse_ns.valeurs(): vitesse_ns.futur();
1117
1118 // vitesse_convection_ is Champ_Inc but never turns the wheel! So the field is always in .valeurs()
1120 vitesse_convection_->valeurs() += val_vitesse_ns;
1121 //Cerr << inconnue()->temps() << " =! " << vitesse_ns.temps() << " " << vitesse_convection_.temps() << finl;
1122 //Process::exit();
1123 }
1124 else
1125 {
1126 // Compute vitesse_convection_ which is equal to ns.inconnue() in phase_ and is extended (divergence-free) in the other phase:
1128 }
1129 statistics().end_count("extend_ui");
1130
1131 // Application of 2 operators: convection & diffusion
1132 // STEP 3: Convection operator
1133 // STEP 4: Diffusion operator
1134 // Convection and diffusion are dealt with in the standard way;
1135 // diffusion can be implicited.
1136 // rhoCp is used for convection.
1137 // vitesse_convection_ is used for convection.
1138 DoubleTab& temperature = inconnue().valeurs();
1139 derivee = 0.;
1140
1141 // STEP 3: Diffusion operator
1142 bool calcul_explicite = false;
1143 if (parametre_equation_ && sub_type(Parametre_implicite, parametre_equation_.valeur()))
1144 {
1145 Parametre_implicite& param2 = ref_cast(Parametre_implicite, parametre_equation_.valeur());
1146 calcul_explicite = param2.calcul_explicite();
1147 }
1148
1149 if (schema_temps().diffusion_implicite() && !calcul_explicite)
1150 {
1151 // do it later?
1152 }
1153 else
1154 {
1155 terme_diffusif.ajouter(temperature, derivee);
1156 }
1157 const int nb_diffu=mixed_elems_.size_array();
1158 // const double temps = schema_temps().temps_courant();
1159 lost_fluxes_diffu_.resize_array(nb_diffu);
1160 mixed_elems_diffu_.resize_array(nb_diffu);
1161 {
1162 double total_flux_lost = 0.;
1163 for (int nd=0 ; nd<nb_diffu ; nd++)
1164 {
1165 total_flux_lost += lost_fluxes_(nd);
1168 }
1169 total_flux_lost = mp_sum(total_flux_lost);
1170 // Cerr << "[Lost-fluxes-diffusif] Time= " << temps << " nb_faces= " << nb_diffu
1171 // << " Lost= " << total_flux_lost << finl;
1172 }
1173
1174 // STEP 4: Convection operator
1175 {
1176 const DoubleTab& rhoCp = get_champ("rho_cp_comme_T").valeurs();
1177 DoubleTab derivee_tmp(derivee);
1178 derivee_tmp = 0.;
1179 terme_convectif.ajouter(temperature, derivee_tmp);
1180 derivee_tmp *= rhoCp;
1181 derivee += derivee_tmp;
1182
1183 const int nb_conv=mixed_elems_.size_array()-nb_diffu;
1184 lost_fluxes_conv_.resize_array(nb_conv);
1185 mixed_elems_conv_.resize_array(nb_conv);
1186 double total_flux_conv_lost = 0.;
1187 for (int nd=0 ; nd<nb_conv ; nd++)
1188 {
1189 const int elem = mixed_elems_(nb_diffu+nd);
1190 const double flux = lost_fluxes_(nb_diffu+nd)*rhoCp[elem];
1191 total_flux_conv_lost += flux;
1192 lost_fluxes_conv_(nd) = flux;
1193 mixed_elems_conv_(nd) = elem;
1194 }
1195
1196 total_flux_conv_lost = mp_sum(total_flux_conv_lost);
1197 // Cerr << "[Lost-fluxes-convection] Time= " << temps << " nb_faces= " << nb_conv
1198 // << " Lost= " << total_flux_conv_lost << finl;
1199
1200 }
1201
1202 solveur_masse->appliquer(derivee);
1203 if (schema_temps().diffusion_implicite() && !calcul_explicite)
1204 {
1206 return derivee;
1207 }
1208 else
1209 {
1210 // TODO : J'aimerais bien deplacer la diffusion explicite la aussi.
1211 // Il faut juste revoir les boucles pour deplacer le lost_fluxes associes ici aussi
1212 // terme_diffusif.ajouter(temperature, derivee);
1213 }
1214
1215 // To remove duplicates in the list of mixed_elems (some elements are there several times, twice (conv+diff) for each face-to-pure-liquid)
1216 collect_into_unique_occurence(mixed_elems_, lost_fluxes_);
1217 collect_into_unique_occurence(mixed_elems_diffu_, lost_fluxes_diffu_);
1218 collect_into_unique_occurence(mixed_elems_conv_, lost_fluxes_conv_);
1219
1220 {
1221 const int nb=mixed_elems_.size_array();
1222 double total_flux_lost = 0.;
1223 for (int nd=0 ; nd<nb ; nd++)
1224 total_flux_lost += lost_fluxes_(nd);
1225
1226 total_flux_lost = mp_sum(total_flux_lost);
1227 // Cerr << "[Lost-fluxes-conv+diff] Time= " << temps << " nb_faces= " << nb
1228 // << " Lost= " << total_flux_lost << finl;
1229 }
1230
1231 // STEP 5: (OPTIONNAL?) Attempt to correct mpoint to reach an energy conservation.
1232 // Apply a correction to mpoint in order to locally satisfy the energy balance in mixed cells (consistency between incoming fluxes that are lost
1233 // and the phase change mp*ai, all with regards to the liquid energy evolution in the cell: d(rho*cp*chi*T)/dt.
1234 {
1235 mpoint_uncorrected_->valeurs() = mpoint_->valeurs();
1236 DoubleTab& mp = mpoint_->valeurs();
1237 const DoubleTab& ai = ns.get_interfacial_area();
1238 const double temps = schema_temps().temps_courant();
1239 const int nb_elemi = mixed_elems_.size_array();
1240 double mp_sum_before_corr = 0.;
1241 double int_ai_before = 0.;
1242 for (int nd=0 ; nd<nb_elemi ; nd++)
1243 {
1244 const int elembi = mixed_elems_[nd];
1245 int_ai_before += ai[elembi];
1246 // total_flux_lost -= lost_fluxes_(nd)*rhocp; // multiplied by rhocp (vp) // "-" because depends on convention (GB)
1247 // total_derivee_energy += derivee_energy_(nd)*volume[nd];
1248 // mpai_tot += mp[elemb]*ai[elemb]*Lvap;// multiplied by Lvap (vp)
1249 // Cerr << " ai= " << ai[elembi] << " int_ai= " << int_ai_before << finl;
1250 mp_sum_before_corr += mp[elembi]*ai[elembi];
1251 }
1252 if (int_ai_before>DMINFLOAT)
1253 {
1254 const double mean_mp_before_corr = mp_sum_before_corr/int_ai_before;
1255 Cerr << " mp_sum_before_corr= " << mp_sum_before_corr << " mean_mp_before_corr= " << mean_mp_before_corr << " time= " << temps << finl;
1256 }
1258 {
1259 // WARNING!! We don't correct mpoint if correction_mpoint_diff_conv_energy_ are all set to 0
1260 // this method is not related to TCL model but rather to attempting energy conserving Ghost Fluid Method.
1262 }
1263 }
1264
1265 const Probleme_FT_Disc_gen& pb = ref_cast(Probleme_FT_Disc_gen,probleme());
1266 const Triple_Line_Model_FT_Disc& tcl = pb.tcl();
1267 // const double max_val_before = max_array(temperature);
1268 // const double min_val_before = min_array(temperature);
1269 if (tcl.is_activated())
1270 {
1271 // No need to recompute TCL here, it should be up-to-date.
1272#ifdef DEBUG
1273 {
1274 const Transport_Interfaces_FT_Disc& eq_transport = ref_eq_interface_.valeur();
1275 const Maillage_FT_Disc& maillage = eq_transport.maillage_interface();
1276 assert(tcl.tag_tcl() == maillage.get_mesh_tag());
1277 toto ce code n est pas lu
1278 }
1279#endif
1280 // Ne compile pas, pourquoi?
1281 // assert(tcl.tag_tcl() == ref_eq_interface_->maillage_interface().get_mesh_tag());
1282
1283 // We are late enough within the timestep for the correction not to affect the velocities reconstructions (delta_u)
1284 // because we expect it has been done before. Nonetheless, we need to do it before the post-pro to see our corrected fields
1285 // in the lata
1286 //
1287 // Correct the field mpoint in wall-adjacent cells to account for TCL model:
1288 // ---> It cannot be done before because it would disturbs the solution via delta u!
1289 tcl.corriger_mpoint(mpoint_->valeurs());
1290
1291 // Correct the phase-change in wall adjacent cells:
1292 // The mean cell-temperature is simply derived from the TCL solution.
1293 // tcl.set_wall_adjacent_temperature_according_to_TCL_model(temperature);
1294 temperature.echange_espace_virtuel();
1295 }
1296 // Cerr << "[temperature] max before/after TCL model: " << max_val_before << " / " << max_array(temperature) << finl;
1297 // Cerr << "[temperature] min before/after TCL model: " << min_val_before << " / " << min_array(temperature) << finl;
1298
1299 return derivee;
1300}
1301
1303{
1305 vitesse_convection_->mettre_a_jour(temps);
1306 DoubleTab& temperature = inconnue().valeurs();
1307 // GB : Debut du maintien artificiel de la temperature.
1309 {
1310 const Nom nom_sous_domaine = nom_sous_domaine_;
1311 const double temp_moy_ini = temp_moy_ini_;
1312 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1313 const Domaine& dom = domaine_vf.domaine();
1314 const Sous_Domaine& ss_domaine = dom.ss_domaine(nom_sous_domaine);
1315
1316 Transport_Interfaces_FT_Disc& eq_interface_ = ref_eq_interface_.valeur();
1317 const DoubleTab& indicatrice = eq_interface_.get_indicatrice().valeurs();
1318 const DoubleVect& volume = ref_cast(Domaine_VF, domaine_dis()).volumes();
1319 const int nb_elem = domaine_vf.domaine().nb_elem();
1320
1321 // Calcul de la moyenne sous domaine, et du facteur : fac = temp_moy_ini/temp_moy_ss_domaine
1322 double temp_moy_ss_domaine = 0.;
1323 double vol_liq = 0.;
1324 for(int i=0; i<ss_domaine.nb_elem_tot() /*methode d'acces au nombre d'elements*/; i++)
1325 {
1326 int index = ss_domaine[i];
1327 // assert(index < domaine_vf.domaine().nb_elem());
1328 if (index < nb_elem)
1329 {
1330 temp_moy_ss_domaine += temperature[index] * indicatrice[index] * volume[index];
1331 vol_liq += indicatrice[index] * volume[index];
1332 }
1333 }
1334 vol_liq = mp_sum(vol_liq);
1335 temp_moy_ss_domaine = mp_sum(temp_moy_ss_domaine);
1336 if (vol_liq == 0. || temp_moy_ss_domaine == 0.)
1337 {
1338 // ne fien faire
1339 }
1340 else
1341 {
1342 temp_moy_ss_domaine /= vol_liq ;
1343 double fac = temp_moy_ini / temp_moy_ss_domaine;
1344
1345 // Correction du champ de temperature :
1346 temperature *= fac; // Methode de multiplication d'un tableau
1347 }
1348 }
1349 // GB : Fin.
1350 temperature.echange_espace_virtuel();
1351
1352 // check if the wall is ready for reinjection of bubble
1353 const bool is_liq = (get_phase()==1);
1354 if (is_liq && is_reinject_activated())
1356}
1357
1359{
1360
1361 const Navier_Stokes_std& ns = ref_eq_ns_.valeur();
1362 const Domaine_Cl_dis_base& zcldis = ns.domaine_Cl_dis();
1363
1364 Transport_Interfaces_FT_Disc& eq_interface_ = ref_eq_interface_.valeur();
1365 const DoubleTab& indica = eq_interface_.get_indicatrice().valeurs();
1366
1367 // get wall BC frontiere nb
1368 int num_bord = -1;
1369 int nbwall_found = 0;
1370 for (int i=0; i<zcldis.nb_cond_lim(); i++)
1371 {
1372 const Cond_lim& la_cl = zcldis.les_conditions_limites(i);
1373 const Nom& bc_name = la_cl-> frontiere_dis().le_nom();
1374 // For each BC, we check its type to see if it's a wall:
1375 // BC for hydraulic equation
1376 bool is_wall = sub_type(Dirichlet_paroi_fixe,la_cl.valeur())
1377 || sub_type(Dirichlet_paroi_defilante,la_cl.valeur());
1378 if (is_wall)
1379 {
1380 Cerr << "[Convection_Diffusion_Temperature_FT_Disc]: Reinjection bubble: Wall-type BC found at " << bc_name <<finl;
1381 num_bord = i;
1382 nbwall_found = nbwall_found +1;
1383 }
1384 }
1385 if (nbwall_found != 1)
1386 Process::exit(Nom(nbwall_found) + " wall-type BC found!!!!! Check JDD, pls" );
1387 if (num_bord<0)
1388 Process::exit( "[Convection_Diffusion_Temperature_FT_Disc]: !!! NO WALL-TYPE BOUNDARY WAS FOUND IN THE DOMAINE, PLESEASE CHECK JDD" );
1389
1390 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1391 const IntTab& face_voisins = domaine_vf.face_voisins();
1392
1393 const DoubleTab& centre_gravite_face = domaine_vf.xv();
1394 const DoubleVect& surface= domaine_vf.face_surfaces();
1395
1396 const Frontiere& fr=zcldis.les_conditions_limites(num_bord) -> frontiere_dis().frontiere();
1397 const int nb_first_face = fr.num_premiere_face();
1398 const int nb_face = fr.nb_faces();
1399
1400 ready_inject_ = false;
1401 int BC_has_vap = 0;
1402
1403 // get vap cells
1404 for (int ii = 0; ii < nb_face; ii++)
1405 {
1406 const int num_face = ii + nb_first_face;
1407 const int elemi = face_voisins (num_face, 0)
1408 + face_voisins (num_face, 1) + 1;
1409
1410 if (!est_egal (indica(elemi,0), 1.))
1411 {
1412 BC_has_vap = 1;
1413 break;
1414 }
1415 }
1416 BC_has_vap = Process::mp_max (BC_has_vap);
1417
1418 if (BC_has_vap == 0)
1419 {
1420 double sum_T = 0;
1421 double sum_surface = 0;
1422 for (int ii = 0; ii < nb_face; ii++)
1423 {
1424 const int num_face = ii + nb_first_face;
1425
1426 if (centre_gravite_face(num_face, 0) <= get_Rc_inject ())
1427 {
1428 sum_surface += surface (num_face);
1429 sum_T += surface (num_face) * get_Twall_at_face (num_face);
1430 }
1431 }
1432 sum_T = Process::mp_sum (sum_T);
1433 sum_surface = Process::mp_sum (sum_surface);
1434
1435 sum_T = (sum_surface > DMINFLOAT) ? sum_T / sum_surface : 0;
1436 ready_inject_ = (sum_T >= get_tempC()) ? true : false;
1437 }
1438}
1439
1441{
1442 phase_ = 1;
1443
1444 const Discretisation_base& dis = discretisation();
1445 const double temps = schema_temps().temps_courant();
1446 const Domaine_dis_base& un_domaine_dis = domaine_dis();
1447 LIST(OBS_PTR(Champ_base)) & champs_compris = liste_champs_compris_;
1448 const int nb_valeurs_temps = schema_temps().nb_valeurs_temporelles();
1449
1450 Nom nom;
1451
1452 nom = Nom("temperature_") + le_nom();
1453 dis.discretiser_champ("temperature", un_domaine_dis, nom, "K", 1 /* composantes */, nb_valeurs_temps, temps, la_temperature);
1454 champs_compris.add(la_temperature.valeur());
1455 champs_compris_.ajoute_champ(la_temperature);
1456
1457 nom = Nom("temperature_grad_") + le_nom();
1458 dis.discretiser_champ("temperature", un_domaine_dis, nom, "K/m", 1 /* composantes */, temps, grad_t_);
1459 champs_compris.add(grad_t_.valeur());
1460 champs_compris_.ajoute_champ(grad_t_);
1461
1462 nom = Nom("mpoint_") + le_nom();
1463 dis.discretiser_champ("temperature", un_domaine_dis, nom, "kg/(m2s)", 1 /* composante */, temps, mpoint_);
1464 champs_compris.add(mpoint_.valeur());
1465 champs_compris_.ajoute_champ(mpoint_);
1466
1467 nom = Nom("mpoint_uncorrected_") + le_nom();
1468 dis.discretiser_champ("temperature", un_domaine_dis, nom, "kg/(m2s)", 1 /* composante */, temps, mpoint_uncorrected_);
1469 champs_compris.add(mpoint_uncorrected_.valeur());
1470 champs_compris_.ajoute_champ(mpoint_uncorrected_);
1471
1472 nom = Nom("vitesse_conv_") + le_nom();
1473 dis.discretiser_champ("vitesse", un_domaine_dis, nom, "m/s", -1 /* nb composantes par defaut */, 1 /* valeur temporelle */, temps, vitesse_convection_);
1474 champs_compris.add(vitesse_convection_.valeur());
1475 champs_compris_.ajoute_champ(vitesse_convection_);
1476
1477 // TODO: I'd like the flag to work... But it is not updated yet. Please Help me, at Adrien Bruneton
1478 if (1 || divergence_free_velocity_extension_) // Problem for ABN : On n'a pas encore lu le param.ajouter qui passe mon flag a 1.
1479 {
1480 Cerr << "Fake Pressure gradient discretization" << finl;
1481 nom = Nom("gradient_pression_") + le_nom();
1482 dis.discretiser_champ("vitesse", un_domaine_dis,
1483 nom, "",
1484 -1 /* nb composantes par defaut */, 1 /* valeur temporelle */, temps,
1485 gradient_pression_);
1486 champs_compris.add(gradient_pression_.valeur());
1487 champs_compris_.ajoute_champ(gradient_pression_);
1488
1489 Cerr << "Fake Pressure discretization" << finl;
1490 nom = Nom("fake_pressure_") + le_nom();
1491 dis.discretiser_champ("pression",un_domaine_dis,nom,"Pa.m3/kg",1,1,temps,la_pression);
1492 champs_compris.add(la_pression.valeur());
1493 champs_compris_.ajoute_champ(la_pression);
1494
1495 Cerr << "Velocity (delta_u) divergence discretization" << finl;
1496 nom = Nom("divergence_delta_U_") + le_nom();
1497 dis.discretiser_champ("divergence_vitesse" /*directive */,un_domaine_dis, nom, "m3/s", 1,1,temps,divergence_delta_U);
1498 champs_compris.add(divergence_delta_U.valeur());
1499 champs_compris_.ajoute_champ(divergence_delta_U);
1500
1502 }
1504}
1505
1507{
1508 Nom type = "Assembleur_P_";
1509 type += discretisation().que_suis_je();
1510 //type += "_homogene";
1511 Cerr << "Navier_Stokes_std::discretiser_assembleur_pression : type="<< type << finl;
1512 assembleur_pression_.typer(type);
1513 assembleur_pression_->associer_domaine_dis_base(domaine_dis());
1514}
1515
1517{
1519 const Transport_Interfaces_FT_Disc& ft = ref_eq_interface_.valeur();
1520 const int ndist = ft.get_n_iterations_distance();
1521 if (stencil_width_ <= ndist)
1522 {
1523 Cerr << "The value of the stencil to compute mpoint should at least be strictly larger than "
1524 << "the width on which the distance is computed (given by n_iterations_distance in " << ft.que_suis_je() << ")" << finl;
1525 Cerr << "Current options : stencil= " << stencil_width_ << " and n_iterations_distance= " << ndist << " are invalid! Exiting." << finl;
1526 Process::exit();
1527 }
1529 {
1530 if (!solveur_pression_)
1531 {
1532 Cerr << "You are trying to make the extension of velocity divergence free. " << finl;
1533 Cerr << "A poisson solver is then required and should be defined in your equation by the addition of the optional keyword solveur_pression_fictive " << finl;
1534 Cerr << "as in e.g.: solveur_pression_fictive GCP { precond ssor { omega 1.5 } seuil 1e-15 impr } " << finl;
1535 Process::exit();
1536 }
1537 const Navier_Stokes_std& ns = ref_eq_ns_.valeur();
1538
1539 //
1540 // Build dummy Domaine_cl_dis object to pass to the assembleur_pression_ object:
1541 //
1542 // Step 0: Build string corresponding to the list of CLs we want to pass:
1543 SChaine instructions;
1544 instructions << "{" << finl;
1545 const Domaine& ladomaine=ns.domaine_dis().domaine();
1546 int nfront = ladomaine.nb_front_Cl();
1547 // The idea is to open the pressure on boundaries in contact with the other phase ie "(1-phase_)"
1548 // The goal is to let some fictitious pressure out (to accomodate for an (\int div(u_conv) dv !=0)
1549 for (int ifront=0; ifront<nfront; ifront++)
1550 {
1551 const Nom& nom_front = ladomaine.frontiere(ifront).le_nom();
1552 if (name_bc_opening_pressure_.contient_(nom_front))
1553 instructions << " " <<nom_front << " sortie_libre_rho_variable champ_front_uniforme 1 0" << finl;
1554 else
1555 instructions << " " <<nom_front << " symetrie" << finl;
1556 }
1557 instructions << "}" << finl;
1558 Cerr << "Interpretation de la chaine suivante:" << finl << instructions.get_str();
1559 EChaine is(instructions.get_str());
1560
1561 // Step 1: discretise (see Equation_base::discretiser())
1562 Cerr << "Discretisation of fictitious CL ..." << finl;
1563 zcl_fictitious_.typer("Domaine_Cl_VDF");
1564 Domaine_Cl_VDF& zcl_fictitious_vdf = ref_cast(Domaine_Cl_VDF, zcl_fictitious_.valeur());
1565 Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, domaine_dis());
1566 zcl_fictitious_vdf.associer(domaine_vdf);
1567 zcl_fictitious_->associer_eqn(ns);
1568 // zcl_fictitious_->associer_inconnue(inconnue()); // Useless
1569
1570 // Step 2: read input (see Equation_base::lire_cl())
1571 Cerr << "Interpreting input string ..." << finl;
1572 is >> zcl_fictitious_vdf ;
1573
1574 // Step 3: completer (see Equation_base::completer())
1575 Cerr << "Completing fictitious CL ..." << finl;
1576 zcl_fictitious_->completer();
1577
1578 // Associate to the newly created zcl :
1579 // required because It's not a good plan to use ns.domaine_Cl_dis() because of outlet_BC
1580 assembleur_pression_->associer_domaine_cl_dis_base(zcl_fictitious_.valeur());
1581 assembleur_pression_->completer(ns); // Should it be associated to (*this) or ns?
1582 // I think it does not matter because Assembleur_base::completer is called and does nothing
1583 // On assemble la matrice de pression une seule et unique fois (puisqu'elle ne depend pas de rho...).
1584 assembleur_pression_->assembler(matrice_pression_);
1585 // Informe le solveur que la matrice a change :
1586 solveur_pression_->reinit();
1587 }
1588
1589 if ((Rc_GridN_ != 0)and(Rc_inject_>DMINFLOAT))
1590 {
1591 Cerr << "Check your datafile. Rc_GridN and Rc_inject should not but used simultaneously." << finl;
1592 Cerr << "Rc_tcl_GridN = " << Rc_GridN_ << finl;
1593 Cerr << "Rc_inject = " << Rc_inject_ <<finl;
1594 Process::exit();
1595 }
1596
1597 if ((Rc_inject_ == 0.) and is_reinject_activated() )
1598 {
1599 const Navier_Stokes_std& ns = ref_eq_ns_.valeur();
1600 const Domaine_Cl_dis_base& zcldis = ns.domaine_Cl_dis();
1601 int num_bord = -1;
1602 for (int i=0; i<zcldis.nb_cond_lim(); i++)
1603 {
1604 const Cond_lim& la_cl = zcldis.les_conditions_limites(i);
1605 // For each BC, we check its type to see if it's a wall:
1606 // BC for hydraulic equation
1607 bool is_wall = sub_type(Dirichlet_paroi_fixe,la_cl.valeur())
1608 || sub_type(Dirichlet_paroi_defilante,la_cl.valeur());
1609 if (is_wall)
1610 {
1611 num_bord = i;
1612 break;
1613 }
1614 }
1615 if (num_bord<0)
1616 Process::exit( "[Convection_Diffusion_Temperature_FT_Disc]: !!! NO WALL-TYPE BOUNDARY WAS FOUND IN THE DOMAINE, PLESEASE CHECK JDD" );
1617
1618 const Frontiere& fr=zcldis.les_conditions_limites(num_bord)-> frontiere_dis().frontiere();
1619 const int nb_face = fr.nb_faces();
1620 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, ns.domaine_dis());
1621 // supposing deltax = deltay in the first thermal layer
1622 if (nb_face>0)
1623 {
1624 const int num_face= fr.num_premiere_face();;
1625 int elem_voisin = zvdf.face_voisins(num_face, 0) + zvdf.face_voisins(num_face, 1) +1;
1626 const double cell_height = 2.*std::fabs(zvdf.dist_face_elem0(num_face,elem_voisin));
1627 Rc_inject_ = cell_height * Rc_GridN_;
1628 }
1630 Cerr << "[Convection_Diffusion_Temperature_FT_Disc] Rc_inject_ is set to " << Rc_inject_ << " according to provided Rc_GridN_ " << Rc_GridN_ << finl;
1631 }
1632 Rc_inject_ = std::fmax(Rc_inject_,DMINFLOAT);
1633}
1634
1635// Pour que milieu().mettre_a_jour(temps) ne plante pas...
1636// Et d'autres comme diffusivite_pour_transport...
1638{
1639 if (!fluide_dipha_)
1640 {
1641 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
1642 Process::exit();
1643 }
1644 // Cast non const cause acces const a fluide_phase!!
1645 return ref_cast_non_const(Milieu_base,fluide_dipha_->fluide_phase(phase_));
1646}
1648{
1649 if (!fluide_dipha_)
1650 {
1651 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
1652 Process::exit();
1653 }
1654 return fluide_dipha_->fluide_phase(phase_);
1655}
1656
1658{
1659 if (! sub_type(Fluide_Diphasique, un_milieu))
1660 {
1661 Cerr << "Erreur dans Convection_Diffusion_Temperature_FT_Disc::associer_milieu_base\n"
1662 << " On attendait un fluide diphasique" << finl;
1663 Cerr << "Error for Convection_Diffusion_Temperature_FT_Disc::associer_milieu_base\n"
1664 << "A Fluide_Diphasique medium was expected." << finl;
1665 Process::exit();
1666 }
1667 fluide_dipha_ = ref_cast(Fluide_Diphasique, un_milieu);
1668}
1669
1670/*! @brief Methode appelee par Transport_Interfaces_xxx::test_suppression_interfaces_sous_domaine() lorqu'une interfaces disparait.
1671 *
1672 * Il faut remettre la temperature de saturation dans
1673 * l'inclusion supprimee.
1674 *
1675 */
1677 const ArrOfInt& flags_compo_a_supprimer,
1678 int nouvelle_phase)
1679{
1680 // Si la nouvelle phase n'est pas la phase resolue, ne rien faire
1681 if (nouvelle_phase != phase_)
1682 return;
1683
1684 const int n = domaine_dis().domaine().nb_elem();
1685 assert(num_compo.size() == n);
1686 const int nb_valeurs_temporelles = inconnue().nb_valeurs_temporelles();
1687 // Il faut traiter toutes les cases temporelles:
1688 // selon l'ordre des equations dans le probleme, la roue a deja ete tournee ou pas...
1689 // Note B.M. est ce que c'est compatible avec la spec de ICOCO ? (modif
1690 // du temps n autorisee ???)
1691 for (int t = 0; t < nb_valeurs_temporelles; t++)
1692 {
1693 DoubleTab& temp = inconnue().futur(t);
1694 for (int i = 0; i < n; i++)
1695 {
1696 const int c = num_compo[i];
1697 if (c >= 0 && flags_compo_a_supprimer[c])
1698 temp[i] = TSAT_CONSTANTE;
1699 }
1701 }
1702}
1703
1705{
1706 set_is_solid_particle(ref_eq_interface_.valeur().get_is_solid_particle());
1708 ref_eq_interface_.valeur().associate_temp_equation_post_processing(*this);
1710// Si mpoint_ etait un champ inc? mpoint_.mettre_a_jour(schema_temps().temps_courant());
1712}
1713
1714// A few methods for TCL only:
1716{
1717 double interfacial_flux = 0.;
1718 const Domaine_Cl_dis_base& zcldis = domaine_Cl_dis();
1719 if (!sub_type(Domaine_Cl_VDF, zcldis))
1720 {
1721 Cerr << "Woops! Not VDF";
1722 Process::exit();
1723 }
1724 const Domaine_Cl_VDF& zclvdf = ref_cast(Domaine_Cl_VDF, zcldis);
1725 const Cond_lim& la_cl = zclvdf.la_cl_de_la_face(num_face);
1726 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1727 const Nom& bc_name = la_cl->frontiere_dis().le_nom();
1728 const int ndeb = le_bord.num_premiere_face();
1729// Cerr << " BC: " << la_cl.valeur() << " name: " << bc_name << finl;
1730// Cerr << "Dealing with face " << num_face << " belonging to BC " << la_cl.valeur();
1731 if ( sub_type(Neumann_paroi_adiabatique,la_cl.valeur()) )
1732 {
1733 Cerr << "paroi_adiabatique" << finl;
1734 return interfacial_flux;
1735 }
1736 else if ( sub_type(Neumann_paroi,la_cl.valeur()) )
1737 {
1738 Cerr << "paroi_flux_impose" << finl;
1739 const Neumann_paroi& la_cl_typee = ref_cast(Neumann_paroi, la_cl.valeur());
1740 double phi_imp = la_cl_typee.champ_front().valeurs()(num_face-ndeb); // Should it be valeurs instead of ?
1741 return phi_imp;
1742 }
1743 else if (sub_type(Echange_impose_base, la_cl.valeur()))
1744 {
1745 Cerr << "paroi_temperature_imposee (among other possibilities)" << finl;
1746 /* Le terme de flux calcule a partir du couple(h_imp,T_ext) s'ecrit :
1747 // h_t(T_ext - T_entier)*Surf
1748 // avec h_t : coefficient d'echange global.
1749 * */
1750 const Echange_impose_base& la_cl_typee = ref_cast(Echange_impose_base, la_cl.valeur());
1751 // Cerr << " Face " << num_face << " is actually #" << num_face-ndeb << " on this boundary." << finl;
1752 const double h = la_cl_typee.h_imp(num_face-ndeb);
1753 const double T_imp = la_cl_typee.T_ext(num_face-ndeb);
1754 // Cerr << " Reading coefficients h= " << h << " and T_imp= " << T_imp << " for heat flux evaluation." << finl;
1755 // The flux is between the wall and Tsat :
1756 interfacial_flux = h*(T_imp - TSAT_CONSTANTE); // What about the area? surf should be the interfacial area or come from the face area?
1757 // it is taken into account after this function.
1758 return interfacial_flux;
1759 }
1760 /* else if ( sub_type(paroi_contact,la_cl.valeur()) )
1761 {
1762 Cerr << que_suis_je() << "::get_flux_to_face() thermal BC " << la_cl.valeur()
1763 << " at face " << num_face << " not supported yet." << finl;
1764 Cerr << "The BC type " << la_cl << " for boundary "<< la_cl->champ_front().le_nom()
1765 << " is not supported yet."<< finl;
1766 Process::exit();
1767 } */
1768 else
1769 {
1770 Cerr << que_suis_je() << "::get_flux_to_face(). " ;
1771 Cerr << "The BC type " << la_cl.valeur() << " for boundary "<< bc_name
1772 << " is not supported yet."<< finl;
1773 Process::exit();
1774 }
1775 return interfacial_flux;
1776}
1777
1779{
1780 double flux=0., Twall=0.;
1781 get_flux_and_Twall(num_face,
1782 flux, Twall);
1783 return Twall;
1784}
1785
1787{
1788 //ArrOfInt num_faces;
1789 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1790 const IntTab& elem_faces = domaine_vf.elem_faces();
1791 const IntTab& faces_elem = domaine_vf.face_voisins();
1792 const int nb_faces_voisins = elem_faces.dimension(1);
1793 // Struggle to get the boundary face
1794 int num_face=-1;
1795 int i;
1796 for (i=0; i<nb_faces_voisins; i++)
1797 {
1798 num_face = elem_faces(elem,i);
1799 // If it's a boundary face, one of the neighbours doesnot exist so it has "-1".
1800 // We detect a boundary that way:
1801 const int elemb = faces_elem(num_face, 0) + faces_elem(num_face, 1) +1;
1802 if (elem == elemb)
1803 {
1804 //num_faces[idx] = num_face;
1805 break;
1806 }
1807 }
1808 if (i==nb_faces_voisins)
1809 {
1810 Cerr << "Error. No boundary face found in this element "<< elem << finl;
1811 Process::exit();
1812 }
1813 double flux=0., Twall=0.;
1814 get_flux_and_Twall(num_face,
1815 flux, Twall);
1816 return Twall;
1817}
1818
1820 double& flux, double& Twall) const
1821{
1822 flux = 0.;
1823 const Domaine_Cl_dis_base& zcldis = domaine_Cl_dis();
1824 if (!sub_type(Domaine_Cl_VDF, zcldis))
1825 {
1826 Cerr << "Woops! Not VDF";
1827 Process::exit();
1828 }
1829 const Domaine_Cl_VDF& zclvdf = ref_cast(Domaine_Cl_VDF, zcldis);
1830 const Cond_lim& la_cl = zclvdf.la_cl_de_la_face(num_face);
1831 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1832 const Nom& bc_name = la_cl->frontiere_dis().le_nom();
1833 const int ndeb = le_bord.num_premiere_face();
1834// Cerr << " BC: " << la_cl.valeur() << " name: " << bc_name << finl;
1835// Cerr << "Dealing with face " << num_face << " belonging to BC " << la_cl.valeur();
1836 if ( sub_type(Neumann_paroi_adiabatique,la_cl.valeur()) )
1837 {
1838 Cerr << "paroi_adiabatique" << finl;
1839 flux = 0.;
1840 //
1841 Cerr << "How can we set Twall when temperature(elem) is not valid? Or is it?" << finl;
1842 Process::exit();
1843 }
1844 else if ( sub_type(Neumann_paroi,la_cl.valeur()) )
1845 {
1846 Cerr << "paroi_flux_impose" << finl;
1847 const Neumann_paroi& la_cl_typee = ref_cast(Neumann_paroi, la_cl.valeur());
1848 flux = la_cl_typee.champ_front().valeurs()(num_face-ndeb); // Should it be valeurs instead of ?
1849 //
1850 Cerr << "How can we set Twall when temperature(elem) is not valid? Or is it?" << finl;
1851 Process::exit();
1852 }
1853 else if (sub_type(Echange_impose_base, la_cl.valeur()))
1854 {
1855
1856 if (sub_type(Echange_contact_VDF_FT_Disc, la_cl.valeur()))
1857 {
1858 // Cerr << "Echange_contact_VDF_FT_Disc" << finl;
1859 /* Le terme de flux calcule a partir du (phi_ext) s'ecrit :
1860 // phi_ext_*Surf
1861 // avec phi_ext : heat flux density at the surface.
1862 * */
1863 const Echange_contact_VDF_FT_Disc& la_cl_typee = ref_cast(Echange_contact_VDF_FT_Disc, la_cl.valeur());
1864 // Cerr << " Face " << num_face << " is actually #" << num_face-ndeb << " on this boundary." << finl;
1865 const double h = la_cl_typee.h_imp(num_face-ndeb);
1866 const double T_imp = la_cl_typee.Ti_wall(num_face-ndeb);
1867 // Cerr << " Reading coefficients h= " << h << " and T_imp= " << T_imp << " for heat flux evaluation." << finl;
1868 // We keep the term + h*(T_imp - TSAT_CONSTANTE) as h = 0.;
1869 //
1870 flux = la_cl_typee.flux_exterieur_impose(num_face-ndeb) + h*(T_imp - TSAT_CONSTANTE);
1871 Twall = T_imp;
1872 }
1873 else
1874 {
1875 Cerr << "paroi_temperature_imposee (among other possibilities)" << finl;
1876 /* Le terme de flux calcule a partir du couple(h_imp,T_ext) s'ecrit :
1877 // h_t(T_ext - T_entier)*Surf
1878 // avec h_t : coefficient d'echange global.
1879 * */
1880 const Echange_impose_base& la_cl_typee = ref_cast(Echange_impose_base, la_cl.valeur());
1881 // Cerr << " Face " << num_face << " is actually #" << num_face-ndeb << " on this boundary." << finl;
1882 const double h = la_cl_typee.h_imp(num_face-ndeb);
1883 const double T_imp = la_cl_typee.T_ext(num_face-ndeb);
1884
1885 // Cerr << " Reading coefficients h= " << h << " and T_imp= " << T_imp << " for heat flux evaluation." << finl;
1886 // The flux is between the wall and Tsat :
1887 flux = h*(T_imp - TSAT_CONSTANTE); // What about the area? surf should be the interfacial area or come from the face area?
1888 // it is taken into account after this function.
1889 Twall = T_imp;
1890
1891 }
1892 }
1893 /* else if ( sub_type(paroi_contact,la_cl.valeur()) )
1894 {
1895 Cerr << que_suis_je() << "::get_flux_to_face() thermal BC " << la_cl.valeur()
1896 << " at face " << num_face << " not supported yet." << finl;
1897 Cerr << "The BC type " << la_cl << " for boundary "<< la_cl->champ_front().le_nom()
1898 << " is not supported yet."<< finl;
1899 Process::exit();
1900 } */
1901 else
1902 {
1903 Cerr << que_suis_je() << "::get_flux_and_Twall(). " ;
1904 Cerr << "The BC type " << la_cl.valeur() << " for boundary "<< bc_name
1905 << " is not supported yet."<< finl;
1906 Process::exit();
1907 }
1908}
1909
1910
1912{
1913 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1914 const IntTab& faces_elem = domaine_vf.face_voisins();
1915 // On of the neighbours doesnot exist so it has "-1". We get the other elem by:
1916 const int elem = faces_elem(num_face, 0) + faces_elem(num_face, 1) +1;
1917 const DoubleTab& temperature = inconnue().valeurs();
1918
1919 double P[3] = {0.,0.,0.}, xyz_face[3] = {0.,0.,0.};
1920 xyz_face[0] = domaine_vf.xv(num_face,0);
1921 xyz_face[1] = domaine_vf.xv(num_face,1);
1922 P[0] = domaine_vf.xp(elem, 0);
1923 P[1] = domaine_vf.xp(elem, 1);
1924 if (Objet_U::dimension == 3)
1925 {
1926 xyz_face[2] = domaine_vf.xv(num_face,2);
1927 P[2] = domaine_vf.xp(elem, 2);
1928 }
1929
1930 double d=0;
1931 for (int i=0; i<3; i++)
1932 d += (xyz_face[i] - P[i])*(xyz_face[i] - P[i]);
1933 d= sqrt(d);
1934 const double flux = get_flux_to_face(num_face);
1935 const double k = fluide_dipha_->fluide_phase(phase_).conductivite().valeurs()(0,0);
1936// Cerr << "flux/d/k" << flux << " " << d << " " << k << finl;
1937 // flux is incoming. So "-flux" is needed.
1938 const double Twall = temperature(elem) - d/k*flux;
1939// Cerr << "We have Twall = "<< Twall << " at face= " << num_face << " elem= " << elem << finl;
1940 return Twall;
1941}
1942
1944{
1945 return TSAT_CONSTANTE;
1946}
Classe Champ_Inc_base.
DoubleTab & futur(int i=1) override
Renvoie les valeurs du champs a l'instant t+i.
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
virtual int nb_valeurs_temporelles() const
Renvoie le nombre de valeurs temporelles actuellement conservees.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ.
Champ_front_base & champ_front()
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
void associer_milieu_base(const Milieu_base &milieu) override
Associe un milieu physique a l'equation, le milieu est en fait caste en Fluide_base.
int preparer_calcul() override
Tout ce qui ne depend pas des autres problemes eventuels.
void completer() override
Complete la construction (initialisation) des objets associes a l'equation.
void get_flux_and_Twall(const int num_face, double &flux, double &Twall) const
void calculer_grad_t()
met a jour le champ grad_t en fonction du champ inconnue.
DoubleTab & derivee_en_temps_inco(DoubleTab &) override
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
LIST(OBS_PTR(Champ_base)) liste_champs_compris_
void mettre_a_jour(double temps) override
La valeur de l'inconnue sur le pas de temps a ete calculee.
OBS_PTR(Fluide_Diphasique) fluide_dipha_
virtual void suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer, int nouvelle_phase)
Methode appelee par Transport_Interfaces_xxx::test_suppression_interfaces_sous_domaine() lorqu'une in...
classe Convection_Diffusion_Temperature Cas particulier de Convection_Diffusion_std
const Champ_Inc_base & inconnue() const override
const Champ_base & get_champ(const Motcle &nom) const override
DoubleTab & derivee_en_temps_inco(DoubleTab &) override
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
classe Dirichlet_paroi_defilante Impose la vitesse de paroi dnas une equation de type Navier_Stokes.
classe Dirichlet_paroi_fixe Represente une paroi immobile dans une equation de type Navier_Stokes.
classe Discretisation_base Cette classe represente un schema de discretisation en espace,...
virtual Nom get_name_of_type_for(const Nom &class_operateur, const Nom &type_operteur, const Equation_base &eqn, const OBS_PTR(Champ_base)&champ_supp=OBS_PTR(Champ_base)()) const
remplit le Nom type en focntion de la classe de operateur, du type de l'operateur et de l'equation
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
int nb_front_Cl() const
Definition Domaine.h:236
const Frontiere_t & frontiere(int i) const
Definition Domaine.h:539
int_t nb_elem() const
Definition Domaine.h:131
class Domaine_Cl_VDF
void completer(const Domaine_dis_base &) override
const Cond_lim & la_cl_de_la_face(int numfa) const override
A partir d'un indice de face de bord dans le Domaine_VF, renvoie la condition aux limites a laquelle ...
void associer(const Domaine_dis_base &) override
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VDF
Definition Domaine_VDF.h:64
double dist_face_elem0(int, int) const override
Fonction de calcul utilisable uniquement en coordonnees cartesiennes de la distance entre le centre d...
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Domaine & domaine() const
Une entree dont la source est une chaine de caracteres.
Definition EChaine.h:31
: class Echange_contact_VDF_FT_Disc
virtual double Ti_wall(int num) const
virtual double flux_exterieur_impose(int i) const
classe Echange_impose_base: Cette condition limite sert uniquement pour l'equation d'energie.
virtual double h_imp(int num) const
Renvoie la valeur du coefficient d'echange de chaleur impose sur la i-eme composante.
virtual double T_ext(int num) const
Renvoie la valeur de la temperature imposee sur la i-eme composante du champ de frontiere.
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.
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual void mettre_a_jour(double temps)
La valeur de l'inconnue sur le pas de temps a ete calculee.
virtual void completer()
Complete la construction (initialisation) des objets associes a l'equation.
virtual int preparer_calcul()
Tout ce qui ne depend pas des autres problemes eventuels.
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
virtual void discretiser()
Discretise l'equation.
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
class Front_VF
Definition Front_VF.h:36
int num_premiere_face() const
Definition Front_VF.h:63
int_t num_premiere_face() const
Definition Frontiere.h:67
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Frontiere.h:49
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
: class Maillage_FT_Disc Cette classe decrit un maillage:
int get_mesh_tag() const
return mesh_state_tag_
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
void associer_eqn(const Equation_base &)
Associe une equation a l'objet.
Definition MorEqn.cpp:28
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
void calculer_delta_u_interface(Champ_base &u0, int phase_pilote, int ordre, const bool future_or_past=false)
Calcul du saut de vitesse a l'interface du au changement de phase.
const DoubleTab & get_interfacial_area() const
virtual const Champ_base & calculer_div_normale_interface()
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
Classe Neumann_paroi_adiabatique Cette condition limite correspond a une paroi adiabatique dans une.
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Nom & suffix(const char *const)
Extraction de suffixe : Nom x("azerty");.
Definition Nom.cpp:271
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur_Div Classe generique de la hierarchie des operateurs calculant la divergence
Operateur_base & l_op_base() override
Renvoie l'objet sous-jacent upcaste en Operateur_base.
void typer() override
Type l'operateur: se type "Op_div_"+discretisation()+.
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initialise le tableau passe en parametre avec la contribution de l'operateur.
Classe Operateur_Grad Classe generique de la hierarchie des operateurs calculant le gradient.
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initialise le tableau passe en parametre avec la contribution de l'operateur.
Operateur_base & l_op_base() override
Renvoie l'objet sous-jacent upcaste en Operateur_base.
void typer() override
Type l'operateur: se type "Op_Grad_"+discretisation()+.
virtual void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &inco)=0
void associer_eqn(const Equation_base &)
Associe une equation a l'operateur.
const Nom & type() const
Renvoie le (nom du) type de l'operateur a creer.
virtual void completer()
Met a jour les references des objets associes a l'operateur.
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_condition(const char *condition, const char *message, const char *name=0)
Declare a post-read logical condition that must hold on the parameter values.
Definition Param.cpp:496
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ OPTIONAL
Definition Param.h:115
@ REQUIRED
Definition Param.h:115
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
classe Parametre_implicite Un objet Parametre_implicite est un objet regroupant les differentes
virtual const Transport_Interfaces_FT_Disc & equation_interfaces(const Motcle &nom) const
virtual const Navier_Stokes_FT_Disc & equation_hydraulique(const Motcle &nom) const
const Triple_Line_Model_FT_Disc & tcl() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
static double mp_max(double)
Definition Process.cpp:376
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe derivee de Sortie empile ce qu'on lui envoie dans une chaine de caracteres.
Definition SChaine.h:26
const char * get_str() const
returns a copy of the string stored by the SChaine
Definition SChaine.cpp:72
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual int nb_valeurs_temporelles() const =0
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
Classe de base des flux de sortie.
Definition Sortie.h:52
int_t nb_elem_tot() const
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
const Champ_Inc_base & inconnue() const override
const Champ_base & get_indicatrice() override
getter champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
virtual const Champ_base & get_normale_interface() const
const Maillage_FT_Disc & maillage_interface() const
virtual const Champ_base & get_distance_interface() const
virtual const int & get_n_iterations_distance() const
void corriger_mpoint(DoubleTab &mpoint) const