TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Triple_Line_Model_FT_Disc.cpp
1/****************************************************************************
2* Copyright (c) 2019, 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 <Triple_Line_Model_FT_Disc.h>
17#include <Param.h>
18#include <Convection_Diffusion_Temperature_FT_Disc.h>
19// passed into the .h for assert in inline method... #include <Transport_Interfaces_FT_Disc.h>
20#include <Fluide_Diphasique.h>
21#include <Fluide_Incompressible.h>
22#include <Navier_Stokes_FT_Disc.h>
23#include <Domaine_VF.h>
24#include <Dirichlet_paroi_fixe.h>
25#include <Dirichlet_paroi_defilante.h>
26#include <LecFicDiffuse.h>
27#include <Domaine_Cl_VDF.h>
28#include <Echange_contact_VDF_FT_Disc.h>
29#include <Probleme_FT_Disc_gen.h>
30
31
32static const double TSAT_CONSTANTE = 0.;
33
34Implemente_instanciable_sans_constructeur( Triple_Line_Model_FT_Disc, "Triple_Line_Model_FT_Disc", Objet_U ) ;
35// XD Triple_Line_Model_FT_Disc objet_u Triple_Line_Model_FT_Disc INHERITS_BRACE Triple Line Model (TCL)
36// XD ref navier_stokes_ft_disc navier_stokes_ft_disc
37// XD ref transport_interfaces_ft_disc transport_interfaces_ft_disc
38// XD ref convection_diffusion_temperature_ft_disc convection_diffusion_temperature_ft_disc
39
40
42 n_ext_meso_(2),
43 tag_tcl_(-1),
44 Qtcl_(0),
45 ls_(0.),
46 theta_app_(0.),
47 x_cl_(0.),
48 xm_(0.),
49 ym_(0.),
50 sm_(0.),
51 ymeso_(0.),
53 kl_cond_(-1.), // Invalid
54 rhocpl_(-1.), // Invalid
61 Rc_inject_(0.),
62 thetaC_tcl_(150.),
63 tempC_tcl_(10.),
64 Ri_(0.),
65 t_injection_(0.),
74 vevap_int_(0.)
75{
76}
77
79{
80 Param p(que_suis_je());
81 // Je peux pas car c'est const... set_param(p);
82 p.print(os);
83 return os;
84}
85
87{
88 Param p(que_suis_je());
89 set_param(p);
90 p.lire_avec_accolades_depuis(is);
91 if (!deactivate_)
92 activated_ = true;
94 {
95 LecFicDiffuse fic;
96 if(!fic.ouvrir(Nom_ficher_tcl_))
97 {
98 Cerr << " File " <<Nom_ficher_tcl_<< " doesn't exist. To generate it, please, check JDD " << finl;
100 }
101
102
103
104
105 Cerr << "Reading of the ascii file : " << Nom_ficher_tcl_ << finl;
106
107 const int nb_colons = nb_columns_tab_; // nb colons in the readed file
108
109 for (int k = 0; k < nb_colons; k++)
110 {
111 Nom name_colon_;
112 fic >> name_colon_;
113 Cerr << "--Name of the " << k + 1 << "-th colon : " << name_colon_
114 << finl;
115 }
116
117
118 double tmp;
119 ArrOfDouble list_val;
120
121 while (fic.get(&tmp, 1))
122 {
123 list_val.append_array(tmp);
124 }
125
126 int nb_lines = list_val.size_array () / nb_colons;
127 tab_Mtcl_.resize (nb_colons, nb_lines);
128
129 for (int i = 0; i < nb_lines; i++)
130 for (int k = 0; k < nb_colons; k++)
131 {
132 tab_Mtcl_ (k, i) = list_val[i * nb_colons + k];
133 }
134 }
135 return is;
136}
137
138// Description: Methode appelee par readOn. Declaration des parametres a lire dans le .data
140{
141 p.ajouter("Qtcl", &Qtcl_); // XD_ADD_P floattant
142 // XD_CONT Heat flux contribution to micro-region [W/m]
143 p.ajouter("ls", &ls_); // XD_ADD_P floattant
144 // XD_CONT Slip length (unused)
145 p.ajouter("theta_app", &theta_app_); // XD_ADD_P floattant
146 // XD_CONT Apparent contact angle (Cox-Voinov)
147
148 p.ajouter("xm", &xm_); // XD_ADD_P floattant
149 // XD_CONT Wall distance [x] of the point M delimiting micro/meso transition [m]
150 p.ajouter("ym", &ym_); // XD_ADD_P floattant
151 // XD_CONT Wall distance [y] of the point M delimiting micro/meso transition [m]
152 p.ajouter("sm", &sm_,Param::REQUIRED); // XD_ADD_P floattant
153 // XD_CONT Curvilinear abscissa of the point M delimiting micro/meso transition [m]
154
155 p.ajouter("hydraulic_equation|equation_navier_stokes", &nom_eq_hydr_,Param::REQUIRED); // XD_ADD_P chaine
156 // XD_CONT Hydraulic equation name
157 p.ajouter("thermal_equation|equation_temperature", &nom_eq_therm_,Param::REQUIRED); // XD_ADD_P chaine
158 // XD_CONT Thermal equation name
159 p.ajouter("interface_equation|equation_interface", &nom_eq_interf_,Param::REQUIRED); // XD_ADD_P chaine
160 // XD_CONT Interface equation name
161
162 p.ajouter("ymeso", &ymeso_); // XD_ADD_P floattant
163 // XD_CONT Meso region extension in wall-normal direction [m]
164 p.ajouter("n_extend_meso", &n_ext_meso_); // XD_ADD_P entier
165 // XD_CONT Meso region extension in number of cells [-]
166 p.ajouter("initial_CL_xcoord", &initial_CL_xcoord_); // XD_ADD_P floattant
167 // XD_CONT Initial interface position (unused)
168 p.ajouter("read_via_file", &read_via_file_); // XD_ADD_P entier
169 // XD_CONT not_set
170 p.ajouter("Rc_tcl_GridN", &Rc_tcl_GridN_); // XD_ADD_P floattant
171 // XD_CONT Radius of nucleate site; [in number of grids]
172 p.ajouter("Rc_inject", &Rc_inject_); // XD_ADD_P floattant
173 // XD_CONT Radius of bubble reinjected; [in m]
174 p.ajouter("thetaC_tcl", &thetaC_tcl_); // XD_ADD_P floattant
175 // XD_CONT imposed contact angle [in degree] to force bubble pinching / necking once TCL entre nucleate site
176 p.ajouter_flag("reinjection_tcl", &reinjection_tcl_); // XD_ADD_P flag
177 // XD_CONT This flag activates the automatic injection of a new nucleate seed with a specified shape when the
178 // XD_CONT temperature in the nucleation site becomes higher than a certain threshold (tempC_tcl). The shape of the
179 // XD_CONT seed is determined by the radius Rc_tcl_GridN and the contact angle thetaC_tcl. The nucleation site is
180 // XD_CONT considered free when there are no bubbles present. The site size is defined by Rc_tcl_GridN. This
181 // XD_CONT temperature threshold, termed tempC_tcl, is the activation temperature. Setting this temperature implies a
182 // XD_CONT wall temperature, therefore, activating reinjection_tcl is ONLY possible for a simulation coupled with
183 // XD_CONT solid conduction. NL2 When reinjection_tcl is activated, the values of tempC_tcl (default 10K),
184 // XD_CONT Rc_tcl_GridN (default 4 grid sizes), and thetaC_tcl (default 150 degrees) should be provided. Unless
185 // XD_CONT (STRONGLY not recommended), the default values (indicated in parentheses) will be used. NL2 If
186 // XD_CONT reinjection_tcl is not activated (by default), the mechanism of Numerically forcing bubble pinching/necking
187 // XD_CONT will be used for multi-cycle simulation. Once the Triple Contact Line (TCL) enters the nucleation site, a
188 // XD_CONT big contact angle thetaC_tcl is imposed to initiate bubble pinching/necking. After the bubble pinching
189 // XD_CONT ends, the large bubble above will depart, leaving the remaining part to serve as the nucleate seed. This
190 // XD_CONT process is equivalent to immediately inserting a new seed with a prescribed shape (determined by the
191 // XD_CONT nucleation site size and contact angle) once a bubble departs. Site size is defined by Rc_tcl_GridN
192 // XD_CONT (default 4 grid sizes). Contact angle thetaC_tcl (default 150 degrees). Useful for a standalone (not
193 // XD_CONT coupling with solid conduction) simulation.
194 p.ajouter_flag("distri_first_facette", &distri_first_facette_); // XD_ADD_P flag
195 // XD_CONT This flag determines whether to distribute the Qtcl into all grids occupied by the first facette according
196 // XD_CONT to their area proportions. When set, the flux is redistributed into all grids occupied by the first facette
197 // XD_CONT based on their area proportions. Default value is 0, the flux is distributed differently: similar to the
198 // XD_CONT Meso zone, it is only distributed to grids within the Micro-zone (where the height of the front y is
199 // XD_CONT smaller than the size of Micro ym). The distribution of this flux is logarithmically proportional to y
200 // XD_CONT between 5.6nm (here interpreted as the value 0 in logarithm) and ym. In practice, in most cases, it will
201 // XD_CONT distribute all the flux locally in the first grid.
202 p.ajouter_flag("adjust_meso_ML", &adjust_meso_ML_); // XD_ADD_P flag
203 // XD_CONT This flag determines whether to correct of qmeso in Micro-layer
204 p.ajouter_flag("lissage_tcl", &lissage_tcl_); // XD_ADD_P flag
205 // XD_CONT This flag determines whether to active lissage of Qmicro and theta_app
206 p.ajouter("t_injection", &t_injection_);
207 p.ajouter("Ri_thermal", &Ri_); // XD_ADD_P floattant
208 // XD_CONT not_set
209 p.ajouter("tempC_tcl", &tempC_tcl_); // XD_ADD_P double
210 // XD_CONT temperature threshold
211 p.ajouter("file_name", &Nom_ficher_tcl_); // XD_ADD_P chaine
212 // XD_CONT Input file to set TCL model
213 p.ajouter("nb_columns", &nb_columns_tab_);
214 p.ajouter("num_column_tem", &num_column_tem_);
215 p.ajouter("num_column_app", &num_column_theta_);
216 p.ajouter("num_column_qtcl", &num_column_qtcl_);
217 p.ajouter_flag("enable_energy_correction", &TCL_energy_correction_);
218 p.ajouter_flag("capillary_effect_on_theta", &capillary_effect_on_theta_activated_);
219 p.ajouter_flag("deactivate", &deactivate_); // XD_ADD_P flag
220 // XD_CONT Simple way to disable completely the TCL model contribution
221 p.ajouter("inout_method", &inout_method_); // XD_ADD_P chaine(into=["exact","approx","both"])
222 // XD_CONT Type of method for in out calc. By defautl, exact method is used
223 p.dictionnaire("exact", EXACT);
224 p.dictionnaire("approx", APPROX);
225 p.dictionnaire("both", BOTH); // Makes both and compare them
226}
227
229{
230 pb_base_ = pb;
231}
232
234{
235 const auto& list_eqs = ref_cast(Probleme_FT_Disc_gen, pb_base_.valeur()).get_list_equations();
236
237 for (const auto &itr : list_eqs)
238 {
239 if (itr->le_nom() == nom_eq_hydr_)
240 ref_ns_ = ref_cast(Navier_Stokes_FT_Disc, itr.valeur());
241
242 if (itr->le_nom() == nom_eq_therm_)
243 ref_eq_temp_ = ref_cast(Convection_Diffusion_Temperature_FT_Disc, itr.valeur());
244
245 if (itr->le_nom() == nom_eq_interf_)
246 ref_eq_interf_ = ref_cast(Transport_Interfaces_FT_Disc, itr.valeur());
247 }
248
249 assert(ref_ns_ && ref_eq_temp_ && ref_eq_interf_);
250
251 const Transport_Interfaces_FT_Disc& transport = ref_eq_interf_.valeur();
252 const Maillage_FT_Disc& maillage = transport.maillage_interface();
253 tag_tcl_ = maillage.get_mesh_tag();
254
255 // Issue: we don't know which phase is for the temperature at the initialize step.
256 // It is required to store kl_cond_
257 // So we do it in the completer.
258
259 // how to access fluid diphasique? Through (eq_ns or pb)? We have ns.
260 // const Milieu_base& milieu = ref_eq_temp_->milieu();
261 // const Fluide_Diphasique& fluid_dipha = ref_cast(Fluide_Diphasique, milieu); -> no it's not a Fluide_diphasique
262 // Or maybe we can give access to fluide_dipha_ from Convection_Diffusion_Temperature_FT_Disc.
263 //
264 // int phase = ref_eq_temp_->get_phase();
265 // L_vap_ = fluide_dipha->chaleur_latente();
266
267 // We may compute the true position here for old_xcl_
268 // All of (integration_time_, instant_m_evap_, instant_vmicro_evap_, instant_vmeso_evap_,
269 // integrated_m_evap_, integrated_vmicro_evap_, integrated_vmeso_evap_)
270 // are set to zero by construction. For restart, something more tricky should be done.
271
272 // Information on the TCL region :
273 // Resize the tables :
274 elems_.resize_array(0);
275 boundary_faces_.resize_array(0);
276 mp_.resize_array(0);
277 Q_.resize_array(0);
278}
279
281{
282 int num_bc_face=-1;
283 const Transport_Interfaces_FT_Disc& transport = ref_eq_interf_.valeur();
284 const Maillage_FT_Disc& maillage = transport.maillage_interface();
285 for (int s = 0; s < maillage.nb_sommets(); s++)
286 {
287 if (maillage.sommet_ligne_contact(s) and (not(maillage.sommet_virtuel(s))))
288 {
289 num_bc_face = maillage.sommet_face_bord(s);
290 break;
291 }
292 }
293 return num_bc_face;
294}
295
297{
298 // Via the temperature transport equation, we directly get access to a Fluide_Incompressible:
299 const Milieu_base& milieu = ref_eq_temp_->milieu();
300 kl_cond_ = milieu.conductivite().valeurs()(0,0);
301 rhocpl_ = milieu.masse_volumique().valeurs()(0,0) * milieu.capacite_calorifique().valeurs()(0,0);
302
303 if ((n_ext_meso_ != 1)and(ymeso_>DMINFLOAT))
304 {
305 Cerr << "Check your datafile. n_extend_meso and ymeso should not but used simultaneously." << finl;
306 Cerr << "n_extend_meso = " << n_ext_meso_<< finl;
307 Cerr << "ymeso = " << ymeso_ <<finl;
309 }
310 if (n_ext_meso_ <2 )
311 {
312 Cerr << "n_extend_meso = " << n_ext_meso_<< finl;
313 Cerr << "Check your datafile. n_extend_meso should be >= 2" << finl;
315 }
316
317 if (ymeso_==0.)
318 {
319 // ymeso has not been initialised. n_ext_meso is used instead:
320 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
321 const Domaine_Cl_dis_base& zcldis = ns.domaine_Cl_dis();
322 // get wall BC frontiere nb
323 int num_bord = -1;
324 for (int i=0; i<zcldis.nb_cond_lim(); i++)
325 {
326 const Cond_lim& la_cl = zcldis.les_conditions_limites(i);
327 // For each BC, we check its type to see if it's a wall:
328 // BC for hydraulic equation
329 bool is_wall = sub_type(Dirichlet_paroi_fixe,la_cl.valeur())
330 || sub_type(Dirichlet_paroi_defilante,la_cl.valeur());
331 if (is_wall)
332 {
333 num_bord = i;
334 break;
335 }
336 }
337 if (num_bord<0)
338 Process::exit( "[TCL: ymeso]: !!! NO WALL-TYPE BOUNDARY WAS FOUND IN THE DOMAINE, PLESEASE CHECK JDD" );
339
340 const Frontiere& fr=zcldis.les_conditions_limites(num_bord)->frontiere_dis().frontiere();
341 const int nb_face = fr.nb_faces();
342 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, ns.domaine_dis());
343 // get TCL cells
344 if (nb_face>0)
345 {
346 const int num_face= fr.num_premiere_face();;
347 int elem_voisin = zvdf.face_voisins(num_face, 0) + zvdf.face_voisins(num_face, 1) +1;
348 const double cell_height = 2.*std::fabs(zvdf.dist_face_elem0(num_face,elem_voisin));
349 ymeso_ = cell_height * n_ext_meso_;
350 }
352 Cerr << "[TCL] ymeso is set to " << ymeso_ << " according to provided n_ext_meso_ " << n_ext_meso_ << finl;
353 }
354
355 ymeso_ = std::fmax(ymeso_,DMINFLOAT);
356
357
358 if ((read_via_file_) and (theta_app_>DMINFLOAT))
359 {
360 Cerr << "Check your datafile. read_via_file and theta_app should not but set simultaneously." << finl;
361 Cerr << "read_via_file = " << read_via_file_<< finl;
362 Cerr << "theta_app = " << theta_app_ <<finl;
364 }
365
366 if ( !est_egal(Rc_tcl_GridN_, 0) and (Rc_inject_>DMINFLOAT) )
367 {
368 Cerr << "Check your datafile. Rc_tcl_GridN and Rc_inject should not but used simultaneously." << finl;
369 Cerr << "Rc_tcl_GridN = " << Rc_tcl_GridN_ << finl;
370 Cerr << "Rc_inject = " << Rc_inject_ <<finl;
372 }
373
374 if ( est_egal(Rc_inject_, 0.) and reinjection_tcl() )
375 {
376 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
377 const Domaine_Cl_dis_base& zcldis = ns.domaine_Cl_dis();
378 // get wall BC frontiere nb
379 int num_bord = -1;
380 for (int i=0; i<zcldis.nb_cond_lim(); i++)
381 {
382 const Cond_lim& la_cl = zcldis.les_conditions_limites(i);
383 // For each BC, we check its type to see if it's a wall:
384 // BC for hydraulic equation
385 bool is_wall = sub_type(Dirichlet_paroi_fixe,la_cl.valeur())
386 || sub_type(Dirichlet_paroi_defilante,la_cl.valeur());
387 if (is_wall)
388 {
389 num_bord = i;
390 break;
391 }
392 }
393 if (num_bord<0)
394 Process::exit( "[TCL: Re-injection]: !!! NO WALL-TYPE BOUNDARY WAS FOUND IN THE DOMAINE, PLESEASE CHECK JDD" );
395
396 const Frontiere& fr=zcldis.les_conditions_limites(num_bord)->frontiere_dis().frontiere();
397 const int nb_face = fr.nb_faces();
398 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, ns.domaine_dis());
399 // supposing deltax = deltay in the first thermal layer
400 if (nb_face>0)
401 {
402 const int num_face= fr.num_premiere_face();;
403 int elem_voisin = zvdf.face_voisins(num_face, 0) + zvdf.face_voisins(num_face, 1) +1;
404 const double cell_height = 2.*std::fabs(zvdf.dist_face_elem0(num_face,elem_voisin));
405 Rc_inject_ = cell_height * Rc_tcl_GridN_;
406 }
408 Cerr << "[TCL] Rc_inject_ is set to " << Rc_inject_ << " according to provided Rc_tcl_GridN_ " << Rc_tcl_GridN_ << finl;
409 }
410 // Rc_tcl_GridN_ -= Objet_U::precision_geom;
411 Rc_inject_ = std::fmax(Rc_inject_,DMINFLOAT);
412
413 //assert(tag_tcl_ == ref_eq_interf_->maillage_interface().get_mesh_tag());
414 const Transport_Interfaces_FT_Disc& transport = ref_eq_interf_.valeur();
415 const Maillage_FT_Disc& maillage = transport.maillage_interface();
416 assert(tag_tcl_ == maillage.get_mesh_tag());
417 if (maillage.temps()<0.)
418 {
419
420 }
421
423 {
424 if (xm_ <= 0.)
425 Process::exit( "[TCL: capillary_activated]: !!! xm should be STRICTLY POSITIVE, PLESEASE CHECK JDD" );
426 if (ls_ <= 0.)
427 Process::exit( "[TCL: capillary_activated]: !!! ls should be STRICTLY POSITIVE, PLESEASE CHECK JDD" );
428 }
429
430 // how to access fluid diphasique? Through (eq_ns or pb)? We have neither so far.
431 // const Fluide_Diphasique& fluid_dipha = ref_cast(Fluide_Diphasique, milieu); -> no it's not a Fluide_diphasique
432 // Or maybe we can give access to fluide_dipha_ from Convection_Diffusion_Temperature_FT_Disc.
433 //
434 // int phase = ref_eq_temp_->get_phase();
435 // L_vap_ = fluide_dipha->chaleur_latente();
436
437 // We may compute the true position here for old_xcl_
438 // All of (integration_time_, instant_m_evap_, instant_vmicro_evap_, instant_vmeso_evap_,
439 // integrated_m_evap_, integrated_vmicro_evap_, integrated_vmeso_evap_)
440 // are set to zero by construction. For restart, something more tricky should be done.
441}
442
444{
445
446
447 return 0.;
448}
449
450// Description : For a given elem in the domaine, computes the crossing points of the interface and the averaged normal.
451// The method is not const because it changes the value of old_xcl_.
452// I believe there is a convention that y_in <= y_out
453// Parameters :
454// elem -> the id of the cell of interest in the domaine
455// norm_elem : the averaged normal into the element.
456// surface_tot : The local interfacial area [m2].
457// in_out : Real coordinates of the interface intersection with the cell
458//
459// in_out(0,0) -> x_in
460// in_out(0,1) -> y_in
461// in_out(1,0) -> x_out
462// in_out(1,1) -> y_out
464 const double dt,
465 DoubleTab& in_out, FTd_vecteur3& norm_elem, double& surface_tot)
466{
467 const int dim = Objet_U::dimension;
468 const Transport_Interfaces_FT_Disc& transport = ref_eq_interf_.valeur();
469 const Maillage_FT_Disc& maillage = transport.maillage_interface();
470 const IntTab& facettes = maillage.facettes();
471 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
472 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
473 const DoubleTab& sommets = maillage.sommets();
474
475 in_out.resize(2, dim); // The first param '2' is for in and out
476 if (dim != 2)
477 {
478 Cerr << que_suis_je() << "::get_in_out_coords() only coded in 2 dimensions" << finl;
480 }
481
482 // We get the barycenter of the boundary face:
483 // const double xG = zvdf.xv(num_face, 0);
484 // const double yG = zvdf.xv(num_face, 1);
485 // double zG = 0.;
486 // if (dim3)
487 // zG = zvdf.xv(num_face, 2);
488
489 //...VP-modifications for calculating the intersections.....
490 // We get the barycenter of the center of the elem:
491 // const double fraction = data.fraction_surface_intersection_;
492 const double xP = zvdf.xp(elem, 0);
493 const double yP = zvdf.xp(elem, 1);
494 //Cerr << "Barycentre coordinates are " << " xP = " << xP << "and yP =" << yP << finl;
495
496 // We get the width of the elem:
497 const double delta_x = zvdf.dim_elem(elem, 0);
498 const double delta_y = zvdf.dim_elem(elem, 1);
499
500 //x coordinates of the barycenter of the right and left faces:
501 double rface_dis = xP + delta_x/2;
502 double lface_dis = xP - delta_x/2;
503 //y coordinates of the barycenter of the top and bottom faces:
504 double tface_dis = yP + delta_y/2;
505 double bface_dis = yP - delta_y/2;
506 DoubleTab coo_faces(2,dim);
507 coo_faces(0,0) = lface_dis;
508 coo_faces(1,0) = rface_dis;
509 coo_faces(0,1) = bface_dis;
510 coo_faces(1,1) = tface_dis;
511
512 FTd_vecteur3 bary_facettes_dans_elem = {0., 0., 0.} ;
513 // Boucle sur les facettes qui traversent l'element elem :
514 double yl = 0.;
515 double yr = 0.;
516 double xl = 0.;
517 double xr = 0.;
518 // We anticipate for more than 2 intersections because with tolerances, when the FT sommet is
519 // close to the element face, 2 intersections will be found instead of one.
520 double xint[4] = {}; // X coords of the intersections.
521 double yint[4] = {}; // Y coords of the intersections.
522 int nint = 0;
523 const double eps = Objet_U::precision_geom;
524 int index=intersections.index_elem()[elem];
525 while (index >= 0)
526 {
527 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
528 const int fa7 = data.numero_facette_;
529 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
530 const double surface_facette = surface_facettes[fa7];
531 const double surf = data.fraction_surface_intersection_ * surface_facette;
532 surface_tot +=surf;
533 FTd_vecteur3 coord_barycentre_fraction = {0., 0., 0.};
534 FTd_vecteur3 coord_sommet = {0., 0., 0.};
535 for (int dir = 0; dir< Objet_U::dimension; dir++)
536 {
537 const double nx = normale_facettes(fa7,dir);
538 norm_elem[dir] += nx * surf;
539 }
540 int inner_nodes = 0;
541
542 for (int isom = 0; isom< Objet_U::dimension; isom++)
543 {
544 const int num_som = facettes(fa7, isom); // numero du sommet dans le tableau sommets
545 // Cerr << " node-number #" << num_som << "face-number #" << fa7 << finl;
546
547 const double bary_som = data.barycentre_[isom];
548 for (int dir = 0; dir < Objet_U::dimension; dir++)
549 {
550 //modifications
551 coord_sommet[dir] = sommets(num_som,dir);
552 coord_barycentre_fraction[dir] += bary_som * sommets(num_som,dir) * surf;
553 // coord_barycentre_fraction[dir] += bary_som * sommets(num_som,dir);
554 }
555
556 // Cerr << "coordinate x = " << coord_sommet[0] << " coordinate y = " << coord_sommet[1] << finl;
557 // if(coord_sommet[0] < rface_dis && coord_sommet[0] > lface_dis &&
558 // coord_sommet[1] < tface_dis && coord_sommet[1] >= bface_dis)
559 if(coord_sommet[0] - rface_dis< eps && coord_sommet[0] - lface_dis > -eps &&
560 coord_sommet[1]-tface_dis < eps && coord_sommet[1] - bface_dis > -eps)
561 {
562 // Cerr << " This node lies inside the element #" << elem << finl;
563 inner_nodes += 1;
564 }
565 }
566 // Cerr << " nb of inner nodes = " << inner_nodes << " in elem " << elem
567 // << " when runnning fa7= " << fa7 << finl;
568 // Cerr << " inside " << inside[0] << " "<< inside[1] << " "<< inside[2] << " "<< finl;
569
570 if (inner_nodes >= 2)
571 {
572 // Cerr << " This facette lies totally inside the element #" << elem << finl;
573 // Still we check if one intersection is close to the border :
574 for (int isom = 0; isom< Objet_U::dimension; isom++)
575 {
576 const int node_number = facettes(fa7, isom); // numero du sommet dans le tableau sommets
577 // Cerr << " node-number #" << node_number << "face-number #" << fa7 << finl;
578 for (int dir = 0; dir < Objet_U::dimension; dir++)
579 {
580 coord_sommet[dir] = sommets(node_number,dir);
581 }
582 if((std::abs(coord_sommet[0]-lface_dis) <= eps)
583 ||(std::abs(coord_sommet[0]-rface_dis) <= eps)
584 ||(std::abs(coord_sommet[1]-bface_dis) <= eps)
585 ||(std::abs(coord_sommet[1]-tface_dis) <= eps))
586 {
587 xint[nint] = coord_sommet[0];
588 yint[nint] = coord_sommet[1];
589 nint += 1;
590 Cerr<< "Intersection found at node " << node_number << " belonging to " <<fa7 << finl;
591 }
592 }
593 // Cerr<< "nint = "<< nint << finl;
594 }
595 else if((inner_nodes == 1)||(inner_nodes == 0))
596 {
597 // TODO : If this method works also when there are 2 intersections, we
598 // could remove the for loop before and the if (....) ... else if ... and just keep below:
599 // Cerr << " find the intersection points of the facettes and elem-faces "<< finl;
600 // One point in, one point out, search 1 intersect
601 // OR Two points out, search 2 intersect
602 const int s0 = facettes(fa7, 0);
603 const int s1 = facettes(fa7, 1);
604 const double x0 = sommets(s0,0);
605 const double x1 = sommets(s1,0);
606 const double y0 = sommets(s0,1);
607 const double y1 = sommets(s1,1);
608 for (int jj=0; jj< 2; jj++)
609 {
610 const double xF = coo_faces(jj,0);
611 if ((x0-xF)*(x1-xF)<eps*(std::fabs(x0-x1)+eps))
612 {
613 // points s0 and s1 lies on both sides of face jj.
614 double tmp_yint = 0.;
615 if (std::fabs(x0-x1)< eps)
616 {
617 tmp_yint = y0;
618 Cerr << "Almost // to the face, which intersect?" <<finl;
619 Cerr << "Should we count two extrems as intersect" << finl;
620 xint[nint] = xF;
621 yint[nint] = std::max(bface_dis,std::min(tface_dis, y0));
622 nint += 1;
623 xint[nint] = xF;
624 yint[nint] = std::max(bface_dis,std::min(tface_dis, y1));
625 nint += 1;
627 }
628 else
629 tmp_yint = y0-(x0-xF)*(y0-y1)/(x0-x1);
630 // Is the intersection inside the cell:
631 if ((bface_dis-tmp_yint)*(tface_dis-tmp_yint)<eps*delta_y)
632 {
633 // lface or rface is cut:
634 xint[nint] = xF;
635 yint[nint] = tmp_yint;
636 nint += 1;
637 }
638 }
639 const double yF = coo_faces(jj,1);
640 if ((y0-yF)*(y1-yF)<eps*(std::fabs(y0-y1)+eps))
641 {
642 // points s0 and s1 lies on both sides of face jj.
643 double tmp_xint = 0.;
644 if (std::fabs(y0-y1)< eps)
645 {
646 tmp_xint = x0;
647 Cerr << "Almost // to the face, which intersect?" <<finl;
648 Cerr << "Should we count two extrems as intersect" << finl;
649 yint[nint] = yF;
650 xint[nint] = std::max(lface_dis,std::min(rface_dis, x0));
651 nint += 1;
652 yint[nint] = yF;
653 xint[nint] = std::max(lface_dis,std::min(rface_dis, x1));
654 nint += 1;
655 Cerr << "Code to be validated" << finl;
657 }
658 else
659 tmp_xint = x0-(y0-yF)*(x0-x1)/(y0-y1);
660 // Is the intersection inside the cell:
661 if ((lface_dis-tmp_xint)*(rface_dis-tmp_xint)<eps*delta_x)
662 {
663 // bface or tface is cut:
664 yint[nint] = yF;
665 xint[nint] = tmp_xint;
666 nint += 1;
667 }
668 }
669 }
670 }
671 else
672 {
673 Cerr << "WTF inner_nodes : " << inner_nodes << finl;
675 }
676
677 for (int dir = 0; dir < Objet_U::dimension; dir++)
678 bary_facettes_dans_elem[dir] += coord_barycentre_fraction[dir];
679 index = data.index_facette_suivante_;
680 }
681
682 // removing two closing point
683 if (nint > 2)
684 {
685 for (int i=0; i < nint; i++)
686 {
687 for (int j=0; j < nint; j++)
688 {
689 if (i < j)
690 {
691 const double dist = sqrt(pow((xint[i]-xint[j]), 2) + pow((yint[i]-yint[j]), 2));
692 if (dist < Objet_U::precision_geom)
693 {
694 if (j!=nint-1)
695 {
696
697 xint[j] = xint[nint-1];
698 yint[j] = yint[nint-1];
699 nint--;
700 j--;
701 }
702 else
703 {
704 nint--;
705
706
707 }
708 }
709 }
710
711 }
712 }
713 }
714 // We should have found 2 intersections in the end:
715 if (nint != 2)
716 {
717 if (nint > 2)
718 {
719 Cerr << "Too many intersections " << nint << " -> trying to suppress duplicates" << finl;
720 Cerr << "Too many points, maybe a FT sommet was close to a border and is counted twice" << finl;
721 Cerr << "Intersections are: " << finl;
722 for (int i=0; i<nint; i++)
723 Cerr << xint[i] << " " << yint[i] << finl;
724 Cerr << "In cell: " << elem << " at : " << finl;
725 Cerr << "x in : " << lface_dis << " " << lface_dis << finl;
726 Cerr << "y in : " << bface_dis << " " << tface_dis << finl;
727 for (int i=0; i<nint-1; i++)
728 {
729 for (int i2=0; i2<nint; i2++)
730 {
731 double dist = std::sqrt(pow(xint[i]-xint[i2],2) +pow(yint[i]-yint[i2],2));
732 if (dist < Objet_U::precision_geom)
733 {
734 // Ce sont les memes points :
735 if (i2!= nint)
736 {
737 // Ce n'est pas le dernier point. On met le dernier point a la place de i2 puis on refait i2:
738 xint[i2] = xint[nint-1];
739 yint[i2] = yint[nint-1];
740 }
741 // On supprime donc le dernier:
742 nint--;
743 }
744 }
745 }
746 }
747 if (nint > 2)
748 {
749 Cerr << "Wrong number of intersections " << nint << finl;
750 Cerr << "STILL Too many points, maybe a FT sommet was close to a border and is counted twice" << finl;
751 Cerr << "Intersections are: " << finl;
752 for (int i=0; i<nint; i++)
753 Cerr << xint[i] << " " << yint[i] << finl;
754 Cerr << "In cell: " << elem << "at : " << finl;
755 Cerr << "x in : " << lface_dis << " " << lface_dis << finl;
756 Cerr << "y in : " << bface_dis << " " << tface_dis << finl;
757 // TODO : le tri n'a pas fonctionne? trier, supprimer le/les doublons et decrementer le nint.
759 }
760 }
761
762 if (surface_tot > 0.)
763 {
764 for (int dir = 0; dir< Objet_U::dimension; dir++)
765 norm_elem[dir] *= 1./surface_tot;
766 }
767// Cerr<< "nint = "<< nint << finl;
768// Cerr << " xint[0] = " << xint[0] << " xint[1] = " << xint[1] << finl;
769 if(xint[1] > xint[0])
770 {
771 xr = xint[1];
772 xl = xint[0];
773 yr = yint[1];
774 yl = yint[0];
775 }
776 else
777 {
778 xr = xint[0];
779 xl = xint[1];
780 yr = yint[0];
781 yl = yint[1];
782 }
783// Cerr << "Elem #" << elem << " yr = " << yr << " xr = " << xr
784// << " yl = " << yl << " xl = " << xl <<finl;
785// Fill in the table :
786 in_out(0,0) = xl;
787 in_out(0,1) = yl;
788 in_out(1,0) = xr;
789 in_out(1,1) = yr;
790}
791
792// const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, ref_eq_temp_->domaine_dis());
793// const IntTab& faces_elem = domaine_vf.face_voisins();
794// // One of the neighbours doesnot exist so it has "-1". We get the other elem by:
795// const int elem = faces_elem(num_face, 0) + faces_elem(num_face, 1) +1;
796// const double d = compute_distance(ref_cast(Domaine_VF, ref_eq_temp_->domaine_dis()),
797// num_face, elem);
798//
799// Computes the distance between a face centre and an element centre.
800double compute_distance(const Domaine_VF& domaine_vf, const int num_face, const int elem)
801{
802 double d=0;
803 double P[3] = {0.,0.,0.}, xyz_face[3] = {0.,0.,0.};
804 xyz_face[0] = domaine_vf.xv(num_face,0);
805 xyz_face[1] = domaine_vf.xv(num_face,1);
806 P[0] = domaine_vf.xp(elem, 0);
807 P[1] = domaine_vf.xp(elem, 1);
808 if (Objet_U::dimension == 3)
809 {
810 xyz_face[2] = domaine_vf.xv(num_face,2);
811 P[2] = domaine_vf.xp(elem, 2);
812 }
813
814 for (int i=0; i<3; i++)
815 d += (xyz_face[i] - P[i])*(xyz_face[i] - P[i]);
816 d= sqrt(d);
817 return d;
818}
819
820// Q_int = Q_meso*circum_dis is W
821double Triple_Line_Model_FT_Disc::compute_Qint(const DoubleTab& in_out, const double theta_app_loc,
822 const int num_wall_face, double& Q_meso) const
823{
824 const double yl = in_out(0,1);
825 const double yr = in_out(1,1);
826
827 const double ytop = std::fmax(yr,yl);
828 const double ybot = std::fmin(yr,yl);
829
830 // Meso region is between ym_ and ymeso_:
831
832 double ln_y = log(std::fmin(ymeso_,std::fmax(ytop,ym_))/std::fmin(ymeso_,std::fmax(ybot,ym_)));
833
834 double circum_dis = 1.;
836 {
837 const double xl = in_out(0,0);
838 const double xr = in_out(1,0);
839
840
841 double radial_dis = (xl + xr)/2;
842
843 if ((ym_ > ybot) && (ym_ < ytop))
844 {
845
846 const double cotan = (fabs(theta_app_loc)>DMINFLOAT) ? 1./tan(theta_app_loc) : DMAXFLOAT;
847
848 const double xm = xl + (ym_-yl)*cotan;
849 if ((xm > xr) || (xm < xl))
850 {
851 Cerr << "(xl, xm, xr) = (" << xl << " "<< xm << " "<< xr << " )" << finl;
852 Process::exit("Point M should be between l and r radially!");
853 }
854 radial_dis = (xr + xm)/2;
855 }
856
857 const double angle_bidim_axi = Maillage_FT_Disc::angle_bidim_axi();
858 circum_dis = angle_bidim_axi*radial_dis;
859 // Cerr << "[TCL: MESO:] FILLING LIST Qmeso [bidim_axi] circum_dis = " << circum_dis << finl;
860 }
861
862 double Twall = 0.;
863 double flux = 0.;
864 ref_eq_temp_->get_flux_and_Twall(num_wall_face, flux, Twall);
865
866
867
868 assert(kl_cond_>0.);
869// Cerr << "ln_y = " << ln_y << " time_total = " << temps << " Theta_app_local = " << theta_app_loc
870// <<" delT = "<< Twall << " kl = "<< kl_cond_ << finl;
871 if (adjust_meso_ML())
872 {
873 if (thetaC_tcl() >= 90.)
874 Process::exit(Nom("Triple_Line_Model_FT_Disc::compute_Qint, BAD critial angle to find Micro Layer ") + Nom(thetaC_tcl()) + " ! Pls set thetaC_tcl in you dataset" );
875 if ((theta_app_loc/M_PI*180. < thetaC_tcl()) || (theta_app_loc/M_PI*180. > 90.))
876 {
877 Cerr << "[TCL: MESO:] Micro-Layer detected with slope " << theta_app_loc/M_PI*180. << " distance to wall "<< (yl+yr)/2. <<finl;
878 const double dx =in_out(1,0)-in_out(0,0);
879 const double dy =ytop-ybot;
880 const double s_meso = sqrt(dx*dx+dy*dy);
881 const double h_loc = (yl+yr)/2.;
882 Q_meso = kl_cond_*Twall/( h_loc+ Ri()*kl_cond_)*s_meso;
883 }
884 else
885 {
886 const double un_sur_theta_app_loc = (fabs(theta_app_loc)>DMINFLOAT) ? 1./theta_app_loc : DMAXFLOAT;
887 Q_meso = kl_cond_*(Twall*un_sur_theta_app_loc)*ln_y; // Twall here is (Wall temperature - saturation temperature)..unit of Q_meso is W/m
888 }
889 }
890 else
891 {
892 const double un_sur_theta_app_loc = (fabs(theta_app_loc)>DMINFLOAT) ? 1./theta_app_loc : DMAXFLOAT;
893 Q_meso = kl_cond_*(Twall*un_sur_theta_app_loc)*ln_y; // Twall here is (Wall temperature - saturation temperature)..unit of Q_meso is W/m
894 }
895
896 double Q_int = Q_meso*circum_dis; // unit of Q_int is W
897// Cerr << "Q_meso = " << Q_meso << finl;
898 return Q_int;
899}
900
901// in_out are real absolute coordinates
903 const int elem, const int num_face,
904 DoubleTab& in_out, FTd_vecteur3& normale, double& surface_tot) const
905{
906 const int dim = Objet_U::dimension;
907 if (Objet_U::dimension == 3)
908 {
909 Cerr << "not coded yet " <<finl;
911 }
912 in_out.resize(2,dim);
913 const Maillage_FT_Disc& maillage = ref_eq_interf_->maillage_interface();
914 const IntTab& facettes = maillage.facettes();
915 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
916 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
917 const DoubleTab& sommets = maillage.sommets();
918
919 // Boucle sur les facettes qui traversent l'element elem :
920 // Moyenne ponderee des normales aux facettes qui traversent l'element
921 //normale = {0., 0., 0.};
922 normale[0] = 0.;
923 normale[1] = 0.;
924 normale[2] = 0.;
925 // Centre de gravite de l'intersection facettes/element
926 double centre[3] = {0., 0., 0.};
927 // Somme des poids
928 surface_tot =0.;
929 int index=intersections.index_elem()[elem];
930 while (index >= 0)
931 {
932 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
933 const int fa7 = data.numero_facette_;
934 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
935 const double surface_facette = surface_facettes[fa7];
936 const double surf = data.fraction_surface_intersection_ * surface_facette;
937 surface_tot +=surf;
938 for (int i = 0; i< dim; i++)
939 {
940 normale[i] += surf * normale_facettes(fa7, i);
941 // Calcul du centre de gravite de l'intersection facette/element
942 double g_i = 0.; // Composante i de la coordonnee du centre de gravite
943 for (int j = 0; j < dim; j++)
944 {
945 const int som = facettes(fa7, j);
946 const double coord = sommets(som, i);
947 const double coeff = data.barycentre_[j];
948 g_i += coord * coeff;
949 }
950 centre[i] += surf * g_i;
951 }
952 index = data.index_facette_suivante_;
953 }
954 if (surface_tot > 0.)
955 {
956 const double inverse_surface_tot = 1. / surface_tot;
957 double norme = 0.;
958 for (int j = 0; j < dim; j++)
959 {
960 norme += normale[j] * normale[j];
961 centre[j] *= inverse_surface_tot;
962 }
963 if (norme > 0)
964 {
965 double i_norme = 1./sqrt(norme);
966 for (int j = 0; j < dim; j++)
967 {
968 double n_j = normale[j] * i_norme; // normale normee
969 normale[j] = n_j;
970 }
971 }
972 }
973
974 // L'interface moyenne passe donc par "centre" (P) et de normale unitaire "normale" n=(a,b,c).
975 // The interfacial plane equation is :
976 // a * (x-xP) + b*(y-yP) + c * (z-zP) = 0
977
978 // The cell width is : zvdf.dim_elem(elem, k);
979 // In the tangential direction:
980 const double delta_tangential = zvdf.dim_elem(elem, 1-korient); // 1-korient is the direction // to wall in 2D.
981 const double xc = zvdf.xp(elem,1-korient); // Cell-center in the direction // to the wall in 2D.
982 // So left and right faces are at :
983 double xL = xc - 0.5*delta_tangential;
984 double xR = xc + 0.5*delta_tangential;
985
986 // In the wall normal direction:
987 const double delta_normal = zvdf.dim_elem(elem, korient); // korient is the direction perp to wall in 2D.
988 const double yc = zvdf.xp(elem,korient);
989 const double ymin = yc - 0.5*delta_normal;
990 const double ymax = yc + 0.5*delta_normal;
991
992 // And the normal to the faces is such that nface[1-korient] = \pm 1.
993
994 // So left and right faces are at :
995 const double a = -normale[1-korient];
996 const double b = normale[korient];
997
998 const double yG = centre[korient];
999 const double xG = centre[1-korient];
1000 double yL = 0.;
1001 double yR = 0.;
1002 if (std::fabs(b)< DMINFLOAT)
1003 {
1004 // vertical interface:
1005 yL = ymin;
1006 yR = ymax;
1007 xL = xG;
1008 xR = xG;
1009 }
1010 else
1011 {
1012 const double coeff_directeur = a/b;
1013 yL = yG + coeff_directeur * (xL - xG);
1014 yR = yG + coeff_directeur * (xR - xG);
1015 yL = std::min(std::max(ymin,yL),ymax);
1016 yR = std::min(std::max(ymin,yR),ymax);
1017
1018 if (std::fabs(a)< DMINFLOAT)
1019 {
1020 // horizontal interface:
1021 // in and out are at left and right faces so we already have :
1022 // xL = xL; xR = xR;
1023 }
1024 else
1025 {
1026 xL = xG + (yL-yG)/coeff_directeur;
1027 xR = xG + (yR-yG)/coeff_directeur;
1028 }
1029 }
1030
1031 // Fill in the table :
1032 in_out(0,0) = xL;
1033 in_out(0,1) = yL;
1034 in_out(1,0) = xR;
1035 in_out(1,1) = yR;
1036}
1037
1038double Triple_Line_Model_FT_Disc::compute_local_cos_theta(const Parcours_interface& parcours, const int num_face, const FTd_vecteur3& norm_elem) const
1039{
1040 FTd_vecteur3 nface = {0., 0., 0.} ;
1041 // GF is the vector from the cell to the interface barycenters:
1042 // FTd_vecteur3 GF = {bary_facettes_dans_elem[0]-xG, bary_facettes_dans_elem[1]-yG, bary_facettes_dans_elem[2]-zG} ;
1043 // The 3 zeros are useless parameters...
1044 parcours.calculer_normale_face_bord(num_face, 0.,0.,0., nface[0], nface[1], nface[2]) ;
1045
1046 double nl = 0.;
1047 double nl_fac = 0.;
1048 double n_dot = 0.;
1049 for (int dir = 0; dir< Objet_U::dimension; dir++)
1050 {
1051 nl += pow(norm_elem[dir],2);
1052 nl_fac += pow(nface[dir],2);
1053 n_dot += norm_elem[dir]*nface[dir];
1054 }
1055 double cos_theta = n_dot/(sqrt(nl)*sqrt(nl_fac));
1056// Cerr << " cos_theta = " << cos_theta << finl;
1057 double theta_app_loc = acos(-cos_theta);
1058 return theta_app_loc;
1059}
1060
1061
1062/*
1063double Triple_Line_Model_FT_Disc::get_update_AAA()
1064{
1065 if (tag_tcl_ == maillage.get_mesh_tag())
1066 {
1067 return AAA;
1068 }
1069
1070 // update the tcl model :
1071 tag_tcl_ = maillage.get_mesh_tag();
1072 compute_AAA();
1073}
1074*/
1075
1076// Search for the numero of the wall_face in a given direction
1077int wall_face_towards(const int iface, const int starting_elem, const int num_bord, const Domaine_VDF& zvdf)
1078{
1079 const IntTab& face_voisins = zvdf.face_voisins();
1080 const IntTab& elem_faces = zvdf.elem_faces();
1081 //const Front_VF& the_wall = zvdf.front_VF(num_bord);
1082 int num_face_wall = -1;
1083 int elem = starting_elem;
1084 // Conventions TRUST VDF :
1085 //static const int NUM_FACE_GAUCHE = 0;
1086 //static const int NUM_FACE_BAS = 1;
1087 //static const int NUM_FACE_HAUT = 3;
1088 //static const int NUM_FACE_DROITE = 2;
1089 int count = 0;
1090 int is_wall=0;
1091 while (not(is_wall))
1092 {
1093 num_face_wall = elem_faces(elem,iface);
1094 if (zvdf.face_numero_bord(num_face_wall) == num_bord)
1095 {
1096 // The face num_face_wall is actually on the same boundary (wall) as num_face
1097 is_wall = 1;
1098 break;
1099 }
1100 else
1101 {
1102 // We move to the next elem:
1103 elem = face_voisins(num_face_wall, 0) + face_voisins(num_face_wall, 1) - elem;
1104 count++;
1105 }
1106 if (count>30) //n_ext_meso_)
1107 {
1108 Cerr << "Looking too far and wall not found" << finl;
1109 Process::exit();
1110 }
1111 if (elem==-1)
1112 {
1113 Cerr << "We reached a boundary but not the expected wall?"
1114 << " border reached :" << zvdf.face_numero_bord(num_face_wall)
1115 << " is not within num_bord :" << num_bord << finl;
1116 Process::exit();
1117 }
1118 }
1119 return num_face_wall;
1120}
1121
1122bool is_in_list(const ArrOfInt& list, const int elem)
1123{
1124 const int nb_mixed = list.size_array();
1125 int j=0;
1126 for(j=0; j<nb_mixed; j++)
1127 {
1128 const int elemj = list[j];
1129 if (elem == elemj)
1130 {
1131 // yes, then we hit the "continue" in the next if and the loop continues with the next element
1132 break;
1133 }
1134 }
1135 if (j!=nb_mixed)
1136 return true;
1137
1138 return false;
1139}
1140
1142{
1143 ArrOfInt elems_with_CL_contrib, faces_with_CL_contrib;
1144 ArrOfDouble mpoint_from_CL, Q_from_CL;
1145 compute_TCL_fluxes_in_all_boundary_cells(elems_with_CL_contrib, faces_with_CL_contrib, mpoint_from_CL, Q_from_CL);
1146}
1147// Arguments :
1148// elems_with_CL_contrib : The list of elements containing either the TCL itself, or the meso domaine.
1149// In all of them, the flux_evap has to be modified.
1150// num_faces : Corresponding wall faces to which the flux should be assigned.
1151// mpoint_from_CL : corresponding value to be assigned to each cell (as a surface mass flux [kg/(m2s)] of total interface area within the cell)
1152// Q_from_CL : corresponding value to be assigned to each cell (as a thermal flux Q [unit?])
1153//
1154// Note that the same elem may appear twice (or more when contribution has to be displaced...) in the list,
1155// once (or more) for the micro contribution, once for the meso.
1156// It is not a problem, it will be considered by "+=" later
1157//
1158// num_faces is a locally temporary storages that in the end, is copied back into the class attribute boundary_faces_.
1159// theta_app_ is also updated here if read_via_file_ is activated;
1160// ATTENTION: explicit scheme: qtcl_ and theta_app_ are base on Temperature and Velocity at TCL at n-1;
1162 ArrOfInt& num_faces,
1163 ArrOfDouble& mpoint_from_CL, ArrOfDouble& Q_from_CL)
1164{
1165 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
1166 const double dt = ns.schema_temps().pas_de_temps();
1167 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, ns.domaine_dis());
1168 const DoubleVect& volumes = domaine_vf.volumes();
1169 const Fluide_Diphasique& fluide = ns.fluide_diphasique();
1170 const Fluide_Incompressible& phase_0 = fluide.fluide_phase(0);
1171 const Fluide_Incompressible& phase_1 = fluide.fluide_phase(1);
1172 const DoubleTab& tab_rho_phase_0 = phase_0.masse_volumique().valeurs();
1173 const DoubleTab& tab_rho_phase_1 = phase_1.masse_volumique().valeurs();
1174 const double rho_phase_0 = tab_rho_phase_0(0,0);
1175 const double rho_phase_1 = tab_rho_phase_1(0,0);
1176 const double jump_inv_rho = 1./rho_phase_1 - 1./rho_phase_0;
1177 const double Lvap = fluide.chaleur_latente();
1178 //const double coef = jump_inv_rho/Lvap;
1179 // const int dim3 = Objet_U::dimension == 3;
1180 const Transport_Interfaces_FT_Disc& eq_transport = ref_eq_interf_.valeur();
1181 const Maillage_FT_Disc& maillage = eq_transport.maillage_interface();
1182 const IntTab& facettes = maillage.facettes();
1183 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
1184 const ArrOfInt& index_facette_elem = intersections.index_facette();
1185 const DoubleTab& sommets = maillage.sommets();
1186 // OBS_PTR(Transport_Interfaces_FT_Disc) & refeq_transport =
1187 // variables_internes().ref_eq_interf_proprietes_fluide;
1188 // const Transport_Interfaces_FT_Disc& eq_transport = refeq_transport.valeur();
1189 const bool first_call_for_this_mesh = (tag_tcl_ != maillage.get_mesh_tag());
1190 double instant_Qmicro = 0., instant_Qmeso = 0.;
1191 if (first_call_for_this_mesh)
1192 {
1193 tag_tcl_ = maillage.get_mesh_tag(); // update the TCL tag to match the mesh that was used.
1194 // reset instantaneous values :
1196 instant_Qmicro = 0.;
1200 instant_Qmeso = 0.;
1201 // Update the integration time :
1202 integration_time_ += dt;
1203 }
1204 else
1205 {
1206 Cerr << "Now that elems_, mp_and Q_ are stored as members to the TCL class, we shouldn't need to call this function "
1207 << "several times for the same timestep. Please check or contact support." << finl;
1208 Process::exit();
1209 }
1210
1211 const Parcours_interface& parcours = eq_transport.parcours_interface();
1212 // const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
1213
1214 // We store the elements (eulerian) crossed by a contact line.
1215 // As the specific source term is introduced here, a contribution of mdot should not be included afterwards.
1216
1217 elems_with_CL_contrib.resize_array(0);
1218
1219 num_faces.resize_array(0);
1220
1221 mpoint_from_CL.resize_array(0);
1222
1223 Q_from_CL.resize_array(0);
1224
1225 // List to be completed with the meso region:
1226 ArrOfInt list_meso_elems;
1227 ArrOfInt list_meso_faces;
1228
1229 // List to be completed with the micro region:
1230 ArrOfInt list_micro_elems;
1231 ArrOfInt list_micro_faces;
1232 ArrOfInt list_micro_indexs;
1233
1234 // list of Qtot W/m from TCL model for printing
1235 ArrOfDouble list_micro_fraction;
1236
1237 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, ns.domaine_dis());
1238 const IntTab& face_voisins = zvdf.face_voisins();
1239 const IntVect& orientation = zvdf.orientation();
1240 // const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis);
1241 const IntTab& elem_faces = zvdf.elem_faces();
1242
1243 if (read_via_file_)
1244 {
1245 theta_app_ = 0.;
1246 Qtcl_ = 0.;
1247 }
1248
1249 const int nsom = maillage.nb_sommets();
1250 const int dim = Objet_U::dimension;
1251 DoubleTab vit(nsom, dim);
1252
1254 {
1256 Motcle nom_du_champ = "vitesse";
1257 // Cerr << "Validation and checking required in Maillage_FT_Disc::calcul_courbure_sommets" << finl;
1258 eq_transport.get_champ_post_FT(nom_du_champ, loc, &vit); // HACK !!!! (warning, try debug to make sure it works if you want to remove it!!)
1259 }
1260
1261
1262 // 1. First loop on contact line cells:
1263 // Micro cells: 1, at wall BC + 2, 0<indicatrice <1 3, height < ym
1264 {
1265 // const double temps = ns.schema_temps().temps_courant();
1266 // Cerr << " ****************************** TCL ****************************** " << finl;
1267 // Cerr << que_suis_je() << "::compute_TCL_fluxes_in_all_boundary_cells() searching TCL cells" <<finl;
1268 const Domaine_Cl_dis_base& zcldis = ns.domaine_Cl_dis();
1269 // get wall BC frontiere nb
1270 int num_bord = -1;
1271 int nbwall_found = 0;
1272 for (int i=0; i<zcldis.nb_cond_lim(); i++)
1273 {
1274 const Cond_lim& la_cl = zcldis.les_conditions_limites(i);
1275 const Nom& bc_name = la_cl->frontiere_dis().le_nom();
1276 // For each BC, we check its type to see if it's a wall:
1277 // BC for hydraulic equation
1278 bool is_wall = sub_type(Dirichlet_paroi_fixe,la_cl.valeur())
1279 || sub_type(Dirichlet_paroi_defilante,la_cl.valeur());
1280 if (is_wall)
1281 {
1282 Cerr << "[TCL]: Wall-type BC found at " << bc_name <<finl;
1283 num_bord = i;
1284 nbwall_found = nbwall_found +1;
1285// break;
1286 }
1287 }
1288 if (nbwall_found != 1)
1289 Process::exit(Nom(nbwall_found) + " wall-type BC found!!!!! Check JDD, pls" );
1290 if (num_bord<0)
1291 Process::exit( "[TCL]: !!! NO WALL-TYPE BOUNDARY WAS FOUND IN THE DOMAINE, PLESEASE CHECK JDD" );
1292
1293 const Frontiere& fr=zcldis.les_conditions_limites(num_bord)->frontiere_dis().frontiere();
1294 const int nb_first_face = fr.num_premiere_face();
1295 const int nb_face = fr.nb_faces();
1296 const DoubleTab& indica = eq_transport.inconnue().valeurs();
1297
1298 // get TCL cells
1299 for (int ii = 0; ii < nb_face; ii++)
1300 {
1301 const int num_face = ii + nb_first_face;
1302 const int elemi = face_voisins (num_face, 0)
1303 + face_voisins (num_face, 1) + 1;
1304 // if (is_in_list(list_micro_elems,elemi))
1305 // continue;
1306
1307 bool is_interf = (indica(elemi,0)>0.) && (indica(elemi,0)<1.) ;
1308 if (is_interf)
1309 {
1310 int index=intersections.index_elem()[elemi]; // index > 0 if Front presents
1311 if (index < 0)
1312 {
1313
1314 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << finl;
1315 Cerr << "[TCL!!!]: INDICATRICE and FT are NOT CONSISTENT "<< finl;
1316 Cerr << "[TCL!!!]: elem number " << elemi<< " | indicatrice " << indica(elemi,0) << finl;
1317 Cerr << "[TCL!!!]: index " << index<< " | iteration " << ii << finl;
1318 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << finl;
1319 // Process::exit( "[TCL]: !!! INDICATTICE and FT are NOT CONSISTENT " );
1320 continue;
1321 }
1322 // else
1323 // Cerr << "[TCL] FOUND interface cell at #" << elemi <<" with face number #" << num_face << finl;
1324
1325 const int korient = orientation(num_face); // 0:x 1:y or 2:z (gives the direction it is normal to the wall)
1326 const double xwall = zvdf.xv(num_face, korient);
1327 double nwall[3] = { 0., 0., 0. }; // Away from the wall by convention here
1328 (zvdf.xp(elemi, korient) > xwall) ? nwall[korient] = 1. : nwall[korient] = -1.;
1329 // "-nwall " because we want to go to the wall
1330
1331 int a = (-nwall[korient] < 0) ? 0 : Objet_U::dimension;
1332 int b = korient; // if the normal is along y, korient=1 and we want 1 for x
1333 int iface = a + b;
1334
1335
1337 {
1338 while (index >= 0) // loop over index inside an elem, loop effective when one facette has go through serveral mesh
1339 {
1340 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
1341 const int fa7 = data.numero_facette_;
1342 const int sommet0 = facettes(fa7, 0);
1343 const int sommet1 = facettes(fa7, 1);
1344
1345 if ((maillage.sommet_ligne_contact(sommet0)) || (maillage.sommet_ligne_contact(sommet1)))
1346 {
1347 int indextmp=index_facette_elem[fa7];
1348 while (indextmp >= 0)
1349 {
1350 const Intersections_Elem_Facettes_Data& datatmp = intersections.data_intersection(indextmp);
1351 const int elem = datatmp.numero_element_;
1352 if (!is_in_list(list_micro_elems,elem))
1353 {
1354 // Cerr << "[TCL: MICRO] FOUND MICRO cell at #" << elem <<" also part of first facette #" << finl;
1355 list_micro_elems.append_array(elem);
1356
1357 // Cerr << "[TCL: MICRO]: SERCHING corresponding face number at wall, DIRECTION = " << iface << finl;
1358 // Cerr << "[TCL: MICRO]: (2D case: 0 LEFT; 1 DOWN; 2 Right; 3 UP.)" << finl;
1359 const int num_face_wall = wall_face_towards(iface, elem, num_bord, zvdf);
1360 list_micro_faces.append_array(num_face_wall);
1361 list_micro_indexs.append_array(indextmp);
1362 // Cerr << "[TCL: MICRO]: Corresponding face number at wall " << num_face_wall << finl;
1363 // Cerr << "[TCL: MICRO]: elem " << elem << " | face number at wall " << num_face_wall << finl;
1364
1366 {
1367 int num_som = maillage.sommet_ligne_contact(sommet0) ? sommet0: sommet1;
1368 x_cl_ = sommets(num_som,0);
1369 Cerr << "[TCL: MICRO] position of the CL is set to be " << x_cl_ << finl;
1370
1371
1372 if (read_via_file_)
1373 {
1374 const int face = maillage.sommet_face_bord()[num_som];
1375 if( est_egal(face, num_face_wall))
1376 {
1377 theta_app_ = get_theta_app(num_face_wall);
1378 Cerr << "[TCL-model] Contact_angle apparent is modified to " << theta_app_ << finl;
1380 {
1381 // int num_som = maillage.sommet_ligne_contact(sommet0) ? sommet0: sommet1;
1382 correct_theta_app_qtcl(theta_app_, Qtcl_, num_face_wall, num_som, vit);
1383 }
1384 else
1385 Qtcl_ = get_Qtcl(num_face_wall);
1386 Cerr << "[TCL-model] Qmicro is modified to " << Qtcl_ << finl;
1387 }
1388 }
1389 }
1390 }
1391 indextmp = datatmp.index_element_suivant_;
1392 }
1393 }
1394 index = data.index_facette_suivante_;
1395 }
1396 }
1397 else
1398 {
1399
1400 while (index >= 0) // loop over index inside an elem, check if the facette suivant is also in the same elem
1401 {
1402 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
1403 const int fa7 = data.numero_facette_;
1404 const int sommet0 = facettes(fa7, 0);
1405 const int sommet1 = facettes(fa7, 1);
1406
1407 if ((maillage.sommet_ligne_contact(sommet0)) || (maillage.sommet_ligne_contact(sommet1)))
1408 {
1409 int indextmp=index_facette_elem[fa7];
1410 if (indextmp >= 0)
1411 {
1412 const Intersections_Elem_Facettes_Data& datatmp = intersections.data_intersection(indextmp);
1413 const int elem = datatmp.numero_element_;
1414 if (!is_in_list(list_micro_elems,elem))
1415 {
1416 // Cerr << "[TCL: MICRO] FOUND MICRO cell at #" << elem <<" also part of first facette #" << finl;
1417 list_micro_elems.append_array(elem);
1418
1419 // Cerr << "[TCL: MICRO]: SERCHING corresponding face number at wall, DIRECTION = " << iface << finl;
1420 // Cerr << "[TCL: MICRO]: (2D case: 0 LEFT; 1 DOWN; 2 Right; 3 UP.)" << finl;
1421 const int num_face_wall = wall_face_towards(iface, elem, num_bord, zvdf);
1422 list_micro_faces.append_array(num_face_wall);
1423 list_micro_indexs.append_array(indextmp);
1424 // Cerr << "[TCL: MICRO]: Corresponding face number at wall " << num_face_wall << finl;
1425 // Cerr << "[TCL: MICRO]: elem " << elem << " | face number at wall " << num_face_wall << finl;
1426
1428 {
1429 int num_som = maillage.sommet_ligne_contact(sommet0) ? sommet0: sommet1;
1430 x_cl_ = sommets(num_som,0);
1431 Cerr << "[TCL: MICRO] position of the CL is set to be " << x_cl_ << finl;
1432
1433 if (read_via_file_)
1434 {
1435 const int face = maillage.sommet_face_bord()[num_som];
1436 if( est_egal(face, num_face_wall))
1437 {
1438 theta_app_ = get_theta_app(num_face_wall);
1439 Cerr << "[TCL-model] Contact_angle apparent is modified to " << theta_app_ << finl;
1441 {
1442 // int num_som = maillage.sommet_ligne_contact(sommet0) ? sommet0: sommet1;
1443 correct_theta_app_qtcl(theta_app_, Qtcl_, num_face_wall, num_som, vit);
1444 }
1445 else
1446 Qtcl_ = get_Qtcl(num_face_wall);
1447 Cerr << "[TCL-model] Qmicro is modified to " << Qtcl_ << finl;
1448 }
1449 }
1450
1451 }
1452
1453 }
1454 }
1455 }
1456 index = data.index_facette_suivante_;
1457
1458 }
1459
1460
1461
1462 }
1463
1464 // Cerr << "[TCL] Check if this CELL A MICRO and/or MESO cell by h" << finl;
1465
1466 const double dist1 = std::fabs(zvdf.dist_face_elem0(num_face,elemi)); // h
1467 const double half_cell_height1 = std::fabs(zvdf.dist_face_elem0(elem_faces(elemi,iface),elemi)); // half distanct to furface parallel to wall
1468 const double hcell_top = dist1+half_cell_height1;
1469 const double hcell_bot = dist1-half_cell_height1;
1470
1471 if (hcell_top <= ym_ + Objet_U::precision_geom && !is_in_list(list_micro_elems,elemi))
1472 {
1473 if (!is_in_list(list_micro_elems,elemi) && !distri_first_facette())
1474 {
1475
1476 list_micro_elems.append_array(elemi);
1477 list_micro_faces.append_array(num_face);
1478 // Cerr << "[TCL: MICRO]: elem " << elemi << " | face number at wall " << num_face << finl;
1479 }
1480 }
1481 else if (hcell_bot <= ym_ + Objet_U::precision_geom)
1482 {
1483 // Cerr << "[TCL: MICRO+MESO] FOUND cell can contribue both MICRO and MESO #" << elemi << finl;
1484 if (!distri_first_facette() && !is_in_list(list_micro_elems,elemi))
1485 {
1486 list_micro_elems.append_array(elemi);
1487 list_micro_faces.append_array(num_face);
1488 }
1489
1490 if (!is_in_list(list_meso_elems,elemi))
1491 {
1492 list_meso_faces.append_array(num_face);
1493 list_meso_elems.append_array(elemi);
1494 }
1495
1496 // Cerr << "[TCL: MICRO+MESO]: elem " << elemi << " | face number at wall " << num_face << finl;
1497
1498 }
1499 else if (hcell_bot <= ymeso_ + Objet_U::precision_geom && !is_in_list(list_meso_elems,elemi) )
1500 {
1501 list_meso_elems.append_array(elemi);
1502 list_meso_faces.append_array(num_face);
1503 // Cerr << "[TCL: MESO]: elem " << elemi << " | face number at wall " << num_face << finl;
1504 }
1505
1506
1507
1508 // Cerr << "[TCL] Searching MICRO CELLS (INTERFACE + 1.e-10m<Y<YM) among Neighboorhood cells of iElem #" << elemi << finl;
1509 // Cerr << "[TCL] Searching MESO CELLS (INTERFACE + YM<Y<YMeso) among Neighboorhood cells of iElem #" << elemi << finl;
1510 // loop to find all cells with interface
1511 // Cerr << "[TCL] Searching neighboor cells from Elem #" << elemi << " and face #" << num_face << finl;
1512
1513 ArrOfInt future_new_elems;
1514
1515 future_new_elems.append_array(elemi); // Initialize the list with the current micro cells
1516 while (future_new_elems.size_array()) // There are some elements to deal with
1517 {
1518 ArrOfInt new_elems(future_new_elems);
1519 future_new_elems.resize_array(0); // Empty the future list to be constructed
1520 for (int i=0; i< new_elems.size_array(); i++)
1521 {
1522 const int ielem = new_elems[i];
1523 // Cerr << "[TCL ] Searching MICRO (INTERFACE + 1.e-10m<Y<YM) or MESO (INTERFACE + YM<Y<YMeso) cells among Neighboorhood of iElem #" << ielem << finl;
1524 const int nb_voisins = elem_faces.dimension(1);
1525 for (int iv=0; iv < nb_voisins; iv++)
1526 {
1527 const int num_face2 = elem_faces(ielem,iv);
1528 int elem_voisin = face_voisins(num_face2, 0) + face_voisins(num_face2, 1) - ielem;
1529 if (elem_voisin<0)
1530 continue; // We hit a border, there is no neighbour here
1531 const int nbelemt= intersections.index_elem().size_array();
1532 // set to -1 if the next elem is out of range, i.e., elem_voisin is a virtual element (paralisation)
1533 int index2= (elem_voisin < nbelemt) ? intersections.index_elem()[elem_voisin]:-1;
1534 if (index2 < 0)
1535 continue; // This element is not crossed by the interface. Go to the next face.
1536 // We won't want to do ielem twice (unless it was a micro elem)
1537 // Have we seen this element already in the TCL list?
1538 if (is_in_list(list_micro_elems,elem_voisin) && is_in_list(list_meso_elems,elem_voisin))
1539 continue;
1540
1541 // Cerr << "[TCL ] FOUND interface cell #" << elem_voisin <<" among Neighboorhood cells of iElem #" << ielem << finl;
1542 // Here, we are with a new element elem_voisin to append to both lists
1543
1544
1545 const double dist = std::fabs(zvdf.dist_face_elem0(num_face,elem_voisin)); // h
1546 const double half_cell_height = std::fabs(zvdf.dist_face_elem0(elem_faces(elem_voisin,iface),elem_voisin)); // half distanct to furface parallel to wall
1547 const double hcell_dn = dist-half_cell_height;
1548 const double hcell_up = dist+half_cell_height;
1549 if (hcell_up <= ym_+Objet_U::precision_geom)
1550 {
1551 if (!distri_first_facette() && !is_in_list(list_micro_elems,elem_voisin))
1552 {
1553 // Cerr << "[TCL: MICRO] FOUND MICRO cell at #" << elem_voisin <<" among Neighboorhood cells of iElem #" << ielem << finl;
1554 list_micro_elems.append_array(elem_voisin);
1555 // Cerr << "[TCL: MICRO]: SERCHING corresponding face number at wall, DIRECTION = " << iface << finl;
1556 // Cerr << "[TCL: MICRO]: (2D case: 0 LEFT; 1 DOWN; 2 Right; 3 UP.)" << finl;
1557 const int num_face_wall = wall_face_towards(iface, elem_voisin, num_bord, zvdf);
1558 list_micro_faces.append_array(num_face_wall);
1559 // Cerr << "[TCL: MICRO]: Corresponding face number at wall " << num_face_wall << finl;
1560 // Cerr << "[TCL: MICRO]: elem " << elem_voisin << " | face number at wall " << num_face_wall << finl;
1561 future_new_elems.append_array(elem_voisin);
1562 }
1563 }
1564 else if (hcell_dn <= ym_+Objet_U::precision_geom)
1565 {
1566 // Cerr << "[TCL: MICRO+MESO] FOUND cell can contribue both MICRO and MESO #" << elem_voisin <<" among Neighboorhood cells of iElem #" << ielem << finl;
1567 // Cerr << "[TCL: MICRO+MESO]: SERCHING corresponding face number at wall, DIRECTION = " << iface << finl;
1568 // Cerr << "[TCL: MICRO+MESO]: (2D case: 0 LEFT; 1 DOWN; 2 Right; 3 UP.)" << finl;
1569 const int num_face_wall = wall_face_towards(iface, elem_voisin, num_bord, zvdf);
1570
1571
1572 if (!distri_first_facette() && !is_in_list(list_micro_elems,elem_voisin))
1573 {
1574 list_micro_elems.append_array(elem_voisin);
1575 list_micro_faces.append_array(num_face_wall);
1576 // Cerr << "[TCL: MICRO]: elem " << elem_voisin << " | face number at wall " << num_face_wall << finl;
1577 future_new_elems.append_array(elem_voisin);
1578 }
1579
1580 if (!is_in_list(list_meso_elems,elem_voisin))
1581 {
1582 list_meso_elems.append_array(elem_voisin);
1583 list_meso_faces.append_array(num_face_wall);
1584 // Cerr << "[TCL: MESO]: elem " << elem_voisin << " | face number at wall " << num_face_wall << finl;
1585 if(!is_in_list(future_new_elems,elem_voisin))
1586 future_new_elems.append_array(elem_voisin);
1587 }
1588 // Cerr << "[TCL: MICRO+MESO]: Corresponding face number at wall " << num_face_wall << finl;
1589
1590 }
1591 else if (hcell_dn<ymeso_)
1592 {
1593 if (!is_in_list(list_meso_elems,elem_voisin))
1594 {
1595 // Cerr << "[TCL: MESO] FOUND MESO cell at #" << elem_voisin <<" among Neighboorhood cells of iElem #" << ielem << finl;
1596 list_meso_elems.append_array(elem_voisin);
1597 // Cerr << "[TCL: MESO]: SERCHING corresponding face number at wall, DIRECTION = " << iface << finl;
1598 // Cerr << "[TCL: MESO]: (2D case: 0 LEFT; 1 DOWN; 2 Right; 3 UP.)" << finl;
1599 const int num_face_wall = wall_face_towards(iface, elem_voisin, num_bord, zvdf);
1600 list_meso_faces.append_array(num_face_wall);
1601 // Cerr << "[TCL: MESO]: elem " << elem_voisin << " | face number at wall " << num_face_wall << finl;
1602 future_new_elems.append_array(elem_voisin);
1603 }
1604 }
1605 else
1606 {
1607 // Cerr << "[TCL] HOWEVER ## elem " << elem_voisin << " NOT part of MICRO or Macro Region" << finl;
1608 break;
1609 }
1610
1611 }
1612 }
1613 }
1614 }
1615 } // ==========================fin==============loop 1===================
1616
1617 // Cerr << "[TCL: MICRO]: list_micro_elems number of elems: " << list_micro_elems << finl;
1618 // Cerr << "[TCL: MICRO]: list_micro_faces number of faces: " << list_micro_faces << finl;
1619 // Cerr << " *************************************** " << finl;
1620 // Cerr << "[TCL: MESO]: list_meso_elems number of elems: " << list_meso_elems << finl;
1621 // Cerr << "[TCL: MESO]: list_meso_faces number of faces: " << list_meso_faces << finl;
1622
1623 if (read_via_file_)
1624 {
1625 theta_app_ = Process::mp_max(theta_app_); // diffuse into all processeur
1627 }
1628
1629
1630 // 2. send loop to fill-in micro contribution
1631 // We have our list of cells, we can complete their contribution and add them to the list
1632 {
1633 const double nn = list_micro_elems.size_array();
1634 for (int idx=0; idx<nn; idx++)
1635 {
1636 const int elem = list_micro_elems[idx];
1637 const int num_face = list_micro_faces[idx];
1638
1639 double surface_tot = 0.;
1640 DoubleTab in_out(2,Objet_U::dimension); // The coords of left and right points where the interface cross the cell boundary
1641 FTd_vecteur3 norm_elem = {0., 0., 0.};
1642 if (inout_method_ == EXACT)
1643 {
1644 get_in_out_coords(zvdf, elem, dt, in_out, norm_elem, surface_tot);
1645 }
1646 else if (inout_method_ == APPROX)
1647 {
1648 const int korient= zvdf.orientation(num_face);
1650 elem, num_face,
1651 in_out, norm_elem, surface_tot);
1652 }
1653 else
1654 {
1655 // both methods are used and compared :
1656 get_in_out_coords(zvdf, elem, dt, in_out, norm_elem, surface_tot);
1657
1658 DoubleTab in_out_approx(2,Objet_U::dimension);
1659 FTd_vecteur3 norm_elem_approx = {0., 0., 0.};
1660 double surface_tot_approx = 0.;
1661 const int korient= zvdf.orientation(num_face);
1663 elem, num_face,
1664 in_out_approx, norm_elem_approx, surface_tot_approx);
1665 Cerr << "comparison of approx to exact method in elem " << elem << finl;
1666 // in_out(0,0) -> x_in
1667 // in_out(0,1) -> y_in
1668 // in_out(1,0) -> x_out
1669 // in_out(1,1) -> y_out
1670 // Sorting points in/out with point 'in' closer to origin than 'ou' for the comparison:
1671 const double d0 = std::sqrt(in_out(0,0)*in_out(0,0)+in_out(0,1)*in_out(0,1));
1672 const double d1 = std::sqrt(in_out(1,0)*in_out(1,0)+in_out(1,1)*in_out(1,1));
1673 const double x_in = (d0<d1) ? in_out(0,0) : in_out(1,0);
1674 const double y_in = (d0<d1) ? in_out(0,1) : in_out(1,1);
1675 const double x_ou = (d0<d1) ? in_out(1,0) : in_out(0,0);
1676 const double y_ou = (d0<d1) ? in_out(1,1) : in_out(0,1);
1677 // approx points
1678 const double da0 = std::sqrt(in_out_approx(0,0)*in_out_approx(0,0)+in_out_approx(0,1)*in_out_approx(0,1));
1679 const double da1 = std::sqrt(in_out_approx(1,0)*in_out_approx(1,0)+in_out_approx(1,1)*in_out_approx(1,1));
1680 const double xa_in = (da0<da1) ? in_out_approx(0,0) : in_out_approx(1,0);
1681 const double ya_in = (da0<da1) ? in_out_approx(0,1) : in_out_approx(1,1);
1682 const double xa_ou = (da0<da1) ? in_out_approx(1,0) : in_out_approx(0,0);
1683 const double ya_ou = (da0<da1) ? in_out_approx(1,1) : in_out_approx(0,1);
1684 if ((std::fabs(x_in-xa_in)>DMINFLOAT) or (std::fabs(x_ou-xa_ou)>DMINFLOAT))
1685 Cerr << "inout x -- exact "
1686 << x_in << " "
1687 << x_ou << " approx "
1688 << xa_in << " "
1689 << xa_ou << " delta "
1690 << x_in-xa_in << " "
1691 << x_ou-xa_ou << finl;
1692 if ((std::fabs(y_in-ya_in)>DMINFLOAT) or (std::fabs(y_ou-ya_ou)>DMINFLOAT))
1693 Cerr << "inout y -- exact "
1694 << y_in << " "
1695 << y_ou << " approx "
1696 << ya_in << " "
1697 << ya_ou << " delta "
1698 << y_in-ya_in << " "
1699 << y_ou-ya_ou << finl;
1700 if ((std::fabs(norm_elem[0]-norm_elem_approx[0])>DMINFLOAT) or
1701 (std::fabs(norm_elem[1]-norm_elem_approx[1])>DMINFLOAT))
1702 Cerr << "normal_elem -- exact " << norm_elem[0] << " " << norm_elem[1]
1703 << " approx " << norm_elem_approx[0] << " " << norm_elem_approx[1]
1704 << " delta " << norm_elem[0]-norm_elem_approx[0] << " " << norm_elem[1]-norm_elem_approx[1]
1705 << finl;
1706 if (std::fabs(surface_tot-surface_tot_approx)>DMINFLOAT)
1707 Cerr << "surface -- exact "
1708 << surface_tot << " approx "
1709 << surface_tot_approx << " delta "
1710 << surface_tot-surface_tot_approx << finl;
1711 Cerr << "End of comparison" << finl;
1712 }
1713
1714
1715 // The offset distance should be accounted for because the methods in_out counts the origin at the cell
1716 {
1717 // in_out are real absolute coordinates.
1718 // We should make the "y" a normal distance to TCL
1719 const int korient = zvdf.orientation(num_face);
1720 const double xwall =zvdf.xv(num_face, korient);
1721 in_out(0,korient) -= xwall;
1722 in_out(1,korient) -= xwall;
1723 //in_out(0,1) += dist;
1724 //in_out(1,1) += dist;
1725 if (zvdf.dist_face_elem0(num_face,elem)>0)
1726 {
1727 // The face is on top of the element, so distance will be negative.
1728 // We want to count it positive by convention so :
1729 in_out(0,korient) *= -1;
1730 in_out(1,korient) *= -1;
1731 }
1732 assert(in_out(0,korient) >=-Objet_U::precision_geom);
1733 assert(in_out(1,korient) >=-Objet_U::precision_geom);
1734 }
1735 // const double xl = in_out(0,0);
1736 const double yl = in_out(0,1);
1737 // const double xr = in_out(1,0);
1738 const double yr = in_out(1,1);
1739 // Cerr << "xl,yl, xr,yr = " << xl << " " << yl << " " << xr << " " << yr << finl;
1740
1741
1742
1743 double circum_dis = 1.;
1745 {
1746 const double angle_bidim_axi = Maillage_FT_Disc::angle_bidim_axi();
1747 circum_dis = angle_bidim_axi*x_cl_;
1748 // Cerr << "[TCL: MICRO] FILLING LIST MICRO [bidim_axi] circum_dis = " << circum_dis << finl;
1749 }
1750
1751
1752 const double ytop = std::fmax(yr,yl);
1753 const double ybot = std::fmin(yr,yl);
1754
1755 // Micro region is between 1.e-10 and ym_:
1756 const double ymin = exp(-19);
1757
1758 double Qtot = get_Qtcl();
1759
1760 double Qmicro = 0.;
1761 double fraction = 0.;
1762
1764 {
1765 Qmicro = log(std::fmin(ym_,std::fmax(ytop,ymin))/ std::fmin(ym_,std::fmax(ybot,ymin))) / (log(ym_) +19.)*Qtot;
1766 fraction = log(std::fmin(ym_,std::fmax(ytop,ymin))/ std::fmin(ym_,std::fmax(ybot,ymin))) / (log(ym_) +19.);
1767 }
1768 else
1769 {
1770 // const int index=intersections.index_elem()[elem]; // index > 0 if Front presents
1771 const int index= list_micro_indexs[idx];
1772 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
1773 fraction = data.fraction_surface_intersection_;
1774 Qmicro = fraction*Qtot;
1775 }
1776
1777 double Q_int = Qmicro*circum_dis; // unit of Q_int is W
1778
1779 if (std::fabs(Q_int)<DMINFLOAT)
1780 continue;
1781
1782 if (first_call_for_this_mesh)
1783 {
1784 // We update values and integrals only at the first call
1785 instant_mmicro_evap_ += (Q_int/Lvap)*dt;
1786 instant_vmicro_evap_ = instant_mmicro_evap_*jump_inv_rho; // '=' not '+=' because the '+=' is already in instant_mmicro_evap_
1787 }
1788
1789
1790 elems_with_CL_contrib.append_array(elem);
1791 num_faces.append_array(num_face);
1792 mpoint_from_CL.append_array(Q_int/(surface_tot*Lvap));
1793 Q_from_CL.append_array(Q_int);
1794 list_micro_fraction.append_array(fraction);
1795
1796
1797 instant_Qmicro += Qmicro;
1798
1799 Cerr.precision(16);
1800 Cerr << "[TCL: MICRO]:" << " Instantaneous tcl-evaporation = "<< instant_vmicro_evap_ << " time = " << integration_time_ << finl;
1801 Cerr << "[TCL: MICRO] time = " << integration_time_ << " Qmicro= " << Qmicro << " Qint " << Q_int << finl;
1802 Cerr.precision(7);
1803
1804
1805 }
1806 }
1807
1808 instant_Qmicro = mp_sum(instant_Qmicro);
1809
1810 if (elems_with_CL_contrib.size_array()>0)
1811 {
1812 Cerr << " nb_contact_line_contribution " << Q_from_CL.size_array() << finl;
1813 Cerr << " ********* VALUES OF MICRO CONTRIBUTION *************** " << finl;
1814 Cerr << "elem\t| face\t| Q\t\t| mp\t\t| fraction" << finl;
1815 for (int idx = 0; idx < Q_from_CL.size_array(); idx++)
1816 {
1817 Cerr << elems_with_CL_contrib[idx] << "\t| " << num_faces[idx] << "\t| "
1818 << Q_from_CL[idx] << "\t| " << mpoint_from_CL[idx] << "\t| "
1819 <<list_micro_fraction[idx] << finl;
1820 }
1821 Cerr << " ************************************************************* " << finl;
1822 }
1823
1824// 3. Third loop to fill-in meso contribution
1825// We have our list of cells, we can complete their contribution and add them to the list
1826 {
1827 const double nn = list_meso_elems.size_array();
1828 for (int idx=0; idx<nn; idx++)
1829 {
1830 const int elem = list_meso_elems[idx];
1831 const int num_face = list_meso_faces[idx];
1832
1833
1834 double surface_tot = 0.;
1835 DoubleTab in_out(2,Objet_U::dimension); // The coords of left and right points where the interface cross the cell boundary
1836 FTd_vecteur3 norm_elem = {0., 0., 0.};
1837 if (inout_method_ == EXACT)
1838 {
1839 get_in_out_coords(zvdf, elem, dt, in_out, norm_elem, surface_tot);
1840 }
1841 else if (inout_method_ == APPROX)
1842 {
1843 const int korient= zvdf.orientation(num_face);
1845 elem, num_face,
1846 in_out, norm_elem, surface_tot);
1847 }
1848 else
1849 {
1850 // both methods are used and compared :
1851 get_in_out_coords(zvdf, elem, dt, in_out, norm_elem, surface_tot);
1852
1853 DoubleTab in_out_approx(2,Objet_U::dimension);
1854 FTd_vecteur3 norm_elem_approx = {0., 0., 0.};
1855 double surface_tot_approx = 0.;
1856 const int korient= zvdf.orientation(num_face);
1858 elem, num_face,
1859 in_out_approx, norm_elem_approx, surface_tot_approx);
1860 Cerr << "comparison of approx to exact method in elem " << elem << finl;
1861 // in_out(0,0) -> x_in
1862 // in_out(0,1) -> y_in
1863 // in_out(1,0) -> x_out
1864 // in_out(1,1) -> y_out
1865 // Sorting points in/out with point 'in' closer to origin than 'ou' for the comparison:
1866 const double d0 = std::sqrt(in_out(0,0)*in_out(0,0)+in_out(0,1)*in_out(0,1));
1867 const double d1 = std::sqrt(in_out(1,0)*in_out(1,0)+in_out(1,1)*in_out(1,1));
1868 const double x_in = (d0<d1) ? in_out(0,0) : in_out(1,0);
1869 const double y_in = (d0<d1) ? in_out(0,1) : in_out(1,1);
1870 const double x_ou = (d0<d1) ? in_out(1,0) : in_out(0,0);
1871 const double y_ou = (d0<d1) ? in_out(1,1) : in_out(0,1);
1872 // approx points
1873 const double da0 = std::sqrt(in_out_approx(0,0)*in_out_approx(0,0)+in_out_approx(0,1)*in_out_approx(0,1));
1874 const double da1 = std::sqrt(in_out_approx(1,0)*in_out_approx(1,0)+in_out_approx(1,1)*in_out_approx(1,1));
1875 const double xa_in = (da0<da1) ? in_out_approx(0,0) : in_out_approx(1,0);
1876 const double ya_in = (da0<da1) ? in_out_approx(0,1) : in_out_approx(1,1);
1877 const double xa_ou = (da0<da1) ? in_out_approx(1,0) : in_out_approx(0,0);
1878 const double ya_ou = (da0<da1) ? in_out_approx(1,1) : in_out_approx(0,1);
1879 if ((std::fabs(x_in-xa_in)>DMINFLOAT) or (std::fabs(x_ou-xa_ou)>DMINFLOAT))
1880 Cerr << "inout x -- exact "
1881 << x_in << " "
1882 << x_ou << " approx "
1883 << xa_in << " "
1884 << xa_ou << " delta "
1885 << x_in-xa_in << " "
1886 << x_ou-xa_ou << finl;
1887 if ((std::fabs(y_in-ya_in)>DMINFLOAT) or (std::fabs(y_ou-ya_ou)>DMINFLOAT))
1888 Cerr << "inout y -- exact "
1889 << y_in << " "
1890 << y_ou << " approx "
1891 << ya_in << " "
1892 << ya_ou << " delta "
1893 << y_in-ya_in << " "
1894 << y_ou-ya_ou << finl;
1895 if ((std::fabs(norm_elem[0]-norm_elem_approx[0])>DMINFLOAT) or
1896 (std::fabs(norm_elem[1]-norm_elem_approx[1])>DMINFLOAT))
1897 Cerr << "normal_elem -- exact " << norm_elem[0] << " " << norm_elem[1]
1898 << " approx " << norm_elem_approx[0] << " " << norm_elem_approx[1]
1899 << " delta " << norm_elem[0]-norm_elem_approx[0] << " " << norm_elem[1]-norm_elem_approx[1]
1900 << finl;
1901 if (std::fabs(surface_tot-surface_tot_approx)>DMINFLOAT)
1902 Cerr << "surface -- exact "
1903 << surface_tot << " approx "
1904 << surface_tot_approx << " delta "
1905 << surface_tot-surface_tot_approx << finl;
1906 Cerr << "End of comparison" << finl;
1907 }
1908 double factor = surface_tot/pow(volumes[elem], 2./3.);
1909 if (factor < 1.e-6)
1910 {
1911 Cerr << "We are skipping cell " << elem << "because the interface in it has negligible surface!!" << finl;
1912 continue; // skip cells crossed by almost no interface.
1913 }
1914
1915 // The offset distance should be accounted for because the methods in_out counts the origin at the cell
1916 {
1917 // in_out are real absolute coordinates.
1918 // We should make the "y" a normal distance to TCL
1919 const int korient = zvdf.orientation(num_face);
1920 const double ywall =zvdf.xv(num_face, korient); // the y coord of the wall y0
1921 in_out(0,korient) -= ywall; // yl -y0
1922 in_out(1,korient) -= ywall; // yr -y0
1923 //in_out(0,1) += dist;
1924 //in_out(1,1) += dist;
1925 if (zvdf.dist_face_elem0(num_face,elem)>0)
1926 {
1927 // The face is on top of the element, so distance will be negative.
1928 // We want to count it positive by convention so :
1929 in_out(0,korient) *= -1;
1930 in_out(1,korient) *= -1;
1931 }
1932 assert(in_out(0,korient) >=-Objet_U::precision_geom);
1933 assert(in_out(1,korient) >=-Objet_U::precision_geom);
1934 }
1935 const double xl = in_out(0,0);
1936 const double yl = in_out(0,1);
1937 const double xr = in_out(1,0);
1938 const double yr = in_out(1,1);
1939
1940 // Cerr << "xl,yl, xr,yr = " << xl << " " << yl << " " << xr << " " << yr << finl;
1941 double theta_app_loc = compute_local_cos_theta(parcours, num_face, norm_elem);
1942
1943 double Q_meso = 0.;
1944 double Q_int = 0.;
1945
1946
1947 // for the last meso cell, if Front do not cut the right face of cell, only part of Meso contri is considered
1948 // the corresponding flux will be underestimated
1949 // we should ONLY consider cells before this last one
1950 // To do this, here we put 0 for the this flux, it will then be eliminated in the subsequent part of the compute_tcl_flux.
1951 // flux in this cell is compute by the default macro zone
1952 const int korient = zvdf.orientation(num_face);
1953 const double cell_left = zvdf.xp(elem, 1-korient)-0.5*zvdf.dim_elem(elem, 1-korient); // in 2D case
1954 const double ytop = std::fmax(yr,yl);
1955 const double xleft = std::fmin(xr,xl);
1956
1957 if (est_egal(xleft, cell_left) && est_egal(ytop, ymeso_))
1958 {
1959 Q_int = 0.;
1960 }
1961 else
1962 {
1963 Q_int = compute_Qint(in_out, theta_app_loc, num_face, Q_meso);
1964 }
1965
1966
1967 // const double value = jump_inv_rho*Q_int/Lvap;
1968 // Cerr << "[TCL-meso] Local source in elem=[" << elem << "] with value= " << value << "[m2.s-1]" << finl;
1969 // Cerr << "Qint= " << Q_int << finl;
1970
1971 if (std::fabs(Q_int)<DMINFLOAT)
1972 continue;
1973
1974 if (first_call_for_this_mesh)
1975 {
1976 // We update values and integrals only at the first call
1977 instant_mmeso_evap_ += (Q_int/Lvap)*dt; // total mass of liquid evaporated
1978 instant_vmeso_evap_ = (instant_mmeso_evap_*jump_inv_rho); // total volume of liquid evaporated
1980 }
1981 Cerr.precision(16);
1982 // Cerr << "[TCL: MESO] time = " << integration_time_ << " Qmeso= " << Q_meso << " Qint " << Q_int << finl;
1983 Cerr.precision(7);
1984 Cerr << "time = " << integration_time_ << " instantaneous mass-meso-evaporation = " << instant_mmeso_evap_ << " instantaneous meso-evaporation = " << instant_vmeso_evap_ << finl;
1985 elems_with_CL_contrib.append_array(elem);
1986 //mpoint_from_CL.append_array((Q_meso*surface_tot/v)/Lvap); // VP: replaced Q_int by Q_meso....unit--kg/m^2.s
1987 double x1=0., y1=0.;
1988 double x2=0., y2=0.;
1989 // point 0 will be the left if (left lower than right)&&(M lower than left)
1990 // otherwise, it should be point M if M is in the elem
1991 double x0=0., y0=0.;
1992 if (yl<yr)
1993 {
1994 x1=xl;
1995 y1=yl;
1996 x2=xr;
1997 y2=yr;
1998 }
1999 else
2000 {
2001 x2=xl;
2002 y2=yl;
2003 x1=xr;
2004 y1=yr;
2005 }
2006 if (ym_<=y1)
2007 {
2008 // micro not in that cell:
2009 x0=x1;
2010 y0=y1;
2011 }
2012 else if(ym_<=y2)
2013 {
2014 // point M is in that cell:
2015 // ie PART of the interface is in micro.
2016 y0=ym_;
2017 const double f = (y0-y1)/(y2-y1);
2018 x0=x1+f*(x2-x1);
2019 Cerr << "[x0 vs x_cl] t= "<< integration_time_ << " elem= " << elem << " x0/x_cl " << x0<< " " <<x_cl_<< finl;
2020 }
2021 else
2022 {
2023 // That cell is fully micro ie ym>y2>y1
2024 // in that case, smeso should be 0. :
2025 y0=y2;
2026 }
2027 const double dx = x2-x0;
2028 const double dy = y2-y0;
2029 const double s_meso = sqrt(dx*dx+dy*dy);
2030 if (s_meso<DMINFLOAT)
2031 {
2032 // Qmeso is probably zero too
2033 mpoint_from_CL.append_array(0.);
2034 }
2035 else
2036 {
2037 mpoint_from_CL.append_array(Q_int/(surface_tot*Lvap)); // LW 2023.27.09 coherance with Qint used in Q_from_CL to compute a mean weighted by surface_tot
2038 }
2039 instant_Qmeso += Q_meso;
2040 {
2041 // comparison s_meso as dist_LR to the reconstruction based on surface_tot
2042 // Si la CL est dans la maille...
2043 if ((Objet_U::bidim_axi) && ((xr-x_cl_)*(xl-x_cl_)<=0.))
2044 {
2045 double S_micro = Maillage_FT_Disc::angle_bidim_axi()*x_cl_*sm_;
2046 const double rm = 0.5*(xr+xl);
2047 const double s_meso_assessed = (surface_tot-S_micro)/(Maillage_FT_Disc::angle_bidim_axi()*rm);
2048 Cerr.precision(16);
2049 Cerr << "[TCL: MESO: Assessment-S_meso] t= "<< integration_time_ << " elem= " << elem << " LR= " ;
2050 Cerr << s_meso << " Ameso/2pir= " << s_meso_assessed << " err(%)= " << 50.*std::abs(s_meso_assessed-s_meso)/(s_meso_assessed+s_meso) << finl;
2051 Cerr.precision(7);
2052 }
2053 }
2054 Q_from_CL.append_array(Q_int);
2055 num_faces.append_array(num_face);
2056 // instant_mmeso_evap_ += Q_int/Lvap; // total mass of liquid evaporated
2057 // instant_vmeso_evap_ += instant_mmeso_evap_/rho_phase_1; // total volume of liquid evaporated
2058 }
2059 }
2060 instant_Qmeso = mp_sum(instant_Qmeso);
2061
2062 const double verbosity=1;
2063 if (verbosity)
2064 {
2065 const int nb_contact_line_contribution = elems_with_CL_contrib.size_array();
2066 if (nb_contact_line_contribution>0 )
2067 {
2068 const double t = ns.schema_temps().temps_courant();
2069 Cerr << " time " << t << finl;
2070 Cerr << " nb_contact_line_contribution " << nb_contact_line_contribution << finl;
2071 Cerr << " ********* VALUES OF CONTACT LINE CONTRIBUTION *************** " << finl;
2072 Cerr << "elem\t| face\t| Q\t\t| mp" << finl;
2073 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2074 {
2075 Cerr << elems_with_CL_contrib[idx] << "\t| " << num_faces[idx] << "\t| "
2076 << Q_from_CL[idx] << "\t| " << mpoint_from_CL[idx] << finl;
2077 }
2078 Cerr << " ************************************************************* " << finl;
2079 Cerr << "[instant-Q] time micro meso " << t << " " <<
2080 instant_Qmicro << " " << instant_Qmeso << finl;
2081 Cerr << " ************************************************************* " << finl;
2082 }
2083 }
2084
2085 // double micro_mevap = instant_mmicro_evap_ + instant_mmeso_evap_;
2086 // You want the total value on all processors:
2087 // micro_mevap = Process::mp_sum(micro_mevap);
2088
2089 // Temporary code : Later, we will either (i) fill elems_ directly without using a temporary elems_with_CL_contrib
2090 // or (ii) make a list without repetition (summing up values for micro and meso together)
2091 // Store :
2092
2093 elems_.resize_array(0); // to empty the list
2094 boundary_faces_.resize_array(0);
2095 mp_.resize_array(0);
2096 Q_.resize_array(0);
2097 const int nn = elems_with_CL_contrib.size_array();
2098 assert(num_faces.size_array() == nn);
2099 assert(mpoint_from_CL.size_array() == nn);
2100 assert(Q_from_CL.size_array() == nn);
2101 for (int idx = 0; idx < nn; idx++)
2102 {
2103 const int elem = elems_with_CL_contrib[idx];
2104 elems_.append_array(elem);
2105 boundary_faces_.append_array(num_faces[idx]);
2106 mp_.append_array(mpoint_from_CL[idx]);
2107 Q_.append_array(Q_from_CL[idx]);
2108 }
2109 // GB 2023.04.07: a time integral. Formulae modified but not validated.
2110 const double collect_vevap = Process::mp_sum(instant_vmicro_evap_ + instant_vmeso_evap_)*dt;
2112 {
2113 vevap_int_ +=collect_vevap;
2114 Cerr << "[TCL: MICRO+MESO] vevap_int_(micro+meso) = " << vevap_int_ << " time = " << integration_time_ << finl;
2115 }
2116 }
2117}
2118
2119// correct mpoint with values from TCL model.
2121{
2122 const int nb_contact_line_contribution = elems_.size_array();
2123 Cerr << " nb_contact_line_contribution #" << nb_contact_line_contribution << finl;
2124
2125 // I believe it is required to put zero in all cells first to remove any possible macroscopic contribution.
2126 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2127 {
2128 const int elem = elems_[idx];
2129 mpoint(elem) = 0.;
2130 }
2131
2132 // Then, we can sum our micro and meso contributions :
2133 // Unit: kg/(m2s)
2134 // The area on which mp_ should be applied is by definition the total interface area within that cell.
2135 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2136 {
2137 const int elem = elems_[idx];
2138 mpoint(elem) += mp_[idx];
2139 Cerr << "[TCL] contrib added to mpoint for cell " << elem << " with value= " << mp_[idx] << finl;
2140 }
2141}
2142
2143// correct secmem2 with values from TCL model.
2144void Triple_Line_Model_FT_Disc::corriger_secmem(const double coef, DoubleTab& secmem2) const
2145{
2146 const int nb_contact_line_contribution = elems_.size_array();
2147 // const double max_val_before = max_array(secmem2);
2148 // const double min_val_before = min_array(secmem2);
2149 // I believe it is required to put zero in all cells with TCL model first to remove any possible macroscopic contribution.
2150 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2151 {
2152 const int elem = elems_[idx];
2153 secmem2(elem) =0.;
2154 }
2155
2156 // Then, we can sum our micro and meso contributions :
2157 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2158 {
2159 const int elem = elems_[idx];
2160 const double Q_val = Q_[idx];
2161 const double value = coef*Q_val;
2162 secmem2(elem) += value; // '+=' because several contribs are in the same cell element.
2163 }
2164 // Cerr << "[secmem2] max before/after TCL model: " << max_val_before << " / " << max_array(secmem2) << finl;
2165 // Cerr << "[secmem2] min before/after TCL model: " << min_val_before << " / " << min_array(secmem2) << finl;
2166}
2167
2168// In cells where the TCL model is activated, the mean liquid temperature in each cell should be
2169// computed in agreement with the meso-scale model. Based on the quasi-steady solution of diffusion in
2170// a wedge, the temperature is assumed to depend only on the local angle (in polar coordinates) as :
2171// T = Twall + DeltaT * theta/alpha,
2172// where DeltaT = Tsat-Twall, alpha is the wedge angle (current interface slope at local coord 's'
2173// (ie within the current cell), and theta is the angular coordinate.
2174// Based on this temperature profile, the mean value in cell 'j' can be readily calculated as :
2175// <T>(j) = Twall + 0.5 * DeltaT
2176//
2178{
2179 for (int idx = 0; idx < elems_.size_array(); idx++)
2180 {
2181 const int elem = elems_[idx];
2182 const int num_face = boundary_faces_[idx];
2183 const double Twall =ref_eq_temp_->get_Twall_at_face(num_face);
2184 const double DeltaT = TSAT_CONSTANTE-Twall;
2185 const double Tbefore = temperature(elem);
2186 temperature(elem) =Twall + 0.5*DeltaT;
2187 Cerr << "[Temperature correction] elem= " << elem << " Tbefore/Tafter: " << Tbefore << " / " << temperature(elem) << finl;
2188 }
2189}
2190
2191// In the TCL region, each cell recieve a wall-flux phi_w assumed in direct transfer with the interface, that is:
2192// Qwall = A_w phi_w = A_i phi_i = Qinterf = Qmicro + Qmeso.
2193// Besides, internal (diffusive) fluxes are set to zero.
2194// And the cell mean-temperature is set according to the model to :
2195// <T>(j) = Twall + 0.5 * DeltaT
2196// Consequently, if either (Twall is time-dependent) or (a cell gets in/out of the TCL region), or (there is a
2197// convective flux at the matching face), then there is an imbalance between the time evolution of the internal
2198// energy in the TCL region and the fluxes.
2199// Several options :
2200// (i) We store it to correct the interfacial flux (for instance the micro) at the next time-step?
2201// (ii) The disequilibrium is used to modify the wall flux (complicated, as fluxes have already been computed)?
2202// (iii) We correct the closest fully liquid neighbor with this energy difference.
2203//
2204// Option (iii) seems the simplest, so we go for it.
2205double compute_global_TCL_energy_disequilibrium()
2206{
2207 return 0.;
2208}
2209
2211{
2212 if (TCL_energy_correction_ == 0)
2213 return;
2214
2215 // In Joules :
2216 const double disequilibrium = compute_global_TCL_energy_disequilibrium();
2217 const int elem = 0; //closest_liquid_neighbour has to be determined;
2218 Cerr << "Code unfinished in Triple_Line_Model_FT_Disc::correct_TCL_energy_evolution" << finl;
2219 Process::exit();
2220 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, ref_eq_temp_->domaine_dis());
2221 const double vol = domaine_vf.volumes(elem);
2222 // Minus sign because we want to compensate the disequilibrium
2223 const double deltaT = -disequilibrium/(rhocpl_*vol);
2224 temperature(elem) += deltaT;
2225}
2226
2228{
2229 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, ref_eq_temp_->domaine_dis());
2230 const int nb_contact_line_contribution = elems_.size_array();
2231 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2232 {
2233 const int elem = elems_[idx];
2234 const int num_face = boundary_faces_[idx];
2235 double flux=0., Twall=0.;
2236 ref_eq_temp_->get_flux_and_Twall(num_face,
2237 flux, Twall);
2238 temperature(elem) =Twall;
2239 }
2240 // MEMO : remove the previous loop if num_faces is computed here.
2241 // Then, we can sum our micro and meso contributions :
2242 for (int idx = 0; idx < nb_contact_line_contribution; idx++)
2243 {
2244 const int elem = elems_[idx];
2245 const int num_face = boundary_faces_[idx];
2246 // Get the distance between the center of the elem and the given face:
2247 const double d = compute_distance(domaine_vf, num_face, elem);
2248 double flux=0., Twall=0.;
2249 ref_eq_temp_->get_flux_and_Twall(num_face, flux, Twall);
2250 // It is the total flux, so It should simply be :
2251 temperature(elem) = Twall - flux*d/kl_cond_; // Can be done several times, no problem.
2252 }
2253}
2254
2256{
2257 if (read_via_file_)
2258 {
2259 const double Twall = ref_eq_temp_.valeur ().get_Twall_at_face (
2260 num_face);
2261
2262 const int num_col = num_column_qtcl_; // colon number corresponding to Qtcl
2263 const int num_tem = num_column_tem_;
2264
2265 double Qtcl_present_ = 0.;
2266
2267 int ind = 0;
2268 while (ind < tab_Mtcl_.dimension (1) && tab_Mtcl_ (num_tem, ind) < Twall)
2269 {
2270 ++ind;
2271 }
2272 if (ind == 0)
2273 {
2274 if (!est_egal (tab_Mtcl_ (num_tem, ind), 0))
2275 Qtcl_present_ = tab_Mtcl_ (num_col, ind) *Twall / tab_Mtcl_ (num_tem, ind);
2276 else
2277 Qtcl_present_ = 0. ;
2278 }
2279 else if (ind == tab_Mtcl_.dimension (1))
2280 {
2281 Qtcl_present_ = tab_Mtcl_ (num_col, ind - 1);
2282 }
2283 else
2284 {
2285 double x1 = tab_Mtcl_ (num_tem, ind - 1);
2286 double x2 = tab_Mtcl_ (num_tem, ind);
2287 double y1 = tab_Mtcl_ (num_col, ind - 1);
2288 double y2 = tab_Mtcl_ (num_col, ind);
2289 assert(!est_egal (x1, x2));
2290 Qtcl_present_ = y1 + (y2 - y1) * (Twall - x1) / (x2 - x1);
2291 }
2292
2293 if(lissage_tcl_)
2294 {
2295 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
2296 const double t_present = ns.schema_temps().temps_courant();
2297 const double dt = ns.schema_temps().pas_de_temps();
2298 if ( t_present > t_injection_)
2299 {
2300 Qtcl_ = (Qtcl_*(t_present-t_injection_) + dt*Qtcl_present_)/(t_present-t_injection_+dt);
2301 }
2302 else
2303 Qtcl_ = Qtcl_present_;
2304 }
2305 else
2306 Qtcl_ = Qtcl_present_;
2307
2308 }
2309 return Qtcl_;
2310}
2311
2313{
2314 if (read_via_file_)
2315 {
2316
2317 double Twall = 0.;
2318 const Domaine_Cl_dis_base& zcldis = ref_eq_temp_->domaine_Cl_dis();
2319 const Domaine_Cl_VDF& zclvdf = ref_cast(Domaine_Cl_VDF, zcldis);
2320 const Cond_lim& la_cl = zclvdf.la_cl_de_la_face (num_face);
2321 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2322 const int ndeb = le_bord.num_premiere_face();
2323 if (sub_type(Echange_contact_VDF_FT_Disc, la_cl.valeur ()))
2324 {
2325 const Echange_contact_VDF_FT_Disc& la_cl_typee = ref_cast(
2326 Echange_contact_VDF_FT_Disc, la_cl.valeur ());
2327 const double T_imp = la_cl_typee.Ti_wall (num_face - ndeb);
2328 Twall = T_imp;
2329 }
2330 else if (sub_type(Echange_impose_base, la_cl.valeur ()))
2331 {
2332 const Echange_impose_base& la_cl_typee = ref_cast(Echange_impose_base,
2333 la_cl.valeur ());
2334 const double T_imp = la_cl_typee.T_ext (num_face - ndeb);
2335 Twall = T_imp;
2336 }
2337 else
2338 {
2339 Cerr
2340 << "How can we set Twall when temperature(elem) is not valid? Or is it?"
2341 << finl;
2342 Process::exit ();
2343 }
2344
2345 // const double Twall = ref_eq_temp_.valeur ().get_Twall_at_face (
2346 // num_face);
2347
2348 const int num_col = num_column_theta_; // colon number corresponding to theta_app
2349 const int num_tem = num_column_tem_;
2350 double theta_app_present_ = 0.;
2351
2352 int ind = 0;
2353 while (ind < tab_Mtcl_.dimension (1) && tab_Mtcl_ (num_tem, ind) < Twall)
2354 {
2355 ++ind;
2356 }
2357 if (ind == 0)
2358 {
2359 theta_app_present_ = tab_Mtcl_ (num_col, 0);
2360 }
2361 else if (ind == tab_Mtcl_.dimension (1))
2362 {
2363 theta_app_present_ = tab_Mtcl_ (num_col, ind - 1);
2364 }
2365 else
2366 {
2367 double x1 = tab_Mtcl_ (num_tem, ind - 1);
2368 double x2 = tab_Mtcl_ (num_tem, ind);
2369 double y1 = tab_Mtcl_ (num_col, ind - 1);
2370 double y2 = tab_Mtcl_ (num_col, ind);
2371 assert(!est_egal (x1, x2));
2372 theta_app_present_ = y1 + (y2 - y1) * (Twall - x1) / (x2 - x1);
2373 }
2374 // if num <= 1, i.e., =0 or =1 we do not change the theta_app_:No numerical forcing breakup
2375 // else replaced by a big value for forcing numerical breakup
2376 if ( Rc_tcl_GridN() >= 1 && !reinjection_tcl())
2377 {
2378 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur ();
2379 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, ns.domaine_dis());
2380
2381 const IntVect& orientation = zvdf.orientation();
2382 const IntTab& elem_faces = zvdf.elem_faces();
2383
2384 int elem_voisin = zvdf.face_voisins (num_face, 0) + zvdf.face_voisins (num_face, 1) + 1;
2385 int numfacex = -1;
2386
2387 const int nb_voisins = elem_faces.dimension(1);
2388 for (int iv=0; iv < nb_voisins; iv++)
2389 {
2390 const int num_face2 = elem_faces(elem_voisin,iv);
2391 if (orientation(num_face2) == 0 )
2392 {
2393 numfacex = num_face2;
2394 break;
2395 }
2396 }
2397 assert(numfacex>=0);
2398 const double cell_size = 2. * std::fabs (zvdf.dist_face_elem0 (numfacex, elem_voisin));
2399 const double xwall_ = zvdf.xv(num_face, 0);
2400 if (xwall_ <= cell_size*Rc_tcl_GridN() )
2401 theta_app_present_ = thetaC_tcl();
2402 }
2403
2404 if(lissage_tcl_)
2405 {
2406 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
2407 const double t_present = ns.schema_temps().temps_courant();
2408 const double dt = ns.schema_temps().pas_de_temps();
2409 if ( t_present > t_injection_)
2410 {
2411 theta_app_ = (theta_app_*(t_present-t_injection_) + dt*theta_app_present_)/(t_present-t_injection_+dt);
2412 }
2413 else
2414 theta_app_ = theta_app_present_;
2415 }
2416 else
2417 theta_app_ = theta_app_present_;
2418 }
2419
2420 return theta_app_;
2421}
2422
2423// Account the effect of velocity on the apparent contact angle and heat flux
2424// Interpolation uni-lineaire dans chaque direction de chaque compo : interpoler_simple_vitesse_point_vdf(champ_vitesse, coord, element, vitesse, explicit_u_NS_);
2425// !!! vit should be updated for all procs... as a echange_espace_virtuel is called at the end of
2426// Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee() maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2427void Triple_Line_Model_FT_Disc:: correct_theta_app_qtcl(double& theta_v,double& qtcl,const int num_face_wall, const int num_som, const DoubleTab& vit) const
2428{
2429
2430 const Transport_Interfaces_FT_Disc& eq_transport = ref_eq_interf_.valeur();
2431 const Maillage_FT_Disc& maillage = eq_transport.maillage_interface();
2432 const DoubleTab& sommets = maillage.sommets();
2433 const Parcours_interface& parcours = eq_transport.parcours_interface();
2434
2435 FTd_vecteur3 nface = {0., 0., 0.} ;
2436 parcours.calculer_normale_face_bord(num_face_wall, sommets(num_som,0)
2437 , sommets(num_som,1), 0., nface[0], nface[1], nface[2]) ;
2438
2439 // The other som of the facette is som[1-i2] :
2440 // Cerr << " sommet-1 x= " << sommets_(som[1-i2],0) << " y= " << sommets_(som[1-i2],1) << " time_sommet= " << t << finl;
2441 // if(dt != 0.) double cl_v = (sommets_(som[i2],0) - x_cl_)/dt;
2442 const int isom1 = num_som;
2443 // The second vertex of the segment should not be a contact line
2444 // so we compute its tangential velocity:
2445
2446 const int nb_compo = vit.dimension(1);
2447 double vn = 0.;
2448 double v_cl = 0.;
2449 double v_comp = 0.;
2450 // Component of the velocity is calculated along the direction of wall as vw = v - (v.n)n where n is the wall face normal
2451 // and v is the velocity vector of the node under consideration.
2452 for (int k=0 ; k<nb_compo ; k++)
2453 {
2454 const double vk = (double) vit(isom1,k);
2455 vn += vk*nface[k];
2456 Cerr << "[TCL-model] Estimated TCL velocity[som=" << isom1
2457 << ", compo["<< k<<"]= " << vk << "m/s)" << " face-normal= " << nface[k] << finl;
2458 // Cerr << "Vn= " << vn << finl;
2459 }
2460 nface[0] = vn*nface[0];
2461 nface[1] = vn*nface[1];
2462 nface[2] = vn*nface[2];
2463 for (int k=0 ; k<nb_compo ; k++)
2464 {
2465 v_comp = vit(isom1,k) - nface[k];
2466 v_cl += v_comp*v_comp;
2467 }
2468 v_cl = sqrt(v_cl);
2469
2470
2471 {
2472 const double absX = abs(vit(isom1,0) - nface[0]);
2473 const double absY = abs(vit(isom1,1) - nface[1]);
2474 const double absZ = abs(vit(isom1,2) - nface[2]);
2475
2476 if (absX >= absY && absX >= absZ)
2477 {
2478 // x component is the largest
2479 v_cl = (vit(isom1,0) - nface[0]) > 0. ? v_cl : -v_cl;
2480 }
2481 else if (absY >= absX && absY >= absZ)
2482 {
2483 // y component is the largest
2484 v_cl = (vit(isom1,1) - nface[1]) > 0. ? v_cl : -v_cl;
2485 }
2486 else
2487 {
2488 // z component is the largest
2489 v_cl = (vit(isom1,2) - nface[2]) > 0. ? v_cl : -v_cl;
2490 }
2491 }
2492
2493 Cerr << "[TCL-model] projected v_cl = " << v_cl << finl;
2494
2495 // And we assume as a best guess that the contact line
2496 // velocity should be approximately that of the first
2497 // marker that is not a contact line. We use it
2498 // directly to build the Capilary number Ca.
2499
2500 // !!! phase 1: liquid; I: phase indicator of LIQUID
2501 const Navier_Stokes_FT_Disc& ns = ref_ns_.valeur();
2502
2503 const Fluide_Diphasique& fluide = ns.fluide_diphasique();
2504 const double sigma = fluide.sigma();
2505
2506 const DoubleTab& tab_nu_phase_1 = fluide.fluide_phase(1).viscosite_cinematique().valeurs();
2507 const double nu_phase_1 = tab_nu_phase_1(0, 0);
2508 const double Ca = nu_phase_1*v_cl/sigma;
2509 Cerr << "[TCL-model] Capillary_number = " << Ca << finl;
2510
2511 const double cst_e = exp(1.);
2512 const double deg_to_rad = M_PI / 180.;
2513 const double lv = 3.*ls_/cst_e/(theta_v*deg_to_rad); // Voinov length Eq 17 Vadim S. Nikolayev et al 2024 J. Phys.: Conf. Ser. 2766 012123
2514
2515 double theta_app = pow((theta_v*deg_to_rad),3) - 9. * Ca * log(std::max(xm_, 1.e-20)/lv);
2516 theta_app = pow(std::max(theta_app, 0.),1./3.);
2517
2518 // Cerr << "[TCL-model] theta_after " << theta_app << finl;
2519 // We store the apparent contact angle in costheta for
2520 // later use in the calculation of the curvature
2521 // (it is through this mean that we will consider
2522 // it and try to indirectly satisfy it).
2523 theta_v =(theta_app/M_PI)*180;
2524
2525 Cerr << "[TCL-model] Contact_angle after correction= " << theta_v << finl;
2526
2527 double Twall = 0.;
2528 const Domaine_Cl_dis_base& zcldis = ref_cast(Domaine_Cl_dis_base, ref_eq_temp_->domaine_Cl_dis());
2529 const Domaine_Cl_VDF& zclvdf = ref_cast(Domaine_Cl_VDF, zcldis);
2530 const Cond_lim& la_cl = zclvdf.la_cl_de_la_face (num_face_wall);
2531 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2532 const int ndeb = le_bord.num_premiere_face();
2533 if (sub_type(Echange_contact_VDF_FT_Disc, la_cl.valeur ()))
2534 {
2535 const Echange_contact_VDF_FT_Disc& la_cl_typee = ref_cast(
2536 Echange_contact_VDF_FT_Disc, la_cl.valeur ());
2537 const double T_imp = la_cl_typee.Ti_wall (num_face_wall - ndeb);
2538 Twall = T_imp;
2539 }
2540 else if (sub_type(Echange_impose_base, la_cl.valeur ()))
2541 {
2542 const Echange_impose_base& la_cl_typee = ref_cast(Echange_impose_base,
2543 la_cl.valeur ());
2544 const double T_imp = la_cl_typee.T_ext (num_face_wall - ndeb);
2545 Twall = T_imp;
2546 }
2547 else
2548 {
2549 Cerr
2550 << "How can we set Twall when temperature(elem) is not valid? Or is it?"
2551 << finl;
2552 Process::exit ();
2553 }
2554 assert(kl_cond_*Ri_>0.);
2555 double ln_y = log(sm_*theta_app/kl_cond_/Ri_+1.);
2556 // Twall here is (Wall temperature - saturation temperature)..unit of Q_meso is W/m
2557 qtcl = kl_cond_*(Twall/theta_app)*ln_y; // qtcl of Q_int is W/m
2558}
2559
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
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.
class Domaine_Cl_VDF
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 ...
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 dim_elem(int, int) const
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
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
int face_numero_bord(int num_face) const
Definition Domaine_VF.h:689
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
double volumes(int i) const
Definition Domaine_VF.h:113
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
: class Echange_contact_VDF_FT_Disc
virtual double Ti_wall(int num) const
classe Echange_impose_base: Cette condition limite sert uniquement pour l'equation d'energie.
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
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
double chaleur_latente() const
const Fluide_Incompressible & fluide_phase(int la_phase) const
classe Fluide_Incompressible Cette classe represente un d'un fluide incompressible ainsi que
const Champ_Don_base & viscosite_cinematique() const
Definition Fluide_base.h:58
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
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
: class Intersections_Elem_Facettes
const ArrOfInt & index_elem() const
Renvoie un tableau de taille domaine.
const ArrOfInt & index_facette() const
Renvoie un tableau de taille "nombre de facettes de l'interface" pour un element 0 <= facette < nb_fa...
const Intersections_Elem_Facettes_Data & data_intersection(int index) const
Renvoie les donnees de l'intersection stockee a l'indice "index" dans le tableau "data" ( 0 <= index ...
int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::in) override
Ouverture du fichier.
int get(int *ob, std::streamsize n) override
: class Maillage_FT_Disc Cette classe decrit un maillage:
int get_mesh_tag() const
return mesh_state_tag_
int nb_sommets() const
renvoie le nombre de sommets (reels et virtuels) (egal a sommets().
const DoubleTab & sommets() const
renvoie le tableau des sommets (reels et virtuels) dimension(0) = nombre de sommets,
int sommet_ligne_contact(int i) const
double temps() const
return temps_physique_ (temps_physique_ ne sert a rien en interne.
virtual const DoubleTab & get_update_normale_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
int sommet_virtuel(int i) const
const Intersections_Elem_Facettes & intersections_elem_facettes() const
virtual const ArrOfDouble & get_update_surface_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
const ArrOfInt & sommet_face_bord() const
pour postraitement, renvoie sommet_face_bord_
static double angle_bidim_axi()
renvoie l'angle solide qui sert a calculer les surfaces et les volumes en bidim_axi
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
virtual const Champ_Don_base & capacite_calorifique() const
Renvoie la capacite calorifique du milieu.
virtual const Champ_Don_base & conductivite() const
Renvoie la conductivite du milieu.
virtual const Champ_base & masse_volumique() const
Renvoie la masse volumique du milieu.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
virtual const Fluide_Diphasique & fluide_diphasique() const
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
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
static double precision_geom
Definition Objet_U.h:86
static int bidim_axi
Definition Objet_U.h:102
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void dictionnaire(const char *option_name, int value)
Add an (option name, integer value) entry to the dictionary attached to a previously registered integ...
Definition Param.cpp:293
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
void calculer_normale_face_bord(int num_face, double x, double y, double z, double &nx_, double &ny_, double &nz_) const
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
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 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
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
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
virtual int get_champ_post_FT(const Motcle &champ, Postraitement_base::Localisation loc, DoubleTab *dtab=0) const
Cherche le champ discret aux interfaces dont le nom est "champ", et verifie qu'il peut etre postraite...
virtual const Parcours_interface & parcours_interface() const
const Champ_Inc_base & inconnue() const override
const Maillage_FT_Disc & maillage_interface() const
void set_wall_adjacent_temperature_according_to_TCL_model(DoubleTab &temperature) const
const double & get_theta_app() const
void corriger_secmem(const double coef, DoubleTab &secmem2) const
void corriger_mpoint(DoubleTab &mpoint) const
void correct_TCL_energy_evolution(DoubleTab &temperature) const
void associer_pb(const Probleme_base &)
void correct_theta_app_qtcl(double &theta_app_, double &qtcl, const int num_face_wall, const int num_som, const DoubleTab &vit) const
double compute_local_cos_theta(const Parcours_interface &parcours, const int num_face, const FTd_vecteur3 &norm_elem) const
double compute_Qint(const DoubleTab &in_out, const double theta_app_locs, const int num_face, double &Qmeso) const
void set_param(Param &p) const override
void correct_wall_adjacent_temperature_according_to_TCL_fluxes(DoubleTab &temperature) const
void compute_approximate_interface_inout(const Domaine_VDF &zvdf, const int korient, const int elem, const int num_face, DoubleTab &in_out, FTd_vecteur3 &norm_elem, double &surface_tot) const
void get_in_out_coords(const Domaine_VDF &zvdf, const int elem, const double dt, DoubleTab &in_out, FTd_vecteur3 &norm_elem, double &surface_tot)