TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Transport_Interfaces_FT_Disc.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Transport_Interfaces_FT_Disc.h>
17#include <Probleme_FT_Disc_gen.h>
18#include <Operateur.h>
19#include <Motcle.h>
20#include <EcritureLectureSpecial.h>
21#include <Discret_Thyd.h>
22#include <Schema_Temps_base.h>
23#include <Parser.h>
24#include <Domaine_VF.h>
25#include <Domaine_VDF.h>
26#include <Sous_Domaine.h>
27#include <Champ_Face_VDF.h>
28#include <Champ_P1NC.h>
29#include <Champ_Fonc_P1NC.h>
30#include <Fluide_Diphasique.h>
31#include <Fluide_Incompressible.h>
32#include <Perf_counters.h>
33#include <Paroi_FT_disc.h>
34#include <Champ_Fonc_Face_VDF.h>
35#include <Scatter.h>
36#include <LecFicDiffuse.h>
37#include <Sauvegarde_Reprise_Maillage_FT.h>
38#include <SFichier.h>
39#include <Debog.h>
40#include <Format_Post_Lata.h>
41#include <Connex_components.h>
42#include <Connex_components_FT.h>
43#include <Loi_horaire.h>
44#include <Transport_Marqueur_FT.h>
45#include <communications.h>
46#include <Convection_Diffusion_Temperature_FT_Disc.h>
47
48#include <Champ_Fonc_P0_base.h>
49#include <EFichierBin.h>
50#include <Param.h>
51#include <sys/stat.h>
52#include <TRUSTList.h>
53#include <Domaine.h>
54#include <TRUSTTrav.h>
55#include <Dirichlet_paroi_fixe.h>
56#include <Dirichlet_paroi_defilante.h>
57#include <Echange_contact_VDF_FT_Disc.h>
58#include <TRUST_2_PDI.h>
59#include <Avanc.h>
60
61
62// XD transport_interfaces_ft_disc eqn_base transport_interfaces_ft_disc INHERITS_BRACE Interface tracking equation for
63// XD_CONT Front-Tracking problem in the discontinuous version.
64// XD attr conditions_initiales|initial_conditions cond_init_ft_list conditions_initiales OPT Definition of the
65// XD_CONT initial interface(s) (see the cond_init_ft_list entry list below for the full syntax).
66// XD attr indic_faces_modifiee bloc_lecture indic_faces_modifiee OPT not_set
67Implemente_instanciable_sans_constructeur_ni_destructeur(Transport_Interfaces_FT_Disc,"Transport_Interfaces_FT_Disc",Transport_Interfaces_base);
68
69/*! @brief Classe outil ou on stocke tout le bazar qui sert au fonctionnement de l'equation de transport.
70 *
71 * Permet de sauvegarder/reprendre les donnees d'interface
72 * (probleme des reprises avec pas de temps multiples),
73 * et de reduire les dependances en n'incluant presque rien dans Transport_Interfaces_FT_Disc.h
74 *
75 */
76static void eval_vitesse(double x, double y, double z, double t,
77 Parser& px, Parser& py, Parser& pz,
78 double& vx, double& vy, double& vz)
79{
80 int i0=0, i1=1, i2=2, i3=3;
81 px.setVar(i0,x);
82 px.setVar(i1,y);
83 px.setVar(i2,z);
84 px.setVar(i3,t);
85
86 vx = px.eval();
87 py.setVar(i0,x);
88 py.setVar(i1,y);
89 py.setVar(i2,z);
90 py.setVar(i3,t);
91
92 vy = py.eval();
93 pz.setVar(i0,x);
94 pz.setVar(i1,y);
95 pz.setVar(i2,z);
96 pz.setVar(i3,t);
97 vz = pz.eval();
98}
99static void integrer_vitesse_imposee(
100 Parser& parser_vx, Parser& parser_vy, Parser& parser_vz,
101 double temps, double dt, double& x, double& y, double& z)
102{
103 // Runge Kutta ordre 3:
104 double vx, vy, vz;
105 eval_vitesse(x,
106 y,
107 z,
108 temps,
109 parser_vx,parser_vy,parser_vz,vx,vy,vz);
110 double vx1,vy1,vz1;
111 eval_vitesse(x + vx * dt * 0.5,
112 y + vy * dt * 0.5,
113 z + vz * dt * 0.5,
114 temps + dt * 0.5,
115 parser_vx,parser_vy,parser_vz,vx1,vy1,vz1);
116 double vx2,vy2,vz2;
117 eval_vitesse(x + vx1 * dt * 0.5,
118 y + vy1 * dt * 0.5,
119 z + vz1 * dt * 0.5,
120 temps + dt * 0.5,
121 parser_vx,parser_vy,parser_vz,vx2,vy2,vz2);
122 double vx3,vy3,vz3;
123 eval_vitesse(x + vx2 * dt,
124 y + vy2 * dt,
125 z + vz2 * dt,
126 temps + dt,
127 parser_vx,parser_vy,parser_vz,vx3,vy3,vz3);
128
129 x += (vx + 2.*vx1 + 2.*vx2 + vx3) / 6. * dt;
130 y += (vy + 2.*vy1 + 2.*vy2 + vy3) / 6. * dt;
131 z += (vz + 2.*vz1 + 2.*vz2 + vz3) / 6. * dt;
132}
133
134/*! @brief calcul du vecteur normal a l'interface, aux sommets du maillage d'interface.
135 *
136 * Le tableau "normale" est efface et resize.
137 * La normale est la moyenne des normales des facettes voisines, ponderees par
138 * la surface de la facette.
139 * La norme du vecteur normal n'est pas unitaire !
140 * L'espace virtuel n'est pas a jour !
141 *
142 */
143static void calculer_normale_sommets_interface(const Maillage_FT_Disc& maillage,
144 DoubleTab& normale)
145{
146 const int nsom = maillage.nb_sommets();
147 const int nfaces = maillage.nb_facettes();
148 const int dim = maillage.sommets().line_size();
149 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
150 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
151 const IntTab& facettes = maillage.facettes();
152 const int nsommets_faces = facettes.line_size();
153
154 normale.resize(nsom, dim);
155 normale = 0.;
156 double n[3]= {0,0,0};
157
158 for (int i = 0; i < nfaces; i++)
159 {
160
161 // Somme pour les faces reelles:
162 if (maillage.facette_virtuelle(i))
163 continue;
164
165 const double surface = surface_facettes[i];
166 for (int k = 0; k < dim; k++)
167 n[k] = normale_facettes(i,k) * surface;
168
169 for (int j = 0; j < nsommets_faces; j++)
170 {
171 const int sommet = facettes(i,j);
172 for (int k = 0; k < dim; k++)
173 normale(sommet, k) += n[k];
174 }
175 }
176
177 // Sommer les contributions pour les sommets partages par plusieurs processeurs:
179}
180
181Implemente_instanciable_sans_constructeur_ni_destructeur(Transport_Interfaces_FT_Disc_interne,"Transport_Interfaces_FT_Disc_interne",Objet_U);
182
184{
185 assert(0);
186 return is;
187}
189{
190 assert(0);
191 return os;
192}
193
195{
196 const Nom& fullname = restart ? restart_fname_ : checkpoint_fname_;
197 int index = fullname.find(".");
198 std::string fname = index ==-1 ? fullname.getString() : fullname.getString().substr(0, index); //removing file extension
199 Nom nom_fich_xyz(fname);
200 nom_fich_xyz += Nom("_") + pb_name_;
201 nom_fich_xyz += Nom("_") + ident_;
202 nom_fich_xyz += "_maillage_interface";
203 nom_fich_xyz += ".xyz";
204 return nom_fich_xyz;
205}
206
208{
209 if (fic_front_sauv_)
210 {
211 Cerr << "Transport_Interfaces_FT_Disc::init_save_file Backup file for the FT mesh has already been initialized!" << finl;
213 }
214 else
215 {
216 const Nom& nom_fich_xyz = maillage_interface_xyz_filename(0 /*save mode*/);
217 fic_front_sauv_.typer(EcritureLectureSpecial::get_Output());
218 fic_front_sauv_->ouvrir(nom_fich_xyz);
219 }
220
221}
222
224{
225 if (!fic_front_sauv_)
226 {
227 Cerr << "Transport_Interfaces_FT_Disc::close_save_file Backup file for the FT mesh has not been initialized!" << finl;
229 }
230 else
231 {
233 fic_front_sauv_.valeur() << Nom("fin");
234 (fic_front_sauv_.valeur()).flush();
235 (fic_front_sauv_.valeur()).syncfile();
236 }
237}
238
239/*! @brief for PDI IO: retrieve name and type and dimensions of the indicatrice tag
240 *
241 */
243{
244 std::vector<YAML_data> data = indicatrice_cache->data_a_sauvegarder();
245
246 // the indicatrice cache tag
247 std::string name = pb_name_.getString() + "_" + ident_.getString() + "_indicatrice_cache_tag";
248 YAML_data ictag(name, "int");
249 ictag.set_local(false /*same value for everyone*/);
250 data.push_back(ictag);
251 return data;
252}
253
255{
256 // Il faut sauvegarder l'indicatrice_cache car elle ne peut pas toujours etre
257 // correctement reconstruite a partir de l'interface (on tolere qu'il y ait
258 // des inconsistances) :
259 int bytes=0;
260 bytes += indicatrice_cache->sauvegarder(os);
261
262 int special, afaire;
263 const int format_xyz = EcritureLectureSpecial::is_ecriture_special(special, afaire);
264 if (format_xyz)
265 {
267 {
268 os << indicatrice_cache_tag << finl;
269 }
270 }
272 {
273 std::string name = pb_name_.getString() + "_" + ident_.getString() + "_indicatrice_cache_tag";
274 TRUST_2_PDI pdi_interface;
275 pdi_interface.TRUST_start_sharing(name, &indicatrice_cache_tag);
276 }
277 else
278 os << indicatrice_cache_tag << finl;
279
281 {
282 Cerr << "Transport_Interfaces_FT_Disc_interne::sauvegarder : WARNING ! PDI format is not supported for the FT mesh so we save it in xyz format " << finl;
285 Sortie_Fichier_base& xyz_os = const_cast<Sortie_Fichier_base&>(fic_front_sauv_.valeur());
287 {
288 Nom mon_ident(maillage_interface.que_suis_je());
289 mon_ident += Nom(time_,"%e");
290 xyz_os << mon_ident << finl;
291 xyz_os << maillage_interface.que_suis_je() << finl;
292 }
293 bytes += maillage_interface.sauvegarder(xyz_os);
294
296 {
297 Nom mon_ident(remaillage_interface_.que_suis_je());
298 mon_ident += Nom(time_,"%e");
299 xyz_os << mon_ident << finl;
300 xyz_os << remaillage_interface_.que_suis_je() << finl;
301 }
302 bytes += remaillage_interface_.sauvegarder(xyz_os);
305 }
306 else
307 {
308 bytes += maillage_interface.sauvegarder(os);
309 bytes += remaillage_interface_.sauvegarder(os); // Sauvegarde du temps du dernier remaillage...
310 }
311 return bytes;
312}
313
315{
316 Cerr << "Transport_Interfaces_FT_Disc_interne::reprendre" << finl;
317 Nom ident, type;
319 {
320 TRUST_2_PDI pdi_interface;
321 // getting type
322 Nom name = pb_name_ + "_" + indicatrice_cache->le_nom();
323 pdi_interface.get_type(name, type);
324
325 // getting indicatrice cache tag
326 name = pb_name_ + "_" + ident_ + "_indicatrice_cache_tag";
327 pdi_interface.read(name.getString(), &indicatrice_cache_tag);
328 }
329 else
330 is >> ident >> type;
331
332 if (!indicatrice_cache)
333 {
334 // Le champ n'est pas discretise, on lit ceci pour sauter le bloc
335 indicatrice_cache.typer(type);
336 }
337 indicatrice_cache->reprendre(is);
338
340 {
341 Cerr << "Transport_Interfaces_FT_Disc_interne::reprendre : WARNING ! PDI format is not supported for the FT mesh so we use xyz format" << finl;
345 xyz_is.typer(EcritureLectureSpecial::Input);
346 const Nom& nomfic = maillage_interface_xyz_filename(1 /* restart mode */);
347 xyz_is->ouvrir(nomfic);
348 if (xyz_is->fail())
349 {
350 Cerr << "Error during the opening of the restart file : " << nomfic << finl;
352 }
353 else
354 Cerr << "Reading interface in file " << nomfic << finl;
355
356 Nom mon_ident(maillage_interface.que_suis_je());
357 mon_ident += Nom(time_,"%e");
358 avancer_fichier(xyz_is, mon_ident);
359 maillage_interface.reprendre(xyz_is);
360
361 mon_ident=remaillage_interface_.que_suis_je();
362 mon_ident += Nom(time_,"%e");
363 avancer_fichier(xyz_is, mon_ident);
364 remaillage_interface_.reprendre(xyz_is);
367 }
368 else
369 {
371 maillage_interface.reprendre(is);
372 remaillage_interface_.reprendre(is);
373 }
374 return 1;
375}
376
377/*! @brief constructeur par defaut
378 *
379 * TODO: remove the new Transport_Interfaces_FT_Disc_interne in there. why do that ?
380 */
382{
383 variables_internes_ = new Transport_Interfaces_FT_Disc_interne;
384 temps_debut_=-1.e38;
385 interpolation_repere_local_ = 0;
386 force_.resize(dimension);
387 moment_.resize((dimension==2?1:dimension));
388}
389
390/*! @brief le destructeur qui va avec
391 *
392 */
393Transport_Interfaces_FT_Disc::~Transport_Interfaces_FT_Disc()
394{
395 delete variables_internes_;
396}
397
399{
401}
402
404{
405
406 /* Noms& nom=champs_compris_.liste_noms_compris();
407 nom[0] += le_nom();
408 nom[1] += le_nom();
409 nom[2] += le_nom();
410 nom[3] += le_nom();
411 */
412
415 {
416 Cerr << "Name of subdomaine for interfaces deletion: " << suppression_interfaces_sous_domaine_ << finl;
417 // Juste un test pour verifier que le nom existe:
419 }
420 return is;
421}
422
424{
426 param.ajouter_non_std("maillage",(this)); // XD_ADD_P bloc_lecture
427 // XD_CONT This optional block is used to specify that we want a Gnuplot drawing of the initial mesh. There is only
428 // XD_CONT one keyword, niveau_plot, that is used only to define if a Gnuplot drawing is active (value 1) or not
429 // XD_CONT active (value -1). By default, skipping the block will produce non Gnuplot drawing. This option is to be
430 // XD_CONT used only in a debug process.
431 param.ajouter("remaillage",&remaillage_interface()); // XD_ADD_P bloc_lecture_remaillage
432 // XD_CONT This block is used to specify the operations that are used to keep the solid interfaces in a proper
433 // XD_CONT condition. The remaillage block only contains parameter\'s values.
434 param.ajouter("collisions",&topologie_interface()); // XD_ADD_P bloc_lecture
435 // XD_CONT This block is used to specify the operations that are used when a collision occurs between two parts of
436 // XD_CONT interfaces. When this occurs, it is necessary to build a new mesh that has locally a clear definition of
437 // XD_CONT what is inside and what is outside of the mesh. The collisions can either be active or inactive. If the
438 // XD_CONT collisions are active (highly recommended), a Juric level-set reconstruction method will be used to
439 // XD_CONT re-create the new mesh after each coalescence or breakup. An option Juric_local phase_continue N can be
440 // XD_CONT used to force the remeshing to impact only a local portion of the mesh, near the collision. The next line
441 // XD_CONT (type_remaillage) is used to state whose field will be used for the level-set computation. Main option is
442 // XD_CONT Juric, a remeshing that is compatible with parallel computing. When using Juric level-set remeshing, the
443 // XD_CONT source field (source_isovaleur) that is used to compute the level-sets is then defined. It can be either
444 // XD_CONT the indicator function (indicatrice), a choice which is the default one and the most robust, or a
445 // XD_CONT geometrical distance computed from the mesh at the beginning of the time step (fonction_distance), a choice
446 // XD_CONT that may be more accurate in specific situations.NL2 Type_remaillage can be either Juric or Thomas. When
447 // XD_CONT Thomas is used, it is an enhancement of the Juric remeshing algorithm designed to compensate for mass loss
448 // XD_CONT during remeshing. The mesh is always reconstructed with the indicator function (not with the distance
449 // XD_CONT function). After having reconstructed the mesh with the Juric algorithm, the difference between the old
450 // XD_CONT indicator function (before remeshing) and the new indicator function is computed. The differences occuring
451 // XD_CONT at a distance below or equal to N elements from the interface are summed up and used to move the interface
452 // XD_CONT in the normal direction. The displacement of the interface is such that the volume of each phase after
453 // XD_CONT displacement is equal to the volume of the phase before remeshing. N (default value 1) must be smaller than
454 // XD_CONT n_iterations_distance (suggested value: 2).
455 param.ajouter_non_std("methode_transport",(this),Param::REQUIRED); // XD_ADD_P methode_transport_deriv
456 // XD_CONT Method of transport of interface.
457 param.ajouter_non_std("n_iterations_distance",(this)); // XD_ADD_P entier
458 // XD_CONT Keyword to specify the number or iterations requested for the smoothing process of computing the field
459 // XD_CONT corresponding to the signed distance to the interfaces and located at the center of the Eulerian elements.
460 // XD_CONT This smoothing is necessary when there are more Lagrangian nodes than Eulerian two-phase cells.
461 param.ajouter_non_std("iterations_correction_volume",(this)); // Former Keyword, Obsolete // XD_ADD_P entier Number of volume-correction iterations (obsolete keyword).
462 param.ajouter("VOFlike_correction_volume",&variables_internes_->VOFlike_correction_volume); // XD_ADD_P entier
463 // XD_CONT flag (0 or 1). If activated, code will perfom the requested number of iterations for the correction process
464 // XD_CONT that can be used to keep the volume of the phases constant during the transport process.
465 param.ajouter("nb_lissage_correction_volume",&variables_internes_->nb_lissage_correction_volume); // XD_ADD_P entier
466 // XD_CONT Select 0 or N, the number of smothing to apply to avoid potential spikes due to volume correction.
467 param.ajouter("nb_iterations_correction_volume",&variables_internes_->nb_iterations_correction_volume); // XD_ADD_P entier
468 // XD_CONT to iterate on the volume correction until seuil is reached.
469 param.ajouter_non_std("volume_impose_phase_1",(this)); // XD_ADD_P floattant
470 // XD_CONT this keyword is used to specify the volume of one phase to keep the volume of the phases constant during
471 // XD_CONT the remeshing process. It is an alternate solution to trouble in mass conservation. This option is mainly
472 // XD_CONT realistic when only one inclusion of phase 1 is present in the domain. In most other situations, the
473 // XD_CONT iterations_correction_volume keyword seems easier to justify. The volume to be keep is in m3 and should
474 // XD_CONT agree with initial condition.
475 param.ajouter_non_std("methode_interpolation_v",(this)); // XD_ADD_P chaine(into=["valeur_a_elem","vdf_lineaire","mean_volumic_velocity"])
476 // XD_CONT In this block, two keywords are possible for method to select the way the interpolation is performed. With
477 // XD_CONT the choice valeur_a_elem the speed of displacement of the nodes of the interfaces is the velocity at the
478 // XD_CONT center of the Eulerian element in which each node is located at the beginning of the time step. This choice
479 // XD_CONT is the default interpolation method. The choice VDF_lineaire is only available with a VDF discretization
480 // XD_CONT (VDF). In this case, the speed of displacement of the nodes of the interfaces is linearly interpolated on
481 // XD_CONT the 4 (in 2D) or the 6 (in 3D) Eulerian velocities closest the location of each node at the beginning of
482 // XD_CONT the time step. In peculiar situation, this choice may provide a better interpolated value. Of course, this
483 // XD_CONT choice is not available with a VEF discretization (VEFPreP1B).
484 param.ajouter("parcours_interface",&variables_internes_->parcours_interface_); // XD_ADD_P parcours_interface
485 // XD_CONT Parcours_interface allows you to configure the algorithm that computes the surface mesh to volume mesh
486 // XD_CONT intersection. This algorithm has some serious trouble when the surface mesh points coincide with some faces
487 // XD_CONT of the volume mesh. Effects are visible on the indicator function, in VDF when a plane interface coincides
488 // XD_CONT with a volume mesh surface. NL2 To overcome these problems, the keyword correction_parcours_thomas keyword
489 // XD_CONT can be used: it allows the algorithm to slightly move some mesh points. This algorithm is experimental and
490 // XD_CONT is NOT activated by default.
491 param.ajouter_non_std("injecteur_interfaces",(this)); // XD_ADD_P chaine
492 // XD_CONT not_set
493 param.ajouter("suppression_sous_domaine",&suppression_interfaces_sous_domaine_); // XD_ADD_P chaine
494 // XD_CONT not_set
495 param.ajouter("sous_domaine_volume_impose",&variables_internes_->nom_domaine_volume_impose_); // XD_ADD_P chaine Name of the sub-domain over which the phase volume is imposed.
496 param.ajouter_flag("interpolation_repere_local", &interpolation_repere_local_); // XD_ADD_P rien
497 // XD_CONT Triggers a new transport algorithm for the interface: the velocity vector of lagrangian nodes is computed
498 // XD_CONT in the moving frame of reference of the center of each connex component, in such a way that relative
499 // XD_CONT displacements of nodes within a connex component of the lagrangian mesh are minimized, hence reducing the
500 // XD_CONT necessity of barycentering, smooting and local remeshing. Very efficient for bubbly flows.
501 param.ajouter_non_std("interpolation_champ_face",(this)); // XD_ADD_P interpolation_champ_face_deriv
502 // XD_CONT It is possible to compute the imposed velocity for the solid-fluid interface by direct affectation
503 // XD_CONT (interpolation_scheme would be set to base) or by multi-linear interpolation (interpolation_scheme would be
504 // XD_CONT set to lineaire). The default value is base.
505 param.ajouter("n_iterations_interpolation_ibc",&variables_internes_->n_iterations_interpolation_ibc); // XD_ADD_P entier
506 // XD_CONT Useful only with interpolation_champ_face positioned to lineaire. Set the value concerning the width of the
507 // XD_CONT region of the linear interpolation. For the Penalized Direct Forcing model, a value equals to 1 is enough.
508 param.ajouter_non_std("type_vitesse_imposee",(this)); // XD_ADD_P chaine(into=["uniforme","analytique"])
509 // XD_CONT Useful only with interpolation_champ_face positioned to lineaire. Value of the keyword is uniforme (for an
510 // XD_CONT uniform solid-fluide interface\'s velocity, i.e. zero for instance) or analytique (for an analytic
511 // XD_CONT expression of the solid-fluide interface\'s velocity depending on the spatial coordinates). The default
512 // XD_CONT value is uniforme.
513 param.ajouter("nombre_facettes_retenues_par_cellule",&variables_internes_->nomb_fa7_accepted); // XD_ADD_P entier
514 // XD_CONT Keyword to specify the default number (3) of facets per cell used to describe the geometry of the
515 // XD_CONT solid-solid interface. This number should be increased if the geometry of the solid-solid interface is
516 // XD_CONT complex in each cell (eulerian mesh too coarse for example).
517 param.ajouter("seuil_convergence_uzawa",&variables_internes_->seuil_uzawa) ; // XD_ADD_P floattant
518 // XD_CONT Optional option to change the default value (10-8) of the threshold convergence for the Uzawa algorithm if
519 // XD_CONT used in the Penalized Direct Forcing model. Sometime, the value should be decreased to insure a better
520 // XD_CONT convergence to force equality between sequential and parallel results.
521 param.ajouter("nb_iteration_max_uzawa",&variables_internes_->nb_iter_uzawa) ; // XD_ADD_P entier
522 // XD_CONT Optional option to change the default value (10-8) of the threshold convergence for the Uzawa algorithm if
523 // XD_CONT used in the Penalized Direct Forcing model. Sometime, the value should be decreased to insure a better
524 // XD_CONT convergence to force equality between sequential and parallel results.
525 param.ajouter_non_std("distance_IBC_faces",(this)); // XD_ADD_P chaine(into=["initiale","modifiee"]) Method to compute the IBC face distance.
526 param.ajouter_non_std("distance_projete_faces",(this)); // XD_ADD_P chaine(into=["simplifiee","initiale","modifiee"])
527 // XD_CONT not_set
528 param.ajouter("temps_debut",&temps_debut_); // XD_ADD_P floattant Physical time at which the interface transport starts.
529 param.ajouter("vitesse_imposee_regularisee", &variables_internes_->vimp_regul) ; // XD_ADD_P entier
530 // XD_CONT not_set
531 param.ajouter_flag("explicit_u_NS", &explicit_u_NS_); // X_D_ADD_P rien Flag to force a really explicit scheme
532 param.ajouter_non_std("type_indic_faces", (this)) ; // XD_ADD_P type_indic_faces_deriv
533 // XD_CONT kind of interpolation to compute the face value of the phase indicator function (advanced option). Could be
534 // XD_CONT STANDARD, MODIFIEE or AI_BASED
535 param.ajouter("collision_model_fpi",&collision_model_); // XD_ADD_P Collision_Model_FT_base
536 // XD_CONT Collision model to use for the Fluid-Particle Interaction feature
537 param.ajouter_flag("compute_particles_rms",&compute_particles_rms_); // XD_ADD_P rien
538 // XD_CONT not_set
539 param.ajouter("post_process_hydrodynamic_forces", &post_process_hydro_forces_); // XD_ADD_P bloc_lecture
540 // XD_CONT not_set
541}
542
544{
545 if (un_mot=="maillage")
546 {
547 //lecture des parametres du remaillage
549 return 1;
550 }
551 else if (un_mot=="methode_transport")
552 {
553 Motcles motcles2(3);
554 motcles2[0] = "vitesse_imposee";
555 motcles2[1] = "loi_horaire";
556 motcles2[2] = "vitesse_interpolee";
557 Motcle motlu;
558 is >> motlu;
559 Cerr << un_mot << " " << motlu << finl;
560 int rang = motcles2.search(motlu);
561 switch(rang)
562 {
563 case 0:
564 {
566 Cerr << " Transport velocity imposed : reading " << Objet_U::dimension
567 << " analytical expressions vx(x,y,[z,]t) vy(...) [vz(...)]" << finl;
568 // vitesse de deplacement de la phase 1 imposee
569 variables_internes_->methode_transport =
571 // lecture de Objet_U::dimension expressions analytiques
572 // contenant les composantes du champ de vitesse de transport
573 // (voir calculer_vitesse_imposee)
574 // Ce sont des fonctions de x,y,[z,]t
575 for (int i = 0; i < Objet_U::dimension; i++)
576 {
577 Nom& expression = variables_internes_->expression_vitesse_imposee[i];
578 is >> expression;
580 Cerr << " Component " << i << " of the velocity : " << expression << finl;
581 }
582 break;
583 }
584 case 1:
585 {
586 Cerr << " Imposed motion by the time scheme : ";
587 variables_internes_->methode_transport = Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE;
588 Nom nom_loi;
589 is >> nom_loi;
590 Cerr << nom_loi << finl;
591 variables_internes_->loi_horaire_ = ref_cast(Loi_horaire, Interprete::objet(nom_loi));
592 break;
593 }
594 case 2:
595 {
597 Cerr << " Transport velocity interpolated from the velocity \n"
598 << " of the following Navier_Stokes equation :" << finl;
599 // vitesse de deplacement interpolee a partir du champ de vitesse fluide
600 variables_internes_->methode_transport =
602 // lecture du nom de l'equation de navier_stokes :
603 Motcle nom_eq;
604 is >> nom_eq;
605 Cerr << nom_eq << finl;
606 variables_internes_->refequation_vitesse_transport =
607 ref_cast(Probleme_FT_Disc_gen,
608 probleme_base_.valeur()).equation_hydraulique(nom_eq);
609
610 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
611 if (sub_type(Navier_Stokes_FT_Disc,eqn_hydraulique))
612 {
613 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
615 // for fpi mmodule
616 set_is_solid_particle(ns.get_is_solid_particle()); // must be done before Collision_Model_FT::reprendre
619 }
620 break;
621 }
622 default:
623 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
624 << "The options for methode_transport are :\n"
625 << motcles2;
627 }
628 return 1;
629 }
630
631 else if (un_mot=="n_iterations_distance")
632 {
633 int n;
634 is >> n;
635 variables_internes_->n_iterations_distance = n;
637 Cerr << "Iterations number of the smoothing tool \"distance_interface\": " << n << finl;
638 return 1;
639 }
640 else if (un_mot=="iterations_correction_volume")
641 {
642 int n;
643 is >> n;
644 variables_internes_->iterations_correction_volume = n;
645 if (n>0)
646 variables_internes_->VOFlike_correction_volume = 1;
647 variables_internes_->nb_lissage_correction_volume = n; // Historical behavior was to set it to the same value as the nb of iterations
648 variables_internes_->nb_iterations_correction_volume = n;
650 {
651 Cerr << "Obsolete Keyword is read Iterations_correction_volume : " << n << finl;
652 Cerr << "For future compatibility, it is recommended to switch to the new syntax : " << finl;
653 if (n>0)
654 Cerr << " VOFlike_correction_volume 1 # a flag (0 or 1) for activation #" << finl;
655 else
656 Cerr << " VOFlike_correction_volume 0 # a flag (0 or 1) for activation #" << finl;
657 Cerr << " nb_lissage_correction_volume " << n << " # Select 0 or N the number of smoothing to apply to avoid potential spikes due to volume correction. #" << finl;
658 Cerr << " nb_iterations_correction_volume " << n << " # to iterate on the volume correction until seuil is reached. #" << finl;
659 // Note: looking at past commits, there may have been a mistake when changing these parameters.
660 // The value 'n' may be wrong and it may be better to use remaillage_interface().get_nb_iter_bary_volume_seul() for nb_iterations_correction_volume.
661 // If you are motivated, you can investigate.
662 Cerr << "The value of nb_iterations_correction_volume is read from bloc remaillage at keyword: nb_iter_correction_volume" << finl;
664 }
665 return 1;
666 }
667 else if (un_mot=="volume_impose_phase_1")
668 {
669 double x;
670 is >> x;
671 variables_internes_->volume_impose_phase_1 = x;
673 Cerr << "volume_impose_phase_1 : " << x << finl;
674 return 1;
675 }
676 else if (un_mot=="methode_interpolation_v")
677 {
678 Motcles motcles2(3);
679 motcles2[0] = "valeur_a_elem";
680 motcles2[1] = "vdf_lineaire";
681 motcles2[2] = "mean_volumic_velocity";
682 Motcle motlu;
683 is >> motlu;
685 Cerr << un_mot << " " << motlu << finl;
686 int rang = motcles2.search(motlu);
687 switch(rang)
688 {
689 case 0:
690 variables_internes_->methode_interpolation_v =
692 break;
693 case 1:
694 variables_internes_->methode_interpolation_v =
696 break;
697 case 2:
698 variables_internes_->methode_interpolation_v =
700 if (interpolation_repere_local_)
701 {
702 Cerr <<"ERROR : interpolation_repere_local should not be employed"
703 " with methode_interpolation_v::MEAN_VOLUMIC_VELOCITY !!!!!!!!!!!" << finl;
704 exit();
705 }
706 break;
707
708 default:
709 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
710 << "The options for " << un_mot << " are :\n"
711 << motcles2;
713 }
714 return 1;
715 }
716 else if (un_mot=="parcours_interface")
717 {
718 is >> variables_internes_->parcours_interface_;
719 return 1;
720 }
721 else if (un_mot=="injecteur_interfaces")
722 {
723 Nom nom_fichier;
724 is >> nom_fichier;
726 {
727 Cerr << "Reading of the interfaces to inject in the file " << nom_fichier << finl;
728 EFichier fic(nom_fichier);
729 ArrOfDouble& temps = variables_internes_->injection_interfaces_temps_;
730 ArrOfInt& phase = variables_internes_->injection_interfaces_phase_;
731 Noms& expr = variables_internes_->injection_interfaces_expressions_;
732 Nom une_expr;
733 while(1)
734 {
735 double t;
736 fic >> t;
737 if (fic.eof())
738 break;
739 temps.append_array(t);
740 int ph;
741 fic >> ph;
742 fic >> une_expr;
743 phase.append_array(ph);
744 expr.add(une_expr);
745 Cerr << "Time=" << t << " phase=" << ph << " expression=" << une_expr << finl;
746 }
747 }
748 envoyer_broadcast(variables_internes_->injection_interfaces_temps_, 0);
749 envoyer_broadcast(variables_internes_->injection_interfaces_phase_, 0);
750 envoyer_broadcast(variables_internes_->injection_interfaces_expressions_, 0);
751 barrier();
752 return 1;
753 }
754 else if (un_mot=="interpolation_champ_face")
755 {
756 Motcles motcles2(2);
757 motcles2[0] = "base";
758 motcles2[1] = "lineaire";
759 Motcle motbis;
760 is >> motbis;
761 int rang = motcles2.search(motbis);
762 switch(rang)
763 {
764 case 0:
765 variables_internes_->interpolation_champ_face =
767 break;
768 case 1:
769 {
770 variables_internes_->interpolation_champ_face =
772
773 Motcles mots;
774 mots.add("vitesse_fluide_explicite"); // vitesse utilisee pour calculer l'interpolation du schema lineaire
775 mots.add("extrapolation_diphasique_solide"); // le gradient est etendu dans les mailles diphasiques solides
776 mots.add("extrapolation_solide"); // le gradient est etendu dans les mailles solides
777 mots.add("distance_projete_face"); // utilisation de la distance reelle entre le barycentre de la face
778 // et le point projete (au lieu d'utiliser dSigma)
779
780 Motcle mot2;
781 is >> mot2;
782 Motcle accouverte = "{" , accfermee = "}" ;
783 if (mot2 == accouverte)
784 {
785 is >> mot2;
786
787 while (mot2 != accfermee)
788 {
789 int rang2 = mots.search(mot2);
790 switch(rang2)
791 {
792 case 0:
793 {
794 variables_internes_->vf_explicite = 1 ;
795 Cerr << "Lecture du type de vitesse fluide pour le calcul de v_imp : vf_explicite " << finl;
796 break;
797 }
798 case 1:
799 {
800 variables_internes_->is_extra_diphasique_solide = 1 ;
801 variables_internes_->is_extra_solide = 0 ;
802 Cerr << "Lecture du type d'extrapolation considere : diphasique_solide " << finl;
803 break;
804 }
805 case 2:
806 {
807 variables_internes_->is_extra_solide = 1 ;
808 variables_internes_->is_extra_diphasique_solide = 1 ;
809 Cerr << "Lecture du type d'extrapolation considere : solide " << finl;
810 break;
811 }
812 case 3:
813 {
814 variables_internes_->is_distance_projete_face = 1 ;
815 Cerr << "Lecture du type de distance consideree dans l'interpolation : distance reelle entre projete et face " << finl;
816 break;
817 }
818 }
819 is >> mot2;
820 }
821 }
822 else
823 {
824 Cerr << "Erreur a la lecture des parametres de l'interpolation lineaire : " << finl;
825 Cerr << "On attendait : " << accouverte << " , on a eu " << mot2 << finl;
827 }
828 break;
829 }
830 default:
831 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
832 << " les options de interpolation_champ_face sont :\n"
833 << motcles2;
835 }
836 }
837 else if (un_mot=="type_vitesse_imposee")
838 {
839 Motcles motcles2(2);
840 motcles2[0] = "uniforme";
841 motcles2[1] = "analytique";
842 Motcle motbis;
843 is >> motbis;
844 int rang = motcles2.search(motbis);
845 switch(rang)
846 {
847 case 0:
848 variables_internes_-> type_vitesse_imposee = Transport_Interfaces_FT_Disc_interne::UNIFORME;
849 break;
850 case 1:
851 variables_internes_-> type_vitesse_imposee = Transport_Interfaces_FT_Disc_interne::ANALYTIQUE;
852 break;
853 default:
854 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
855 << " les options de type_vitesse_imposee sont :\n"
856 << motcles2;
858 }
859 }
860 else if (un_mot=="distance_IBC_faces")
861 {
862 Motcles motcles2(2);
863 motcles2[0] = "initiale";
864 motcles2[1] = "modifiee";
865 Motcle motbis;
866 is >> motbis;
867
868 int rang = motcles2.search(motbis);
869 switch(rang)
870 {
871 case 0:
872 variables_internes_-> type_distance_calculee = Transport_Interfaces_FT_Disc_interne::DIST_INITIALE;
873 break;
874 case 1:
875 {
876 variables_internes_-> type_distance_calculee = Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE;
877 break;
878 }
879 default:
880 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
881 << " les options de distance_IBC_faces sont :\n"
882 << motcles2;
884 }
885 }
886 else if (un_mot=="distance_projete_faces")
887 {
888 Motcles motcles2(3);
889 motcles2[0] = "initiale";
890 motcles2[1] = "modifiee";
891 motcles2[2] = "simplifiee";
892 Motcle motbis;
893 is >> motbis;
894
895 int rang = motcles2.search(motbis);
896 switch(rang)
897 {
898 case 0:
899 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_INITIAL;
900 break;
901 case 1:
902 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE;
903 break;
904 case 2:
905 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE;
906 break;
907 default:
908 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
909 << " les options de distance_projete_faces sont :\n"
910 << motcles2;
912 }
913 }
914 else if (un_mot=="type_indic_faces")
915 {
916 Motcles motcles2(3);
917 motcles2[0] = "standard";
918 motcles2[1] = "modifiee";
919 motcles2[2] = "ai_based";
920 Motcle motlu;
921 is >> motlu;
922 Cerr << un_mot << " " << motlu << finl;
923 int rang = motcles2.search(motlu);
924 switch(rang)
925 {
927 {
928 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::STANDARD;
930 Cerr << " Standard interpolation of indicatrice to faces." << finl;
931 return 1;
932 }
934 {
936 Cerr << " Transport velocity imposed : reading " << Objet_U::dimension
937 << " analytical expressions vx(x,y,[z,]t) vy(...) [vz(...)]" << finl;
938
939 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::MODIFIEE;
940 // modified_indic_faces_* : Valeurs de la position et de l epaisseur de l indicatrice modifiee,
941 // exprimees en multiples de taille de maille. Cette nouvelle indicatrice est calculee
942 // a partir de la distance a l interface. La position represente une iso-ligne
943 // de distance a l interface, et l epaisseur, le domaine de variation lineaire vis a vis de la distance,
944 // qui fait passer l indicatrice de 0 a 1 (le domaine est centre sur l iso-ligne representee par la position).
945 // Par defaut :
946 variables_internes_->modified_indic_faces_position = 0. ;
947 variables_internes_->modified_indic_faces_thickness= 1. ;
948 Motcles mots;
949 mots.add("position");
950 mots.add("thickness");
951
952 Motcle mot;
953 is >> mot;
954 Motcle accouverte = "{" , accfermee = "}" ;
955 if (mot == accouverte)
956 {
957 is >> mot;
958
959 while (mot != accfermee)
960 {
961 int rang2 = mots.search(mot);
962 switch(rang2)
963 {
964 case 0:
965 {
966 is >> variables_internes_->modified_indic_faces_position ;
967 Cerr << "Lecture de la position de l interface modifiee " << finl;
968 break;
969 }
970 case 1:
971 {
972 is >> variables_internes_->modified_indic_faces_thickness ;
973 if ( variables_internes_->modified_indic_faces_thickness < 0.)
974 {
975 Cerr << "L epaisseur de l interface doit etre positive ou nulle!!" << finl;
977 }
978 Cerr << "Lecture de l epaisseur de l interface modifiee " << finl;
979 break;
980 }
981 }
982 is >> mot;
983 }
984 }
985 else
986 {
987 Cerr << "Erreur a la lecture des parametres de l'indicatrice modifiee " << finl;
988 Cerr << "On attendait : " << accouverte << finl;
990 }
992 {
993 Cerr << "L indicatrice face sera calculee a partir de la distance. Position : d=" << variables_internes_->modified_indic_faces_position << "h ; Epaisseur : "<< variables_internes_->modified_indic_faces_thickness << "h" <<finl;
994 }
995 return 1;
996 }
998 {
999 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::AI_BASED;
1001 Cerr << " The interpolation of indicatrice to faces is based on the interfacial area"
1002 << " and on the normal to the interface." << finl;
1003 return 1;
1004 }
1005 default:
1006 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
1007 << " les options de type_indic_faces sont :\n"
1008 << motcles2;
1009 Process::exit();
1010 }
1011 }
1012 else
1014 return 1;
1015}
1016
1017/*! @brief Methode appelee par Equation_base::readOn On verifie que toutes les cl sont de type Paroi_FT_disc.
1018 *
1019 * Fait Process::exit() si erreur.
1020 *
1021 */
1023{
1024 const Conds_lim& les_cl = le_dom_Cl_dis->les_conditions_limites();
1025 const int n = les_cl.size();
1026 int i;
1027 for (i = 0; i < n; i++)
1028 {
1029 if (! sub_type(Paroi_FT_disc, les_cl[i].valeur()))
1030 break;
1031 }
1032 if (i < n)
1033 {
1034 Cerr << "Error in Transport_Interfaces_FT_Disc::verif_Cl():\n"
1035 << " Boundary conditions for Transport_Interfaces_FT_Disc must be\n"
1036 << " of type Paroi_FT_disc (example : \"Paroi_FT_disc symetrie\")" << finl;
1037 Process::exit();
1038 }
1039 return 1;
1040}
1041
1042template <int _DIM_>
1043int facettes_trier_retirer_doublons(IntTab& fa7)
1044{
1045 using line = std::array<int, _DIM_>;
1046 line* chunked_fa7 = reinterpret_cast<line*>(fa7.addr());
1047 int nb_facettes = fa7.dimension(0);
1048 int dim = _DIM_;
1049 auto same_fa7 = [&](line A, line B)
1050 {
1051 // here, A and B are copies, so we can sort them
1052 std::sort(A.begin(), A.end());
1053 std::sort(B.begin(), B.end());
1054 int cmp = 0;
1055 for (int i = 0; i < dim; i++)
1056 {
1057 cmp = A[i] - B[i];
1058 if (cmp != 0)
1059 break;
1060 }
1061 return cmp;
1062 };
1063
1064 // sorting
1065 std::sort(chunked_fa7, chunked_fa7 + nb_facettes, [&](const line& fa1, const line& fa2)
1066 {
1067 return (same_fa7(fa1,fa2) < 0);
1068 });
1069
1070 // cleaning
1071 int count = 0;
1072 for (int i = 1; i < nb_facettes; i++)
1073 {
1074 line& fa1 = chunked_fa7[i];
1075 line& fa2 = chunked_fa7[i-1];
1076 if(same_fa7(fa1,fa2)!=0)
1077 {
1078 count++;
1079 for(int j=0; j<dim; j++)
1080 fa7(count,j)=fa7(i,j);
1081 }
1082 }
1083 fa7.resize(count+1,dim);
1084 return count;
1085}
1086
1088{
1089 Domaine dom;
1090 OBS_PTR(Domaine) ref_dom;
1091 Nom filename;
1092 ArrOfInt phase_specifiee;
1093 DoubleTab points;
1094 int default_phase = -1;
1095 Nom lata_file;
1096 Nom domain_name;
1097 int reverse_normal = 0;
1098
1099 Motcle motlu;
1100 is >> motlu;
1101 if (motlu != "{")
1102 {
1103 Cerr << "Error in Transport_Interfaces_FT_Disc::lire_cond_init, expected { after fichier_geom" << finl;
1104 Process::exit();
1105 }
1106
1107 Motcles motcles(6);
1108 motcles[0] = "fichier_geom";
1109 motcles[1] = "point_phase";
1110 motcles[2] = "default_phase";
1111 motcles[3] = "lata_dump";
1112 motcles[4] = "nom_domaine";
1113 motcles[5] = "reverse_normal";
1114 do
1115 {
1116 is >> motlu;
1117 if (motlu == "}")
1118 break;
1119 const int rang = motcles.search(motlu);
1120 switch(rang)
1121 {
1122 case 0:
1123 is >> filename;
1124 Cerr << " Reading .geom file in following file: " << filename << finl;
1125 break;
1126 case 1:
1127 {
1128 const int i = phase_specifiee.size_array();
1129 phase_specifiee.resize_array(i+1);
1130 points.resize(i+1, dimension);
1131 is >> phase_specifiee[i];
1132 Cerr << " Reading point in phase " << phase_specifiee[i];
1133 if (phase_specifiee[i] != 0 && phase_specifiee[i] != 1)
1134 {
1135 Cerr << " Error reading point_phase : expected 0 or 1" << finl;
1136 Process::exit();
1137 }
1138 for (int j = 0; j < dimension; j++)
1139 {
1140 is >> points(i, j);
1141 Cerr << " " << points(i,j);
1142 }
1143 Cerr << finl;
1144 break;
1145 }
1146 case 2:
1147 is >> default_phase;
1148 if (default_phase != 0 && default_phase != 1)
1149 {
1150 Cerr << " Error reading default_phase : expected 0 or 1" << finl;
1151 Process::exit();
1152 }
1153 Cerr << " Default phase : " << default_phase << finl;
1154 break;
1155 case 3:
1156 is >> lata_file;
1157 Cerr << " Dumping connex components and indicator function in lata file : "
1158 << lata_file << finl;
1159 break;
1160 case 4:
1161 is >> domain_name;
1162 Cerr << " Reading interface data in domain: " << domain_name << finl;
1163 break;
1164 case 5:
1165 reverse_normal = 1;
1166 Cerr << " Reverse_normal : swap nodes to reverse the normal vector of the surface mesh" << finl;
1167 break;
1168 default:
1169 Cerr << " Unknown keyword " << motlu
1170 << "\n Known keywords are " << motcles << finl;
1171 Process::exit();
1172 }
1173 }
1174 while (1);
1175
1176 if (filename != "??" && domain_name != "??")
1177 {
1178 Cerr << "Error: you specified both a .geom file name AND a domain name" << finl;
1179 Process::exit();
1180 }
1181 else if (filename == "??" && domain_name == "??")
1182 {
1183 Cerr << "Error: you must specify a FICHIER_GEOM or a NOM_DOMAINE" << finl;
1184 Process::exit();
1185 }
1186 if (filename != "??")
1187 {
1188 Cerr << "Reading geometry file and building interface mesh" << finl;
1189 if (is_a_binary_file(filename))
1190 {
1191 EFichierBin fic(filename);
1192 fic >> dom;
1193 }
1194 else
1195 {
1196 LecFicDiffuse fic(filename);
1197 fic >> dom;
1198 }
1199 ref_dom = dom;
1200 }
1201 else
1202 {
1203 Cerr << "Reading interface in existing domain: " << domain_name << finl;
1204 if (!sub_type(Domaine, Interprete::objet(domain_name)))
1205 {
1206 Cerr << "Error : object " << domain_name << " is not a domain" << finl;
1207 Process::exit();
1208 }
1209 ref_dom = ref_cast(Domaine, Interprete::objet(domain_name));
1210 }
1211 if (reverse_normal)
1212 {
1213 Cerr << "Reversing mesh normal vectors" << finl;
1214 Domaine& domaine = ref_dom.valeur();
1215 IntTab& elems = domaine.les_elems();
1216 const int nb_elem = elems.dimension(0);
1217 const int nb_som_elem = elems.line_size();
1218 if (nb_som_elem != 2 && nb_som_elem != 3)
1219 {
1220 Cerr << "Error: mesh has wrong dimension (must be segments in 2D, triangles in 3D)" << finl;
1221 Process::exit();
1222 }
1223 const int j0 = nb_som_elem - 2;
1224 for (int i = 0; i < nb_elem; i++)
1225 {
1226 const int s0 = elems(i, j0);
1227 const int s1 = elems(i, j0+1);
1228 elems(i, j0) = s1;
1229 elems(i, j0+1) = s0;
1230 }
1231 }
1232
1233 //MODIF SM 01/12/08
1234 //Effacer les fa7 doublons dans la cas d'un reprise d'un .MED parallele
1235 // Verification qu'il n'existe pas deux fois la meme facette
1236 {
1237 Scatter::uninit_sequential_domain(ref_dom.valeur());
1238 Domaine& domaine = ref_dom.valeur();
1239 IntTab& fa7 = domaine.les_elems();
1240
1241 // tri du tableau
1242 const int nb_facettes = fa7.dimension(0);
1243 assert(Objet_U::dimension == fa7.line_size());
1244
1245 int count = 0;
1246 if(Objet_U::dimension==2)
1247 count = facettes_trier_retirer_doublons<2>(fa7);
1248 else if(Objet_U::dimension == 3)
1249 count = facettes_trier_retirer_doublons<3>(fa7);
1250
1251 Scatter::init_sequential_domain(ref_dom.valeur());
1252 Cerr<<"End correction SM 12/08 the removed faces number is: "<< nb_facettes <<" - "<< count+1 << " = " << nb_facettes-count-1 << finl;
1253 }
1254 //Fin modif SM 01/12/08
1255
1256
1257 Cerr << "Building interface mesh" << finl;
1258 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1260 Sauvegarde_Reprise_Maillage_FT::lire_xyz(maillage, &domaine_vf, 0, &(ref_dom.valeur()));
1261 Cerr << "Extracting connex components and assigning indicator function." << finl;
1262
1263 maillage.parcourir_maillage();
1264 const int nb_elem = domaine_vf.domaine().nb_elem();
1265 IntVect num_compo;
1266 domaine_vf.domaine().creer_tableau_elements(num_compo);
1267 // On marque avec -1 les elements traverses par une interface:
1268 const ArrOfInt& index_elem = maillage.intersections_elem_facettes().index_elem();
1269 {
1270 for (int i = 0; i < nb_elem; i++)
1271 {
1272 int n = 0;
1273 if (index_elem[i] >= 0)
1274 n = -1; // L'element est traverse par une interface
1275 num_compo[i] = n;
1276 }
1277 }
1278 num_compo.echange_espace_virtuel();
1279 const IntTab& elem_faces = domaine_vf.elem_faces();
1280 const IntTab& faces_elem = domaine_vf.face_voisins();
1281 const int nb_local_connex_components = search_connex_components_local(elem_faces, faces_elem, num_compo);
1282 const int nb_connex_components = compute_global_connex_components(num_compo, nb_local_connex_components);
1283
1284 //const int nb_connex_components = nb_local_connex_components;
1285 Cerr << " found " << nb_connex_components << " connex components" << finl;
1286 // Calcul de la phase a associer a chaque composante:
1287 ArrOfInt phase_of_component(nb_connex_components);
1288 phase_of_component= default_phase;
1289 // Pour chaque point ou la phase a ete specifiee, trouver l'element dans
1290 // lequel il se trouve, puis sa composante connexe et associer cette phase
1291 // a la composante connexe:
1292 const int nb_pts = phase_specifiee.size_array();
1293 if (nb_pts!=0)
1294 {
1295 ArrOfInt elem_points;
1296 domaine_vf.domaine().chercher_elements(points, elem_points);
1297 for (int i = 0; i < nb_pts; i++)
1298 {
1299 int composante_connexe = -2;
1300 if (elem_points[i] >= 0)
1301 composante_connexe = num_compo[elem_points[i]];
1302 // En general un seul processeur trouve le point chez lui, il distribue sa
1303 // trouvaille aux autres :
1304 composante_connexe = (int) mp_max(composante_connexe);
1305 if (composante_connexe == -2)
1306 {
1307 Cerr << "Error : point " << i << " is not in the domain" << finl;
1308 barrier();
1309 Process::exit();
1310 }
1311 else if (composante_connexe == -1)
1312 {
1313 Cerr << "Error : point " << i << " is in connex_component -1"
1314 << " (this point is in a mesh cell containing the interface)."
1315 << " Use the dump_lata keyword to find a point away from the interface" << finl;
1316 barrier();
1317 Process::exit();
1318 }
1319 else
1320 {
1321 const int phase = phase_specifiee[i];
1322 Cerr << "Assigning phase " << phase << " to component " << composante_connexe << finl;
1323 phase_of_component[composante_connexe] = phase;
1324 }
1325 }
1326 }
1327 // Met a jour l'indicatrice de phase:
1328 DoubleTab& indic = variables_internes_->indicatrice_cache->valeurs();
1329 for (int i = 0; i < nb_elem; i++)
1330 {
1331 const int compo = num_compo[i];
1332 if (compo >= 0)
1333 {
1334 const int phase = phase_of_component[compo];
1335 indic(i) = phase;
1336 }
1337 }
1338 // TODO : probablement plutot update_indicatrice_normale_distance(); ? A tester..
1340 // Postraitement des composantes connexes et de l'indicatrice
1341 if (lata_file != "??")
1342 {
1343 Cerr << "Writing lata file" << finl;
1344 Format_Post_Lata lata;
1345 const Domaine& un_dom = domaine_vf.domaine();
1346 constexpr double TEMPS = 0.;
1347 constexpr int FIRST_POST = 1;
1348 lata.initialize(lata_file, Format_Post_Lata::BINAIRE, "SIMPLE");
1349 lata.ecrire_entete(TEMPS, 0 /*reprise*/, FIRST_POST);
1350 lata.ecrire_domaine(un_dom, FIRST_POST);
1351 lata.ecrire_temps(TEMPS);
1352 DoubleTab data(nb_elem);
1353 for (int i = 0; i < nb_elem; i++)
1354 data(i) = num_compo(i);
1355 Noms unites;
1356 unites.add("-");
1357 Noms noms_compo;
1358 noms_compo.add("");
1359 Nom nom_dom(un_dom.le_nom());
1360
1361 Nom nom_champ("connex_component");
1362 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1363 data);
1364 nom_champ = "indicatrice";
1365 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1366 indic);
1367 nom_champ = "distance";
1368 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1369 get_distance_interface().valeurs());
1370 }
1371 // permettra de passer le assert et de recalculer indic et distance dans le mettre_a_jour meme si c'est inutile dans ce cas
1372 // on a dû le faire une fois de trop ci-dessus pour permettre de le postprocesser juste avant ici.
1374
1375 if (phase_of_component.size_array() > 0 && min_array(phase_of_component) < 0)
1376 {
1377 Cerr << "Error: some connex components of the indicator function were not initialized\n"
1378 << " you must either specify more points or specify a default_phase.\n"
1379 << " With the lata_dump keyword, you can watch connex components and find where\n"
1380 << " points should be added." << finl;
1381 Process::exit();
1382 }
1383}
1384
1385
1386// Grammar of the conditions_initiales block parsed below (no backing C++ class:
1387// these entries are read directly here). It is a comma-separated list of entries.
1388// XD cond_init_ft_list listobj nul BRACE cond_init_ft_base COMMA Definition of the initial interface(s): a braced,
1389// XD_CONT comma-separated list of entries, each one of:
1390// XD_CONT
1391// XD_CONT - `fonction [ajout_phase0|ajout_phase1] EXPR`
1392// XD_CONT - `fonction_ignorer_collision [ajout_phase0|ajout_phase1] EXPR`
1393// XD_CONT - `fichier_geom { ... }` (build from a geometry/mesh file)
1394// XD_CONT - `reprise FILE.xyz` (resume the interfaces from a save file).
1395// XD_CONT
1396// XD_CONT EXPR is a single-token analytical function of (x,y,z): each fonction entry adds an interface as its zero
1397// XD_CONT level-set, with the indicator set to 0 (fluide0) where EXPR<0 and to 1 (fluide1) where EXPR>0.
1398// XD_CONT
1399// XD_CONT The first entry sets the indicator field; ajout_phase0/ajout_phase1 (only allowed from the second entry on)
1400// XD_CONT compose further interfaces onto it: ajout_phase0 keeps the field where its function is positive and sets the
1401// XD_CONT indicator to 0 where it is negative; ajout_phase1 is symmetric (keeps it where negative, sets it to 1 where
1402// XD_CONT positive).
1403// XD_CONT
1404// XD_CONT Example - two bubbles below a free surface:
1405// XD_CONT
1406// XD_CONT ```
1407// XD_CONT conditions_initiales {
1408// XD_CONT fonction z-0.020 ,
1409// XD_CONT fonction ajout_phase1 (x-0.002)^2+(y-0.002)^2+z^2-(0.00125)^2 ,
1410// XD_CONT fonction ajout_phase1 (x-0.005)^2+(y-0.007)^2+z^2-(0.00150)^2
1411// XD_CONT }
1412// XD_CONT ```
1413
1414// XD cond_init_ft_base objet_lecture cond_init_ft_base NO_BRACE Base class for a Front-Tracking initial-condition
1415// XD_CONT entry (see conditions_initiales of transport_interfaces_ft_disc).
1416// XD fonction cond_init_ft_base fonction NO_BRACE Define an interface as the zero level-set of an analytical function
1417// XD_CONT of (x,y,z).
1418// XD attr ajout_phase chaine(into=["ajout_phase0","ajout_phase1"]) ajout_phase OPT From the second entry on, selects
1419// XD_CONT the phase the new interface is added to: ajout_phase0 keeps the field where the function is positive,
1420// XD_CONT ajout_phase1 where it is negative.
1421// XD attr expression chaine expression REQ Analytical function whose zero level-set defines the interface (a single
1422// XD_CONT token, no spaces).
1423// XD fonction_ignorer_collision cond_init_ft_base fonction_ignorer_collision NO_BRACE Like fonction, but tolerate a
1424// XD_CONT collision with an already-defined interface instead of stopping.
1425// XD attr ajout_phase chaine(into=["ajout_phase0","ajout_phase1"]) ajout_phase OPT Selects the phase the new interface
1426// XD_CONT is added to.
1427// XD attr expression chaine expression REQ Analytical function whose zero level-set defines the interface (a single
1428// XD_CONT token, no spaces).
1429// XD fichier_geom cond_init_ft_base fichier_geom NO_BRACE Build the initial interface from a geometry/mesh file block.
1430// XD attr bloc bloc_lecture bloc REQ Opaque geometry block (read by lire_maillage_ft_cao).
1431// XD reprise cond_init_ft_base reprise NO_BRACE Resume the interface(s) from a .xyz save file.
1432// XD attr fichier chaine fichier REQ Name of the .xyz save file.
1433
1434/*! @brief Lecture des conditions initiales.
1435 *
1436 * On s'attend a trouver ceci : { fonction EXPRESSION }
1437 * ou expression depend de x, y et z et sera interpretee par le
1438 * parser de TRUST. L'expression est envoyee a Marching_Cubes
1439 * pour construire l'interface.
1440 * Voir aussi parser et Marching_Cubes.
1441 *
1442 */
1444{
1446 Cerr << "Reading initial condition" << finl;
1447 Motcles motcles(4);
1448 motcles[0] = "fonction";
1449 motcles[1] = "fichier_geom";
1450 motcles[2] = "fonction_ignorer_collision";
1451 motcles[3] = "reprise";
1452 Motcle motlu;
1453 is >> motlu;
1454 if (motlu != "{")
1455 {
1456 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::lire_cond_init\n";
1457 Cerr << " On attendait {\n On a trouve " << motlu << finl;
1458 Process::exit();
1459 }
1460 const Motcle virgule = ",";
1461 int init = 1;
1462 do
1463 {
1464 Maillage_FT_Disc maillage_tmp;
1465 maillage_tmp.associer_equation_transport(*this);
1466 //boucle sur la lecture des conditions intiales
1467 is >> motlu;
1468 int rang = motcles.search(motlu);
1469 switch (rang)
1470 {
1471 case 0:
1472 case 2:
1473 {
1475 if (init)
1476 {
1477 init = 0;
1478 }
1479 else
1480 {
1481 //a partir de la 2e interface ajoutee, il faut indiquer quelle phase on ajoute
1482 Motcle nom_phase;
1483 is >> nom_phase;
1484 if (nom_phase=="ajout_phase1")
1485 {
1487 }
1488 else if (nom_phase=="ajout_phase0")
1489 {
1491 }
1492 else
1493 {
1494 Cerr << "Transport_Interfaces_FT::lire_cond_init :\n";
1495 Cerr << " The keyword " << nom_phase << " is not understood.\n";
1496 Cerr << " Allowed keywords are : ajout_phase0 or ajout_phase1" << finl;
1497 assert(0);
1498 Process::exit();
1499 }
1500 }
1501 Nom expression;
1502 is >> expression;;
1503 if (probleme().reprise_effectuee())
1504 {
1505 Cerr << " Interface not build since a restarting is expected." << finl;
1506 }
1507 else
1508 {
1509 Cerr << " Interface construction : " << expression << finl;
1510 // Construction de l'interface comme l'isovaleur zero de la fonction
1511 // La valeur de la fonction "expression" aux sommets est temporairement stockee
1512 // dans distance_interface_sommets qui a la bonne structure d'espace virtuel
1513 // (items communs correctement initialises).
1514 int ignorer_collision = (rang==2);
1515 const int ok = marching_cubes().construire_iso(expression, 0., maillage_tmp,
1516 variables_internes_->indicatrice_cache->valeurs(),
1517 phase,
1518 variables_internes_->distance_interface_sommets,
1519 ignorer_collision);
1520 if (!ok)
1521 {
1522 if (ignorer_collision)
1523 Cerr << "Warning: the interface is colliding with an existing interface (ignorer_collision=1)." << finl;
1524 else
1525 {
1526 Cerr << "Error: the interface is colliding with an existing interface." << finl;
1527 barrier();
1528 Process::exit();
1529 }
1530 }
1531 maillage_interface().ajouter_maillage(maillage_tmp);
1532 }
1533 break;
1534 }
1535 case 1:
1536 {
1538 break;
1539 }
1540 case 3:
1541 {
1542 Nom file;
1543 is >> file;
1544 if (!file.finit_par(".xyz"))
1545 {
1546 Cerr << "A .xyz file is waited to restart the calculation for the interface equation." << finl;
1547 Process::exit();
1548 }
1549 int mode_lec_sa = EcritureLectureSpecial::mode_lec;
1551 EFichierBin is2(file);
1552 Motcle tmp;
1553 int version;
1554 is2 >> tmp >> version; // FORMAT_SAUVEGARDE: VERSION
1555 reprendre(is2);
1557 break;
1558 }
1559 default:
1560 Cerr << "Transport_Interfaces_FT::lire_cond_init :\n";
1561 Cerr << " The keyword " << motlu << " is not understood here.\n";
1562 Cerr << " Allowed keywords are :\n" << motcles << finl;
1563 Process::exit();
1564 }
1565 is >> motlu;
1566 Cerr<<"lectureF "<<motlu<<finl;
1567 }
1568 while (motlu==virgule);
1569
1570 if (motlu != "}")
1571 {
1572 Cerr << "Error for method Transport_Interfaces_FT_Disc::lire_cond_init\n";
1573 Cerr << " A } was expected\n It has been found " << motlu << finl;
1574 Process::exit();
1575 }
1576
1577 return is;
1578}
1579
1581{
1582 assert(!probleme_base_);
1583 if ( (! sub_type(Probleme_FT_Disc_gen, un_probleme))
1584 && !(un_probleme.is_dilatable()))
1585 {
1586 Cerr << "Error for method Transport_Interfaces_FT_Disc::associer_pb_base\n";
1587 Cerr << " The Transport_Interfaces_FT_Disc equation must be associated to a problem\n";
1588 Cerr << " of type Probleme_FT_Disc_gen" << finl;
1589 Cerr << " or type Pb_Thermohydraulique_Especes_QC" << finl;
1590 Cerr << " or type Pb_Thermohydraulique_Especes_Turbulent_QC" << finl;
1591 Process::exit();
1592 }
1593 probleme_base_ = un_probleme;
1595
1596 Nom pb_name = un_probleme.le_nom();
1597 variables_internes_->set_pb_name(pb_name);
1598}
1599
1600/*! @brief Discretisation des champs: - indicatrice_ : champ scalaire discretise aux elements
1601 *
1602 * - typage du maillage et de l'algorithme marching cubes
1603 *
1604 */
1606{
1607 // Le nom des differents champs est un identifiant (indicatrice, vitesse, ...)
1608 // suivi de "_nom_de_l_equation" :
1609 Nom suffix("_");
1610 suffix += le_nom();
1611 variables_internes_->set_ident(le_nom());
1612
1613 const Discretisation_base& dis = discretisation();
1614 const double temps = schema_temps().temps_courant();
1615 const Domaine_dis_base& mon_dom_dis = domaine_dis();
1616 const int nb_valeurs_temps = schema_temps().nb_valeurs_temporelles();
1617
1618 Nom fieldname;
1619 fieldname = "INDICATRICE";
1620 fieldname += suffix;
1621 dis.discretiser_champ("champ_elem", mon_dom_dis,
1622 fieldname, "-",
1623 1 /* composantes */, nb_valeurs_temps,
1624 temps,
1625 indicatrice_);
1626 indicatrice_->associer_eqn(*this);
1627 //Nouvelle formulation
1628 champs_compris_.ajoute_champ(indicatrice_);
1629 //champs_compris_.liste_noms_compris()[0]+le_nom();
1630
1631 fieldname = "INDICATRICE_CACHE";
1632 fieldname += suffix;
1633 dis.discretiser_champ("champ_elem", mon_dom_dis,
1634 fieldname, "-",
1635 1 /* composantes */, 1 /* valeur temporelle */,
1636 temps,
1637 variables_internes_->indicatrice_cache);
1638 variables_internes_->indicatrice_cache->associer_eqn(*this);
1639 champs_compris_.ajoute_champ(variables_internes_->indicatrice_cache);
1640 variables_internes_->indicatrice_cache->PDI_save_type(true);
1641
1642 //champs_compris_.liste_noms_compris()[1]+le_nom();
1643
1644 fieldname = "INDICATRICE_FACES";
1645 fieldname += suffix;
1646 dis.discretiser_champ("vitesse", mon_dom_dis,
1647 fieldname, "-",
1648 1 /* composantes */, nb_valeurs_temps,
1649 temps,
1650 indicatrice_faces_);
1651 indicatrice_faces_->associer_eqn(*this);
1652 champs_compris_.ajoute_champ(indicatrice_faces_);
1653
1654 fieldname = "VITESSE_FILTREE";
1655 fieldname += suffix;
1656 dis.discretiser_champ("vitesse", mon_dom_dis,
1657 fieldname, "m/s",
1658 Objet_U::dimension /* composantes */, 1, /* valeur temporelle */
1659 temps,
1660 variables_internes_->vitesse_filtree);
1661 variables_internes_->vitesse_filtree->associer_eqn(*this);
1662 champs_compris_.ajoute_champ(variables_internes_->vitesse_filtree);
1663 //champs_compris_.liste_noms_compris()[2]+le_nom();
1664
1665 fieldname = "FLUX_TMP";
1666 fieldname += suffix;
1667 dis.discretiser_champ("vitesse", mon_dom_dis,
1668 fieldname, "m/s",
1669 1 /* composantes */,
1670 temps,
1671 variables_internes_->tmp_flux);
1672 champs_compris_.ajoute_champ(variables_internes_->tmp_flux);
1673 //champs_compris_.liste_noms_compris()[2]+le_nom();
1674
1675 fieldname = "INDEX_ELEM";
1676 dis.discretiser_champ("champ_elem", mon_dom_dis,
1677 fieldname, "m",
1678 Objet_U::dimension /* composantes */,
1679 temps,
1680 variables_internes_->index_element);
1681 champs_compris_.ajoute_champ(variables_internes_->index_element);
1682
1683 fieldname = "NELEM_PAR_DIRECTION";
1684 dis.discretiser_champ("champ_elem", mon_dom_dis,
1685 fieldname, "m",
1686 1 /* composantes */,
1687 temps,
1688 variables_internes_->nelem_par_direction);
1689 champs_compris_.ajoute_champ(variables_internes_->nelem_par_direction);
1690
1691 fieldname = "DISTANCE_INTERFACE_ELEM";
1692 fieldname += suffix;
1693 dis.discretiser_champ("champ_elem", mon_dom_dis,
1694 fieldname, "m",
1695 1 /* composantes */,
1696 temps,
1697 variables_internes_->distance_interface);
1698 champs_compris_.ajoute_champ(variables_internes_->distance_interface);
1699
1700 fieldname = "DISTANCE_INTERFACE_FACE";
1701 fieldname += suffix;
1702 dis.discretiser_champ("vitesse", mon_dom_dis,
1703 fieldname, "m",
1704 1 /* composantes */,
1705 temps,
1706 variables_internes_->distance_interface_faces);
1707 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces);
1708
1709 fieldname = "DISTANCE_INTERFACE_FACE_COR";
1710 fieldname += suffix;
1711 dis.discretiser_champ("vitesse", mon_dom_dis,
1712 fieldname, "m",
1713 1 /* composantes */,
1714 temps,
1715 variables_internes_->distance_interface_faces_corrigee);
1716 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces_corrigee);
1717
1718 fieldname = "DISTANCE_INTERFACE_FACE_DIF";
1719 fieldname += suffix;
1720 dis.discretiser_champ("vitesse", mon_dom_dis,
1721 fieldname, "m",
1722 1 /* composantes */,
1723 temps,
1724 variables_internes_->distance_interface_faces_difference);
1725 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces_difference);
1726
1727 fieldname = "VITESSE_IMP_INTERP";
1728 fieldname += suffix;
1729 dis.discretiser_champ("vitesse", mon_dom_dis,
1730 fieldname, "m",
1731 -1 /* composantes */,
1732 temps,
1733 vitesse_imp_interp_);
1734 champs_compris_.ajoute_champ(vitesse_imp_interp_);
1735
1736 //champs_compris_.liste_noms_compris()[3]+le_nom();
1737
1738 // Construction de la structure du tableau avec l'espace virtuel:
1739 {
1740 DoubleTab& d = variables_internes_->distance_interface_sommets;
1741 const Domaine& dom = domaine_dis().domaine();
1742 d.resize(0);
1743 dom.creer_tableau_sommets(d);
1744 }
1745 variables_internes_->distance_interface_sommets = 0.;
1746
1747 fieldname = "NORMALE_INTERFACE";
1748 fieldname += suffix;
1749 dis.discretiser_champ("champ_elem", mon_dom_dis,
1750 fieldname, "-",
1751 Objet_U::dimension /* composantes */,
1752 temps,
1753 variables_internes_->normale_interface);
1754 champs_compris_.ajoute_champ(variables_internes_->normale_interface);
1755 //champs_compris_.liste_noms_compris()[4]+le_nom();
1756
1757 //GB : Ajout du post-traitement de l'aire interfaciale par cellule :
1758 fieldname = "SURFACE_INTERFACE";
1759 fieldname += suffix;
1760 dis.discretiser_champ("champ_elem", mon_dom_dis,
1761 fieldname, "m2",
1762 1 /* composantes */,
1763 temps,
1764 variables_internes_->surface_interface);
1765 champs_compris_.ajoute_champ(variables_internes_->surface_interface);
1766 //GB : Fin de l'ajout.
1767
1769 {
1770 //TF : Ajout de la gestion de la derivee en temps
1771 fieldname = "TIME_DERIVATIVE_INTERFACE";
1772 fieldname += suffix;
1773 dis.discretiser_champ(Motcle("champ_elem"), mon_dom_dis,
1774 fieldname, Nom(""),
1775 1 /* composantes */,
1776 schema_temps().nb_valeurs_temporelles(),
1777 temps,
1778 derivee_en_temps_);
1779 //TF : Fin de l'ajout
1780 }
1781
1783 {
1784 // On modifie le domaine ici => on a besoin d'une reference non constante
1785 Domaine_dis_base& le_dom_dis2 = domaine_dis();
1786 le_dom_dis2.domaine().construire_elem_virt_pe_num();
1787 }
1788 {
1789 Domaine_VF& domaine_vf = ref_cast_non_const(Domaine_VF, mon_dom_dis);
1790 domaine_vf.construire_face_virt_pe_num();
1791 variables_internes_->connectivite_frontieres_.associer_domaine_vf(domaine_vf);
1792 }
1793 {
1794 Parcours_interface& parcours = variables_internes_->parcours_interface_;
1797 }
1798 {
1799 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
1800 marching_cubes().associer_domaine_vf(domaine_vf);
1801 }
1804
1805 variables_internes_->algorithmes_transport_.typer("Algorithmes_Transport_FT_Disc");
1806 // On n'appelle pas Equation_base::discretiser car on ne veut pas
1807 // de solveur masse.
1808
1809 Cerr << "Discretizing of the boundary conditions... ";
1810 le_dom_Cl_dis.typer(discretisation().domaine_cl_dis_type());
1811 le_dom_Cl_dis->associer(domaine_dis());
1812 Cerr << " OK " << finl;
1813
1814 le_dom_Cl_dis->associer_eqn(*this);
1815 le_dom_Cl_dis->associer_inconnue(inconnue());
1816
1817}
1818
1819/*! @brief Remaillage de l'interface : - amelioration petites et grandes facettes,
1820 *
1821 * - barycentrage,
1822 * - gestion des coalescences-fragmentations.
1823 *
1824 */
1826{
1827 Journal() << "Transport_Interfaces_FT_Disc::remailler_interface " << le_nom() << finl;
1828 const double temps = schema_temps().temps_courant();
1830 // Ce champ sera mis a jour si on realise un remaillage global...
1831 Champ_base& indicatrice = variables_internes_->indicatrice_cache.valeur();
1832 Remaillage_FT& algo_remaillage_local = remaillage_interface();
1833 Topologie_Maillage_FT& algo_topologie = topologie_interface();
1834 algo_topologie.remailler_interface(temps, maillage, indicatrice, algo_remaillage_local);
1835}
1836
1838{
1839
1840 if (not(preparer_calcul_anticipated_done_))
1841 {
1843 }
1844 else
1845 {
1846 Process::Journal()<<"Transport_Interfaces_FT_Disc::preparer_calcul does nothing because it has been anticipated in the problem"<<finl;
1847 }
1848 return 1;
1849}
1850
1852{
1853 Process::Journal()<<"Transport_Interfaces_FT_Disc::preparer_calcul"<<finl;
1854
1855 preparer_calcul_anticipated_done_ = true;
1856
1858 {
1859 compute_nb_particles_tot(); // must be done before Collision_Model_FT::reprendre
1861 mean_particles_volumic_velocity_.resize(nb_particles_tot_,dimension);
1862 mean_particles_volumic_squared_velocity_.resize(nb_particles_tot_,dimension);
1863 rms_particles_volumic_velocity_.resize(nb_particles_tot_,dimension);
1864 particles_purely_solid_mesh_volume_.resize(nb_particles_tot_);
1865 post_process_hydro_forces_.associate_ns_equation(equation_ns_);
1866 post_process_hydro_forces_.associate_transport_equation(*this);
1867 post_process_hydro_forces_Stokes_.associate_ns_equation(equation_ns_);
1868 post_process_hydro_forces_Stokes_.associate_transport_equation(*this);
1870 post_process_hydro_forces_.resize_and_init_tables(nb_particles_tot_);
1871 post_process_hydro_forces_Stokes_.resize_and_init_tables(nb_particles_tot_);
1872 }
1873
1874 if (collision_model_)
1875 {
1876 const Navier_Stokes_FT_Disc& ns = equation_ns_.valeur();
1877 const Domaine_VDF& domain_vdf = ref_cast(Domaine_VDF, domaine_dis());
1878 const Schema_Comm& schema_comm_FT=maillage_interface().get_schema_comm_FT();
1879 collision_model_.valeur().preparer_calcul(domain_vdf, nb_particles_tot_,
1880 ns, *this, schema_comm_FT);
1881 }
1882
1883 const double temps = schema_temps().temps_courant();
1884 // La ligne suivante doit figurer avant le premier remaillage
1885 // car le remaillage utilise les angles de contact (lissage courbure)
1886 le_dom_Cl_dis->initialiser(temps);
1887
1888 if (probleme().reprise_effectuee())
1889 {
1890 Cerr << "Calculation restarting : no initial meshing" << finl;
1891 }
1892 else
1893 {
1894 Cerr << "Initial condition remeshing." << finl;
1895 //maillage_interface().nettoyer_maillage(); // GB : Pour supprimer toutes ces facettes nulles...
1897 //maillage_interface().nettoyer_maillage(); // GB : Pour supprimer toutes ces facettes nulles...
1898 }
1899
1900 // Ajout pour la sauvegarde au premier pas de temps si reprise
1901 indicatrice_->changer_temps(temps);
1902 variables_internes_->indicatrice_cache->changer_temps(temps);
1903 indicatrice_faces_->changer_temps(temps);
1904 variables_internes_->vitesse_filtree->changer_temps(temps);
1905 variables_internes_->tmp_flux->changer_temps(temps);
1906 variables_internes_->index_element->changer_temps(temps);
1907 variables_internes_->nelem_par_direction->changer_temps(temps);
1908 variables_internes_->distance_interface->changer_temps(temps);
1909 variables_internes_->distance_interface_faces->changer_temps(temps);
1910 variables_internes_->distance_interface_faces_corrigee->changer_temps(temps);
1911 variables_internes_->distance_interface_faces_difference->changer_temps(temps);
1912 vitesse_imp_interp_->changer_temps(temps);
1913 variables_internes_->normale_interface->changer_temps(temps);
1914 variables_internes_->surface_interface->changer_temps(temps);
1915
1916 const Nom& checkpoint_fname = get_probleme_base().checkpoint_filename();
1917 variables_internes_->set_checkpoint_fname(checkpoint_fname);
1918
1919 //calcul de l'indicatrice
1922
1923 // On verifie que la methode de transport a bien ete fournie dans le jeu
1924 // de donnees:
1925 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::INDEFINI)
1926 {
1927 Cerr << "Error for the method Transport_Interfaces_FT_Disc::preparer_calcul\n"
1928 << "The transport method has not indicated for the equation\n"
1929 << le_nom() << finl;
1930 assert(0);
1931 Process::exit();
1932 }
1933
1934 // Pour le premier postraitement :
1935 //variables_internes_->maillage_pour_post.recopie(maillage,
1936 // Maillage_FT_Disc::MINIMAL);
1937
1938 //Ajout TF : gestion de la derivee en temps
1940 //Fin TF
1941 return 1;
1942}
1943
1945{
1946 // PDI not supported for FT so writing front in xyz format
1947 variables_internes_->init_save_file();
1948}
1949
1951{
1952 variables_internes_->close_save_file();
1953}
1954
1959
1961{
1962 // TODO:
1963 // We should think of implementing it as in eq. 16 for instance:
1964 // https://hal.archives-ouvertes.fr/hal-02304125/document
1965 // and use the Lagrangian min edge length instead of Delta_x.
1966 //
1967 // Ou encore :
1968 // Par ailleurs du fait de la contrainte sur le pas de temps capillaire (Popinet 2009) cette approche
1969 // connait egalement des limites (Pierson 2021). En effet, quand les films deviennent suffisamment minces,
1970 // et que les cellules composant le film sont suffisamment petites, le pas de temps necessaire au calcul
1971 // decroit drastiquement, comme la taille des cellules a la puissance trois-demi.
1972 // Pierson, J. (2021). Numerical study of drop bouncing on a fluid-fluid interface. ICTAM, Milan.
1973 // Popinet, S. (2020). A vertically-Lagrangian, non-hydrostatic, multilayer model for multiscale free-surface flows. Journal of Computational Physics, 109609
1974 //
1975 return DMAXFLOAT;
1976}
1977
1978/*! @brief Updates normals and distances to interface, then updates indicatrice
1979 *
1980 * calls Maillage_FT_Disc::parcourir_maillage() first.
1981 * calls update_normale_distance_interface then update_indicatrice
1982 */
1984{
1985 // Si le Maillage_FT_Disc::MINIMAL, le parcourir:
1987
1988 // L'indicatrice a besoin de la distance Eulerienne (type LS) pour etre calculee
1989 // (plus precisement, la distance permet de la corriger localement):
1992}
1993
1994/*! @brief Calcule la normale et la distance a l'interface,
1995 * evaluees sur une epaisseur egale a n_iterations_distance aux elements et discretisee aux elements
1996 *
1997 */
1999{
2000 const int tag = maillage_interface().get_mesh_tag();
2001
2002 // Check if the call is useful
2003 if (tag == variables_internes_->distance_normale_cache_tag)
2004 {
2005 Cerr << "WARNING : Unneeded call to Transport_Interfaces_FT_Disc::update_normale_distance_interface" << finl;
2006 Cerr << " mesh tag: " << tag << ", cache tag: "<< variables_internes_->distance_normale_cache_tag << finl;
2007 Process::exit();
2008 }
2009
2010 DoubleTab& distance = variables_internes_->distance_interface->valeurs();
2011 DoubleTab& normale = variables_internes_->normale_interface->valeurs();
2013 distance,
2014 normale,
2015 variables_internes_->n_iterations_distance);
2016 variables_internes_->distance_normale_cache_tag = tag;
2017}
2018
2019/*! @brief Recalcul du champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
2020 *
2021 * ATTENTION, ce n'est pas l'inconnue du probleme. L'inconnue est mise a jour
2022 * a partir de ce champ dans mettre_a_jour.
2023 *
2024 */
2026{
2027 const int tag = maillage_interface().get_mesh_tag();
2028
2029 // Check if the call is useful
2030 // can be bypassed by changing the tag before calling update_indicatrice (use this knowledge carefully)
2031 if (tag == variables_internes_->indicatrice_cache_tag)
2032 {
2033 Cerr << "WARNING : Unneeded call to Transport_Interfaces_FT_Disc::update_indicatrice. tag = " << tag << finl;
2034 Cerr << " indicatrice is already up to date" << finl;
2035 Process::exit();
2036 }
2037
2038 // Le calcul de l'indicatrice a besoin d'une distance qui soit bien a jour...
2039 if (tag != variables_internes_->distance_normale_cache_tag)
2040 {
2041 Cerr << "ERROR : in Transport_Interfaces_FT_Disc::update_indicatrice : distance_normale not up to date" << finl;
2042 Cerr << " Call update_indicatrice_normale_distance before or update_normale_distance_interface to do both at the same time" << finl;
2043 Cerr << " mesh tag: " << tag << ", cache tag: "<< variables_internes_->distance_normale_cache_tag << finl;
2044 Process::exit();
2045 }
2046
2047 // Voir s'il manque un appel a maillage_interface().parcourir_maillage()
2048 if (not(maillage_interface().type_statut()>=Maillage_FT_Disc::PARCOURU))
2049 {
2050 Cerr << "ERROR : in Transport_Interfaces_FT_Disc::update_indicatrice : maillage pas parcouru" << finl;
2051 Process::exit();
2052 }
2053
2054 DoubleVect& valeurs_indicatrice = variables_internes_->indicatrice_cache->valeurs();
2055
2056
2057 maillage_interface().calcul_indicatrice(valeurs_indicatrice, valeurs_indicatrice);
2058 variables_internes_->indicatrice_cache_tag = tag;
2059
2060 // TODO : nettoyer ce doublon de champs historique pour ne garder qu'un champ
2061 indicatrice_->valeurs() = get_indicatrice().valeurs(); // met a jour l'indicatrice a partir de indicatrice_cache qui vient d'etre calculee.
2062}
2063
2064/*! @brief Checks if the indicator is up to date
2065 *
2066 * Exits if it is not the case. To be used when we want to be sure that update_indicatrice has been called recently enough.
2067 * The same test is also done in Transport_Interfaces_FT_Disc::get_indicatrice
2068 *
2069 */
2071{
2072 const int tag = maillage_interface().get_mesh_tag();
2073 if (tag != variables_internes_->indicatrice_cache_tag)
2074 {
2075 Cerr << "Error: indicatrice not up to date" << finl;
2076 Process::exit();
2077 }
2078}
2079
2080/*! @brief getter champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
2081 *
2082 * ATTENTION, ce n'est pas l'inconnue du probleme. L'inconnue est mise a jour
2083 * a partir de ce champ dans mettre_a_jour.
2084 *
2085 */
2087{
2088 const int tag = maillage_interface().get_mesh_tag();
2089 if (tag != variables_internes_->indicatrice_cache_tag)
2090 {
2091 Cerr << "Error: indicatrice not up to date in get_indicatrice. " << finl;
2092 Process::exit();
2093 }
2094 return variables_internes_->indicatrice_cache.valeur();
2095}
2096
2098{
2099 const int tag = maillage_interface().get_mesh_tag();
2100 if (tag != variables_internes_->distance_normale_cache_tag)
2101 {
2102 Cerr << "Error: indicatrice not up to date in get_distance_interface. " << finl;
2103 Process::exit();
2104 }
2105 return variables_internes_->distance_interface.valeur();
2106}
2107
2109{
2110 const int tag = maillage_interface().get_mesh_tag();
2111 if (tag != variables_internes_->distance_normale_cache_tag)
2112 {
2113 Cerr << "Error: indicatrice not up to date in get_normale_interface. " << finl;
2114 Process::exit();
2115 }
2116 return variables_internes_->normale_interface.valeur();
2117}
2118
2119/*! @brief Interpolation lineaire d'un champ de vitesse VDF aux faces en un point de coordonnees coord_som.
2120 *
2121 * Le point coord_som est suppose se trouver dans
2122 * l'element "element".
2123 * Pour chaque composante, on cherche le cube contenant coord_som et dont
2124 * les sommets sont des noeuds de vitesse pour cette composante et on
2125 * interpole lineairement dans ce cube. Au bord du domaine, la vitesse
2126 * tangentielle dans le demi-element colle a la paroi est la vitesse
2127 * discrete de l'element (la condition aux limites n'est PAS utilisee).
2128 *
2129 */
2130void interpoler_vitesse_point_vdf(const Champ_base& champ_vitesse,
2131 const FTd_vecteur3& coord_som,
2132 const int element,
2133 FTd_vecteur3& vitesse,
2134 const int future_or_past)
2135{
2136 const DoubleTab& valeurs_v = (bool)(future_or_past) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2137 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, champ_vitesse.domaine_dis_base());
2138 const IntTab& elem_faces = domaine_vf.elem_faces();
2139 const DoubleTab& xv = domaine_vf.xv();
2140 const DoubleTab& xp = domaine_vf.xp();
2141 const IntTab& face_voisins = domaine_vf.face_voisins();
2142
2143 // La vitesse est la moyenne ponderee des 4 ou 8 vitesses
2144 // aux faces qui encadrent le sommet.
2145 // On designe par i,j,k l'une des 8 faces, avec 0<=i<=1, 0<=j<=1, 0<=k<=1.
2146 // La composante vitesse au sommet est
2147 // vitesse = SOMME(vitesse(face_i,j,k)*coef[0]*coef[1]*coef[2]);
2148 // Exemple : interpolation de la composante horizontale de vitesse
2149 // pour le sommet "x". On fait une interpolation bilineaire
2150 // entre les quatre composantes horizontales de vitesses v (8 vitesses en 3d)
2151 // On a besoin de l'element voisin situe au dessus car le sommet
2152 // est dans la moitie superieure de l'element :
2153 // --------
2154 // | |
2155 // | v10 | v11
2156 // |--> |-->
2157 // | |
2158 // | |
2159 // --------
2160 // | x |
2161 // | v00 | v01
2162 // |--> |-->
2163 // | |
2164 // | |
2165 // --------
2166
2167 // Boucle sur les 2 ou 3 composantes de la vitesse
2168 int compo;
2169 const int dim = Objet_U::dimension;
2170 for (compo = 0; compo < dim; compo++)
2171 {
2172 // ****
2173 // Calcul des 2 ou 3 coefficients de ponderation coef[x]
2174 // ****
2175 double coef[3];
2176 // Numeros des elements voisins dans chaque direction
2177 // (le numero de l'element voisins dans la direction "compo" n'est pas
2178 // utilise et reste a -1)
2179 int elem_voisins[3] = { -1, -1, -1 };
2180 // Indice local de la face de "element" qui est commune avec elem_voisin[i]:
2181 int indice_local_face_voisine[3] = { -1, -1, -1 };
2182 // Numero du quatrieme element utilise pour interpoler la vitesse
2183 // (les elements utilises en 3D sont "element", "elem_voisins[(compo+1)%3]",
2184 // "elem_voisins[(compo+2)%3]" et "elem_diagonal".
2185 int elem_diagonal = -1;
2186
2187 // Boucle sur les 2 ou 3 dimensions du cube dans lequel on interpole la valeur
2188 int direction;
2189 for (direction = 0; direction < dim; direction++)
2190 {
2191 // Coordonnee du point ou il faut interpoler la vitesse
2192 const double x = coord_som[direction];
2193 double a; // Le coef d'interpolation dans la direction
2194 if (direction == compo)
2195 {
2196 // Dans la direction de la composante traitee on interpole
2197 // entre les deux faces opposees de l'element. Coordonnees
2198 // de ces faces :
2199 const int face_inf_compo = elem_faces(element, compo);
2200 const int face_sup_compo = elem_faces(element, compo + dim);
2201 const double xmin = xv(face_inf_compo, direction);
2202 const double xmax = xv(face_sup_compo, direction);
2203 a = (xmax - x) / (xmax - xmin);
2204 }
2205 else
2206 {
2207 // Dans les autres directions, on cherche les faces des
2208 // elements voisins si elles existent.
2209 // Calcul de l'element voisin a utiliser: le plus proche du point
2210 // a interpoler
2211 const double centre_elem = xp(element, direction);
2212 // Indice local dans l'element de la face la plus proche dans la
2213 // direction i
2214 const int i_face_voisine = direction + ((x < centre_elem) ? 0 : dim);
2215 // Indice de la face dans le domaine
2216 const int face_voisine = elem_faces(element, i_face_voisine);
2217 // Indice de l'element voisin par cette face
2218 const int elem_voisin =
2219 face_voisins(face_voisine, 0) + face_voisins(face_voisine, 1) - element;
2220 if (elem_voisin >= 0)
2221 {
2222 // Il y a un voisin: coordonnee du centre de la face voisine
2223 const double centre_voisin = xp(elem_voisin, direction);
2224 a = (centre_voisin - x) / (centre_voisin - centre_elem);
2225 elem_voisins[direction] = elem_voisin;
2226 indice_local_face_voisine[direction] = i_face_voisine;
2227 }
2228 else
2229 {
2230 // Pas de voisin (face de bord). La vitesse est supposee constante
2231 // dans la direction "i".
2232 a = 1.;
2233 }
2234 }
2235 if (a < 0.)
2236 a = 0.;
2237 if (a > 1.)
2238 a = 1.;
2239 coef[direction] = a;
2240 }
2241
2242 if (dim == 3)
2243 {
2244 const int direction1 = (compo + 1) % 3;
2245 const int direction2 = (compo + 2) % 3;
2246 const int elem_voisin1 = elem_voisins[direction1];
2247 const int elem_voisin2 = elem_voisins[direction2];
2248 // Recherche de l'element diagonal:
2249 if (elem_voisin1 >= 0 && elem_voisin2 >= 0)
2250 {
2251 // On cherche l'element voisin de elem_voisin1 dans la direction direction2:
2252 int i_face_voisine, face_voisine, elem_diagonal1, elem_diagonal2;
2253
2254 i_face_voisine = indice_local_face_voisine[direction2];
2255 face_voisine = elem_faces(elem_voisin1, i_face_voisine);
2256 // element diagonal obtenu par le voisin de elem_voisin1:
2257 elem_diagonal1 = face_voisins(face_voisine, 0)
2258 + face_voisins(face_voisine, 1) - elem_voisin1;
2259 if (elem_diagonal1 >= 0)
2260 {
2261 // Ok, on a un element diagonal, on verifie qu'on l'a aussi par
2262 // l'autre cote (voisin de elem_voisin2 dans la direction direction1) :
2263 i_face_voisine = indice_local_face_voisine[direction1];
2264 face_voisine = elem_faces(elem_voisin2, i_face_voisine);
2265 // element diagonal obtenu par le voisin de elem_voisin2:
2266 elem_diagonal2 = face_voisins(face_voisine, 0)
2267 + face_voisins(face_voisine, 1) - elem_voisin2;
2268 if (elem_diagonal1 == elem_diagonal2)
2269 {
2270 // Les deux elements existent et sont identiques:
2271 elem_diagonal = elem_diagonal1;
2272 }
2273 else
2274 {
2275 // L'un des deux elements n'existe pas (il y a un bord)
2276 // => pas d'element diagonal
2277 elem_diagonal = -1;
2278 }
2279 }
2280 else
2281 {
2282 // Pas de voisin => pas d'element diagonal
2283 elem_diagonal = -1;
2284 }
2285 if (elem_diagonal < 0)
2286 {
2287 // Pas d'element diagonal => il y a un coin => pas d'interpolation.
2288 elem_voisins[direction1] = -1;
2289 elem_voisins[direction2] = -1;
2290 }
2291 }
2292 else
2293 {
2294 // Il n'y a qu'un voisin au maximum, donc pas d'element diagonal.
2295 // Rien a faire.
2296 }
2297 }
2298 if (dim == 2)
2299 {
2300 // Numeros des faces utilisees pour interpoler le champ:
2301 const int direction1 = 1 - compo;
2302 int element_voisin = elem_voisins[direction1];
2303 if (element_voisin < 0)
2304 element_voisin = element;
2305 const int f00 = elem_faces(element, compo);
2306 const int f10 = elem_faces(element, compo + dim);
2307 const int f01 = elem_faces(element_voisin, compo);
2308 const int f11 = elem_faces(element_voisin, compo + dim);
2309 // Coefficient d'interpolation dans la direction de la composante traitee
2310 double ci = coef[compo];
2311 // Coefficient dans l'autre direction
2312 double cj = coef[direction1];
2313 vitesse[compo] =
2314 ci * cj * valeurs_v(f00)
2315 + (1.-ci) * cj * valeurs_v(f10)
2316 + ci * (1.-cj) * valeurs_v(f01)
2317 + (1.-ci) * (1.-cj) * valeurs_v(f11);
2318 if (Objet_U::bidim_axi && (compo==0) && (ci>Objet_U::precision_geom) && (ci<1.-Objet_U::precision_geom)
2319 && (xv(f00,0) <DMINFLOAT)
2320 && ((fabs(valeurs_v(f00)-valeurs_v(f10))>DMINFLOAT) || (fabs(valeurs_v(f01)-valeurs_v(f11))>DMINFLOAT)))
2321 {
2322 Cerr << "In bidim_axi, when interpolating u_r within the first cell, we use the value on the symetry axis u_r(r=0)=0." << finl;
2323 Cerr << "We take a simple mean on that and the value at the other face. But for a divergence-free field, neglecting dv/dy, " << finl;
2324 Cerr << "it would be better to assume a velocity as u(x) = x_1/x * u_1 (if x!=0). GB 2020/03/05." << finl;
2325 const double x = coord_som[0];
2326 Cerr << "Here, the difference is "<< (1.-ci) << " vs. " << xv(f10, 0)/x << finl;
2327 Cerr << "u1= " << valeurs_v(f10) << " direction1 : " << direction1 << finl;
2328 Cerr << "interpoler_vitesse_point_vdf of Transport_Interface..cpp not exiting but interpolation is adapted" << finl;
2329 Cerr << "Former: " << vitesse[compo];
2330 vitesse[compo] = xv(f10, 0)/x * (
2331 cj * valeurs_v(f10)
2332 + (1.-cj) * valeurs_v(f11));
2333 Cerr << " New: " << vitesse[compo] << finl;
2334 //Process::exit();
2335 }
2336 }
2337 else if (dim == 3)
2338 {
2339 // 4 elements utilises pour interpoler la valeur:
2340 const int direction1 = (compo + 1) % 3;
2341 const int direction2 = (compo + 2) % 3;
2342 int elem00 = element;
2343 int elem10 = elem_voisins[direction1];
2344 int elem01 = elem_voisins[direction2];
2345 int elem11 = elem_diagonal;
2346 if (elem10 < 0) elem10 = element;
2347 if (elem01 < 0) elem01 = element;
2348 if (elem11 < 0) elem11 = element;
2349 // Numeros des faces utilisees pour interpoler le champ:
2350 const int f000 = elem_faces(elem00, compo);
2351 const int f100 = elem_faces(elem00, compo + dim);
2352 const int f010 = elem_faces(elem10, compo);
2353 const int f110 = elem_faces(elem10, compo + dim);
2354 const int f001 = elem_faces(elem01, compo);
2355 const int f101 = elem_faces(elem01, compo + dim);
2356 const int f011 = elem_faces(elem11, compo);
2357 const int f111 = elem_faces(elem11, compo + dim);
2358 // Coefficients d'interpolation
2359 double ci = coef[compo];
2360 double cj = coef[direction1];
2361 double ck = coef[direction2];
2362 // Calcul de la valeur interpolee
2363 vitesse[compo] =
2364 ( ci * cj * valeurs_v(f000)
2365 + (1.-ci) * cj * valeurs_v(f100)
2366 + ci * (1.-cj) * valeurs_v(f010)
2367 + (1.-ci) * (1.-cj) * valeurs_v(f110)) * ck
2368 +( ci * cj * valeurs_v(f001)
2369 + (1.-ci) * cj * valeurs_v(f101)
2370 + ci * (1.-cj) * valeurs_v(f011)
2371 + (1.-ci) * (1.-cj) * valeurs_v(f111)) * (1. - ck);
2372
2373 }
2374 else
2375 {
2376 // Hey, what are you doing here ?
2377 Process::exit();
2378 }
2379 }
2380}
2381
2382
2383// Description:
2384// Interpolation uni-lineaire d'un champ de vitesse VDF aux faces en un point
2385// de coordonnees coord_som. Le point coord_som est suppose se trouver dans
2386// l'element "element". Contrairement a la methode interpoler_vitesse_point_vdf
2387// dont elle s'inspire, cette methode n'interpole chaque composante que dans sa propre
2388// direction
2389// Pour chaque composante, on cherche le cube contenant coord_som et dont
2390// les sommets sont des noeuds de vitesse pour cette composante et on
2391// interpole lineairement dans ce cube. Au bord du domaine, la vitesse
2392// tangentielle dans le demi-element colle a la paroi est la vitesse
2393// discrete de l'element (la condition aux limites n'est PAS utilisee).
2394void interpoler_simple_vitesse_point_vdf(const Champ_base& champ_vitesse,
2395 const FTd_vecteur3& coord_som,
2396 const int element,
2397 FTd_vecteur3& vitesse,
2398 const int future_or_past)
2399{
2400 const DoubleTab& valeurs_v = (bool)(future_or_past) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2401 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, champ_vitesse.domaine_dis_base());
2402 const IntTab& elem_faces = domaine_vf.elem_faces();
2403 const DoubleTab& xv = domaine_vf.xv();
2404
2405 // Chaque composante de vitesse est la moyenne ponderee des 2 vitesses
2406 // aux faces de l'element qui encadrent le sommet.
2407 // On designe par i,j,k l'une des 8 faces, avec 0<=i<=1, 0<=j<=1, 0<=k<=1.
2408 // La composante vitesse au sommet est
2409 // vitesse = SOMME(vitesse(face_i,j,k)*coef[0]*coef[1]*coef[2]);
2410 // Exemple : interpolation de la composante horizontale de vitesse
2411 // pour le sommet "x". On fait une interpolation bilineaire
2412 // entre les DEUX composantes horizontales de vitesses v.
2413 // Pas besoin des voisins!
2414 // --------
2415 // | x |
2416 // | v0 | v1
2417 // |--> |-->
2418 // | |
2419 // | |
2420 // --------
2421
2422 // Boucle sur les 2 ou 3 composantes de la vitesse
2423 int compo;
2424 const int dim = Objet_U::dimension;
2425 for (compo = 0; compo < dim; compo++)
2426 {
2427 // ****
2428 // Calcul d'un unique coefficient de ponderation coef
2429 // ****
2430 double coef;
2431
2432 // Boucle sur les 2 ou 3 dimensions du cube dans lequel on interpole la valeur
2433 int direction = compo;
2434 // Coordonnee du point ou il faut interpoler la vitesse
2435 const double x = coord_som[direction];
2436 // Dans la direction de la composante traitee on interpole
2437 // entre les deux faces opposees de l'element. Coordonnees
2438 // de ces faces :
2439 const int face_inf_compo = elem_faces(element, compo);
2440 const int face_sup_compo = elem_faces(element, compo + dim);
2441 const double xmin = xv(face_inf_compo, direction);
2442 const double xmax = xv(face_sup_compo, direction);
2443 coef = (xmax - x) / (xmax - xmin); // Le coef d'interpolation dans la direction
2444
2445 if (coef < 0.)
2446 coef = 0.;
2447 if (coef > 1.)
2448 coef = 1.;
2449
2450 vitesse[compo] = coef * valeurs_v(face_inf_compo) + (1.-coef) * valeurs_v(face_sup_compo);
2451 }
2452}
2453
2454double Transport_Interfaces_FT_Disc::calculer_integrale_indicatrice(const DoubleVect& indicatrice, double& integrale_ph0) const
2455{
2456 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
2457 const DoubleVect& volumes = domaine_vf.volumes();
2458 int nd, nb_nd = indicatrice.size();
2459 assert(nb_nd==domaine_vf.nb_elem());
2460
2461 double integrale = 0.;
2462 integrale_ph0 = 0.;
2463 for (nd=0 ; nd<nb_nd ; nd++)
2464 {
2465 integrale += indicatrice(nd) * volumes(nd);
2466 integrale_ph0 += (1 - indicatrice(nd))*volumes(nd);
2467 }
2468 // Reduce 2 mp_sum calls to 1 by using mp_sum_for_each
2469 Process::mp_sum_for_each(integrale_ph0, integrale);
2470 return integrale;
2471}
2472
2473/*! @brief Calcul de la vitesse de deplacement des noeuds du maillage a partir d'un champ eulerien par interpolation.
2474 *
2475 * Le deplacement fourni n'a aucune propriete particuliere de conservation
2476 * du volume.
2477 * Les lignes de contact sont deplacees avec une vitesse qui n'a pas de
2478 * propriete particuliere non plus...
2479 *
2480 * ATTENTION : on evalue simplement la vitesse a l'endroit ou sont les sommets.
2481 * Param nv_calc : si =1 : recalcule le champ eulerien de la vitesse par filtrage L2
2482 * sinon, reutilise celui stocke dans variables_internes_
2483 *
2484 */
2486 const Champ_base& champ_vitesse,
2487 const Maillage_FT_Disc& maillage,
2488 DoubleTab& vitesse_noeuds,
2489 const int nv_calc,
2490 const int standard,
2491 const bool la_roue_de_vitesse_a_deja_tournee) const
2492{
2493 switch(variables_internes_->methode_interpolation_v)
2494 {
2496 {
2497 const Champ_base * champ_vitesse_interp = 0; // Le champ a utiliser pour interpoler
2498 if (sub_type(Champ_P1NC, champ_vitesse) || sub_type(Champ_Fonc_P1NC,champ_vitesse))
2499 {
2500 // Champ P1NC en VEF: on projette L2 sur un champ P1,
2501 // puis on interpole lineairement
2502 Champ_base& champ_filtre = variables_internes_->vitesse_filtree.valeur();
2503 champ_vitesse_interp = & champ_filtre;
2504
2505 if (nv_calc)
2506 {
2507 // Premier jet :
2508 // Calcul d'un champ aux sommets par filtrage L2 (inversion d'une matrice)
2509 // c'est assez long...
2510 // TODO GB2024 : Selon d'ou on fait l'appel, il faut .valeurs() ou .futur()
2511 // Je ne sais pas si l'option explicit_u_NS_ est correcte ici.
2512 const DoubleTab& val_champ_vitesse = (bool)(explicit_u_NS_) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2513 champ_filtre.valeurs() = val_champ_vitesse;
2514 ////if (type == "Champ_P1NC")
2515 if (sub_type(Champ_P1NC, champ_vitesse))
2516 ref_cast(Champ_P1NC, champ_vitesse).filtrer_L2(champ_filtre.valeurs());
2517 else
2518 ref_cast(Champ_Fonc_P1NC, champ_vitesse).filtrer_L2(champ_filtre.valeurs());
2519 if (explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee) champ_filtre.futur() = champ_filtre.valeurs();
2520 }
2521 }
2522 else if (sub_type(Champ_Face_VDF, champ_vitesse) || sub_type(Champ_Fonc_Face_VDF,champ_vitesse))
2523 {
2524 // On appelle 'valeur_aux_elems' du champ aux faces.
2525 champ_vitesse_interp = &champ_vitesse;
2526 }
2527 else
2528 {
2529 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n";
2530 Cerr << "The interpolation from a field " << champ_vitesse.que_suis_je();
2531 Cerr << "is not developped." << finl;
2532 assert(0); // a coder...
2533 Process::exit();
2534 }
2535
2536 // Calcul de la vitesse interpolee a partir du champ P1
2537 // On ne calcule que les vitesses des sommets reels :
2538 DoubleTab& les_positions = variables_internes_->doubletab_pos;
2539 IntVect& les_elements = variables_internes_->intvect_elements;
2540 DoubleTab& les_vitesses = variables_internes_->doubletab_vitesses;
2541 // Remplissage des tableaux :
2542 const DoubleTab& pos = maillage.sommets();
2543 const ArrOfInt& elem = maillage.sommet_elem();
2544 const int nb_pos_tot = pos.dimension(0);
2545 const int dim = Objet_U::dimension;
2546 les_positions.resize(nb_pos_tot, dim);
2547 les_elements.resize(nb_pos_tot);
2548 int i, j;
2549 int nb_positions = 0;
2550 for (i = 0; i < nb_pos_tot; i++)
2551 {
2552 const int num_elem = elem[i];
2553 if (num_elem >= 0)
2554 {
2555 for (j = 0; j < dim; j++)
2556 les_positions(nb_positions, j) = pos(i, j);
2557 les_elements(nb_positions) = num_elem;
2558 nb_positions++;
2559 }
2560 }
2561 les_positions.resize(nb_positions, dim);
2562 les_elements.resize(nb_positions);
2563 les_vitesses.resize(nb_positions, dim);
2564
2565 if (explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee)
2566 //champ_vitesse_interp->valeur_aux_elems_passe(les_positions, les_elements, les_vitesses);
2567 champ_vitesse_interp->valeur_aux_elems_passe(les_positions, les_elements, les_vitesses);
2568 else
2569 champ_vitesse_interp->valeur_aux_elems(les_positions, les_elements, les_vitesses);
2570
2571 // Copie des vitesses :
2572 vitesse_noeuds.resize(nb_pos_tot, dim);
2573 nb_positions = 0;
2574 for (i = 0; i < nb_pos_tot; i++)
2575 {
2576 if (elem[i] >= 0)
2577 {
2578 for (j = 0; j < dim; j++)
2579 vitesse_noeuds(i, j) = les_vitesses(nb_positions, j);
2580 nb_positions++;
2581 }
2582 }
2583 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2584
2585 break;
2586 }
2588 {
2589 if (!sub_type(Champ_Face_VDF, champ_vitesse) && !sub_type(Champ_Fonc_Face_VDF,champ_vitesse) )
2590 {
2591 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n"
2592 << "the interpolation VDF_LINEAIRE is valid only for a VDF discretization with a Champ_face field\n"
2593 << " (type for the current field: " << champ_vitesse.que_suis_je() << finl;
2594 Process::exit();
2595 }
2596 const DoubleTab& pos = maillage.sommets();
2597 const ArrOfInt& elem = maillage.sommet_elem();
2598 const int nb_pos_tot = pos.dimension(0);
2599 const int dim = Objet_U::dimension;
2600 int i;
2601 FTd_vecteur3 coord;
2602 FTd_vecteur3 vitesse;
2603 vitesse_noeuds.resize(nb_pos_tot, dim);
2604 for (i = 0; i < nb_pos_tot; i++)
2605 {
2606 const int element = elem[i];
2607 if (element >= 0) // sommet reel ?
2608 {
2609 int j;
2610 for (j = 0; j < dim; j++)
2611 coord[j] = pos(i,j);
2612 if (standard)
2613 {
2614 // Interpolation M-lineaire dans toutes les M-directions pour chaque compo
2615 interpoler_vitesse_point_vdf(champ_vitesse, coord, element, vitesse, explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee);
2616 }
2617 else
2618 {
2619 // Interpolation uni-lineaire dans chaque direction de chaque compo :
2620 interpoler_simple_vitesse_point_vdf(champ_vitesse, coord, element, vitesse, explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee);
2621 }
2622 for (j = 0; j < dim; j++)
2623 vitesse_noeuds(i,j) = vitesse[j];
2624 }
2625 }
2626 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2627 break;
2628 }
2630 {
2631 const DoubleTab& vertices = maillage.sommets();
2632 const int nb_vertices_tot = vertices.dimension(0);
2633 vitesse_noeuds.resize(nb_vertices_tot, dimension);
2634 const int& nb_fa7 = maillage.nb_facettes();
2635 ArrOfInt id_number_fa7(nb_fa7);
2636 const ArrOfDouble& surface_fa7 = maillage.get_update_surface_facettes();
2637 int n = search_connex_components_local_FT(maillage, id_number_fa7);
2638 const int nb_particles_tot=compute_global_connex_components_FT(maillage, id_number_fa7, n);
2639 const DoubleTab& phase_indicator_function = indicatrice_->valeurs();
2640 const ArrOfInt& sommets_elem = maillage.sommet_elem();
2641 const IntTab& facettes = maillage.facettes();
2642 DoubleTab Particles_velocity(nb_particles_tot,dimension);
2643 Particles_velocity=0;
2644 DoubleVect V_compo_elem(nb_particles_tot);
2645 V_compo_elem=0;
2646 ArrOfDouble Particles_surfaces(nb_particles_tot);
2647 Particles_surfaces=0;
2648 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
2649 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
2650 const DoubleTab& tab_velocity=champ_vitesse.valeurs();
2651 const Domaine_dis_base& mon_dom_dis = domaine_dis();
2652 const Domaine_VDF& domain_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
2653 const DoubleVect& volumes_maille = domain_vdf.volumes();
2654 const IntTab& elem_faces = domain_vdf.elem_faces();
2655 ns.compute_particles_eulerian_id_number(collision_model_);
2657 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
2658
2659 // STEP 1 : computing the mean volumic velocity inside each particle.
2660 // The ideal method would be to obtain the elem containing the gravity center of each
2661 // particle, then to locate the purely solid cells from near to far in order to avoid
2662 // a loop on all elements of the domain. However, a domain can contain zero real
2663 // particles (in the sense that it doesn't contain a particle's gravity center)
2664 // and still have purely solid cells due to the overlap of a particle between
2665 // the domain of two CPUs.
2666 // The "ideal" method would therefore require the CPU that owns the particle to
2667 // send its first row of distant element that are purely solid to the other CPU for
2668 // it to add velocity contributions.
2669 // As it add complexity to the implementation and communication time between CPU,
2670 // the naive method is implemented.
2671 const Fluide_Diphasique& two_phase_elem=ns.fluide_diphasique();
2672 const int id_solid_phase=1-two_phase_elem.get_id_fluid_phase();
2673 for (int elem=0; elem<domain_vdf.nb_elem(); elem++)
2674 {
2675 // the mean is realized on pure elem only
2676
2677 if (phase_indicator_function(elem)==id_solid_phase)
2678 {
2679 const int compo= particles_eulerian_id_number(elem);
2680 V_compo_elem(compo)+=volumes_maille(elem)*(1-phase_indicator_function(elem));
2681 for (int dim=0; dim<dimension; dim++) Particles_velocity(compo,dim)+=0.5*
2682 (tab_velocity(elem_faces(elem,dim))
2683 +tab_velocity(elem_faces(elem,dim+dimension))
2684 )*volumes_maille(elem);
2685 }
2686 }
2687
2688 mp_sum_for_each_item(Particles_velocity);
2689 mp_sum_for_each_item(V_compo_elem);
2690 DoubleVect s_vcompo;
2691 s_vcompo.ref_array(V_compo_elem);
2692 tab_divide_any_shape(Particles_velocity, s_vcompo);
2693 particles_velocity_collision_ = Particles_velocity;
2694
2695 // STEP 2 : computing the gravity center of particles
2696 DoubleTab Positions_compo(nb_particles_tot_,dimension);
2697 Positions_compo=0;
2698 for (int fa7=0; fa7<nb_fa7; fa7++)
2699 {
2700 if (!maillage.facette_virtuelle(fa7))
2701 {
2702 const int compo = id_number_fa7(fa7);
2703 const double s_fa7 = surface_fa7(fa7);
2704 Particles_surfaces(compo)+=s_fa7;
2705 for (int dim=0; dim<dimension; dim++)
2706 {
2707 for (int k = 0; k < vertices.dimension(1); k++)
2708 {
2709 int som = facettes(fa7, k);
2710 Positions_compo(compo, dim) += s_fa7 * vertices(som, dim)/dimension;
2711 }
2712 }
2713 }
2714 }
2715 mp_sum_for_each_item(Positions_compo);
2716 mp_sum_for_each_item(Particles_surfaces);
2717 DoubleVect s_scompo;
2718 s_scompo.ref_array(Particles_surfaces);
2719 tab_divide_any_shape(Positions_compo, s_scompo);
2720 particles_position_collision_ = Positions_compo;
2721 const Domaine& domain = domaine_dis().domaine();
2723
2724 // STEP 3 : identification of the id number of lagrangian vertices
2725 IntVect id_number_lagrangian_vertices;
2726 maillage.creer_tableau_sommets(id_number_lagrangian_vertices,
2727 RESIZE_OPTIONS::NOCOPY_NOINIT);
2728 id_number_lagrangian_vertices = -1;
2729 {
2730 const int dim = vitesse_noeuds.dimension(1);
2731 for (int iface = 0; iface < nb_fa7; iface++)
2732 {
2733 const int id_number = id_number_fa7[iface];
2734 for (int j = 0; j < dim; j++)
2735 id_number_lagrangian_vertices[facettes(iface, j)] = id_number;
2736 }
2737 MD_Vector_tools::echange_espace_virtuel(id_number_lagrangian_vertices,
2739 }
2740
2741 // STEP 4 : updating the lagrangian vertices displacement table
2742 for (int som = 0; som < nb_vertices_tot; som++)
2743 {
2744 if (sommets_elem[som] >= 0)
2745 {
2746 for (int dim = 0; dim < dimension; dim++)
2747 vitesse_noeuds(som, dim) =
2748 Particles_velocity(id_number_lagrangian_vertices(som), dim);
2749 }
2750
2751 }
2752 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2753 break;
2754 }
2755 default:
2756 {
2757 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n"
2758 << " interpolation method not developped" << finl;
2759 Process::exit();
2760 }
2761 }
2762}
2763
2764
2766 const Champ_base& champ_scal,
2767 const Maillage_FT_Disc& maillage,
2768 DoubleTab& val_scal_noeuds,
2769 int nv_calc) const
2770{
2771
2772 switch(variables_internes_->methode_interpolation_v)
2773 {
2775 {
2776
2777 OWN_PTR(Champ_base) champ_scal_interp;
2778 champ_scal_interp=champ_scal;
2779 if (sub_type(Champ_P1NC, champ_scal) || sub_type(Champ_Fonc_P1NC,champ_scal))
2780 {
2781
2782 if (nv_calc)
2783 {
2784 // Premier jet :
2785 // Calcul d'un champ aux sommets par filtrage L2 (inversion d'une matrice)
2786 // c'est assez long...
2787
2788 DoubleTab scal_filtre_val(champ_scal.valeurs());
2789
2790 if (sub_type(Champ_P1NC, champ_scal))
2791 ref_cast(Champ_P1NC, champ_scal).filtrer_L2(scal_filtre_val);
2792 else if (sub_type(Champ_Fonc_P1NC, champ_scal))
2793 ref_cast(Champ_Fonc_P1NC, champ_scal).filtrer_L2(scal_filtre_val);
2794 champ_scal_interp->valeurs() = scal_filtre_val;
2795 }
2796
2797 }
2798 else if (sub_type(Champ_Fonc_P0_base, champ_scal))
2799 champ_scal_interp->valeurs() = champ_scal.valeurs();
2800
2801 else
2802 {
2803 Cerr<<"champ_scal type ="<<champ_scal.que_suis_je()<<finl;
2804 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n";
2805 Cerr << " L'interpolation a partir d'un champ " << champ_scal.que_suis_je();
2806 Cerr << " n'est pas codee." << finl;
2807
2808 Cerr<<"champ_scal type ="<<champ_scal.que_suis_je()<<finl;
2809 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n";
2810 Cerr << " The interpolation from a field " << champ_scal.que_suis_je();
2811 Cerr << " is not developped." << finl;
2812 assert(0); // a coder...
2813 Process::exit();
2814 }
2815
2816 // Calcul de la vitesse interpolee a partir du champ P1
2817 // On ne calcule que les vitesses des sommets reels :
2818 DoubleTab& les_positions = variables_internes_->doubletab_pos;
2819 IntVect& les_elements = variables_internes_->intvect_elements;
2820 ///DoubleTab & les_vitesses = variables_internes_->doubletab_vitesses;
2821 // Remplissage des tableaux :
2822 const DoubleTab& pos = maillage.sommets();
2823 const ArrOfInt& elem = maillage.sommet_elem();
2824 const int nb_pos_tot = pos.dimension(0);
2825 const int dim = Objet_U::dimension;
2826 les_positions.resize(nb_pos_tot, dim);
2827 les_elements.resize(nb_pos_tot);
2828 int i, j;
2829 int nb_positions = 0;
2830 for (i = 0; i < nb_pos_tot; i++)
2831 {
2832 const int num_elem = elem[i];
2833 if (num_elem >= 0)
2834 {
2835 for (j = 0; j < dim; j++)
2836 les_positions(nb_positions, j) = pos(i, j);
2837 les_elements(nb_positions) = num_elem;
2838 nb_positions++;
2839 }
2840 }
2841 les_positions.resize(nb_positions, dim);
2842 les_elements.resize(nb_positions);
2843
2844 champ_scal_interp->valeur_aux_elems(les_positions, les_elements,val_scal_noeuds);
2845
2846 break;
2847 }
2850 {
2851
2852 Process::exit();
2853 break;
2854 }
2855 default:
2856 {
2857 Cerr << "Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n"
2858 << " the interpolation method is not coded" << finl;
2859 Process::exit();
2860 }
2861 }
2862}
2863
2864
2865/*! @brief Calcul de la derivee en temps de l'inconnue : zero.
2866 *
2867 */
2869{
2870 derivee = 0.;
2871 return derivee;
2872}
2873
2874void Transport_Interfaces_FT_Disc::assembler( Matrice_Morse& mat_morse, const DoubleTab& present, DoubleTab& secmem)
2875{
2876 Cerr<<" On ne doit pas resoudre Transport_Interfaces_FT_Disc en implicite "<<finl;
2877 abort();
2878}
2879
2880static void init_parser_v_impose(const Noms& expression_vitesse, Parser& parser_x, Parser& parser_y, Parser& parser_z, double temps)
2881{
2882 const int dimension3 = (Objet_U::dimension==3);
2883 // Preparation des parsers...
2884 std::string sx(expression_vitesse[0]);
2885 parser_x.setString(sx);
2886 parser_x.setNbVar(4);
2887 parser_x.addVar("x");
2888 parser_x.addVar("y");
2889 parser_x.addVar("z");
2890 parser_x.addVar("t");
2891 parser_x.parseString();
2892 parser_x.setVar("z", 0.);
2893 parser_x.setVar("t", temps);
2894
2895 std::string sy(expression_vitesse[1]);
2896 parser_y.setString(sy);
2897 parser_y.setNbVar(4);
2898 parser_y.addVar("x");
2899 parser_y.addVar("y");
2900 parser_y.addVar("z");
2901 parser_y.addVar("t");
2902 parser_y.parseString();
2903 parser_y.setVar("z", 0.);
2904 parser_y.setVar("t", temps);
2905
2906 Nom unused_expr("0");
2907 std::string sz(dimension3
2908 ? expression_vitesse[2]
2909 : unused_expr /* inutilise */);
2910
2911 parser_z.setString(sz);
2912 parser_z.setNbVar(4);
2913 parser_z.addVar("x");
2914 parser_z.addVar("y");
2915 parser_z.addVar("z");
2916 parser_z.addVar("t");
2917 parser_z.parseString();
2918 parser_z.setVar("z", 0.);
2919 parser_z.setVar("t", temps);
2920}
2921
2922
2923//La presence d un interface solide dans l ecoulement implique d appliquer un terme source
2924//dans l equation de quantite de mouvement pour imposer au fluide la vitesse de l interface.
2925//Ce terme source n est pas standard mais consiste en une modification de vpoint qui depend
2926//de la valeur de vpoint elle meme.
2927//Contrainte : methode_transport==VITESSE_IMPOSEE
2928//
2929//Les etapes de la methode sont :
2930//-Calcul de la vitesse imposee a l interface a un temps donne: calcul_vitesse(...)
2931//-On determine le type du domaine discretisee (is_VDF vaut 1 pour VDF et 0 pour VEF)
2932// et le type dequation traitee (is_QC vaut 0 pour Navier_Stokes_FT_Disc et 1 sinon)
2933//-Estimation de l increment de quantite de mouvement a ajouter a vpoint
2934// puis ajout de cet increment : calcul_source_et_modifie_vpoint(...)
2935// Rq : la methode est parallele pour vpoint
2936// Le terme vpoint*dt permet d'impliciter un peu le terme source, mais
2937// semble poser quelques problemes avec la gravite. Un solide fixe dans un
2938// liquide sous gravite avec l'option terme_gravite rho_g met en mouvement
2939// le fluide dans le sens inverse a la gravite !!!
2940void Transport_Interfaces_FT_Disc::modifier_vpoint_pour_imposer_vit(const DoubleTab& inco_val,DoubleTab& vpoint0,
2941 DoubleTab& vpoint,const DoubleTab& rho_faces,
2942 DoubleTab& source_val,const double temps,
2943 const double dt,const int is_explicite,
2944 const double eta)
2945{
2946 if (!(temps>temps_debut_))
2947 return;
2948 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE
2949 || variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE)
2950 {
2951 // Etape 1 : calcul de la vitesse imposee sur l'interface a un temps donne
2952 DoubleTab vit_imposee;
2953 calcul_vitesse(vit_imposee,inco_val,vpoint0,temps,dt); // vpoint0 au lieu de vpoint
2954 vit_imposee.echange_espace_virtuel() ;
2955
2956 // Etape 2.1 : determination du domaine de discretisation
2957 const Domaine_dis_base& mon_dom_dis = domaine_dis();
2958 const IntTab& face_voisins = mon_dom_dis.face_voisins();
2959 assert(inco_val.dimension(0) == face_voisins.dimension(0));
2960
2961 // Etape 2.2 : determiniation du systeme d'equations a resoudre
2962 int is_QC=0;
2963 const Equation_base& eq = probleme_base_->equation(0);
2964 if (sub_type(Navier_Stokes_FT_Disc,eq))
2965 is_QC=0;
2966 else
2967 is_QC=1;
2968
2969 // Etape 3 : calcul et ajout du terme de penalisation dans la qdm
2970 const DoubleTab& indicatrice = get_indicatrice().valeurs();
2971
2972 calcul_indicatrice_faces(indicatrice,face_voisins);
2973 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
2974
2975 // Si on souhaite regulariser l interface IBC/fluide :
2976 // combinaison convexe de la vitesse imposee et la vitesse predite.
2977 // Ceci est realise seulement pendant une etape explicite.
2978 // En penalise, pas de regularisation pendant l etape implicite
2979 // (pour regulariser en penalise, on ajoute une etape explicite)
2980 const int n = vpoint.dimension(0);
2981 const int m = vpoint.line_size();
2982 if(variables_internes_->vimp_regul && is_explicite)
2983 {
2984
2985 DoubleTab vitesse(vpoint0);
2986 vitesse *= dt ;
2987 vitesse += inco_val ;
2988
2989 for (int i=0 ; i < n; i++)
2990 {
2991 if (indicatrice_faces(i) > 0. )
2992 {
2993 double f = indicatrice_faces(i);
2994 for (int j = 0; j < m; j++)
2995 {
2996 if (!is_QC)
2997 vit_imposee(i,j) = f*vit_imposee(i,j) + (1.-f)*vitesse(i,j);
2998 else
2999 vit_imposee(i,j) = f*vit_imposee(i,j) + (1.-f)*vitesse(i,j)/rho_faces(i);
3000
3001 vitesse_imp_interp_->valeurs()(i,j)= vit_imposee( i,j ) ;
3002 }
3003
3004 }
3005 }
3006 }
3007
3008 calcul_source(inco_val,vpoint0,rho_faces,source_val,vit_imposee,indicatrice_faces,
3009 is_QC,dt,is_explicite,eta); // vpoint0 au lieu de vpoint
3010 source_val.echange_espace_virtuel();
3011
3012 const DoubleVect& volumes_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
3013 const Solveur_Masse_base& le_solveur_masse = eq.solv_masse();
3014 int i, j;
3015
3016 DoubleTab termes_sources_face(vpoint);
3017 termes_sources_face=0.;
3018 modifie_source(termes_sources_face,source_val,rho_faces,n,m,is_QC,volumes_entrelaces,le_solveur_masse);
3019 termes_sources_face.echange_espace_virtuel() ; // CI
3020
3021 for (i = 0; i < n; i++)
3022 for (j = 0; j < m; j++)
3023 vpoint(i, j) += termes_sources_face(i,j);
3024 }
3025 else if (sub_type(Transport_Marqueur_FT,*this))
3026 {
3027
3028 }
3029 else
3030 {
3031 Cerr << "Error for the method Transport_Interfaces_FT_Disc::modifier_vpoint_pour_imposer_vit\n"
3032 << " The transport equation is not of type \"methode_transport vitesse_imposee\"."
3033 << " or \"methode_transport loi_horaire\"."
3034 << finl;
3035 Process::exit();
3036 }
3037 vpoint.echange_espace_virtuel();
3038 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_vitesse_imposee vpoint",vpoint);
3039}
3040
3041
3043 const IntTab& face_voisins)
3044{
3045 DoubleTab& indicatrice_faces = indicatrice_faces_->valeurs();
3046 const int nfaces = face_voisins.dimension_tot(0);
3047 for (int i = 0; i < nfaces; i++)
3048 {
3049 const int elem0 = face_voisins(i, 0);
3050 const int elem1 = face_voisins(i, 1);
3051 indicatrice_faces(i)= 0.;
3052
3053 if (elem0 >= 0)
3054 indicatrice_faces(i) = indicatrice(elem0);
3055 if (elem1 >= 0)
3056 indicatrice_faces(i) += indicatrice(elem1);
3057 if (elem0 >= 0 && elem1 >= 0)
3058 indicatrice_faces(i) *= 0.5;
3059 double bmax=1.-1e-9;
3060 if(indicatrice_faces(i) <= 1.0e-9) indicatrice_faces(i) = 0. ;
3061 else if(indicatrice_faces(i) >= bmax) indicatrice_faces(i) = 1. ;
3062 }
3063
3064 switch(variables_internes_->type_indic_faces_)
3065 {
3067 {
3068 // Does nothing more.
3069 break;
3070 }
3072 {
3073 // si on souhaite calculer l'indicatrice a partir de la distance :
3074 const DoubleTab& dist_face = get_update_distance_interface_faces().valeurs();
3075 const Domaine_dis_base& domaine_dis_base = domaine_dis();
3076 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, domaine_dis_base);
3077 const DoubleVect& face_surfaces = domaine_vdf.face_surfaces();
3078 const DoubleVect& volumes_entrelaces = domaine_vdf.volumes_entrelaces();
3079 double& position = variables_internes_->modified_indic_faces_position;
3080 double& thickness = variables_internes_->modified_indic_faces_thickness;
3081 for (int i = 0; i < nfaces; i++)
3082 {
3083 double h=volumes_entrelaces(i)/face_surfaces(i);
3084 if (dist_face(i) > (position+thickness/2.)*h || indicatrice_faces(i)==1.)
3085 indicatrice_faces(i)=1.;
3086 else if (dist_face(i) >= (position-thickness/2.)*h && thickness !=0.)
3087 indicatrice_faces(i) = (dist_face(i) - position*h)/(thickness*h) + 0.5 ;
3088 else
3089 indicatrice_faces(i)=0.;
3090 }
3091 break;
3092 }
3094 {
3095 // This method should be very much like case Navier_Stokes_FT_Disc_interne::INTERP_AI_BASED in Navier_Stokes_FT_Disc::calculer_dI_dt
3096 // (but just the part to compute indicatrices faces...
3097 // WARNING : contrary to what is done in Navier_Stokes_FT_Disc::calculer_dI_dt, we compute chi_1 (ie same as indicatrice),
3098 // not the opposite chi_0 = 1-chi_1
3099 //
3100 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
3101 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
3102 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
3103 {
3104 // On recupere le saut de vitesse a l'interface (changement de phase)
3105 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
3106 const DoubleTab& interfacial_area = ns.get_interfacial_area();
3107 const DoubleTab& normale_elements = get_normale_interface().valeurs();
3108
3109 const int dim = ns.inconnue().valeurs().line_size();
3110 const int vef = (dim == 2);
3111 if (vef)
3112 {
3113 Cerr << "Code never applied or checked in VEF. You should read the algo first and assess it!" << finl;
3114 Process::exit();
3115 }
3116 // On fait la moyenne des 2 valeurs calculees sur les voisins
3117 // ATTENTION, ici on veut la valeur de chiv (cad chi_0) a la face.
3118 for (int face = 0; face < nfaces; face++)
3119 {
3120 double indic_face = 0.;
3121 int v;
3122 for (v = 0; v < 2; v++)
3123 {
3124 const int elem = face_voisins(face, v);
3125 if (elem >=0)
3126 {
3127 // If a neighbour is pure, we use that value at the face and stop further calculation.
3128 const double indic = indicatrice[elem]; // This is the value of chi_1 (ie =1 in phase 1!)
3129 //if (indic == 0. || indic == 1.)
3130 if (indic <=5e-3 || indic >= 1.-5e-3)
3131 {
3132 indic_face = indic; // Obviously, We want chi of phase_1
3133 break;
3134 }
3135 else
3136 {
3137 const double surface=domaine_vf.face_surfaces(face);
3138 const double ai= interfacial_area(elem); // nx pointe vers le liquide (sortant de phase 0)
3139 if (fabs(ai)>DMINFLOAT)
3140 {
3141 double x = 0.;
3142 if (vef)
3143 {
3144 for (int j = 0; j < dim; j++)
3145 {
3146 const double nf = domaine_vf.face_normales(face , j);
3147 const double nx = normale_elements(elem, j);
3148 // produit scalaire :
3149 x += nf*nx;
3150 }
3151 x *= ai/surface;
3152 // Que/comment Choisir?
3153 indic_face += x;
3154 Cerr << "Never tested. To be verified. It should depend on a scalar product with the vect (xp-xv)" << finl;
3155 Process::exit();
3156 }
3157 else
3158 {
3159 // En VDF, l'acces a orientation permet d'eviter le calcul du produit scalaire.
3160 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, domaine_dis());
3161 const IntVect& orientation = zvdf.orientation();
3162 const int dir = orientation[face];
3163 const double nx = normale_elements(elem, dir);
3164 // Assumes a cube, nx larger than diag means we can use the method rather safely
3165 if (nx>0.707)
3166 {
3167 x = ai/surface*nx;
3168 // On suppose que v0 est a gauche et v1 a droite!!!
3169 if (v==0)
3170 indic_face += x; // This way, we build chi_1 because normale points towards chi_1
3171 else
3172 indic_face += 1-x;
3173 }
3174 else
3175 {
3176 // L'interface croise probablement la face d'en face et la methode ne marche plus.
3177 // We revert back to the standard method :
3178 double tmp = 0.;
3179 if (elem >= 0)
3180 tmp = indicatrice(elem);
3181
3182 double bmax=1.-1e-9;
3183 if(tmp <= 1.0e-9) tmp = 0. ;
3184 else if(tmp >= bmax) tmp = 1. ;
3185
3186 indic_face += tmp;
3187 }
3188 }
3189 }
3190 else
3191 {
3192 Cerr <<" WTF, c'est impossible" << finl;
3193 Process::exit();
3194 }
3195 }
3196 }
3197 else
3198 {
3199 // The only neighbour to the face :
3200 const int elem_voisin = face_voisins(face, 1-v); // The other one is accessed by 1-v
3201 const double indic = indicatrice[elem_voisin]; // This is the value of chi_1 (ie =1 in phase 1!)
3202 indic_face = indic; // We want chi of phase_1
3203 break; // c'est important pour le if d'apres.
3204 }
3205 }
3206 if (v==2)
3207 // On n'a pas touche le break, on est donc passe 2 fois. donc :
3208 indic_face*=0.5;
3209
3210 // assert((indic_face >=0) && (indic_face<=1.));
3211 // ca arrive des petits derapages..
3212 if (indic_face <0)
3213 indic_face=0.;
3214 if (indic_face >1.)
3215 indic_face=1.;
3216
3217 indicatrice_faces_->valeurs()(face) = indic_face;
3218 }
3219 }
3220 else
3221 {
3222 Cerr << "Interpolation option AI_BASED in Transport_Interfaces_FT_Disc is not available "
3223 << "in Transport_Interfaces_FT_Disc::calcul_indicatrice_faces if we do not "
3224 << "have a Navier_Stokes_FT_Disc equation..." << finl;
3225 Process::exit();
3226 }
3227 break;
3228 }
3229 default:
3230 Cerr << "Transport_Interfaces_FT_Disc::calcul_indicatrice_faces\n"
3231 << " unknown case?" << finl;
3232 Process::exit();
3233 }
3234
3235 indicatrice_faces.echange_espace_virtuel();
3236 Debog::verifier("Transport_Interfaces_FT_Disc::calcul_indicatrice_faces indicatrice_faces",indicatrice_faces);
3237}
3238
3240{
3241 return variables_internes_->vimp_regul;
3242}
3244{
3245 return indicatrice_faces_;
3246}
3247
3249{
3250 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3251 const DoubleTab& indicatrice = get_indicatrice().valeurs();
3252 const IntTab& face_voisins = mon_dom_dis.face_voisins();
3253 calcul_indicatrice_faces(indicatrice,face_voisins);
3254 return indicatrice_faces_;
3255}
3256
3257//Methode outil qui estime la valeur d increment de qdm a ajouter a
3258//la derivee temporelle de la vitesse
3259// L'expression calculee
3260// Cas Front-Tracking (is_QC vaut 0):
3261// (v_impose - (champ_vitesse + vpoint*dt)) / dt * indicatrice * rho_face;
3262// Cas Quasi-compressible (is_QC vaut 1) :
3263// (rho_np1 v_impose - (rho_vitesse_n + vpoint*dt)) / dt * indicatrice
3264
3265void Transport_Interfaces_FT_Disc::calcul_source(const DoubleTab& inco_val,
3266 const DoubleTab& vpoint,
3267 const DoubleTab& rho_faces,
3268 DoubleTab& source_val,const DoubleTab& vit_imposee,const DoubleTab& indicatrice_faces,
3269 const int is_QC,
3270 const double dt,
3271 const int is_explicite,
3272 const double eta)
3273
3274{
3275 DoubleTab terme_explicite(vpoint);
3276 double c;
3277 const int nfaces = vpoint.dimension(0);
3278 c = 1. / eta;
3279 if (indicatrice_faces.dimension(0) == nfaces )
3280 {
3281 if (is_explicite)
3282 {
3283 terme_explicite *= dt;
3284 }
3285 else
3286 {
3287 terme_explicite *= 0.;
3288 }
3289
3290 for (int i = 0; i < nfaces; i++)
3291 {
3292
3293 double indic = (indicatrice_faces(i) > 0. ? 1.0 : 0.0) ;
3294 // Si on veut regulariser le passage de IBC/fluide et que l'on est penalise,
3295 // seules les faces telles que indic=1 sont penalisees, les autres sont DF.
3296 if (variables_internes_->vimp_regul && !is_explicite ) indic = (indicatrice_faces(i) ==1. ? 1.0 : 0.0);
3297 double tsource;
3298 double rho_face = rho_faces(i);
3299 const int dim = inco_val.line_size(); // > 1 => VEF, =1 => VDF
3300
3301 for (int j = 0; j < dim; j++)
3302 {
3303 double increment_inco = inco_val(i,j) + terme_explicite(i,j);
3304 if (!is_QC)
3305 tsource = (vit_imposee(i,j) - increment_inco) / dt * indic * rho_face * c;
3306 else
3307 tsource = (vit_imposee(i,j) * rho_face - increment_inco) / dt * indic * c;
3308
3309 source_val(i,j) = tsource;
3310 }
3311 }
3312 }
3313 else
3314 {
3315
3316 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::calcul_source\n" << finl;
3317 Cerr << "Dimension de indicatrice_face differente de dimension de vpoint.\n" << finl;
3318 Process::exit();
3319 }
3320}
3321
3322void ouvrir_fichier(SFichier& os,const Nom& type, const int flag, const Transport_Interfaces_FT_Disc& equation)
3323{
3324
3325 if (flag==0)
3326 return ;
3327 Noms files(14);
3328 Nom file=Objet_U::nom_du_cas();
3329 if (type=="force")
3330 files[0]=type,
3331 file+="_Force_totale_sur_";
3332 else if( type=="force_totale" )
3333 files[1]= type,
3334 file+="_Friction_totale_sur_";
3335 else if( type=="Friction" )
3336 files[2]= type,
3337 file+="_Friction_conv_diff_sur_";
3338 else if( type=="Pressure" )
3339 files[3]= type ,
3340 file+="_Friction_Pression_sur_";
3341 else if ( type =="moment")
3342 files[4]+= type,
3343 file+="_Moment_total_sur_";
3344 else if ( type=="particles_trajectory" )
3345 files[5]=type,
3346 file+="_particles_trajectory_";
3347 else if ( type=="mean_rms_particles_velocity")
3348 files[6]=type,
3349 file+="_mean_rms_particles_velocity_";
3350 else if (type=="particles_data")
3351 files[7]=type,
3352 file+="_particles_data_";
3353 else if (type=="particle_hydrodynamic_forces")
3354 {
3355 files[8]=type,
3356 file+="_particle_hydrodynamic_forces_";
3357 }
3358 else if( type=="Stokes_theoretical_forces" )
3359 {
3360 files[9]=type,
3361 file+= "_Stokes_theoretical_forces_";
3362 }
3363 else if (type=="particle_hydrodynamic_forces_bed")
3364 {
3365 files[10]=type,
3366 file+= "_particle_hydrodynamic_forces_bed_";
3367 }
3368 else if (type=="fluid_to_particle_heat_transfer")
3369 {
3370 files[11]=type,
3371 file+= "_fluid_to_particle_heat_transfer_";
3372 }
3373 else if (type=="fluid_to_particle_heat_transfer_bed")
3374 {
3375 files[12]=type,
3376 file+= "_fluid_to_particle_heat_transfer_bed_";
3377 }
3378 else if(type=="Friction_diff")
3379 files[13]= type,
3380 file+="_Friction_diff_sur_" ;
3381 else
3382 {
3383 Cerr << "The file " << type << " is not understood by Transport_Interfaces_FT_Disc::ouvrir_fichier. "
3384 << finl;
3385 }
3386
3387 const int rang=files.search(type);
3388 file+=equation.le_nom();
3389 file+=".out";
3390
3391 const Schema_Temps_base& sch=equation.probleme().schema_temps();
3392 const int precision=sch.precision_impr();
3393 // We create the file during the first writting sequence, or if it does not exist
3394 struct stat f;
3395 if ((stat(file,&f) && (sch.nb_impr()==1 && !equation.probleme().reprise_effectuee())))
3396 {
3397 os.ouvrir(file);
3398 SFichier& fic=os;
3399 Nom espace="\t\t";
3400 if (rang<5)
3401 {
3402 fic << (Nom)"# Printing " << (type=="moment"?"of the drag moment exerted":"of the drag exerted");
3403 fic << " by the fluid on the interface " << equation.le_nom();
3404 fic << " " << (type=="moment"?"[N.m]":"[N]") << finl;
3405 int nb_compo=(type=="moment" && Objet_U::dimension==2?1:Objet_U::dimension);
3406 fic << "# Time";
3407
3408 Nom ch=espace;
3409 if (type=="moment")
3410 {
3411 if (Objet_U::dimension==2) ch+="Mz";
3412 else
3413 {
3414 ch+="Mx";
3415 ch+=espace+"My";
3416 ch+=espace+"Mz";
3417 }
3418 }
3419 else
3420 {
3421 if (nb_compo>1) ch+="Fx";
3422 if (nb_compo>=2) ch+=espace+"Fy";
3423 if (nb_compo>=3) ch+=espace+"Fz";
3424 }
3425 fic << ch << finl;
3426 }
3427 else if (rang==5)
3428 {
3429 espace="\t";
3430 fic << "#########################################" << finl;
3431 fic << "# Position - Velocity - Collision force #" << finl;
3432 fic << "#########################################" << finl;
3433 fic << "# Time [s]" << finl;
3434 fic << "# Position of the gravity center of the particle [m] (px py pz)" << finl;
3435 fic << "# Velocity of the gravity center of the particle [m/s] (vx vy vz)" << finl;
3436 fic << "# Collision force discretized on the particle volume [N] (fcx fcy fcz)" << finl;
3437 fic << finl;
3438 fic << "# Time" << espace << "px py pz" << espace << "vx vy vz" << espace << "fcx fcy fcz" << finl;
3439 fic << finl;
3440 }
3441 else if (rang==6)
3442 {
3443 espace="\t";
3444 fic << "#####################################################" << finl;
3445 fic << "# Average velocity - Average velocity squared - RMS #" << finl;
3446 fic << "#####################################################" << finl;
3447 fic << "# Time [s]" << finl;
3448 fic << "# Average velocity of purely solid cells. For each purely solid cell,"
3449 " the velocity at gravity center is computed as the average velocity of"
3450 " the opposing faces weighted by its volume. [m/s] (vx_av vy_av vz_av)" << finl;
3451 fic << "# Average velocity squared of purely solid cells. [m^2/s^2] (vx2_av vy2_av vz2_av)" << finl;
3452 fic << "# Once the average velocity and the average velocity squared is known,"
3453 " the RMS is computed as sqrt(abs(vi_av^2 - vi2_av)) with i in {x,y,z}."
3454 " [-] (rmsx rmsy rmsz)" << finl;
3455 fic << finl;
3456 fic << "# Time" << espace << "vx_av vy_av vz_av" << espace << "vx2_av vy2_av vz2_av"
3457 << espace << "rmsx rmsy rmsz" << finl;
3458 fic << finl;
3459 }
3460 else if (rang==7)
3461 {
3462 espace="\t";
3463 fic << "############################################################" << finl;
3464 fic << "# Position - Velocity - Collision force - Collision number #" << finl;
3465 fic << "############################################################" << finl;
3466 fic << "# Time [s] - Total number of collision " << finl;
3467 fic << "# Position of the gravity center of the particle [m] (px py pz)" << finl;
3468 fic << "# Velocity of the gravity center of the particle [m/s] (vx vy vz)" << finl;
3469 fic << "# Collision force discretized on the particle volume [N] (fcx fcy fcz)" << finl;
3470 fic << finl;
3471 fic << "# Time" <<espace <<"total collision number" << finl;
3472 fic << "# particle_id px py pz vx vy vz fcx fcy fcz number_of_particles_in_collision"<< finl;
3473 fic << finl;
3474 }
3475 else if (rang==8)
3476 {
3477 fic << "###################################" << finl;
3478 fic << "# Hydrodynamic force computation #" << finl;
3479 fic << "###################################" << finl;
3480 fic << finl;
3481 fic << "# Time [s]"<< espace << "Particle surface [m^2]" << espace <<
3482 "Pressure force [N] (fpx fpy fpz)" << espace << "Friction force [N] (ffx ffy ffz)" << finl;
3483 fic << finl;
3484 }
3485 else if (rang==9)
3486 {
3487 fic << "#####################################################################" << finl;
3488 fic << "# Hydrodynamic force computation - Stokes theoretical configuration #" << finl;
3489 fic << "#####################################################################" << finl;
3490 fic << "# Time [s]"<< finl;
3491 fic << "# Stokes theoretical PRESSURE FORCE computed from the integration, on the lagrangian mesh,"
3492 " of the discretized analytical solution [N] (fpx_th fpy_th fpz_th)" << finl;
3493 fic << "# Stokes PRESSURE FORCE computed with the developed method on the theoretical"
3494 " pressure field discretized on the eulerian mesh [N] (fpx_th_interp fpy_th_interp"
3495 " fpz_th_interp)" << finl;
3496 fic << "# Stokes theoretical FRICTION FORCE computed from the integration,"
3497 " on the lagrangian mesh, of the discretized analytical solution [N]"
3498 " (ffx_th ffy_th ffz_th)" << finl;
3499 fic << "# Stokes FRICTION FORCE computed with the developed method on the theoretical"
3500 " velocity field discretized on the eulerian mesh [N] (ffx_th_interp"
3501 " ffy_th_interp ffz_th_interp)" << finl;
3502 fic << finl;
3503 fic << "# Time" << espace << "fpx_th fpy_th fpz_th" << espace <<
3504 "fpx_th_interp fpy_th_interp fpz_th_interp" << espace << "ffx_th ffy_th ffz_th" <<
3505 espace << "ffx_th_interp ffy_th_interp ffz_th_interp" << finl;
3506 fic << finl;
3507 }
3508 else if (rang==10)
3509 {
3510 fic << "#########################################################" << finl;
3511 fic << "# Hydrodynamic force computation in a particle assembly #" << finl;
3512 fic << "#########################################################" << finl;
3513 fic << finl;
3514 fic << "# Time [s]" << espace << "particle_id" << espace << "Pressure force [N] (fpx fpy fpz)"
3515 << espace << "Friction force [N] (ffx ffy ffz)" << espace <<
3516 "Percentage of facets for which forces were computable" << espace <<
3517 "Average fluid velocity in P2" << "Percentage of purely fluid cells in P2"<< finl;
3518 fic << finl;
3519 }
3520 else if (rang==11)
3521 {
3522 fic << "#########################" << finl;
3523 fic << "# Heat flux computation #" << finl;
3524 fic << "#########################" << finl;
3525 fic << "# Time [s]" << finl;
3526 fic << "# Computation of the heat flux received by the particle from the surrounding fluid. [W] (phi)" << finl;
3527 fic << finl;
3528 fic << "# Time" << espace << "phi" << finl;
3529 fic << finl;
3530 }
3531 else if (rang==12)
3532 {
3533 fic << "################################################" << finl;
3534 fic << "# Heat flux computation in a particle assembly #" << finl;
3535 fic << "################################################" << finl;
3536 fic << "# Time [s]" << finl;
3537 fic << "# Computation of the heat flux received by the particle from the surrounding fluid. [W] (phi_i), where i stands for the particle number." << finl;
3538 fic << "# Average temperature of purely fluid cells in P2. [K] (T_i)" << finl;
3539 fic << finl;
3540 fic << "Time" << espace << "phi_0 T_0 ... phi_N T_N" << finl;
3541 fic << finl;
3542 }
3543 }
3544 // otherwise, we open it
3545 else
3546 {
3547 os.ouvrir(file,ios::app);
3548 }
3549 os.precision(precision);
3550 os.setf(ios::scientific);
3551}
3552void Transport_Interfaces_FT_Disc::modifie_source(DoubleTab& termes_sources_face,const DoubleTab& source_val,const DoubleTab& rho_faces,
3553 const int n,const int m, const int is_QC,
3554 const DoubleVect& vol_entrelaces,const Solveur_Masse_base& un_solv_masse)
3555{
3556
3557 for (int face=0; face<n; face++)
3558 for (int dim=0; dim<m; dim++)
3559 termes_sources_face(face,dim)=vol_entrelaces(face)*source_val(face,dim);
3560
3561 termes_sources_face.echange_espace_virtuel() ; // CI
3562 un_solv_masse.appliquer(termes_sources_face);
3563
3564 if (!is_QC)
3565 {
3566 for (int i = 0; i < n; i++)
3567 {
3568 const double rho_face = rho_faces(i);
3569
3570 for (int j = 0; j < m; j++)
3571 termes_sources_face(i,j) = termes_sources_face(i,j) / rho_face;
3572 }
3573 }
3574}
3575
3576void Transport_Interfaces_FT_Disc::impr_effort_fluide_interface( DoubleTab& source_val, DoubleTab& pressure_part, DoubleTab& friction_part, DoubleTab& diff_part)
3577{
3578 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
3579 const int n = source_val.dimension(0);
3580 const int nbdim1 = source_val.line_size() == 1; // VDF
3581 const int m = source_val.line_size();
3582
3583 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3584 const Domaine_VDF * zvdf = 0;
3585 if (sub_type(Domaine_VDF, domaine_dis())) zvdf = &ref_cast(Domaine_VDF, domaine_dis());
3586
3587 DoubleTab termes_sources_face(source_val);
3588 DoubleTab termes_pressure_face(pressure_part);
3589 DoubleTab termes_friction_face(friction_part);
3590 DoubleTab termes_diff_face(diff_part);
3591 DoubleTrav values(4,dimension);
3592 values=0.;
3593
3594 const DoubleVect& vol_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
3595 // Construction d'un tableau des items reels non communs
3596 ArrOfInt sequential_items_flags;
3597 source_val.get_md_vector()->get_sequential_items_flags(sequential_items_flags);
3598
3599
3600 for (int face=0; face<n; face++)
3601 {
3602 double indic = (indicatrice_faces(face) > 0. ? 1.0 : 0.0);
3603 double coef = vol_entrelaces(face)*indic;
3604 for (int dim=0; dim<m; dim++)
3605 {
3606 termes_sources_face(face,dim)=source_val(face,dim)*coef;
3607 termes_pressure_face(face,dim)=pressure_part(face,dim)*coef;
3608 termes_friction_face(face,dim)=friction_part(face,dim)*coef;
3609 termes_diff_face(face,dim)=diff_part(face,dim)*coef;
3610 }
3611 // Calcul de dforce contribution de la force du fluide sur la face i
3612 // si ce n'est pas une face commune a plusieurs processeurs
3613 if (sequential_items_flags[face])
3614 {
3615 if (nbdim1) // VDF
3616 {
3617 int j = zvdf->orientation(face);
3618
3619 values(0,j) -= termes_sources_face(face,0);
3620 values(1,j) -= termes_pressure_face(face,0);
3621 values(2,j) -= termes_friction_face(face,0);
3622 values(3,j) -= termes_diff_face(face,0);
3623 }
3624 else // VEF
3625 {
3626 for (int j = 0; j < dimension; j++)
3627 {
3628 values(0,j) -= termes_sources_face(face,j);
3629 values(1,j) -= termes_pressure_face(face,j);
3630 values(2,j) -= termes_friction_face(face,j);
3631 values(3,j) -= termes_diff_face(face,j);
3632 }
3633 }
3634 }
3635 }
3636
3637 // Impression des efforts exerces par le fluide sur l'interface
3638 {
3639 // Ajout des differents processeurs en //
3640 mp_sum_for_each_item(values);
3641
3642 // Impression dans les fichiers
3644 {
3645 SFichier Force;
3646 ouvrir_fichier(Force,"force_totale",1,*this);
3647 Nom espace=" \t";
3649 Force.precision(10) ;
3650 for(int k=0; k<dimension; k++)
3651// Force << espace << dforce(k);
3652 Force << espace << values(0,k);
3653 Force << finl;
3654 const int impr_mom = 1 ;
3655
3656 SFichier Pressure;
3657 ouvrir_fichier(Pressure,"Pressure",impr_mom,*this);
3659 Pressure.precision(10) ;
3660// for(int k=0; k<pressure.size_array(); k++)
3661 for(int k=0; k<dimension ; k++)
3662// Pressure << espace << pressure(k);
3663 Pressure << espace << values(1,k);
3664 Pressure << finl;
3665
3666 SFichier Friction;
3667 ouvrir_fichier(Friction,"Friction",impr_mom,*this);
3669 Friction.precision(10) ;
3670// for(int k=0; k<friction.size_array(); k++)
3671 for(int k=0; k<dimension; k++)
3672// Friction << espace << friction(k);
3673 Friction << espace << values(2,k);
3674 Friction << finl;
3675
3676 SFichier Friction2;
3677 ouvrir_fichier(Friction2,"Friction_diff",impr_mom,*this);
3679 Friction2.precision(10) ;
3680// for(int k=0; k<friction.size_array(); k++)
3681 for(int k=0; k<dimension; k++)
3682 Friction2 << espace << values(3,k);
3683 Friction2 << finl;
3684 }
3685 }
3686}
3687
3688
3689// Impression des forces et moment
3691{
3692 // Impression dans les fichiers
3694 {
3695 SFichier Force;
3696 ouvrir_fichier(Force,"force",1,*this);
3697 Nom espace=" \t";
3699 for(int k=0; k<dimension; k++)
3700 Force << espace << force_[k];
3701 Force << finl;
3702 const Domaine& domaine=domaine_dis().domaine();
3703 const int impr_mom = domaine.moments_a_imprimer();
3704 if (impr_mom)
3705 {
3706 SFichier Moment;
3707 ouvrir_fichier(Moment,"moment",impr_mom,*this);
3709 for(int k=0; k<moment_.size_array(); k++)
3710 Moment << espace << moment_[k];
3711 Moment << finl;
3712 }
3713
3715 {
3716 espace= " ";
3717 int dim_max_impr=5; // on imprime pas les valeurs si il y a plus de 5 particules dans le domaine
3718 if (nb_particles_tot_<dim_max_impr)
3719 {
3720 SFichier Particles_trajectory;
3721 ouvrir_fichier(Particles_trajectory,"particles_trajectory",1,*this);
3722 schema_temps().imprimer_temps_courant(Particles_trajectory);
3723 for (int particle=0; particle<nb_particles_tot_; particle++)
3724 {
3725 Particles_trajectory << espace;
3726 for (int dim=0; dim<dimension; dim++)
3727 Particles_trajectory << espace << particles_position_collision_(particle,dim);
3728 Particles_trajectory << espace;
3729
3730 for (int dim=0; dim<dimension; dim++)
3731 Particles_trajectory << espace << particles_velocity_collision_(particle,dim);
3732 Particles_trajectory << espace;
3733
3734 if (collision_model_)
3735 {
3736 const DoubleTab& lagrangian_contact_forces=
3737 collision_model_.valeur().get_lagrangian_contact_forces();
3738 for (int dim=0; dim<dimension; dim++)
3739 Particles_trajectory << espace << lagrangian_contact_forces(particle,dim);
3740 }
3741 Particles_trajectory << finl;
3742 }
3743 }
3744
3746 {
3747 SFichier Moy_Rms_Vitesse_Particule;
3748 ouvrir_fichier(Moy_Rms_Vitesse_Particule,"mean_rms_particles_velocity",1,*this);
3749 schema_temps().imprimer_temps_courant(Moy_Rms_Vitesse_Particule);
3750 Moy_Rms_Vitesse_Particule << "Time " << schema_temps().temps_courant() << finl;
3751 const DoubleTab& mean_velocity=get_mean_particles_volumic_velocity();
3752 const DoubleTab& rms_velocity=get_mean_particles_volumic_squared_velocity();
3753 const DoubleTab& mean_squared_velocity=get_rms_particles_volumic_velocity();
3754 const DoubleTab& particles_purely_solid_mesh_volume=get_particles_purely_solid_mesh_volume();
3755
3756 for (int particle=0; particle<nb_particles_tot_; particle++)
3757 {
3758 Moy_Rms_Vitesse_Particule << particle << " ";
3759 Moy_Rms_Vitesse_Particule << espace;
3760 Moy_Rms_Vitesse_Particule << particles_purely_solid_mesh_volume(particle)<< espace;
3761
3762 for (int dim=0; dim<dimension; dim++)
3763 Moy_Rms_Vitesse_Particule << espace << mean_velocity(particle,dim);
3764 Moy_Rms_Vitesse_Particule << espace;
3765
3766 for (int dim=0; dim<dimension; dim++)
3767 Moy_Rms_Vitesse_Particule << espace << mean_squared_velocity(particle,dim);
3768 Moy_Rms_Vitesse_Particule << espace;
3769
3770 for (int dim=0; dim<dimension; dim++)
3771 Moy_Rms_Vitesse_Particule << espace << rms_velocity(particle,dim);
3772
3773 Moy_Rms_Vitesse_Particule << finl;
3774 }
3775 }
3776
3777 SFichier Particles_data;
3778 ouvrir_fichier(Particles_data,"particles_data",1,*this);
3779 if (collision_model_)
3780 {
3781 const int collision_number=collision_model_.valeur().get_collision_number();
3782 Particles_data << "Time " << schema_temps().temps_courant() << "\t" <<
3783 collision_number<< finl;
3784 }
3785 for (int particle = 0; particle < nb_particles_tot_; particle++)
3786 {
3787 Particles_data << particle << " ";
3788 for (int d = 0; d < dimension; d++)
3789 Particles_data << particles_position_collision_(particle,d) << espace ;
3790
3791 for (int d = 0; d < dimension; d++)
3792 Particles_data << particles_velocity_collision_(particle,d) << espace ;
3793
3794 if (collision_model_)
3795 {
3796 const DoubleTab& lagrangian_contact_forces=
3797 collision_model_.valeur().get_lagrangian_contact_forces();
3798 const ArrOfDouble particles_collision_number=collision_model_.valeur().get_particles_collision_number();
3799
3800 for (int d = 0; d < dimension; d++)
3801 Particles_data << lagrangian_contact_forces(particle,d) << espace ;
3802
3803 Particles_data << particles_collision_number(particle) << espace ;
3804 }
3805 Particles_data << finl;
3806 }
3807
3808 const Transport_Interfaces_FT_Disc& mon_eq = *this;
3809 if (post_process_hydro_forces_.get_is_compute_forces())
3810 {
3811 const DoubleTab& total_pressure_force=post_process_hydro_forces_.get_pressure_force();
3812 const DoubleTab& total_friction_force=post_process_hydro_forces_.get_friction_force();
3813 const DoubleVect& total_surface_interf=post_process_hydro_forces_.get_total_surface_interf();
3814
3815 if (nb_particles_tot_<dim_max_impr)
3816 {
3817 SFichier particle_hydro_forces;
3818 ouvrir_fichier(particle_hydro_forces,"particle_hydrodynamic_forces",1,mon_eq);
3819 schema_temps().imprimer_temps_courant(particle_hydro_forces);
3820
3821 for (int compo=0; compo<nb_particles_tot_; compo++)
3822 {
3823 particle_hydro_forces << espace << total_surface_interf(compo) << espace;
3824 for (int dim=0; dim<dimension; dim++) particle_hydro_forces <<
3825 espace << total_pressure_force(compo,dim);
3826 particle_hydro_forces << espace;
3827 for (int dim=0; dim<dimension; dim++) particle_hydro_forces <<
3828 espace << total_friction_force(compo,dim);
3829 particle_hydro_forces << espace;
3830 }
3831
3832 particle_hydro_forces << finl;
3833 }
3834 else
3835 {
3836 SFichier particle_hydro_forces_bed;
3837 ouvrir_fichier(particle_hydro_forces_bed,"particle_hydrodynamic_forces_bed",1,mon_eq);
3838 particle_hydro_forces_bed << "TIME ";
3839 schema_temps().imprimer_temps_courant(particle_hydro_forces_bed);
3840 particle_hydro_forces_bed << finl;
3841 const DoubleTab& U_P2_moy = post_process_hydro_forces_.get_U_P2_moy();
3842 const DoubleTab& Nb_fa7_ok_prop = post_process_hydro_forces_.get_prop_fa7_ok_P2();
3843 const DoubleTab& Prop_indic_fluide_P2 = post_process_hydro_forces_.get_prop_P2_fluid();
3844 for (int particle = 0; particle < nb_particles_tot_; particle++)
3845 {
3846 int dim;
3847 particle_hydro_forces_bed << particle ;
3848 particle_hydro_forces_bed << espace << total_surface_interf(particle) << espace;
3849 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3850 total_pressure_force(particle,dim);
3851 particle_hydro_forces_bed << espace;
3852 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3853 total_friction_force(particle,dim);
3854 particle_hydro_forces_bed << espace;
3855 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3856 Nb_fa7_ok_prop(particle,dim);
3857 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3858 U_P2_moy(particle,dim);
3859 particle_hydro_forces_bed << espace << Prop_indic_fluide_P2(particle);
3860 particle_hydro_forces_bed << finl;
3861 }
3862 }
3863
3864 }
3865
3866 if (post_process_hydro_forces_.get_is_compute_forces_Stokes_th() && schema_temps().nb_pas_dt()==1)
3867 {
3868 const DoubleTab& total_pressure_force=post_process_hydro_forces_Stokes_.get_pressure_force();
3869 const DoubleTab& total_friction_force=post_process_hydro_forces_Stokes_.get_friction_force();
3870 const DoubleTab& total_pressure_force_Stokes=post_process_hydro_forces_Stokes_.
3871 get_pressure_force_Stokes_th();
3872 const DoubleTab& total_friction_force_Stokes=post_process_hydro_forces_Stokes_.
3873 get_friction_force_Stokes_th();
3874 int nb_particles_tot = total_pressure_force.dimension(0);
3875
3876 if (nb_particles_tot<dim_max_impr)
3877 {
3878 SFichier Force_Particule_th;
3879 ouvrir_fichier(Force_Particule_th,"Stokes_theoretical_forces",1,mon_eq);
3880 schema_temps().imprimer_temps_courant(Force_Particule_th);
3881 for (int particle=0; particle<nb_particles_tot; particle++)
3882 {
3883 Force_Particule_th << espace;
3884 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3885 total_pressure_force_Stokes(particle,dim);
3886 Force_Particule_th << espace;
3887 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3888 total_pressure_force(particle,dim);
3889 Force_Particule_th << espace;
3890 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3891 total_friction_force_Stokes(particle,dim);
3892 Force_Particule_th << espace;
3893 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3894 total_friction_force(particle,dim);
3895 Force_Particule_th << finl;
3896 }
3897 }
3898
3899 }
3900
3901 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
3902 {
3903 const DoubleVect& total_heat_transfer =
3904 post_process_hydro_forces_.get_heat_transfer();
3905 if (nb_particles_tot_ < dim_max_impr)
3906 {
3907 SFichier Heat_Transfer;
3908 ouvrir_fichier(Heat_Transfer,
3909 "fluid_to_particle_heat_transfer", 1, mon_eq);
3910 schema_temps().imprimer_temps_courant(Heat_Transfer);
3911 for (int particle = 0; particle < nb_particles_tot_;
3912 particle++)
3913 {
3914 Heat_Transfer << espace << total_heat_transfer(particle);
3915 }
3916 Heat_Transfer << finl;
3917 }
3918 else
3919 {
3920 SFichier Heat_Transfer_bed;
3921 ouvrir_fichier(Heat_Transfer_bed,
3922 "fluid_to_particle_heat_transfer_bed", 1, mon_eq);
3923 schema_temps().imprimer_temps_courant(Heat_Transfer_bed);
3924 for (int particle = 0; particle < nb_particles_tot_;
3925 particle++)
3926 {
3927 Heat_Transfer_bed << espace << total_heat_transfer(particle);
3928 }
3929 Heat_Transfer_bed << finl;
3930 }
3931 }
3932 }
3933 }
3934 return 1;
3935}
3936
3937//Cette methode actualise le critere de stationnnarite dI/dt (en derivee partielle)
3938//du fait que pour ce type d equation derivee_en_temps_inco fixe dI/dt a 0.
3939//
3941{
3942 Schema_Temps_base& sch_tps = schema_temps();
3943 const DoubleTab& present = inconnue().valeurs();
3944 const DoubleTab& passe = inconnue().passe();
3945 const double dt = sch_tps.pas_de_temps();
3946 DoubleTab tab_critere(present);
3947
3948 tab_critere = present;
3949 tab_critere -=passe;
3950 tab_critere /= dt;
3951 sch_tps.update_critere_statio(tab_critere,*this);
3952}
3953
3955 const DoubleTab& rho_faces,DoubleTab& source_val,
3956 const int is_explicite,const double eta)
3957{
3958 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
3959 const int n = vpoint.dimension(0);
3960 const int m = vpoint.line_size();
3961 double c= 1./eta;
3962 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3963
3964 int is_QC=0;
3965 const Equation_base& eq = probleme_base_->equation(0);
3966 const Solveur_Masse_base& le_solveur_masse = eq.solv_masse();
3967 if (sub_type(Navier_Stokes_FT_Disc,eq))
3968 is_QC=0;
3969 else
3970 is_QC=1;
3971
3972 if ( !is_explicite )
3973 {
3974 for (int i = 0; i<n; i++)
3975 {
3976 double indic = (indicatrice_faces(i) > 0. ? 1.0 : 0.0);
3977 for (int j = 0; j < m; j++)
3978 {
3979 if (!is_QC)
3980 source_val(i,j) -= vpoint(i,j) * indic * rho_faces(i) * c;
3981 else
3982 source_val(i,j) -= vpoint(i,j) * indic * c;
3983 }
3984 }
3985 }
3986
3987 DoubleTab termes_sources_face(vpoint);
3988 const DoubleVect& vol_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
3989
3990 for (int face=0; face<n; face++)
3991 for (int dim=0; dim<m; dim++)
3992 {
3993 double indic = (indicatrice_faces(face) > 0. ? 1.0 : 0.0);
3994 termes_sources_face(face,dim)=vol_entrelaces(face)*vol_entrelaces(face)*source_val(face,dim)*indic;
3995 }
3996
3997 termes_sources_face.echange_espace_virtuel() ;
3998 le_solveur_masse.appliquer(termes_sources_face);
3999
4000 // Impression des efforts exerces par le fluide sur l'interface
4001 {
4002 ArrOfDouble dforce(dimension);
4003 force_=0;
4004 moment_=0;
4005 const Domaine& domaine=domaine_dis().domaine();
4006 const int impr_mom = domaine.moments_a_imprimer();
4007 const ArrOfDouble& centre_gravite = domaine.cg_moments();
4008 const DoubleTab& centre_faces = ref_cast(Domaine_VF,domaine_dis()).xv();
4009 ArrOfDouble xgr(dimension);
4010
4011 const Domaine_VDF * zvdf = 0;
4012 if (sub_type(Domaine_VDF, domaine_dis()))
4013 zvdf = &ref_cast(Domaine_VDF, domaine_dis());
4014
4015 // Construction d'un tableau des items sequentiels
4016 ArrOfInt sequential_items_flags;
4017 rho_faces.get_md_vector()->get_sequential_items_flags(sequential_items_flags);
4018
4019 // Calcul de la force et du moment en fonction de la discretisation
4020 for (int i = 0; i < n; i++)
4021 {
4022 // Calcul de dforce contribution de la force du fluide sur la face i
4023 // si c'est une face sequentielle
4024 if (sequential_items_flags[i])
4025 {
4026 dforce=0;
4027 if (zvdf)
4028 {
4029 int j = zvdf->orientation(i);
4030 dforce[j] = -termes_sources_face(i);
4031 force_[j] += dforce[j];
4032 }
4033 else
4034 for (int j = 0; j < dimension; j++)
4035 {
4036 dforce[j] = -termes_sources_face(i,j);
4037 force_[j] += dforce[j];
4038 }
4039 // Ajout de dforce au calcul eventuel du moment
4040 if (impr_mom)
4041 {
4042 for (int j = 0; j < dimension; j++)
4043 xgr[j] = centre_faces(i,j) - centre_gravite[j];
4044
4045 if (dimension==2)
4046 moment_[0] += dforce[1]*xgr[0] - dforce[0]*xgr[1];
4047 else
4048 {
4049 moment_[0] += dforce[2]*xgr[1] - dforce[1]*xgr[2];
4050 moment_[1] += dforce[0]*xgr[2] - dforce[2]*xgr[0];
4051 moment_[2] += dforce[1]*xgr[0] - dforce[0]*xgr[1];
4052 }
4053 }
4054 }
4055 }
4056
4057 // Ajout des differents processeurs en //
4058
4059 mp_sum_for_each_item(force_);
4060 mp_sum_for_each_item(moment_);
4061 // Impression dans les fichiers
4063 }
4064}
4065
4067{
4068 const double temps=le_schema_en_temps->temps_courant();
4069 const int dim = Objet_U::dimension;
4070 const int dimension3 = (dim==3);
4071 Parser parser_x, parser_y, parser_z;
4072 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
4073 const IntTab& face_voisins = domaine_vf.face_voisins();
4074 const int nfaces = face_voisins.dimension(0);
4075 const DoubleTab& xv = domaine_vf.xv();
4076 const Domaine_VDF * zvdf = 0;
4077 if (sub_type(Domaine_VDF, domaine_vf))
4078 zvdf = &ref_cast(Domaine_VDF, domaine_vf);
4079
4080 if (zvdf)
4081 vit_ibc.resize(nfaces,1);
4082 else
4083 vit_ibc.resize(nfaces,dim);
4084
4085 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,
4086 parser_x, parser_y, parser_z,temps);
4087 for (int i = 0; i < nfaces; i++)
4088 {
4089 for (int j = 0; j < dim; j++)
4090 {
4091 const double coord = xv(i,j);
4092 parser_x.setVar(j, coord);
4093 parser_y.setVar(j, coord);
4094 if (dimension3)
4095 parser_z.setVar(j, coord);
4096 }
4097 if (zvdf)
4098 {
4099
4100 switch(zvdf->orientation(i))
4101 {
4102 case 0:
4103 vit_ibc(i,0) = parser_x.eval();
4104 break;
4105 case 1:
4106 vit_ibc(i,0) = parser_y.eval();
4107 break;
4108 case 2:
4109 vit_ibc(i,0) = parser_z.eval();
4110 break;
4111 }
4112 }
4113 else
4114 {
4115 vit_ibc(i,0) = parser_x.eval();
4116 vit_ibc(i,1) = parser_y.eval();
4117 if (dimension3)
4118 vit_ibc(i,2) = parser_z.eval();
4119 }
4120 }
4121}
4122
4123//Methode qui effectue le calcul de la vitesse imposee a l interface a l instant temps
4124//- Utilise l expression de la vitesse imposee specifiee par l utilisateur : expression_vitesse_imposee
4125//- La vitesse calculee est contenue dans vitesse_imp
4126
4128 const DoubleTab& vitesse,
4129 const DoubleTab& vpoint,
4130 const double temps,
4131 const double dt)
4132{
4133 const int dim = Objet_U::dimension;
4134 const int dimension3 = (dim==3);
4135 const Domaine_dis_base& mon_dom_dis = domaine_dis();
4136 const IntTab& face_voisins = mon_dom_dis.face_voisins();
4137 const int nfaces = face_voisins.dimension(0);
4138 const DoubleTab& xv = ref_cast(Domaine_VF, mon_dom_dis).xv();
4139 const Domaine_VDF * zvdf = 0;
4140 if (sub_type(Domaine_VDF, mon_dom_dis))
4141 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
4142
4143 if (zvdf)
4144 vitesse_imp.resize(nfaces,1);
4145 else
4146 vitesse_imp.resize(nfaces,dim);
4147
4148 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE)
4149 {
4150 ArrOfDouble coord(dim);
4151 ArrOfDouble v_imp(dim);
4152 for (int i = 0; i < nfaces; i++)
4153 {
4154 // Calcul de la vitesse au centre de la face par la loi horaire a temps+dt
4155 for (int j = 0; j < dim; j++)
4156 coord[j] = xv(i,j);
4157 v_imp = variables_internes_->loi_horaire_->vitesse(temps+dt,coord);
4158
4159 if (zvdf)
4160 vitesse_imp(i,0) = v_imp[zvdf->orientation(i)];
4161 else
4162 for (int j = 0; j < dim; j++)
4163 vitesse_imp(i,j) = v_imp[j];
4164 }
4165 }
4166 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
4167 {
4168 switch(variables_internes_->interpolation_champ_face)
4169 {
4171 {
4172 Parser parser_x, parser_y, parser_z;
4173 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,
4174 parser_x, parser_y, parser_z,temps);
4175 for (int i = 0; i < nfaces; i++)
4176 {
4177
4178 for (int j = 0; j < dim; j++)
4179 {
4180 // Vitesse evaluee au centre de la face
4181 const double coord = xv(i,j);
4182 parser_x.setVar(j, coord);
4183 parser_y.setVar(j, coord);
4184 if (dimension3)
4185 parser_z.setVar(j, coord);
4186 }
4187 if (zvdf)
4188 {
4189
4190 switch(zvdf->orientation(i))
4191 {
4192 case 0:
4193 vitesse_imp(i,0) = parser_x.eval();
4194 break;
4195 case 1:
4196 vitesse_imp(i,0) = parser_y.eval();
4197 break;
4198 case 2:
4199 vitesse_imp(i,0) = parser_z.eval();
4200 break;
4201 }
4202
4203 }
4204 else
4205 {
4206
4207 vitesse_imp(i,0) = parser_x.eval();
4208 vitesse_imp(i,1) = parser_y.eval();
4209 if (dimension3)
4210 vitesse_imp(i,2) = parser_z.eval();
4211 }
4212 }
4213 break;
4214 }
4216 {
4217 double dt_loc = 0.;
4218 if ( !variables_internes_->vf_explicite )
4219 {
4220 //On calcule un dt_loc car diff et conv sont explicites pour cette estimation de vpoint
4221 const Equation_base& eq = probleme_base_->equation(0);
4222 const double nb_op = eq.nombre_d_operateurs();
4223 if(nb_op > 0) dt_loc += 1. / eq.operateur(0).calculer_pas_de_temps();
4224 if(nb_op > 1) dt_loc += 1. / eq.operateur(1).calculer_pas_de_temps();
4225 dt_loc = (1./dt_loc)*(le_schema_en_temps->facteur_securite_pas());
4226 dt_loc = Process::mp_min(dt_loc);
4227 // si le dt_loc obtenu est plus grand que le dt_min du jdd :
4228 dt_loc = std::min(dt_loc,dt);
4229 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee avec dt_loc : "<<dt_loc<<finl;
4230 }
4231 if (zvdf)
4232 {
4233 const DoubleTab& dist_face = get_update_distance_interface_faces().valeurs();
4234 const int phase = 0;
4235 vitesse_imp = vpoint;
4236 vitesse_imp*= dt_loc;
4237 vitesse_imp += vitesse;
4238 vitesse_imp.echange_espace_virtuel() ; // CI
4239 DoubleTab gradient(vitesse);
4240 interpoler_vitesse_face(dist_face,phase,variables_internes_->n_iterations_interpolation_ibc,vitesse_imp,gradient,temps,dt);
4241 Debog::verifier("Transport_Interfaces_FT_Disc::calcul_vitesse vitesse_imp apres interp. ",vitesse_imp);
4242 }
4243 else
4244 {
4245 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee\n"
4246 << " interpolation lineaire non codee en VEF" << finl;
4247 Process::exit();
4248 }
4249 break;
4250 }
4251 default:
4252 {
4253 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee\n"
4254 << " methode d'interpolation non codee" << finl;
4255 Process::exit();
4256 }
4257 }
4258 }
4259 else
4260 {
4261 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calcul_vitesse\n"
4262 << " The transport equation is not of type \"methode_transport vitesse_imposee\"."
4263 << " or \"methode_transport loi_horaire\"."
4264 << finl;
4265 Process::exit();
4266 }
4267}
4268
4269
4270//Calcul d'une distance signee a l'interface aux centres des faces, interpolee a partir de la distance signee aux
4271//centres des elements (dist_elem) et de la normale a l'interface evaluee aux centres des elements euleriens (normale_elem).
4272//
4273//Pour une face, on evalue la distance entre le centre de la face et l'interface par :
4274// dist_face = d1 + d2,
4275// d1 = dist_elem,
4276// d2 = normale_elem scalaire (position_centre_face - centre_element)
4277//Ensuite, la distance entre le centre d'une face et l'interface est la moyenne de toutes
4278//les distances calculee a l'aide des elements adjacents a cette face.
4279//La distance est invalide au-dela d'une certaine epaisseur autour de l'interface
4280//(voir iterations de lissage dans calculer_distance_interface).
4282 const DoubleTab& dist_elem,
4283 const DoubleTab& normale_elem,
4284 DoubleTab& dist_face) const
4285{
4286 statistics().create_custom_counter("Calculer_distance_interface",3,"FrontTracking");
4287 statistics().begin_count("Calculer_distance_interface",statistics().get_last_opened_counter_level()+1);
4288
4289 static const double distance_faces_invalides = -1.e30;
4290
4291 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
4292 const IntTab& elem_faces = domaine_vf.elem_faces();
4293 const DoubleTab& xv = domaine_vf.xv();
4294 const DoubleTab& xp = domaine_vf.xp();
4295 const int nb_faces = dist_face.dimension_tot(0);
4296 ArrOfInt ncontrib(nb_faces);
4297 ncontrib = 0;
4298 dist_face = 0.;
4299
4300 const int dim = Objet_U::dimension;
4301 double centre[3] = {0., 0., 0.};
4302 double normale[3] = {0., 0., 0.};
4303 // Calcul de SOMME(d1+d2) pour tous les elements voisins de chaque face :
4304 int elem, i;
4305 const int nb_elem_tot = dist_elem.dimension_tot(0);
4306 const int nb_faces_elem = elem_faces.line_size();
4307
4308 for (elem = 0; elem < nb_elem_tot; elem++)
4309 {
4310 const double d1 = dist_elem(elem);
4311 // Si la distance est invalide, on passe:
4312 if (d1 < distance_faces_invalides)
4313 continue;
4314 // Centre de l'element et normale a l'interface pour cet element :
4315 for (i = 0; i < dim; i++)
4316 {
4317 centre[i] = xp(elem, i);
4318 normale[i] = normale_elem(elem, i);
4319 }
4320 // Boucle sur les faces de l'element
4321 for (i = 0; i < nb_faces_elem; i++)
4322 {
4323 const int face = elem_faces(elem, i);
4324 // dist_face ne contient que des faces reelles en general.
4325 // si la face n'est pas dans dist_face, on ne calcule pas.
4326 if (face < nb_faces)
4327 {
4328 double d2 = 0.;
4329 int j;
4330 for (j = 0; j < dim; j++)
4331 {
4332 double position_centre_face = xv(face, j);
4333 d2 += (position_centre_face - centre[j]) * normale[j];
4334 }
4335 dist_face(face) += d1 + d2;
4336 ++(ncontrib[face]);
4337 }
4338 }
4339 }
4340 // Division par le nombre d'elements voisins
4341 const double valeur_invalide = distance_faces_invalides * 1.1;
4342#ifdef __INTEL_COMPILER
4343#pragma novector // Desactive vectorisation sur Intel car crash sinon
4344#endif
4345 for (i = 0; i < nb_faces; i++)
4346 {
4347 const int n = ncontrib[i];
4348 if (n > 0)
4349 dist_face(i) /= n;
4350 else
4351 dist_face(i) = valeur_invalide;
4352 }
4353 dist_face.echange_espace_virtuel();
4354 statistics().end_count("Calculer_distance_interface");
4355}
4356
4357
4359{
4360 // Si le tag du maillage et le tag du champ sont identiques, inutile de recalculer:
4361 const int tag = maillage_interface().get_mesh_tag();
4362 if (tag == variables_internes_->distance_faces_cache_tag)
4363 return variables_internes_->distance_interface_faces.valeur();
4364
4365 variables_internes_->distance_faces_cache_tag = tag;
4366 assert(tag == variables_internes_->distance_normale_cache_tag);
4367 const DoubleTab& dist_elem = get_distance_interface().valeurs();
4368 const DoubleTab& normale_elem = get_normale_interface().valeurs();
4369 DoubleTab& dist_face = variables_internes_->distance_interface_faces->valeurs();
4370
4371 calculer_distance_interface_faces(dist_elem, normale_elem, dist_face);
4372 return variables_internes_->distance_interface_faces.valeur();
4373}
4374
4375// Verification que la vitesse imposee est uniforme
4376inline void check(const DoubleTab& v_imp, int& i_face, double v, int v_est_initialise)
4377{
4378 if (v_est_initialise && v_imp(i_face)!= v)
4379 {
4380 Cerr << "=====================================================================================" << finl;
4381 Cerr << "You defined a non-uniform function for the keyword: methode_transport vitesse_imposee" << finl;
4382 Cerr << "Please add:" << finl;
4383 Cerr << "type_vitesse_imposee analytique" << finl;
4384 Process::exit();
4385 }
4386 else
4387 {
4388 v = v_imp(i_face);
4389 v_est_initialise = 1;
4390 }
4391}
4392// Modifie les valeurs de la vitesse aux faces pres de l'interface (le stencil depend du nombre d'iterations) via une
4393// interpolation lineaire de la vitesse.
4394// A partir d'une indicatrice interpolee aux faces, on calcule le gradient de chaque composante de la vitesse pour les
4395// faces ou :
4396// - indicatrice=phase
4397// - distance face/interface valide (depend du nb iterations de lissage dans calculer_distance_interface).
4398// On en deduit le gradient aux faces telles que indicatrice!=phase, via un processus iteratif qui permet d'etendre
4399// l'interpolation aux points interieurs a l'IBC. L'interpolation s'effectue sur les quatre faces les plus proches de
4400// meme orientation (vitesses non colocalisees).
4401// Le resultat OWN_PTR(Champ_base) est prealablement construit a partir du champ de vitesse Un+vpoint.dt dans la methode
4402// calcule_vitesse
4403//
4404// Attention :
4405// - phase=0 impose que l'indicatrice de la partie fluide soit egale a 0
4406// - l'interpolation est specifique au VDF
4407// - codage pour l'instant pour une IBC immobile ou a vitesse uniforme
4408
4410 const DoubleTab& distance_interface_faces,
4411 const int phase,
4412 const int stencil_width,
4413 DoubleTab& champ,
4414 DoubleTab& gradient,
4415 const double t, const double dt)
4416{
4417 const Domaine_dis_base& mon_dom_dis = domaine_dis();
4418 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
4419 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
4420 const Domaine_VDF * zvdf = 0;
4421 if (sub_type(Domaine_VDF, mon_dom_dis))
4422 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
4423
4424 const IntTab& elem_faces = domaine_vf.elem_faces();
4425 const IntTab& faces_elem = domaine_vf.face_voisins();
4426 const int nfaces = faces_elem.dimension(0);
4427 const int nb_elem = domaine_vf.nb_elem() ;
4428 const int nb_elem_tot = domaine_vf.nb_elem_tot() ;
4429 const IntVect& orientation = domaine_vdf.orientation();
4430 const DoubleTab& xv = domaine_vf.xv();
4431 const DoubleTab& xp = domaine_vf.xp();
4432 assert(champ.dimension(0) == nfaces);
4433 assert(gradient.dimension(0) == nfaces);
4434 assert(distance_interface_faces.dimension(0) == nfaces);
4435
4436 const int dim = Objet_U::dimension;
4437 const int dimension3 = (Objet_U::dimension==3);
4438
4439 Parser parser_x, parser_y, parser_z;
4440 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,parser_x, parser_y, parser_z, t);
4441
4442 const double invalid_test = -1.e30;
4443 const double invalid_value = -2.e30;
4444 gradient = invalid_value;
4445 const double indic_phase = (phase == 0) ? 0. : 1.;
4446 int i_face;
4447 Maillage_FT_Disc& maillage = maillage_interface() ;
4448 const DoubleTab& indicatrice = get_indicatrice().valeurs();
4449 const DoubleTab& indicatrice_face = update_indicatrice_faces().valeurs();
4450 // distance signee aux faces corrigee
4451 DoubleTab dist_face_cor(distance_interface_faces) ;
4452 // type de face : fluide (0), solide (1) et 0.5 si le barycentre de la face est proche de l'IBC
4453 DoubleTab typeface(champ) ;// CI
4454 typeface = -1.e30 ;
4455
4456 if(variables_internes_-> type_distance_calculee == Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE )
4457 {
4458 //////////////////////////////////////////////////////////////////////////////////////////////
4459 ////// LANCE DE RAYON
4460 //////////////////////////////////////////////////////////////////////////////////////////////
4461
4462 //////////////////////////////////////////////////////////////////////////////////////////////
4463 //------- Calcul du nombre de fois qu'un rayon local (par direction) traverse l'IBC dans une cellule
4464 IntTab trav(nb_elem,dim) ;
4465 if( nb_elem < nb_elem_tot )
4466 domaine_vf.domaine().creer_tableau_elements(trav, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
4467 trav = 0 ;
4468
4469 DoubleTab xe(dim) ;
4470 xe = 0. ;
4471 for(int i_elem=0 ; i_elem<nb_elem ; i_elem++)
4472 {
4473 for(int i=0 ; i<dim ; i++ )
4474 xe(i)=xp(i_elem,i) ;
4475 // Cas des elements diphasiques
4476 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
4477 {
4478 for(int dir = 0 ; dir < dim ; dir++ )
4479 {
4480 int a = elem_faces(i_elem, dir) ;
4481 int b = elem_faces(i_elem, dir+dim) ;
4482 const double pas = std::fabs(domaine_vdf.distance_face(a,b,dir)) ;
4483 int traverse = 0 ;
4484 calcul_nb_traverse(xe,pas,dim,dir,maillage,i_elem,traverse) ;
4485 trav(i_elem,dir) = traverse ;
4486 }
4487 }
4488 else if( indicatrice(i_elem) == 0. )
4489 {
4490 // Cas des elements fluides
4491 for( int k=0; k<dim; k++)
4492 trav(i_elem,k) = -1 ;
4493 }
4494 else if( indicatrice(i_elem) == 1. )
4495 {
4496 // Cas des elements solides
4497 for( int k=0; k<dim; k++)
4498 trav(i_elem,k) = -2 ;
4499 }
4500 }
4501 trav.echange_espace_virtuel() ;
4502 //-----------------------------------------------------------------
4503 //-----------------------------------------------------------------
4504 // initialisation des compteurs de faces
4505 // faces monophasiques (de reference) : cpt_ref
4506 // faces diphasiques avec une cellule voisine de reference : cpt_vref
4507 // faces avec indicatrice_face = 0.5 et deux cellules voisines de reference : cpt_halfref
4508 int cpt_ref = 0 ;
4509 int cpt_vref = 0 ;
4510 int cpt_halfref = 0 ;
4511 DoubleTab typefacejoint ;
4512 IntList FACEJOINT ;
4513
4514 int nbjoints=domaine_vf.nb_joints();
4515 for(int njoint=0; njoint<nbjoints; njoint++)
4516 {
4517 const Joint& joint_temp = domaine_vf.joint(njoint);
4518 const IntTab& indices_faces_joint = joint_temp.joint_item(JOINT_ITEM::FACE).renum_items_communs();
4519 const int nb_faces = indices_faces_joint.dimension(0);
4520 for (int j = 0; j < nb_faces; j++)
4521 {
4522 int face_de_joint = indices_faces_joint(j, 1);
4523 FACEJOINT.add_if_not(face_de_joint) ;
4524 }
4525 }
4526 //-----------------------------------------------------------------
4527 // Parcourt des faces monophasiques sur le processeur courant
4528 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4529 {
4530 if( indicatrice_face(i_face) == 0. || indicatrice_face(i_face) == 1. )
4531 {
4532 typeface(i_face) = indicatrice_face(i_face) ;
4533 cpt_ref++ ;
4534 }
4535 }
4536 typefacejoint = typeface ;
4537 typeface.echange_espace_virtuel() ;
4538 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4539 {
4540 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4541 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1 )
4542 cpt_ref++;
4543 }
4544
4545 // Traitement des faces diphasiques locales ayant une cellule voisine de reference
4546 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4547 {
4548 // les faces avec une indicatrice de 0.5 sont traitees apres
4549 if( indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && indicatrice_face(i_face) != 0.5 )
4550 {
4551 // Si l'un des deux voisins est monophasique alors i_face est du meme cote
4552 int reference_trouvee = 0 ;
4553 int i_voisin = 0 ;
4554 while( i_voisin < 2 && reference_trouvee == 0)
4555 {
4556 const int elem_voisin = faces_elem(i_face,i_voisin) ;
4557
4558 if( elem_voisin > -1 &&
4559 ( indicatrice(elem_voisin) == 0. || indicatrice(elem_voisin) == 1. ) )
4560 {
4561 reference_trouvee = 1 ;
4562 typeface(i_face) = indicatrice(elem_voisin) ;
4563 cpt_vref++;
4564 }
4565 i_voisin++ ;
4566 }
4567 }
4568 }
4569 typefacejoint = typeface ;
4570 typeface.echange_espace_virtuel() ;
4571 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4572 {
4573 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4574 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1
4575 && indicatrice_face(FACEJOINT[i]) != 0. && indicatrice_face(FACEJOINT[i]) != 1.
4576 && indicatrice_face(FACEJOINT[i]) != 0.5 )
4577 cpt_vref++;
4578 }
4579
4580 // Traitement des faces avec indicatrice_face = 0.5 et deux cellules voisines de reference
4581 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4582 {
4583 if( indicatrice_face(i_face) == 0.5 )
4584 {
4585 int element = -1 ;
4586 if( faces_elem(i_face,0) > -1 )
4587 element = faces_elem(i_face,0) ;
4588 else
4589 element = faces_elem(i_face,1) ;
4590
4591 if( indicatrice(element) == 0. || indicatrice(element) == 1. )
4592 {
4593 typeface(i_face) = 0.5 ;
4594 cpt_halfref++;
4595 }
4596 }
4597 }
4598 typefacejoint = typeface ;
4599 typeface.echange_espace_virtuel() ;
4600 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4601 {
4602 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4603 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1 && indicatrice_face(FACEJOINT[i]) == 0.5 )
4604 cpt_halfref++;
4605 }
4606
4607
4608 // A ce niveau, il reste a traiter les faces diphasiques ayant
4609 // deux cellules voisines traversees par l'IBC
4610 // Pour determiner leur type, on procede de proche en proche
4611 // a partir des faces deja determinees.
4612 // On itere le processus tant que l'ensemble des faces
4613 // n'a pas ete determine.
4614 // En parallele, il faut que chaque processeur procede
4615 // simultanement car a la fin de chaque processus
4616 // l'info est echangee. Ceci explique le "barrier()" (utile?)
4617 // On s'arrete des que chaque processeur a determine
4618 // toutes ces faces.
4619 //-----------------------------------------------------------
4620 // Initialisation des compteurs de faces
4621 // nombre de faces restant a determiner par processeur
4622 int cpt_rest = nfaces - cpt_ref - cpt_vref - cpt_halfref ;
4623 // nombre de face diphasique determinee au processus n
4624 int cpt_diph = 0 ;
4625 // critere d'arret pour le processeur courant
4626 double proc_stop = -1. ;
4627 // critere d'arret pour l'ensemble des processeurs
4628 double stop = -1. ;
4629 //////////////////////////////////////////////////////////////
4630 //////////////////////////////////////////////////////////////
4631 while( stop < 0 )
4632 {
4633 if( proc_stop < 0. )
4634 {
4635
4636 for( i_face = 0 ; i_face<nfaces ; i_face++)
4637 {
4638 if( typeface( i_face ) < 0 )
4639 {
4640 const int ori = orientation[i_face] ;
4641 const int elem0 = faces_elem(i_face,0) ;
4642 const int elem1 = faces_elem(i_face,1) ;
4643
4644 int elem = 0 ;
4645 if( elem0 > -1 && elem0 < nb_elem_tot )
4646 elem = elem0 ;
4647 else if( elem1 > -1 && elem1 < nb_elem_tot )
4648 elem = elem1 ;
4649 else
4650 {
4651 Process::Journal() << "erreur dans le choix de l'element "<<finl ;
4652 Process::exit() ;
4653 }
4654 int nb = trav(elem,ori) ;
4655
4656 // On regarde la face voisine que l'on va determiner. Elle peut etre virtuelle.
4657 int j_face = elem_faces(elem, ori) + elem_faces(elem, ori+dim) - i_face ;
4658
4659 if( typeface(j_face) > -1 )
4660 {
4661 // On modifie typeface(i_face)
4662 if( fmod( nb, 2. ) > 0 )
4663 {
4664 //Cas impair
4665 // a) le rayon rencontre une face fluide alors la face est solide
4666 // b) le rayon rencontre une face solide alors la face est fluide
4667 typeface(i_face) = 1. - typeface(j_face) ;
4668 }
4669 else
4670 {
4671 //Cas pair
4672 // a) le rayon rencontre une face fluide alors la face est fluide
4673 // b) le rayon rencontre une face solide alors la face est solide
4674 typeface(i_face) = typeface(j_face) ;
4675 }
4676 cpt_diph++ ;
4677 }
4678 else
4679 {
4680 elem = elem0 + elem1 - elem ;
4681 if( elem > -1 && elem < nb_elem_tot )
4682 {
4683 nb = trav(elem,ori) ;
4684 j_face = elem_faces(elem, ori) + elem_faces(elem, ori+dim) - i_face ;
4685
4686 if( typeface(j_face) > -1 )
4687 {
4688 // On modifie typeface(i_face)
4689 if( fmod( nb, 2. ) > 0 )
4690 {
4691 //Cas impair
4692 // a) le rayon rencontre une face fluide alors la face est solide
4693 // b) le rayon rencontre une face solide alors la face est fluide
4694 typeface(i_face) = 1. - typeface(j_face) ;
4695 }
4696 else
4697 {
4698 //Cas pair
4699 // a) le rayon rencontre une face fluide alors la face est fluide
4700 // b) le rayon rencontre une face solide alors la face est solide
4701 typeface(i_face) = typeface(j_face) ;
4702 }
4703 cpt_diph++ ;
4704 }
4705 }
4706 }
4707 }
4708 }
4709 }
4710 typefacejoint = typeface ;
4711 typeface.echange_espace_virtuel() ;
4712 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4713 {
4714 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4715 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1
4716 && indicatrice_face(FACEJOINT[i]) != 0. && indicatrice_face(FACEJOINT[i]) != 1.
4717 && indicatrice_face(FACEJOINT[i]) != 0.5 )
4718 cpt_diph++ ;
4719 }
4720
4721 // A t on determiner toutes les faces reelles du processeurs
4722 if( cpt_diph == cpt_rest )
4723 proc_stop = 0. ;
4724
4726 stop = mp_sum( proc_stop ) ;
4727 }
4728
4729 // Traitement secondaire des faces tres proche de l'IBC
4730 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4731 {
4732 if( indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. )
4733 {
4734 int elem_voisin = 0 ;
4735 int j_face = 0 ;
4736 double dxa = 0 ;
4737 double dxb = 0 ;
4738 double Lref = 0. ;
4739 const int ori = orientation[i_face] ;
4740 if( faces_elem(i_face,0) > -1 )
4741 {
4742 j_face = elem_faces(faces_elem(i_face,0), ori) + elem_faces(faces_elem(i_face,0), ori+dim) - i_face ;
4743 dxa = std::fabs(domaine_vdf.distance_face(i_face,j_face,ori)) ;
4744 }
4745 if( faces_elem(i_face,1) > -1 )
4746 {
4747 j_face = elem_faces(faces_elem(i_face,1), ori) + elem_faces(faces_elem(i_face,1), ori+dim) - i_face ;
4748 dxb = std::fabs(domaine_vdf.distance_face(i_face,j_face,ori)) ;
4749 }
4750 if( dxa < dxb )
4751 {
4752 elem_voisin = faces_elem(i_face,1) ;
4753 Lref = dxb*dxb ;
4754 }
4755 else
4756 {
4757 elem_voisin = faces_elem(i_face,0) ;
4758 Lref = dxa*dxa ;
4759 }
4760
4761 for( int k=0 ; k<dim ; k++ )
4762 {
4763 if( k != ori )
4764 {
4765 int a = elem_faces(elem_voisin, k) ;
4766 int b = elem_faces(elem_voisin, k+dim) ;
4767 double pas = std::fabs(domaine_vdf.distance_face(a,b,k)) ;
4768 Lref += 0.25*pas*pas ;
4769 }
4770 }
4771 const double ratio = std::fabs(distance_interface_faces(i_face))/sqrt(Lref) ;
4772 const double tol_distface = 1e-3 ;
4773 const int test1 = ( ratio < tol_distface ) ;
4774 if( test1 )
4775 typeface(i_face) = 0.5 ;
4776 }
4777 }
4778 typefacejoint = typeface ;
4779 typeface.echange_espace_virtuel() ;
4780 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4781 {
4782 typeface(FACEJOINT[i]) = typefacejoint(FACEJOINT[i]) ;
4783 }
4784
4785
4786 //////////////////////////////////////////////////////////////////////////////////////////////
4787 //////////////////////////////////////////////////////////////////////////////////////////////
4788 // Fin du lance de rayon
4789 //////////////////////////////////////////////////////////////////////////////////////////////
4790 //////////////////////////////////////////////////////////////////////////////////////////////
4791
4792
4793 //////////////////////////////////////////////////////////////////////////////////////////////
4794 //---- Correction de la distance entre les faces et l'IBC (hyp: |distance_interface_faces| correcte)
4795 for( i_face=0 ; i_face<nfaces ; i_face++ )
4796 {
4797 if( distance_interface_faces(i_face) > invalid_test )
4798 dist_face_cor(i_face) = (2.*typeface(i_face) - 1.)*std::fabs(distance_interface_faces(i_face)) ;
4799 else
4800 dist_face_cor(i_face) = distance_interface_faces(i_face) ;
4801 }
4802 }
4803 else
4804 {
4805 for( i_face=0 ; i_face<nfaces ; i_face++ )
4806 {
4807 dist_face_cor(i_face) = distance_interface_faces(i_face) ;
4808 }
4809 }
4810 dist_face_cor.echange_espace_virtuel() ;
4811
4812 //////////////////////////////////////////////////////////////////////////////////////////////
4813 ///----- variables pour post-traitement
4814 for( i_face=0 ; i_face<nfaces ; i_face++ )
4815 {
4816 variables_internes_->distance_interface_faces_corrigee->valeurs()(i_face) = dist_face_cor(i_face) ;
4817 variables_internes_->distance_interface_faces_difference->valeurs()(i_face) = dist_face_cor(i_face) - distance_interface_faces(i_face) ;
4818 }
4819
4820 if( variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::ANALYTIQUE
4821 && variables_internes_-> type_distance_calculee == Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE )
4822 {
4823 int cpt_face_fluide_signefaux = 0 ;
4824 int cpt_face_solide_signefaux = 0 ;
4825 int cpt_face_diphasique_signefaux = 0 ;
4826 int cpt_face_diphasique_signemodifiee = 0 ;
4827 int cpt_face_diphasique_signemodifiee_dnulle = 0 ;
4828 int nfaces_diphasique = 0 ;
4829 int nfaces_fluide = 0 ;
4830 int nfaces_solide = 0 ;
4831
4832 for( i_face=0 ; i_face<nfaces ; i_face++ )
4833 {
4834 if( indicatrice_face( i_face ) == 0. )
4835 nfaces_fluide++ ;
4836 else if( indicatrice_face( i_face ) == 1. )
4837 nfaces_solide++ ;
4838 else
4839 nfaces_diphasique++;
4840
4841 if( indicatrice_face( i_face ) == 0. && dist_face_cor( i_face ) >= 0. )
4842 {
4843 cpt_face_fluide_signefaux++ ;
4844 }
4845 else if( indicatrice_face( i_face ) == 1. && dist_face_cor( i_face ) <= 0. && dist_face_cor( i_face ) > invalid_test )
4846 {
4847 cpt_face_solide_signefaux++ ;
4848 }
4849 else if( indicatrice_face( i_face ) != 1. && indicatrice_face( i_face ) != 0. )
4850 {
4851 int element = -1 ;
4852 if( faces_elem(i_face,0) > -1 )
4853 element = faces_elem(i_face,0) ;
4854 else
4855 element = faces_elem(i_face,1) ;
4856
4857 if( indicatrice( element ) == 0. && dist_face_cor( i_face ) >= 0. )
4858 {
4859 cpt_face_diphasique_signefaux++ ;
4860 }
4861 else if( indicatrice( element ) == 1. && dist_face_cor( i_face ) <= 0. && dist_face_cor( i_face ) > invalid_test )
4862 {
4863 cpt_face_diphasique_signefaux++ ;
4864 }
4865 else
4866 {
4867 if( std::fabs(dist_face_cor(i_face) - distance_interface_faces(i_face)) != 0. )
4868 {
4869 cpt_face_diphasique_signemodifiee++ ;
4870 }
4871 if( dist_face_cor( i_face ) == 0. )
4872 {
4873 cpt_face_diphasique_signemodifiee_dnulle++ ;
4874 }
4875 }
4876 }
4877 }
4878 Cerr <<" -----------------------------------------------------"<< finl ;
4879 Cerr <<" -----------------------------------------------------"<< finl ;
4880 Cerr <<" -----------------------------------------------------"<< finl ;
4881 Cerr <<" Nombre de faces : "<< nfaces <<finl ;
4882 Cerr <<" Nombre de faces fluides : "<<nfaces_fluide<<finl;
4883 Cerr <<" Nombre de faces fluides avec mauvais signe : "<<cpt_face_fluide_signefaux<<finl;
4884 Cerr <<" Nombre de faces solides : "<<nfaces_solide<<finl;
4885 Cerr <<" Nombre de faces solides avec mauvais signe : "<<cpt_face_solide_signefaux<<finl;
4886 Cerr <<" Nombre de faces diphasiques : "<<nfaces_diphasique<<finl;
4887 Cerr <<" Nombre de faces diphasiques avec mauvais signe : "<<cpt_face_diphasique_signefaux<<finl;
4888 Cerr <<" Nombre de faces diphasiques avec signe modifie : "<<cpt_face_diphasique_signemodifiee<<finl;
4889 Cerr <<" Nombre de faces diphasiques avec signe modifie et distance nulle : "<<cpt_face_diphasique_signemodifiee_dnulle<<finl;
4890 Cerr <<" -----------------------------------------------------"<< finl ;
4891 Cerr <<" -----------------------------------------------------"<< finl ;
4892 Cerr <<" -----------------------------------------------------"<< finl ;
4893 }
4894
4895 //on stocke dans v_imp la composante de la vitesse de l'interface correspondant
4896 //au projete du centre de gravite d'une face sur l'interface
4897 DoubleTab v_imp(champ) ;
4898 v_imp = 0. ;
4899 Cerr << " INITIALISATION DE Vimp a Vsolide pour les faces solides "<<finl ;
4900 for ( i_face = 0; i_face < nfaces; i_face++)
4901 {
4902 const double d = dist_face_cor(i_face) ;
4903 if ( d>0. || (indicatrice_face(i_face) == 1. && d < -1.e20) )
4904 {
4905 for (int j = 0; j < dim; j++)
4906 {
4907 const double coord = xv(i_face,j);
4908 parser_x.setVar(j, coord) ;
4909 parser_y.setVar(j, coord) ;
4910 if (dim==3)
4911 parser_z.setVar(j, coord) ;
4912 }
4913 if (zvdf)
4914 {
4915 switch(zvdf->orientation(i_face))
4916 {
4917 case 0:
4918 v_imp(i_face) = parser_x.eval() ;
4919 break ;
4920 case 1:
4921 v_imp(i_face) = parser_y.eval() ;
4922 break ;
4923 case 2:
4924 v_imp(i_face) = parser_z.eval() ;
4925 break ;
4926 }
4927 }
4928 }
4929 }
4930 v_imp.echange_espace_virtuel() ; // CI
4931
4932 if(variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::UNIFORME)
4933 {
4934 //si la vitesse est uniforme on peut calculer directement le gradient ici
4935 Cerr << "Transport_Interfaces_FT_Disc_interne::UNIFORME " << finl;
4936 double vx=0,vy=0,vz=0;
4937 int ix=0,iy=0,iz=0;
4938 for ( i_face = 0; i_face < nfaces; i_face++)
4939 {
4940 // Calcul de la composante normale du gradient du champ:
4941 // gradient normal = (champ - valeur_interface) / distance.
4942
4943 double d = dist_face_cor(i_face) ;
4944 if (indicatrice_face(i_face) == indic_phase && d > invalid_test)
4945 {
4946 //Vitesse imposee evaluee au centre des faces
4947 for (int j = 0; j < dim; j++)
4948 {
4949 const double coord = xv(i_face,j);
4950 parser_x.setVar(j, coord);
4951 parser_y.setVar(j, coord);
4952 if (dimension3)
4953 parser_z.setVar(j, coord);
4954 }
4955
4956 if (zvdf)
4957 {
4958 v_imp(i_face) = 0.;
4959 // PL Ajout de la verification que la vitesse est bien uniforme
4960 switch(zvdf->orientation(i_face))
4961 {
4962 case 0:
4963 v_imp(i_face) = parser_x.eval() ;
4964 check(v_imp,i_face,vx,ix);
4965 break ;
4966 case 1:
4967 v_imp(i_face) = parser_y.eval() ;
4968 check(v_imp,i_face,vy,iy);
4969 break ;
4970 case 2:
4971 v_imp(i_face) = parser_z.eval() ;
4972 check(v_imp,i_face,vz,iz);
4973 break ;
4974 }
4975 gradient(i_face) = (champ(i_face) - v_imp(i_face)) / d ;
4976 }
4977 }
4978 }
4979 }
4980 else if (variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::ANALYTIQUE)
4981 {
4982 // Si la vitesse n'est pas uniforme, on projete les points suceptibles
4983 // d'etre interpoles sur l'interface de facon a calculer un gradient
4984 // correct
4985 Cerr << "Transport_Interfaces_FT_Disc_interne::ANALYTIQUE "<< finl ;
4986
4987 if( variables_internes_->type_indic_faces_ == Transport_Interfaces_FT_Disc_interne::MODIFIEE && variables_internes_-> type_projete_calcule != Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE)
4988 {
4989 double indic_pos=variables_internes_->modified_indic_faces_position;
4990 double indic_thi=variables_internes_->modified_indic_faces_thickness;
4991 if (indic_pos-0.5*indic_thi < -1.)
4992 {
4993 Cerr << "-------------------------------------------------------------------------" << finl;
4994 Cerr << "-------------------------------------------------------------------------" << finl;
4995 Cerr << "The datafile ask to use type_vitesse_imposee=ANALYTIQUE and" << finl;
4996 Cerr << "type_indic_faces modifiee with a too large transition to reach zero" << finl;
4997 Cerr << "There is a big risk that fluid gradients cannot be computed" << finl;
4998 Cerr << "because fluid points (Indic_faces=0) are too far from the interface" << finl;
4999 Cerr << "To fix that, just do one of the following things:" << finl;
5000 Cerr << "If the imposed velocity field is uniform, use type_vitesse_imposee=UNIFORM" << finl;
5001 Cerr << "If not, use \"distance_projete_faces simplifiee\" " << finl;
5002 Cerr << "-------------------------------------------------------------------------" << finl;
5003 Cerr << "-------------------------------------------------------------------------" << finl;
5004 Process::exit();
5005 }
5006
5007 }
5008
5009 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE)
5010 {
5011 Cerr << "Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE, calcul a partir des distances et normales" << finl;
5012
5013 // Ici, on ne calcule pas de projete avec uzawa, on utilise simplement les quantites deja calculees dans le code
5014 // on a la distance interface-faces d, donc en determinant une normale aux faces n_F, on peut en deduire
5015 // le projete x_P de la facon suivante :
5016 // x_P = x_F - d * N_F
5017 // on determine la normale aux faces comme la moyenne de la normale aux elements.
5018
5019 const DoubleTab& normale_elem = get_normale_interface().valeurs();
5020 for (i_face = 0; i_face < nfaces; i_face++)
5021 {
5022 double d = dist_face_cor(i_face) ;
5023 const int diphasique_tmp = (indicatrice_face(i_face) != 0. &&
5024 (indicatrice_face(i_face) != 1. || (indicatrice_face(i_face) == 1. && d<=0. && d> invalid_test)));
5025 const int diphasique = ( variables_internes_->is_extra_diphasique_solide ? diphasique_tmp : (diphasique_tmp && d <= 0.) ) ;
5026 const int fluide = ( indicatrice_face(i_face) == 0. ) ;
5027 const int solide = ( variables_internes_->is_extra_solide && (d>0. || (indicatrice_face(i_face) == 1. && d<-1.e20)) ) ;
5028 const int monophasique = ( fluide || solide ) ;
5029
5030 if (diphasique || (monophasique && d> invalid_test ))
5031 {
5032 DoubleTab coord_projete(dim) ;
5033 DoubleTab normale_face(dim) ;
5034 DoubleTab coord_face(dim) ;
5035 coord_projete = 0. ;
5036 normale_face = 0. ;
5037 coord_face = 0. ;
5038 double cpt_normale = 0.;
5039 // Coordonnee au centre de la face :
5040 for (int i=0 ; i<dim ; i++)
5041 coord_face(i) = xv(i_face, i) ;
5042 // Normale a l IBC au centre de la face
5043 // calculee avec la moyenne des normales aux elements voisins
5044 for(int i=0 ; i<2; i++)
5045 {
5046 const int elem_voisin = faces_elem(i_face,i) ;
5047 if (elem_voisin > -1)
5048 {
5049 for (int j = 0; j < dim; j++)
5050 normale_face(j) += normale_elem(elem_voisin, j);
5051 cpt_normale += 1. ;
5052 }
5053 }
5054 assert(cpt_normale!=0.);
5055 normale_face /=cpt_normale;
5056 double norme_normale = 0.;
5057 for (int i=0 ; i<dim ; i++)
5058 norme_normale +=normale_face(i)*normale_face(i);
5059 assert(norme_normale!=0.);
5060 normale_face /= sqrt(norme_normale);
5061 // Coordonnee du projete :
5062 for (int i=0 ; i<dim ; i++)
5063 coord_projete(i) = coord_face(i) - d*normale_face(i);
5064 //v_imp au projete :
5065 for (int j = 0; j < dim; j++)
5066 {
5067 parser_x.setVar(j, coord_projete(j)) ;
5068 parser_y.setVar(j, coord_projete(j)) ;
5069 if (dim==3)
5070 parser_z.setVar(j, coord_projete(j)) ;
5071 }
5072 if (zvdf)
5073 {
5074 switch(zvdf->orientation(i_face))
5075 {
5076 case 0:
5077 v_imp(i_face) = parser_x.eval() ;
5078 break ;
5079 case 1:
5080 v_imp(i_face) = parser_y.eval() ;
5081 break ;
5082 case 2:
5083 v_imp(i_face) = parser_z.eval() ;
5084 break ;
5085 }
5086 }
5087 }
5088 }
5089 }
5090 else
5091 {
5092
5093 //------------------------
5094 //Initialisation
5095 //------------------------
5096 // 'exec_planfa7existant = 1' permet d'activer la routine
5097 // 'plan_facette_existant' dans 'RenumFa7' et 'StockageFa7'.
5098 // Pour un element donne, cette routine permet d'eviter de
5099 // selectionner deux facettes de meme plan.
5100 // Basee sur des criteres geometriques, elle peut conduire dans
5101 // certains cas a des differences sequentiel/parallele.
5102 // Son activation est recommandee lorsque le nombre de facettes
5103 // par element est important et qu'une majorite d'entre elles
5104 // a le meme plan.
5105 const int exec_planfa7existant = 0 ;
5106 int nb_facettes = maillage.nb_facettes() ;
5107 // dimfa7 :
5108 // Surement gourmand en allocation memoire pour des maillages fins
5109 // +1 pour s'assurer qu'en cas de doublon num_max_facette
5110 // +nb_facettes_dim!=dimfa7
5111 // La somme des facettes par processeur n'est pas egale au nombre
5112 // de facettes total en sequentiel a cause des doublons.
5113 // Note: Cannot combine mp_sum and mp_max as they are different operations
5114 int dimfa7 = int( Process::mp_sum( double(nb_facettes) ) )+1 ;
5115 int nb_facettes_dim = int( Process::mp_max( double(nb_facettes) ) ) ;
5116 // Nombre max de facettes acceptees et calculees par element
5117 // Le nombre de facette acceptees est choisi des que le maillage
5118 // Lagrangien est significativement plus fin que le maillage Eulerien.
5119 // Dans ce cas, on se retrouve avec un nombre consequent de facettes
5120 // par element (eg. maillage importe d'une CAO)
5121 int nb_fa7_accepted = variables_internes_->nomb_fa7_accepted;
5122 int max_fa7 = nb_fa7_accepted ;
5123 // OutElem : liste des eventuels elements qui contiennent un nombre
5124 // de facettes superieurs a nb_fa7_accepted.
5125 // OutFa7 : liste des facettes considerees comme etant les plus
5126 // representatives de l'IBC.
5127 IntList OutElem, OutFa7 ;
5128
5129 // Remplissage des listes OutElem et OutFa7
5130 calcul_OutElemFa7(maillage,indicatrice,nb_elem,nb_fa7_accepted,OutElem,OutFa7) ;
5131
5132 // Dans la mesure ou le nombre de facettes par element est inferieur a
5133 // nb_fa7_accepted alors on calcule le nombre max de facettes afin
5134 // d'optimiser la dimension des tableaux distribues (voir plus bas)
5135 if( OutElem.est_vide() )
5136 calcul_maxfa7(maillage,indicatrice,nb_elem,max_fa7,exec_planfa7existant) ;
5137
5138 int nb_facettes_in_elem = int( Process::mp_max( double(max_fa7) ) ) ;
5139
5140 // Tableaux distribues pour le stokage des facettes par elements
5141 // nb_elem : nb d'elements reels par processeur
5142 // Tab10i :
5143 // - entrees i= 0,1,2,3 : parametres du plan d'une facette (a,b,c,d)
5144 // Tab11i :
5145 // - entrees i= 0,1,2 : coordonnees du barycentre d'une facette
5146 // Tab12 : numero local de la facette ( < nb_facettes )
5147 // utile pour la renumerotation des facettes virtuelles
5148 DoubleTab Tab100( nb_elem, nb_facettes_in_elem ) ;
5149 DoubleTab Tab101( nb_elem, nb_facettes_in_elem ) ;
5150 DoubleTab Tab102( nb_elem, nb_facettes_in_elem ) ;
5151 DoubleTab Tab103( nb_elem, nb_facettes_in_elem ) ;
5152 DoubleTab Tab110( nb_elem, nb_facettes_in_elem ) ;
5153 DoubleTab Tab111( nb_elem, nb_facettes_in_elem ) ;
5154 DoubleTab Tab112( nb_elem, nb_facettes_in_elem ) ;
5155 IntTab Tab12( nb_elem, nb_facettes_in_elem ) ;
5156 // Tableau distribue stockant le nb de facettes par element
5157 IntTab CptFacette( nb_elem ) ;
5158
5159 // Tableau distribue pour le calul du sommet de facette
5160 // le plus proche du barycentre d'une face
5161 DoubleTab Vertex(nfaces,dim) ;
5162 DoubleTab PPP(nfaces,dim) ;
5163
5164 // Distribution des tableaux (uniquement en parallele)
5165 if( nb_elem < nb_elem_tot )
5166 {
5167 domaine_vf.domaine().creer_tableau_elements(Tab100, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5168 domaine_vf.domaine().creer_tableau_elements(Tab101, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5169 domaine_vf.domaine().creer_tableau_elements(Tab102, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5170 domaine_vf.domaine().creer_tableau_elements(Tab103, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5171 domaine_vf.domaine().creer_tableau_elements(Tab110, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5172 domaine_vf.domaine().creer_tableau_elements(Tab111, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5173 domaine_vf.domaine().creer_tableau_elements(Tab112, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5174 domaine_vf.domaine().creer_tableau_elements(Tab12, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5175 domaine_vf.domaine().creer_tableau_elements(CptFacette, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5176 domaine_vf.creer_tableau_faces(Vertex, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5177 domaine_vf.creer_tableau_faces(PPP, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5178 }
5179 CptFacette = 0 ;
5180 Tab100 = -1e+30 ;
5181 Tab101 = -1e+30 ;
5182 Tab102 = -1e+30 ;
5183 Tab103 = -1e+30 ;
5184 Tab110 = -1e+30 ;
5185 Tab111 = -1e+30 ;
5186 Tab112 = -1e+30 ;
5187 Tab12 = -1 ;
5188 Vertex = 1.e30 ;
5189 PPP = 1.e30 ;
5190
5191 // Tableau des coordonnees barycentrique des facettes
5192 DoubleTab Barycentre(nb_facettes, 3) ;
5193 Barycentre = 0. ;
5194
5195 Cerr << "STOKAGE DES FACETTES " << finl ;
5196 ArrOfBit fa7(maillage.nb_facettes()) ;
5197 fa7 = 0 ;
5198 StockageFa7(maillage,CptFacette,Tab100,Tab101,Tab102,Tab103,
5199 Tab110,Tab111,Tab112,Tab12,Barycentre,indicatrice,
5200 OutElem,fa7,exec_planfa7existant) ;
5201
5202 // On traite ici des 'OutElem.size()' elements dont le nombre de
5203 // facettes est superieur a nb_fa7_accepted.
5204 if( !OutElem.est_vide() )
5205 {
5206 if( OutFa7.size() != OutElem.size()*nb_fa7_accepted )
5207 {
5208 Cerr << "ERREUR DE DIMENSIONNEMENT " << finl ;
5209 Cerr << " OutFa7.size() "<<OutFa7.size()<<finl ;
5210 Cerr << " OutElem.size()*nb_fa7_accepted "<<OutElem.size()*nb_fa7_accepted<<finl ;
5211 Process::exit() ;
5212 }
5213
5214 // Tableau des numeros de facettes retenues
5215 // dans les 'OutElem.size()' elements.
5216 IntTab TabOutFa7(OutElem.size(),nb_fa7_accepted) ;
5217 for( int i=0 ; i< OutElem.size() ; i++)
5218 {
5219 // Chaque element contient nb_fa7_accepted facettes.
5220 CptFacette( OutElem[i] ) = nb_fa7_accepted ;
5221 for( int j=0 ; j< nb_fa7_accepted ; j++)
5222 {
5223 TabOutFa7(i,j) = OutFa7[j+i*nb_fa7_accepted] ;
5224 }
5225 }
5226 StockageFa7(maillage,Tab100,Tab101,Tab102,Tab103,Tab110,Tab111,Tab112,
5227 Tab12,Barycentre,OutElem,TabOutFa7,fa7) ;
5228 }
5229 // Echange entre les processeurs
5230 Tab100.echange_espace_virtuel() ;
5231 Tab101.echange_espace_virtuel() ;
5232 Tab102.echange_espace_virtuel() ;
5233 Tab103.echange_espace_virtuel() ;
5234 Tab110.echange_espace_virtuel() ;
5235 Tab111.echange_espace_virtuel() ;
5236 Tab112.echange_espace_virtuel() ;
5237 Tab12.echange_espace_virtuel() ;
5238 CptFacette.echange_espace_virtuel() ;
5239 // Numerotation locale des facettes virtuelles (uniquement en parallele)
5240 if( nb_elem < nb_elem_tot )
5241 {
5242 Cerr << " RENUMEROTATION DES FACETTES VIRTUELLES " << finl ;
5243 RenumFa7(Barycentre,Tab110,Tab111,Tab112,Tab12,CptFacette,
5244 nb_facettes,nb_facettes_dim) ;
5245 }
5246
5247 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
5248 {
5249 // Demarche :
5250 // 1) chaque face diphasique appartient au moins a un element diphasique
5251 // 1) on identifie donc dans ces elements voisins diphasique
5252 // 1) le sommet de facette le plus proche et on le stocke dans
5253 // 1) Vertex.
5254 //
5255 // 2) On parcourt a nouveau les faces diphasiques mais cette fois en regardant les
5256 // 2) elements voisins des elements voisins. Le sommet le plus proche definitif
5257 // 2) pour ces faces est stocke dans PPP.
5258 //
5259 // 3) On parcourt enfin les faces fluides, on determine leurs faces voisines diphasiques
5260 // 3) et a partir de ces dernieres on determine le sommet le plus proche.
5261 // 3) qui est stocke dans PPP.
5262 //
5263 Cerr << " IDENTIFICATICATION DU VERTEX LE PLUS PROCHE POUR LES FACES CONCERNEES PAR LA PROJECTION " << finl ;
5264 Cerr << " CAS DES FACES APPARTENANT A AU MOINS UN ELEMENT TRAVERSE : ETAPE 1 " <<finl ;
5265 PPP_face_interface(maillage,indicatrice,indicatrice_face,Vertex) ;
5267 Cerr << " CAS DES FACES APPARTENANT A AU MOINS UN ELEMENT TRAVERSE : ETAPE 2 " <<finl ;
5268 PPP_face_interface_voisin(indicatrice,indicatrice_face,Vertex,PPP) ;
5270 Cerr << " CAS DES FACES MONOPHASIQUE : ETAPE 3 " <<finl ;
5271 PPP_face_voisin(indicatrice,indicatrice_face,PPP) ;
5273 Cerr << " FIN IDENTIFICATION " << finl ;
5274 }
5275 // Nombre de point projete modifie a partir d'un critere de distance
5276 int nb_proj_modif = 0 ;
5277 int nb_proj_modif_tot = 0 ;
5278 Cerr << "CALCUL DU PROJETE POUR LES FACES QUI APPARTIENNENT " << finl ;
5279 Cerr << "A UN ELEMENT TRAVERSE PAR L INTERFACE" << finl;
5280 projete_point_face_interface(nb_proj_modif,dimfa7,indicatrice_face,indicatrice,dist_face_cor,t,dt,Tab100,
5281 Tab101,Tab102,Tab103,Tab12,CptFacette,v_imp,PPP,parser_x,parser_y,parser_z) ;
5282 nb_proj_modif_tot = Process::check_int_overflow(mp_sum(nb_proj_modif)) ;
5284 Cerr << " Nombre de projete modifie pour les faces diphasiques : "<<nb_proj_modif_tot<<" au temps "<<schema_temps().temps_courant()<<finl ;
5285
5286 //----------------------------------------------------------------
5287 //----------------------------------------------------------------
5288 Cerr << "CALCUL DU PROJETE POUR LES FACES FLUIDE " << finl ;
5289 projete_point_face_fluide(nb_proj_modif,dimfa7,indicatrice_face,indicatrice,dist_face_cor,
5290 t,dt,Tab100,Tab101,Tab102,Tab103,Tab12,CptFacette,v_imp,PPP,parser_x,parser_y,parser_z) ;
5291 v_imp.echange_espace_virtuel() ;
5292 nb_proj_modif_tot = Process::check_int_overflow(mp_sum(nb_proj_modif)) ;
5294 Cerr << " Nombre de projete modifie pour les faces fluides : "<<nb_proj_modif_tot<<" au temps "<<schema_temps().temps_courant()<<finl ;
5295 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face vimp",v_imp);
5296 }
5297 }
5298
5299 for (i_face = 0; i_face < nfaces; i_face++)
5300 {
5301 double d = dist_face_cor(i_face) ;
5302 if (indicatrice_face(i_face) == indic_phase && d > invalid_test)
5303 {
5304 gradient(i_face) = (champ(i_face) - v_imp(i_face))/d ;
5305 }
5306 }
5307 gradient.echange_espace_virtuel();
5308 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face gradient avant etalement",gradient);
5309
5310 // On etale ce gradient par continuite sur une epaisseur de "stencil_value"
5311 // Les iterations de cet algorithme convergent vers une sorte de laplacien=0
5312 // avec condition aux limites de Dirichlet sur les elements de la phase
5313 // "phase".
5314 DoubleTab gradient_old;
5315 Cerr << "Nombre d'iterations de la methode interpoler_vitesse_face = " << stencil_width << finl;
5316 for (int iteration = 0; iteration < stencil_width; iteration++)
5317 {
5318 // Copie de la valeur du gradient: on ne veut pas utiliser les valeurs
5319 // calculees lors de l'iteration courante
5320 gradient_old = gradient;
5321 // La valeur sur une face est la moyenne des valeurs sur les faces
5322 // les plus proches (interpolation 'en croix' : a partir de 4 faces
5323 // voisines en 2D et 6 faces voisines en 3D dans le cas general)
5324 for (i_face = 0; i_face < nfaces; i_face++)
5325 {
5326 const double d = dist_face_cor(i_face) ;
5327 if (indicatrice_face(i_face) != indic_phase && d > invalid_test)
5328 {
5329 // Ne pas toucher au gradient de la phase "phase".
5330 // Iterer sur les autres valeurs.
5331 double somme = 0.;
5332 double coeff = 0.;
5333 const int ori=orientation(i_face);
5334 const int elem0 = faces_elem(i_face, 0);
5335 const int elem1 = faces_elem(i_face, 1);
5336 int elem=-1;
5337 if (elem0 >= 0)
5338 elem=elem0;
5339 else
5340 elem=elem1;
5341
5342 for (int direction=0; direction < dimension; direction++)
5343 {
5344 if (direction==ori)
5345 {
5346 //Dans la direction de la composante de i_face, on ajoute la contribution des 2 faces qui ont un element commun avec i_face
5347 if (elem0 >= 0)
5348 {
5349 const int voisin0 = elem_faces(elem0, ori) + elem_faces(elem0, ori+dimension) - i_face;
5350 if( (elem_faces(elem0, ori) != i_face) && (elem_faces(elem0, ori+dimension) != i_face) )
5351 {
5352 Cerr << "Attention, il y a un probleme sur la numerotation des faces. On calcule en effet" << finl ;
5353 Cerr << "elem_faces(elem0, ori) = " <<elem_faces(elem0, ori)<< finl ;
5354 Cerr << "elem_faces(elem0, ori+dimension) = " <<elem_faces(elem0, ori+dimension)<< finl ;
5355 Cerr << "i_face = " <<i_face<< finl;
5356 Cerr << "tandis qu'au moins un des deux calculs 'elem_faces(elem0, ori)' ou 'elem_faces(elem0, ori+dimension)'"<<finl ;
5357 Cerr << "doit correspondre au nuemro de la face i_face"<<finl ;
5358 Cerr << "Attention, verifier les conditions aux limites."<<finl ;
5359 Cerr << "En effet, le codage suivant ne permet pas de prendre en compte des conditions" << finl ;
5360 Cerr << "de periodicite avec une vitesse solide imposee analytique." << finl ;
5361 Process::exit() ;
5362 }
5363 const double grad0 = gradient_old(voisin0);
5364 if (grad0 > invalid_test)
5365 {
5366 somme += grad0;
5367 coeff++;
5368 }
5369 }
5370 if (elem1 >= 0)
5371 {
5372 const int voisin1 = elem_faces(elem1, ori) + elem_faces(elem1, ori+dimension) - i_face;
5373 if( (elem_faces(elem1, ori) != i_face) && (elem_faces(elem1, ori+dimension) != i_face) )
5374 {
5375 Cerr << "Attention, il y a un probleme sur la numerotation des faces. On calcule en effet" << finl ;
5376 Cerr << "elem_faces(elem1, ori) = " <<elem_faces(elem1, ori)<< finl ;
5377 Cerr << "elem_faces(elem1, ori+dimension) = " <<elem_faces(elem1, ori+dimension)<< finl ;
5378 Cerr << "i_face = " <<i_face<< finl;
5379 Cerr << "tandis qu'au moins un des deux calculs 'elem_faces(elem1, ori)' ou 'elem_faces(elem1, ori+dimension)'"<<finl ;
5380 Cerr << "doit correspondre au nuemro de la face i_face"<<finl ;
5381 Cerr << "Attention, verifier les conditions aux limites."<<finl ;
5382 Cerr << "En effet, le codage suivant ne permet pas de prendre en compte des conditions" << finl ;
5383 Cerr << "de periodicite avec une vitesse solide imposee analytique." << finl ;
5384 Process::exit() ;
5385 }
5386 const double grad1 = gradient_old(voisin1);
5387 if (grad1 > invalid_test)
5388 {
5389 somme += grad1;
5390 coeff++;
5391 }
5392 }
5393 }
5394 else
5395 {
5396 //Dans les autres directions, on ajoute les contributions des faces appartenant aux elements voisins, si elles existent:
5397
5398 //-on identifie les faces de elem (=un des deux elements auxquels appartient i_face) de direction differente de i_face
5399 //-on identifie les elements auxquels appartiennent ces faces
5400 //-pour chaque element voisin, on veut trouver la face la plus proche de i_face : on compare la distance entre les centres des faces
5401 const int face0=elem_faces(elem,direction);
5402 const int face1=elem_faces(elem,direction+dimension);
5403 const int elem_voisin0=faces_elem(face0,0)+faces_elem(face0,1)-elem;
5404 const int elem_voisin1=faces_elem(face1,0)+faces_elem(face1,1)-elem;
5405
5406 double a_carre=0.;
5407 double b_carre=0.;
5408 double grad_voisin0=0.;
5409 double c_carre=0.;
5410 double d_carre=0.;
5411 double grad_voisin1=0.;
5412
5413 if (elem_voisin0 >= 0)
5414 {
5415 for (int compo = 0; compo<dimension; compo++)
5416 {
5417 double c_gravite=xv(i_face,compo);
5418 double c_face_voisin1=xv(elem_faces(elem_voisin0,ori),compo);
5419 double c_face_voisin2=xv(elem_faces(elem_voisin0,ori+dimension),compo);
5420 a_carre+=(c_gravite-c_face_voisin1)*(c_gravite-c_face_voisin1);
5421 b_carre+=(c_gravite-c_face_voisin2)*(c_gravite-c_face_voisin2);
5422 }
5423 if (a_carre<b_carre)
5424 grad_voisin0=gradient_old(elem_faces(elem_voisin0,ori));
5425 else
5426 grad_voisin0=gradient_old(elem_faces(elem_voisin0,ori+dimension));
5427 if (grad_voisin0 > invalid_test)
5428 {
5429 somme += grad_voisin0;
5430 coeff++;
5431 }
5432 }
5433 if (elem_voisin1 >= 0)
5434 {
5435 for (int compo = 0; compo<dimension; compo++)
5436 {
5437 double c_gravite=xv(i_face,compo);
5438 double c_face_voisin3=xv(elem_faces(elem_voisin1,ori),compo);
5439 double c_face_voisin4=xv(elem_faces(elem_voisin1,ori+dimension),compo);
5440 c_carre+=(c_gravite-c_face_voisin3)*(c_gravite-c_face_voisin3);
5441 d_carre+=(c_gravite-c_face_voisin4)*(c_gravite-c_face_voisin4);
5442 }
5443 if (c_carre<d_carre)
5444 grad_voisin1=gradient_old(elem_faces(elem_voisin1,ori));
5445 else
5446 grad_voisin1=gradient_old(elem_faces(elem_voisin1,ori+dimension));
5447 if (grad_voisin1 > invalid_test)
5448 {
5449 somme += grad_voisin1;
5450 coeff++;
5451 }
5452 }
5453 }
5454 }
5455
5456 if (coeff > 0.)
5457 gradient(i_face) = somme / coeff;
5458 }
5459 }
5460 gradient.echange_espace_virtuel();
5461 }
5462
5463 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face gradient",gradient);
5464 // Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face distance_interface_faces",distance_interface_faces);
5465 // On calcule la valeur extrapolee:
5466 for (i_face = 0; i_face < nfaces; i_face++)
5467 {
5468 if (indicatrice_face(i_face) != indic_phase)
5469 {
5470 double d = dist_face_cor(i_face) ;
5471 const double grad = gradient[i_face];
5472 const double indic = indicatrice_face(i_face) ;
5473
5474 const int interpolation = ( d < 0. ) ;
5475 const int extra_diphasique = ( variables_internes_->is_extra_diphasique_solide && indic != 0. && indic != 1. && d > 0. ) ;
5476 const int extra_solide = ( variables_internes_->is_extra_solide && indic == 1. && (d>0. || d < -1.e20) ) ;
5477 const int extrapolation = ( extra_diphasique || extra_solide ) ;
5478 if (variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::UNIFORME)
5479 {
5480 //Vitesse imposee evaluee au centre des faces
5481 for (int j = 0; j < dim; j++)
5482 {
5483 const double coord = xv(i_face,j);
5484 parser_x.setVar(j, coord);
5485 parser_y.setVar(j, coord);
5486 if (dimension3)
5487 parser_z.setVar(j, coord);
5488 }
5489
5490 if (zvdf)
5491 {
5492 v_imp(i_face) = 0. ;
5493 switch(zvdf->orientation(i_face))
5494 {
5495 case 0:
5496 v_imp(i_face) = parser_x.eval();
5497 break;
5498 case 1:
5499 v_imp(i_face) = parser_y.eval();
5500 break;
5501 case 2:
5502 v_imp(i_face) = parser_z.eval();
5503 break;
5504 }
5505 champ( i_face ) = v_imp(i_face) ;
5506
5507
5508 if (grad > invalid_test && d > invalid_test && ( interpolation || extrapolation ) )
5509 {
5510 champ(i_face) += d*grad ;
5511 }
5512 }
5513 }
5514 else
5515 {
5516 // Vitesse non uniforme : il faut projeter utiliser le tableau v_imp
5517 // qui contient la vitesse du projete de i_face sur l'interface
5518
5519 champ(i_face) = v_imp(i_face) ;
5520 if (grad > invalid_test && d > invalid_test && ( interpolation || extrapolation ) )
5521 {
5522 champ(i_face) += d * grad ;
5523 }
5524 }
5525 vitesse_imp_interp_->valeurs()(i_face)= champ( i_face ) ;
5526 }
5527 else
5528 {
5529 vitesse_imp_interp_->valeurs()(i_face)=-3e30;
5530 }
5531 }
5532 champ.echange_espace_virtuel() ;
5533 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face champ",champ );
5534
5535}
5536
5537// Calcul le nombre de fois que l'on traverse l'IBC
5538void Transport_Interfaces_FT_Disc::calcul_nb_traverse( const DoubleTab& xe, const double dx,
5539 const int dim, const int ori,
5540 Maillage_FT_Disc& maillage, int elem,
5541 int& traverse )
5542
5543{
5544 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5545 const ArrOfInt& index_elem = intersection.index_elem() ;
5546 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes() ;
5547 const IntTab& facettes = maillage.facettes() ;
5548 //const int nb_som = facettes.line_size() ;
5549 const DoubleTab& sommets = maillage.sommets() ;
5550 //IntTab Som( nb_som ) ;
5551 // Pour un element donne, on parcourt ces facettes
5552 int index = index_elem[elem] ;
5553 const double precision = Objet_U::precision_geom ;
5554 const double tol_theta = 1e-4 ;
5555 double I_sur_arete_fa7 = 0. ;
5556 double I_sur_arete_vertex = 0. ;
5557 int I_dans_fa7 = 0 ;
5558
5559 while (index >= 0 )
5560 {
5561 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5562 const int i_facette = data.numero_facette_;
5563
5564 // produit scalaire entre un vecteur directeur au rayon et la normale a la facette
5565 // le vecteur de reference est unitaire valant un sur la composante ori.
5566 // Si le produit scalaire est nul alors il n'existe pas de I dans la facette
5567 if( std::fabs( normale_facettes(i_facette,ori) ) > 0. )
5568 {
5569 DoubleTab A(dim), B(dim), C(dim), U(dim), I(dim);
5570 A = 0. ;
5571 B = 0. ;
5572 C = 0. ;
5573 U = 0. ;
5574 I = 0. ;
5575 for(int i = 0 ; i<dim ; i++)
5576 {
5577 I(i) = xe(i) ;
5578 }
5579 I(ori) = 0. ;
5580 for(int i=0 ; i<dim ; i++)
5581 {
5582 U(i) = normale_facettes(i_facette,i) ;
5583 A(i) = sommets(facettes(i_facette, 0),i) ;
5584 B(i) = sommets(facettes(i_facette, 1),i) ;
5585 if( dim == 3 )
5586 C(i) = sommets(facettes(i_facette, 2),i) ;
5587 }
5588
5589 for( int i =0 ; i<dim ; i++)
5590 {
5591 if( i!=ori )
5592 I(ori) += (A(i) - I(i))*U(i)/U(ori) ;
5593 }
5594 I(ori) += A(ori) ;
5595
5596
5597 double FIscalU = (I(ori)-xe(ori))*U(ori) ;
5598 double FI = std::fabs( I(ori)-xe(ori) ) ;
5599 double theta = acos(FIscalU/FI) ;
5600 double theta_rel = std::fabs( theta - (2.0*atan(1.)) ) / (2.0*atan(1.)) ;
5601 double ecart_elem = std::fabs(xe(ori)-I(ori)) ;
5602
5603 if( theta_rel >= tol_theta && ecart_elem <= 0.5*dx )
5604 {
5605 if( dim == 2 )
5606 {
5607 double AIscalAB = (I(0)-A(0))*(B(0)-A(0)) + (I(1)-A(1))*(B(1)-A(1)) ;
5608 double ABscalAB = (B(0)-A(0))*(B(0)-A(0)) + (B(1)-A(1))*(B(1)-A(1)) ;
5609 double xx = AIscalAB / ABscalAB ;
5610
5611 const int test1 = ( std::fabs( xx ) <= precision ) ;
5612 const int test2 = ( std::fabs( xx - 1. ) <= precision ) ;
5613 const int test3 = ( xx > precision ) ;
5614 const int test4 = ( xx < 1.-precision ) ;
5615 if( test1 || test2 )
5616 {
5617 // si I est dans un voisinage d'un vertex
5618 I_sur_arete_vertex += 1./2. ;
5619 }
5620 else if( test3 && test4 )
5621 {
5622 // I est a l'interieur du triangle
5623 I_dans_fa7++;
5624 }
5625 }
5626 else if( dim == 3 )
5627 {
5628 DoubleTab ABvectAC(dim) ;
5629 ABvectAC(0) = (B(1)-A(1))*(C(2)-A(2))-(B(2)-A(2))*(C(1)-A(1)) ;
5630 ABvectAC(1) = (B(2)-A(2))*(C(0)-A(0))-(B(0)-A(0))*(C(2)-A(2)) ;
5631 ABvectAC(2) = (B(0)-A(0))*(C(1)-A(1))-(B(1)-A(1))*(C(0)-A(0)) ;
5632 double ABvectACscalU = ABvectAC(0)*U(0) + ABvectAC(1)*U(1) + ABvectAC(2)*U(2) ;
5633 double AireABC = ABvectACscalU / 2. ;
5634
5635 DoubleTab IBvectIC(dim) ;
5636 IBvectIC(0) = (B(1)-I(1))*(C(2)-I(2))-(B(2)-I(2))*(C(1)-I(1)) ;
5637 IBvectIC(1) = (B(2)-I(2))*(C(0)-I(0))-(B(0)-I(0))*(C(2)-I(2)) ;
5638 IBvectIC(2) = (B(0)-I(0))*(C(1)-I(1))-(B(1)-I(1))*(C(0)-I(0)) ;
5639 double IBvectICscalU = IBvectIC(0)*U(0) + IBvectIC(1)*U(1) + IBvectIC(2)*U(2) ;
5640 double AireIBC = IBvectICscalU / 2. ;
5641
5642 DoubleTab ICvectIA(dim) ;
5643 ICvectIA(0) = (C(1)-I(1))*(A(2)-I(2))-(C(2)-I(2))*(A(1)-I(1)) ;
5644 ICvectIA(1) = (C(2)-I(2))*(A(0)-I(0))-(C(0)-I(0))*(A(2)-I(2)) ;
5645 ICvectIA(2) = (C(0)-I(0))*(A(1)-I(1))-(C(1)-I(1))*(A(0)-I(0)) ;
5646 double ICvectIAscalU = ICvectIA(0)*U(0) + ICvectIA(1)*U(1) + ICvectIA(2)*U(2) ;
5647 double AireICA = ICvectIAscalU / 2. ;
5648
5649 DoubleTab IAvectIB(dim) ;
5650 IAvectIB(0) = (A(1)-I(1))*(B(2)-I(2))-(A(2)-I(2))*(B(1)-I(1)) ;
5651 IAvectIB(1) = (A(2)-I(2))*(B(0)-I(0))-(A(0)-I(0))*(B(2)-I(2)) ;
5652 IAvectIB(2) = (A(0)-I(0))*(B(1)-I(1))-(A(1)-I(1))*(B(0)-I(0)) ;
5653 double IAvectIBscalU = IAvectIB(0)*U(0) + IAvectIB(1)*U(1) + IAvectIB(2)*U(2) ;
5654 double AireIAB = IAvectIBscalU / 2. ;
5655
5656 double alpha = AireIBC/AireABC ;
5657 double beta = AireICA/AireABC ;
5658 double gamma = AireIAB/AireABC ;
5659
5660 int test1 = ( std::fabs(alpha-1.)<=precision && std::fabs(beta)<=precision && std::fabs(gamma)<=precision ) ;
5661 int test2 = ( std::fabs(beta-1.)<=precision && std::fabs(alpha)<=precision && std::fabs(gamma)<=precision ) ;
5662 int test3 = ( std::fabs(gamma-1.)<=precision && std::fabs(alpha)<=precision && std::fabs(beta)<=precision ) ;
5663 int test4 = ( std::fabs(alpha)<=precision && precision<beta && beta<1.-precision && precision<gamma && gamma<1.-precision ) ;
5664 int test5 = ( std::fabs(beta)<=precision && precision<alpha && alpha<1.-precision && precision<gamma && gamma<1.-precision ) ;
5665 int test6 = ( std::fabs(gamma)<=precision && precision<beta && beta<1.-precision && precision<alpha && alpha<1.-precision ) ;
5666 int test7 = ( precision<alpha && alpha<1.-precision) ;
5667 int test8 = ( precision<beta && beta<1.-precision) ;
5668 int test9 = ( precision<gamma && gamma<1.-precision) ;
5669
5670 if( test1 || test2 || test3 )
5671 {
5672 // si I est dans un voisinage d'un vertex
5673 // Dans ce cas, une "infinite" (nombre max de facette dans elem) de facettes peuvent etre concernee.
5674 I_sur_arete_vertex += 1e-5 ;
5675 }
5676 else if( test4 || test5 || test6 )
5677 {
5678 // si I est dans un voisinage d'une arete sans etre un vertex
5679 I_sur_arete_fa7 += 1./2. ;
5680 }
5681 else if( test7 && test8 && test9 )
5682 {
5683 // I est a l'interieur
5684 I_dans_fa7++;
5685 }
5686 }
5687 else
5688 {
5689 Cerr << " attention seules les dimension 2 et 3 sont traitees "<<finl ;
5690 Process::exit() ;
5691 }
5692 }
5693 }
5694 // Iteration des facettes de l'element
5695 index = data.index_facette_suivante_;
5696 }
5697 traverse = int(ceil(I_sur_arete_vertex)) + int(ceil(I_sur_arete_fa7)) + I_dans_fa7 ;
5698}
5699
5700// Methode listant les elements contenant un nombre de facettes superieur a
5701// nb_fa7_accepeted et l'ensemble des facettes associees.
5702void Transport_Interfaces_FT_Disc::calcul_OutElemFa7( Maillage_FT_Disc& maillage, const DoubleTab& indicatrice,
5703 const int nb_elem, int& nb_fa7_accepted,
5704 IntList& OutElem, IntList& OutFa7 )
5705{
5706 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5707 const ArrOfInt& index_elem = intersection.index_elem() ;
5708 // Calcul de la surface des facettes contenues dans i_elem
5709 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
5710
5711 // Parcourt de l'ensemble des elements reels
5712 for (int i_elem = 0; i_elem < nb_elem ; i_elem++)
5713 {
5714 // Test si l'element est traverse par une IBC
5715 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
5716 {
5717 int index = index_elem[i_elem] ;
5718 // Listes contenant la surface des facettes et le numero de la facette
5719 // Les 'nb_fa7_accepted' facettes de plus grande surface sont
5720 // considerees ici comme etant les plus representatives.
5721 DoubleList E ;
5722 IntList F ;
5723
5724 // Parcours des facettes traversant l'element i_elem
5725 while (index >= 0 )
5726 {
5727 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5728 const int i_facette = data.numero_facette_;
5729
5730 // Stokage de la surface de la facette i_facette dans la liste E
5731 E.add(surfaces[i_facette]) ;
5732 // Stokage du numero de la facette dans la liste F
5733 F.add(i_facette) ;
5734 index = data.index_facette_suivante_;
5735 }
5736
5737 // Si le nombre de facette est superieur a nb_fa7_accepted
5738 // alors on choisit les facettes les plus representatives.
5739 // Ici, representative := de plus grande surface
5740 if( F.size() > nb_fa7_accepted )
5741 {
5742 // Stockage de l'element i_elem dans la liste OutElem
5743 OutElem.add_if_not( i_elem ) ;
5744 // Liste des facettes stockees dans i_elem
5745 IntList Fa7Elem ;
5746
5747 // Listing des facettes de plus grande surface
5748 int i = 0 ;
5749 while( i<nb_fa7_accepted )
5750 {
5751 // Recherche de la surface max
5752 double max_data = -1e30 ;
5753 int l=0 ;
5754 int ll = 0 ;
5755 while( l<E.size() )
5756 {
5757 if( E[l]>max_data && !Fa7Elem.contient(F[l]) )
5758 {
5759 max_data = E[l] ;
5760 ll = l ;
5761 }
5762 l++ ;
5763 }
5764 // Ajout de la facette de plus grande surface dans
5765 // la liste OutFa7
5766 Fa7Elem.add( F[ll] ) ;
5767 OutFa7.add( F[ll] ) ;
5768 i++ ;
5769 }
5770 }
5771 }
5772 }
5773}
5774
5775// Calcul du vertex le plus proche pour les faces diphasiques ( etape 1 )
5776void Transport_Interfaces_FT_Disc::PPP_face_interface( Maillage_FT_Disc& maillage, const DoubleTab& indicatrice,
5777 const DoubleTab& indicatrice_face, DoubleTab& Vertex )
5778
5779{
5780 const int dim = Objet_U::dimension;
5781 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5782 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5783 const IntTab& faces_elem = domaine_vf.face_voisins();
5784 const int nb_elem = domaine_vf.nb_elem() ;
5785 const int nfaces = faces_elem.dimension(0) ;
5786 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5787 const ArrOfInt& index_elem = intersection.index_elem() ;
5788 const IntTab& facettes = maillage.facettes() ;
5789 const DoubleTabFT& sommets = maillage.sommets() ;
5790 const DoubleTab& xv = domaine_vf.xv();
5791 DoubleTab coord(dim) ;
5792 coord = 0. ;
5793
5794 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5795 {
5796 // Distance face facette
5797 double dist_fa7 = 1e+30 ;
5798 int ppp_calcule = 0 ;
5799
5800 // Parcourt des faces diphasiques
5801 if( indicatrice_face(i_face) == 0.5 )
5802 {
5803 int voisin = -1 ;
5804 if( faces_elem(i_face,0) > -1 )
5805 voisin = faces_elem(i_face,0) ;
5806 else
5807 voisin = faces_elem(i_face,1) ;
5808
5809 // Dans ce cas, i_face coincide avec les facettes
5810 // Le point le plus proche est lui-meme
5811 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
5812 {
5813 for( int j=0; j<dim; j++)
5814 {
5815 Vertex(i_face,j) = xv(i_face,j) ;
5816 }
5817 ppp_calcule = 1 ;
5818 }
5819 }
5820
5821 if (indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && ppp_calcule == 0 )
5822 {
5823 // Parcourt des elements voisins traverses physiques
5824 for(int i=0 ; i<2; i++)
5825 {
5826 const int elem_voisin = faces_elem(i_face,i) ;
5827
5828 if( elem_voisin<nb_elem && elem_voisin>-1 && indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
5829 {
5830 int index = index_elem[elem_voisin] ;
5831 // Parcourt des facettes de l'element
5832 while (index >= 0 )
5833 {
5834 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5835 const int i_facette = data.numero_facette_;
5836 // Distance min par elements
5837 double dist_min = 1e+30 ;
5838 // Parcourt des sommets des facettes
5839 for( int som=0; som<facettes.dimension(1); som++)
5840 {
5841 // Distance face sommet
5842 double dist_som = 0. ;
5843 for( int j=0; j<dim; j++)
5844 {
5845 // j-ieme coordonnees du sommets som
5846 double sj = sommets(facettes(i_facette, som), j) ;
5847 // j-ieme coordonnees du barycentre de la face
5848 double xj = xv(i_face, j) ;
5849 // Carre de la distance face sommet som
5850 dist_som += (xj - sj)*(xj - sj) ;
5851 }
5852 // Distance face sommet som
5853 dist_som = sqrt(dist_som) ;
5854
5855 // Distance face facette par rapport a distance face sommet de facette
5856 if( dist_som < dist_min )
5857 {
5858 dist_min = dist_som ;
5859 for( int j=0; j<dim; j++)
5860 {
5861 coord(j) = sommets(facettes(i_facette, som), j) ;
5862 }
5863 }
5864 }
5865 // Distance face sommet minimale par rapport a distance face facette
5866 if( dist_min < dist_fa7 )
5867 {
5868 dist_fa7 = dist_min ;
5869 for( int j=0; j<dim; j++)
5870 {
5871 Vertex(i_face,j) = coord(j) ;
5872 }
5873 }
5874 // Ieration des facettes de l'element
5875 index = data.index_facette_suivante_;
5876 }
5877 }
5878 }
5879 }
5880 }
5881}
5882
5883// Calcul du vertex le plus proche des faces diphasiques (etape 2)
5884void Transport_Interfaces_FT_Disc::PPP_face_interface_voisin( const DoubleTab& indicatrice, const DoubleTab& indicatrice_face,
5885 DoubleTab& Vertex, DoubleTab& PPP )
5886
5887{
5888 const int dim = Objet_U::dimension;
5889 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5890 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5891 const IntTab& faces_elem = domaine_vf.face_voisins();
5892 const IntTab& elem_faces = domaine_vf.elem_faces();
5893 const int nfaces = faces_elem.dimension(0) ;
5894 const DoubleTab& xv = domaine_vf.xv();
5895
5896 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5897 {
5898 double d = 0. ;
5899 double dmin = 0. ;
5900 int ppp_calcule = 0 ;
5901
5902 // Parcourt des faces diphasiques
5903 if( indicatrice_face(i_face) == 0.5 )
5904 {
5905 int voisin = -1 ;
5906 if( faces_elem(i_face,0) > -1 )
5907 voisin = faces_elem(i_face,0) ;
5908 else
5909 voisin = faces_elem(i_face,1) ;
5910
5911 // Dans ce cas, i_face coincide avec les facettes
5912 // Le point le plus proche est lui-meme
5913 // On ne modifie pas Vertex
5914 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
5915 {
5916 for( int j=0; j<dim; j++)
5917 {
5918 PPP(i_face,j) = xv(i_face,j) ;
5919 }
5920 ppp_calcule = 1 ;
5921 }
5922 }
5923
5924 if (indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && ppp_calcule == 0 )
5925 {
5926 for( int i=0 ; i<dim ; i++)
5927 {
5928 d += (Vertex(i_face,i)-xv(i_face,i))*(Vertex(i_face,i)-xv(i_face,i)) ;
5929 }
5930 d = sqrt(d) ;
5931 dmin = d ;
5932 for( int k=0 ; k<dim ; k++)
5933 {
5934 PPP(i_face,k) = Vertex(i_face,k) ;
5935 }
5936 // On parcourt les autres faces de mes deux voisins
5937 // On compare le PPP de i_face avec ceux des autres faces.
5938 // Parmi eux, on choisit le plus proche de i_face.
5939 for( int i=0; i<2; i++ )
5940 {
5941 const int elem = faces_elem(i_face,i) ;
5942 // Si cet element voisin existe
5943 if( elem >-1 )
5944 {
5945 // alors on parcourt ses autres faces
5946 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
5947 {
5948 const int autre_face = elem_faces(elem,face_loc) ;
5949 if (indicatrice_face(autre_face) != 0. && (indicatrice_face(autre_face) != 1.
5950 || (indicatrice_face(autre_face) == 1. && d<0.))) //YG: si indicatrice modifiee
5951 {
5952 double dd = 0. ;
5953 for( int j=0 ; j<dim ; j++)
5954 {
5955 dd += (Vertex(autre_face,j)-xv(i_face,j))*(Vertex(autre_face,j)-xv(i_face,j)) ;
5956 }
5957 dd = sqrt(dd) ;
5958 if( dd <= dmin )
5959 {
5960 dmin = dd ;
5961 for( int k=0 ; k<dim ; k++)
5962 {
5963 PPP(i_face,k) = Vertex(autre_face,k) ;
5964 }
5965 }
5966 }
5967 }
5968 }
5969 }
5970 }
5971 }
5972}
5973
5974// Calcul du vertex le plus proche des faces fluides
5975void Transport_Interfaces_FT_Disc::PPP_face_voisin( const DoubleTab& indicatrice, const DoubleTab& indicatrice_face, DoubleTab& PPP )
5976
5977{
5978 const int dim = Objet_U::dimension;
5979 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5980 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5981 const IntTab& faces_elem = domaine_vf.face_voisins();
5982 const IntTab& elem_faces = domaine_vf.elem_faces();
5983 const int nfaces = faces_elem.dimension(0) ;
5984 const DoubleTab& xv = domaine_vf.xv();
5985
5986 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5987 {
5988 // Distance min entre la face et sommet le plus proche
5989 double dmin = 1.e30 ;
5990
5991 if (indicatrice_face(i_face) == 0. || indicatrice_face(i_face) == 1.)
5992 {
5993 // On parcourt les autres faces de mes deux voisins
5994 // On compare le PPP de i_face avec ceux des autres faces.
5995 // Parmi eux, on choisit le plus proche de i_face.
5996 for( int ii=0; ii<2; ii++ )
5997 {
5998 const int elem = faces_elem(i_face,ii) ;
5999 // Si cet element voisin existe
6000 if( elem >-1 )
6001 {
6002 // alors on parcourt ses autres faces
6003 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
6004 {
6005 const int face = elem_faces(elem,face_loc) ;
6006
6007 if (indicatrice_face(face) != 0. && indicatrice_face(face) != 1.)
6008 {
6009 // on identifie les elements auxquels appartient autre_face
6010 for(int i=0 ; i<2; i++)
6011 {
6012 const int elem_voisin = faces_elem(face,i) ;
6013
6014 // On veut que l'element existe, qu'il soit lui-meme
6015 // traverse par une interface
6016 if( elem_voisin>-1 && indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
6017 {
6018 // alors on parcourt ses autres faces
6019 for (int autre_face_loc=0 ; autre_face_loc<2*dim ; autre_face_loc++)
6020 {
6021 const int autre_face = elem_faces(elem_voisin,autre_face_loc) ;
6022 double dd = 0. ;
6023 for( int j=0 ; j<dim ; j++)
6024 {
6025 dd += (PPP(autre_face,j)-xv(i_face,j))*(PPP(autre_face,j)-xv(i_face,j)) ;
6026 }
6027 dd = sqrt(dd) ;
6028 if( dd <= dmin )
6029 {
6030 dmin = dd ;
6031 for( int k=0 ; k<dim ; k++)
6032 {
6033 PPP(i_face,k) = PPP(autre_face,k) ;
6034 }
6035 }
6036 }
6037 }
6038 }
6039 }
6040 }
6041 }
6042 }
6043 }
6044 }
6045}
6046
6047// Calcul du nombre max de facettes du maillage Lagrangien par element.
6049 const DoubleTab& indicatrice,
6050 const int nb_elem, int& max_fa7,
6051 const int exec_planfa7existant)
6052{
6053 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
6054 const ArrOfInt& index_elem = intersection.index_elem() ;
6055 max_fa7 = -1 ;
6056
6057 // Parcourt des elements reels
6058 for (int i_elem = 0; i_elem < nb_elem ; i_elem++)
6059 {
6060 // Test si l'element est traverse par une IBC
6061 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
6062 {
6063 int index = index_elem[i_elem] ;
6064 int cpt = 0 ;
6065 // Liste des parametres du plan de la facette i_facette
6066 DoubleList A, B, C, D ;
6067
6068 // Pour un element, on parcourt les facettes qui le traversent
6069 while (index >= 0 )
6070 {
6071 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
6072 const int i_facette = data.numero_facette_;
6073
6074 int test_liste = 0 ; // test_liste vaut 1 si le plan de i_facette existe
6075 // Calcul des parametres du plan de la facette
6076 // (sauf pour la premiere car les listes sont vides )
6077 if( !(A.est_vide()) && exec_planfa7existant == 1 )
6078 plan_facette_existant( maillage, A, B, C, D, i_facette, test_liste ) ;
6079
6080 // Test si i_facette est la premiere facette parcourue
6081 // ou si le plan qui la traverse n'existe pas encore
6082 if( test_liste==0 )
6083 {
6084 if( exec_planfa7existant == 1 )
6085 {
6086 double aa=0., bb=0., cc=0., dd=0. ;
6087 calcul_eq_plan_facette( i_facette, aa, bb, cc, dd ) ;
6088 // Stokage des parametres du plan de la facette.
6089 // Listes utilisees dans plan_facette_existant
6090 A.add(aa) ;
6091 B.add(bb) ;
6092 C.add(cc) ;
6093 D.add(dd) ;
6094 }
6095 cpt++ ;
6096 }
6097
6098 index = data.index_facette_suivante_;
6099 }
6100 // Calcul du nombre max de facettes retenues par element
6101 if( cpt > max_fa7 )
6102 max_fa7 = cpt ;
6103 }
6104 }
6105}
6106
6107// Renumerotation des facettes virtuelles
6108void Transport_Interfaces_FT_Disc::RenumFa7( DoubleTab& Barycentre, DoubleTab& Tab110,
6109 DoubleTab& Tab111, DoubleTab& Tab112,
6110 IntTab& Tab12, IntTab& CptFacette,
6111 const int nb_facettes,
6112 const int nb_facettes_dim )
6113{
6114 //double eps = 1e-20 ;
6115 const double eps = Objet_U::precision_geom ;
6116
6117 int nn = Tab110.dimension(0) ;
6118 int nn_tot = Tab110.dimension_tot(0) ;
6119 for (int i_elem = nn; i_elem < nn_tot ; i_elem++)
6120 {
6121
6122 for( int cpt=0 ; cpt < CptFacette(i_elem) ; cpt++ )
6123 {
6124 int bary_trouve = 0 ;
6125 int ii = 0 ;
6126 while( ii < nb_facettes && bary_trouve==0 )
6127 {
6128 bool test_0 = (Barycentre(ii,0)-Tab110(i_elem,cpt))*(Barycentre(ii,0)-Tab110(i_elem,cpt))<eps ;
6129 bool test_1 = (Barycentre(ii,1)-Tab111(i_elem,cpt))*(Barycentre(ii,1)-Tab111(i_elem,cpt))<eps ;
6130 bool test_2 = (Barycentre(ii,2)-Tab112(i_elem,cpt))*(Barycentre(ii,2)-Tab112(i_elem,cpt))<eps ;
6131
6132 if( test_0 && test_1 && test_2 )
6133 {
6134 bary_trouve = 1 ;
6135 Tab12( i_elem, cpt ) = ii ;
6136 }
6137 ii++ ;
6138 }
6139 if( bary_trouve==0 && ii==nb_facettes )
6140 {
6141
6142 // On renumerote localement ssi le numero de la facette virtuelle
6143 // existe dans la numerotation des facettes reelles.
6144 if( Tab12( i_elem, cpt ) < nb_facettes )
6145 Tab12( i_elem, cpt )+=nb_facettes_dim ;
6146 }
6147 }
6148 }
6149}
6150
6152 IntTab& CptFacette, DoubleTab& Tab100,
6153 DoubleTab& Tab101, DoubleTab& Tab102,
6154 DoubleTab& Tab103, DoubleTab& Tab110,
6155 DoubleTab& Tab111, DoubleTab& Tab112,
6156 IntTab& Tab12, DoubleTab& Barycentre,
6157 const DoubleTab& indicatrice,
6158 IntList& OutElem, ArrOfBit& fa7,
6159 const int exec_planfa7existant )
6160{
6161 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
6162 const ArrOfInt& index_elem = intersection.index_elem() ;
6163 int nn = Tab100.dimension(0) ;
6164 int nn_tot = Tab100.dimension_tot(0) ;
6165
6166 // Matrice de booleen evitant de calculer deux fois le meme barycentre
6167 fa7=0;
6168 for (int i_elem = 0; i_elem < nn ; i_elem++)
6169 {
6170 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. && !OutElem.contient(i_elem) )
6171 {
6172
6173 int index = index_elem[i_elem] ;
6174 CptFacette(i_elem) = 0 ;
6175 int cpt = 0 ;
6176 // Les listes sont vides pour la premieres facettes de chaque element
6177 DoubleList A, B, C, D ;
6178 while (index >= 0 )
6179 {
6180 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
6181 const int i_facette = data.numero_facette_;
6182
6183
6184 int test_liste = 0 ; // si test_liste=1 le plan de i_facette existe
6185 if( !(A.est_vide()) && exec_planfa7existant == 1 )
6186 plan_facette_existant( maillage, A, B, C, D, i_facette, test_liste ) ;
6187
6188 // Test si i_facette est la premiere facette parcourue
6189 // ou si le plan qui la traverse n'existe pas encore
6190 if( test_liste==0 )
6191 {
6192 // Calcul des parametres du plan de la facette
6193 calcul_eq_plan_facette(maillage,i_facette,Tab100(i_elem,cpt),Tab101(i_elem,cpt),
6194 Tab102(i_elem,cpt),Tab103(i_elem,cpt)) ;
6195 if( exec_planfa7existant == 1 )
6196 {
6197 A.add(Tab100(i_elem,cpt)) ;
6198 B.add(Tab101(i_elem,cpt)) ;
6199 C.add(Tab102(i_elem,cpt)) ;
6200 D.add(Tab103(i_elem,cpt)) ;
6201 }
6202 Tab12(i_elem,cpt) = i_facette ;
6203
6204 // Calcul de l'octree de la facette ( seulement en parallele )
6205 if( nn < nn_tot )
6206 {
6207 // Calcul des coordonnees barycentriques de i_facette
6208 if( !fa7.testsetbit(i_facette) )
6209 {
6210 BaryFa7(maillage,i_facette,Barycentre) ;
6211 }
6212 // Stokage des coordonnees barycentriques de i_facette
6213 Tab110(i_elem,cpt) = Barycentre(i_facette,0) ;
6214 Tab111(i_elem,cpt) = Barycentre(i_facette,1) ;
6215 Tab112(i_elem,cpt) = Barycentre(i_facette,2) ;
6216 }
6217 cpt++ ;
6218 }
6219 index = data.index_facette_suivante_;
6220 }
6221 // Nombre de facettes dans l'element
6222 CptFacette(i_elem) = cpt ;
6223 if( cpt > Tab12.line_size() )
6224 {
6225 Cerr<<"Attention, seulement "<< cpt << " facettes ont ete stokees "<< finl ;
6226 Cerr<<"dans l'element "<< i_elem << " qui en contient plus."<< finl ;
6227 Cerr<<"Regarder la finesse du maillage Lagrangien par rapport au maillage Eulerien" <<finl ;
6228 Process::exit() ;
6229 }
6230 }
6231 }
6232}
6233
6235 DoubleTab& Tab101, DoubleTab& Tab102, DoubleTab& Tab103,
6236 DoubleTab& Tab110,DoubleTab& Tab111, DoubleTab& Tab112,
6237 IntTab& Tab12, DoubleTab& Barycentre, IntList& OutElem,
6238 IntTab& TabOutFa7, ArrOfBit& fa7 )
6239{
6240 int cpt_elem = 0 ;
6241 int nn = Tab100.dimension(0) ;
6242 int nn_tot = Tab100.dimension_tot(0) ;
6243 while( cpt_elem < OutElem.size() )
6244 {
6245 for( int k=0 ; k<TabOutFa7.line_size() ; k++ )
6246 {
6247 const int i_facette = TabOutFa7(cpt_elem,k) ;
6248 calcul_eq_plan_facette(maillage,i_facette,Tab100( OutElem[cpt_elem],k),
6249 Tab101(OutElem[cpt_elem],k),Tab102(OutElem[cpt_elem],k),
6250 Tab103(OutElem[cpt_elem],k)) ;
6251 Tab12(OutElem[cpt_elem],k) = i_facette ;
6252
6253 // Calcul de l'octree de la facette ( seulement en parallele )
6254 if( nn < nn_tot )
6255 {
6256 // Calcul des coordonnees barycentriques de i_facette
6257 if( !fa7.testsetbit(i_facette) )
6258 {
6259 BaryFa7(maillage,i_facette,Barycentre) ;
6260 }
6261 // Stokage des coordonnees barycentriques de i_facette
6262 Tab110(OutElem[cpt_elem],k) = Barycentre(i_facette,0) ;
6263 Tab111(OutElem[cpt_elem],k) = Barycentre(i_facette,1) ;
6264 Tab112(OutElem[cpt_elem],k) = Barycentre(i_facette,2) ;
6265 }
6266 }
6267 cpt_elem++ ;
6268 }
6269}
6270
6271// Calcul des coordonees barycentriques des facettes
6272void Transport_Interfaces_FT_Disc::BaryFa7( Maillage_FT_Disc& maillage, const int i_facette, DoubleTab& Bary )
6273{
6274 const DoubleTabFT& sommets = maillage.sommets() ;
6275 const IntTab& facettes = maillage.facettes() ;
6276 const int dim = Objet_U::dimension ;
6277 IntTab Som( facettes.line_size() ) ;
6278 DoubleTab CoordSom( facettes.line_size(), dim ) ;
6279
6280 // Calcul des coordonnees de chaque sommets
6281 for ( int i=0 ; i<facettes.line_size() ; i ++ )
6282 {
6283 Bary(i_facette,i) = 0. ;
6284 Som(i) = facettes(i_facette, i) ;
6285 for ( int j = 0 ; j < dim ; j++ )
6286 {
6287 CoordSom(i,j) = sommets(Som(i),j) ;
6288 }
6289 }
6290 // Calcul des coordonees barycentriques
6291 for ( int k = 0 ; k< dim ; k++ )
6292 {
6293 for( int l = 0 ; l< facettes.line_size() ; l++ )
6294 {
6295 Bary(i_facette,k) += CoordSom(l,k) / double(facettes.line_size()) ;
6296 }
6297 }
6298 if( dim == 2 )
6299 Bary(i_facette,2) = 0. ;
6300}
6301
6302// Methode determinant si le plan passant par la facette i_facette existe
6304 DoubleList B,DoubleList C,DoubleList D,
6305 const int i_facette,int& test_liste )
6306{
6307 assert( A.size() == B.size() ) ;
6308 assert( A.size() == C.size() ) ;
6309 assert( A.size() == D.size() ) ;
6310 const DoubleTabFT& sommets = maillage.sommets() ;
6311 const IntTab& facettes = maillage.facettes() ;
6312 double x1, y1, z1 = 0. ;
6313 double x2, y2, z2 = 0. ;
6314 double x3 = 0., y3 = 0., z3 = 0. ;
6315 double plan3 = 0. ;
6316 const int s1 = facettes(i_facette, 0) ;
6317 x1 = sommets(s1,0) ;
6318 y1 = sommets(s1,1) ;
6319 const int s2 = facettes(i_facette, 1) ;
6320 x2 = sommets(s2,0) ;
6321 y2 = sommets(s2,1) ;
6322 double eps = 1e-20 ;
6323
6324 // const double eps = Objet_U::precision_geom ;
6325
6326 if (Objet_U::dimension == 3)
6327 {
6328 z1 = sommets(s1,2) ;
6329 z2 = sommets(s2,2) ;
6330 const int s3 = facettes(i_facette, 2) ;
6331 x3 = sommets(s3,0) ;
6332 y3 = sommets(s3,1) ;
6333 z3 = sommets(s3,2) ;
6334 }
6335
6336 int i=0 ;
6337 while( i< A.size() && test_liste==0 )
6338 {
6339 double plan1 = D[i] + A[i] * x1 + B[i] * y1 + C[i] * z1 ;
6340 double plan2 = D[i] + A[i] * x2 + B[i] * y2 + C[i] * z2 ;
6341 if(Objet_U::dimension == 3)
6342 plan3 = D[i] + A[i] * x3 + B[i] * y3 + C[i] * z3 ;
6343
6344
6345 if( std::fabs(plan1)<eps && std::fabs(plan2)<eps && std::fabs(plan3)<eps )
6346 test_liste= 1 ;
6347 i++ ;
6348 }
6349}
6350
6351// Calcul des parametres du plan de la facette. Utile pour l'algorithme d'Uzawa.
6353 double& a,double& b,double& c,double& d )
6354{
6355 const DoubleTabFT& normale_facettes = maillage.get_update_normale_facettes() ;
6356 const DoubleTabFT& sommets = maillage.sommets() ;
6357 const IntTab& facettes = maillage.facettes() ;
6358
6359 c = 0. ;
6360 double x, y, z = 0. ;
6361 double inverse_norme = 0. ;
6362
6363 const int s1 = facettes(i_facette, 0) ;
6364
6365 a = normale_facettes(i_facette, 0) ;
6366 b = normale_facettes(i_facette, 1) ;
6367 x = sommets(s1,0) ;
6368 y = sommets(s1,1) ;
6369
6370 if (Objet_U::dimension == 3)
6371 {
6372 c = normale_facettes(i_facette, 2) ;
6373 z = sommets(s1,2) ;
6374 }
6375 inverse_norme = 1. / sqrt( a*a + b*b + c*c ) ;
6376
6377 a *= inverse_norme ;
6378 b *= inverse_norme ;
6379 c *= inverse_norme ;
6380 d = - (a * x + b * y + c * z) ;
6381}
6382
6383// Calcul des parametres du plan de la facette. Utile pour l'algorithme d'Uzawa.
6385 double& b,double& c,double& d )
6386{
6387 Maillage_FT_Disc& maillage = maillage_interface() ;
6388 const DoubleTabFT& normale_facettes = maillage.get_update_normale_facettes() ;
6389 const DoubleTabFT& sommets = maillage.sommets() ;
6390 const IntTab& facettes = maillage.facettes() ;
6391
6392 c = 0. ;
6393 double x, y, z = 0. ;
6394 double inverse_norme = 0. ;
6395
6396 const int s1 = facettes(i_facette, 0) ;
6397
6398 a = normale_facettes(i_facette, 0) ;
6399 b = normale_facettes(i_facette, 1) ;
6400 x = sommets(s1,0) ;
6401 y = sommets(s1,1) ;
6402
6403 if (Objet_U::dimension == 3)
6404 {
6405 c = normale_facettes(i_facette, 2) ;
6406 z = sommets(s1,2) ;
6407 }
6408 inverse_norme = 1. / sqrt( a*a + b*b + c*c ) ;
6409
6410 a *= inverse_norme ;
6411 b *= inverse_norme ;
6412 c *= inverse_norme ;
6413 d = - (a * x + b * y + c * z) ;
6414}
6415
6416void Transport_Interfaces_FT_Disc::calcul_tolerance_projete_diphasique( const int i_face, const int ori, const int voisin0,
6417 const int voisin1, const DoubleTab& indicatrice, double& tol )
6418{
6419 const int dim = Objet_U::dimension;
6420 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6421 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6422 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis) ;
6423 const IntTab& elem_faces = domaine_vf.elem_faces();
6424 int voisin = 0 ;
6425 DoubleTab L(dim) ;
6426 L = 0. ;
6427 tol = 0. ;
6428 if( voisin0 > -1 && indicatrice(voisin0) != 0. && indicatrice(voisin0) != 1. )
6429 {
6430 voisin = voisin0 ;
6431 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6432 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6433 }
6434 if( voisin1 > -1 && indicatrice(voisin1) != 0. && indicatrice(voisin1) != 1. )
6435 {
6436 voisin = voisin1 ;
6437 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) - i_face ;
6438 double xx = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6439 L(ori) = std::max( L(ori), xx ) ;
6440 }
6441
6442 for( int k = 0 ; k<dim ; k++ )
6443 {
6444 if( k != ori )
6445 {
6446 const int face0 = elem_faces(voisin,k) ;
6447 const int face1 = elem_faces(voisin,k+dim) ;
6448 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6449 }
6450 }
6451 for( int k = 0 ; k<dim ; k++ )
6452 {
6453 tol += L(k)*L(k) ;
6454 }
6455 tol = sqrt(tol) ;
6456}
6457
6458void Transport_Interfaces_FT_Disc::calcul_tolerance_projete_monophasique( const int i_face, const int ori, const int voisin0,
6459 const int voisin1, const DoubleTab& indicatrice_face,
6460 const DoubleTab& indicatrice, double& tol )
6461{
6462 const int dim = Objet_U::dimension ;
6463 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6464 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis) ;
6465 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis) ;
6466 const IntVect& orientation = domaine_vdf.orientation() ;
6467 const IntTab& elem_faces = domaine_vf.elem_faces() ;
6468 const IntTab& faces_elem = domaine_vf.face_voisins() ;
6469
6470 //------------------------------------------------------------------------------------------------
6471 //------------------------------------------------------------------------------------------------
6472 //------------------------------------------------------------------------------------------------
6473 // cas longitudinal
6474 DoubleTab L(dim) ;
6475 L = 0. ;
6476 double tol0 = 0. ;
6477 if( voisin0 > -1 )
6478 {
6479 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6480 if( indicatrice_face(face_voisine) != 0. && indicatrice_face(face_voisine) != 1. )
6481 {
6482 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6483
6484 const int voisin_voisin = faces_elem(face_voisine,0) + faces_elem(face_voisine,1) - voisin0 ;
6485 if( voisin_voisin > -1 )
6486 {
6487 const int face_voisine_voisine = elem_faces(voisin_voisin,ori) + elem_faces(voisin_voisin,ori+dim) - face_voisine ;
6488 L(ori) += std::fabs(domaine_vdf.distance_face(face_voisine,face_voisine_voisine,ori)) ;
6489 }
6490 for( int k = 0 ; k<dim ; k++ )
6491 {
6492 if( k != ori )
6493 {
6494 const int face0 = elem_faces(voisin0,k) ;
6495 const int face1 = elem_faces(voisin0,k+dim) ;
6496 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6497 }
6498 }
6499 for( int k = 0 ; k<dim ; k++ )
6500 {
6501 tol0 += L(k)*L(k) ;
6502 }
6503 tol0 = sqrt(tol0) ;
6504 }
6505 }
6506 double tol1 = 0. ;
6507 L = 0. ;
6508 if( voisin1 > -1 )
6509 {
6510 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) -i_face ;
6511 if( indicatrice_face(face_voisine) != 0. && indicatrice_face(face_voisine) != 1. )
6512 {
6513 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6514
6515 const int voisin_voisin = faces_elem(face_voisine,0) + faces_elem(face_voisine,1) - voisin1 ;
6516 if( voisin_voisin > -1 )
6517 {
6518 const int face_voisine_voisine = elem_faces(voisin_voisin,ori) + elem_faces(voisin_voisin,ori+dim) - face_voisine ;
6519 L(ori) += std::fabs(domaine_vdf.distance_face(face_voisine,face_voisine_voisine,ori)) ;
6520 }
6521 for( int k = 0 ; k<dim ; k++ )
6522 {
6523 if( k != ori )
6524 {
6525 const int face0 = elem_faces(voisin1,k) ;
6526 const int face1 = elem_faces(voisin1,k+dim) ;
6527 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6528 }
6529 }
6530 for( int k = 0 ; k<dim ; k++ )
6531 {
6532 tol1 += L(k)*L(k) ;
6533 }
6534 tol1 = sqrt(tol1) ;
6535 }
6536 }
6537 double tol_long = std::max(tol0,tol1) ;
6538
6539
6540 //------------------------------------------------------------------------------------------------
6541 //------------------------------------------------------------------------------------------------
6542 //------------------------------------------------------------------------------------------------
6543 // cas transverse
6544 L = 0. ;
6545 int voisin = 1 ;
6546 if( voisin0 > -1 )
6547 {
6548 voisin = voisin0 ;
6549 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6550 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6551 }
6552 if( voisin1 > -1 )
6553 {
6554 voisin = voisin1 ;
6555 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) - i_face ;
6556 double xx = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6557 L(ori) = std::max( L(ori), xx ) ;
6558 }
6559
6560 DoubleTab xx_max(dim) ;
6561 xx_max = 0. ;
6562 for (int i=0 ; i<2*dim ; i++)
6563 {
6564 const int autre_face = elem_faces(voisin,i) ;
6565 const int face_voisine = elem_faces(voisin,ori) + elem_faces(voisin,ori+dim) - i_face ;
6566
6567 if( autre_face != i_face && autre_face != face_voisine
6568 && indicatrice_face(autre_face) != 0. && indicatrice_face(autre_face) != 1. )
6569 {
6570 const int voisin_voisin = faces_elem(autre_face,0) + faces_elem(autre_face,1) - voisin ;
6571 const int ori_face = orientation[autre_face] ;
6572 const int autre_face_voisine = elem_faces(voisin_voisin,ori_face) + elem_faces(voisin_voisin,ori_face+dim) - autre_face ;
6573 double xx = std::fabs(domaine_vdf.distance_face(autre_face,autre_face_voisine,ori_face)) ;
6574 if( xx_max(ori_face) < xx )
6575 xx_max(ori_face) = xx ;
6576 }
6577 }
6578
6579 DoubleTab TOL_TMP(dim-1) ;
6580 TOL_TMP = 0. ;
6581 int cpt = 0 ;
6582 for(int k=0 ; k<dim ; k++)
6583 {
6584 if( k != ori )
6585 {
6586 for(int l=0 ; l<dim ; l++)
6587 {
6588 if( l != k && l != ori )
6589 {
6590 const int face0 = elem_faces(voisin,k) ;
6591 const int face1 = elem_faces(voisin,k+dim) ;
6592 double yy = 0.5*std::fabs(domaine_vdf.distance_face(face0,face1,k)) ;
6593 double a = 0.5*yy + xx_max(k) ;
6594 const int face3 = elem_faces(voisin,l) ;
6595 const int face4 = elem_faces(voisin,l+dim) ;
6596 double b = 0.5*std::fabs(domaine_vdf.distance_face(face3,face4,l)) ;
6597 TOL_TMP(cpt) = L(ori)*L(ori) + a*a + b*b ;
6598 cpt++ ;
6599 }
6600 }
6601 }
6602 }
6603 double tol_trans = TOL_TMP(0) ;
6604 if( dim == 3 )
6605 tol_trans = std::max(tol_trans,TOL_TMP(1)) ;
6606 tol_trans = sqrt( tol_trans ) ;
6607 //------------------------------------------------------------------------------------------------
6608 //------------------------------------------------------------------------------------------------
6609 //------------------------------------------------------------------------------------------------
6610 tol = std::max(tol_long,tol_trans) ;
6611}
6612
6613// Verification du projete
6614void Transport_Interfaces_FT_Disc::verifprojete( const int monophasique,const double Lref, double d, const DoubleTab& x,
6615 const DoubleTab& V, DoubleTab& coord_projete, int& cpt )
6616{
6617 const int dim = coord_projete.dimension(0) ;
6618 const double dist_IBC = std::fabs(d) ;
6619 const double precision = Objet_U::precision_geom ;
6620 double dist_proj = 0. ;
6621 int projete_modifie = 0 ;
6622 cpt = 0 ;
6623
6624 DoubleTab coord_projete_old(dim) ;
6625 coord_projete_old = coord_projete ;
6626
6627 for (int j = 0; j < dim ; j++)
6628 {
6629 dist_proj += (x(j) - coord_projete(j))*(x(j) - coord_projete(j)) ;
6630 }
6631 dist_proj = sqrt( dist_proj ) ;
6632 double dist_proj_old = dist_proj ;
6633
6634 const double facsec = 0.5 ;
6635 const int test0 = ( dist_proj < precision ) ;
6636 const int test1 = ( std::fabs( dist_IBC - dist_proj ) > facsec*dist_IBC ) ;
6637 const int test2 = ( dist_proj > (1.+facsec)*Lref ) ;
6638
6639 if( monophasique )
6640 {
6641 if( test0 || (test1 && test2) )
6642 {
6643 // on modifie le projete en prenant le vertex lagrangien le plus proche
6644 for (int j = 0; j < dim ; j++)
6645 {
6646 coord_projete(j) = V(j) ;
6647 }
6648 projete_modifie = 1 ;
6649 cpt++ ;
6650 }
6651 }
6652 else
6653 {
6654 const int test = ( dist_IBC >= (1.-facsec)*Lref ) ;
6655
6656 if( (test0 && test) || (test1 && test2) )
6657 {
6658 // on modifie le projete en prenant le vertex lagrangien le plus proche
6659 for (int j = 0; j < dim ; j++)
6660 {
6661 coord_projete(j) = V(j) ;
6662 }
6663 projete_modifie = 1 ;
6664 cpt++ ;
6665 }
6666 }
6667
6668 if( projete_modifie == 1 )
6669 {
6670 dist_proj = 0. ;
6671 for (int j = 0; j < dim ; j++)
6672 {
6673 dist_proj += (x(j) - coord_projete(j))*(x(j) - coord_projete(j)) ;
6674 }
6675 dist_proj = sqrt( dist_proj ) ;
6676
6677 Cerr << " ------------------------------------------------------- "<<finl;
6678 Cerr << " le projete "<<finl;
6679 for(int i=0; i<dim; i++)
6680 {
6681 Cerr <<" X("<<i<<") = "<<coord_projete_old(i)<<finl ;
6682 }
6683 Cerr << " situe a une distance "<<dist_proj_old<<" du barycentre de la face "<<finl ;
6684 for(int i=0; i<dim; i++)
6685 {
6686 Cerr <<" Y("<<i<<") = "<<x(i)<<finl ;
6687 }
6688 Cerr << " a ete modifie en "<<finl ;
6689 for(int i=0; i<dim; i++)
6690 {
6691 Cerr <<" X("<<i<<") = "<<coord_projete(i)<<finl ;
6692 }
6693 Cerr << "situe a une distance "<<dist_proj<<" du barycentre de face "<<finl ;
6694 Cerr << "distance a l'IBC : "<<dist_IBC<<finl ;
6695 Cerr << "Longueur de reference : "<<Lref<<finl ;
6696 Cerr << " ------------------------------------------------------- "<<finl;
6697 }
6698}
6699
6700// Algorithme d'Uzawa calculant les coordonnees du projete du centre de gravite
6701// d'une face 'i_face' sur l'interface.
6702void Transport_Interfaces_FT_Disc::uzawa(const double d, const DoubleTab& C,
6703 const DoubleTab& x, const DoubleTab& f,
6704 DoubleTab& x_ibc) const
6705{
6706 double rho = 0. ;
6707 const int nb_lignes = C.dimension(0) ;
6708 const int nb_colonnes = C.line_size() ;
6709 assert(x_ibc.dimension(0) == nb_colonnes) ;
6710 assert(f.dimension(0) == nb_lignes) ;
6711 assert(x.dimension(0) == nb_colonnes) ;
6712
6713 // Calcul du pas rho :
6714 // Definition et initialisation des normes induites ||.||_1 et||.||_inf
6715 double norme1 = 0. ;
6716 double norme_infty = 0. ;
6717
6718 for (int j=0; j<nb_colonnes; j++)
6719 {
6720 double norme1_int = 0. ;
6721 for (int i=0; i<nb_lignes; i++)
6722 {
6723 norme1_int += std::fabs( C(i,j) ) ;
6724 }
6725 norme1 = std::max( norme1 , norme1_int ) ;
6726 }
6727
6728 for (int i=0; i<nb_lignes; i++)
6729 {
6730 double norme_infty_int = 0.;
6731 for (int j=0; j<nb_colonnes; j++)
6732 {
6733 norme_infty_int += std::fabs( C(i,j) ) ;
6734 }
6735 norme_infty = std::max( norme_infty , norme_infty_int ) ;
6736 }
6737 rho = 1. / ( norme1 * norme_infty ) ; //car ||A||_2^2 <= ||A||_1 ||A||_infty
6738
6739 // Definition et initialisation d'un multiplicateur de Lagrange
6740 DoubleTab lambda(nb_lignes) ;
6741 lambda = 0. ;
6742
6743 double distance = 1. ;
6744 double distance_old = 0. ;
6745 double deplacement_relatif = 1.;
6746 int nb_iter = 0 ;
6747
6748 double err_uzawa = variables_internes_->seuil_uzawa ;
6749 int nb_iter_max = variables_internes_->nb_iter_uzawa ;
6750 // On arrete l'algorithme des que le carre de la distance (projete,origine)
6751 // a l'etape k moins le carre de la distance (projete,origine) a l'etape k-1
6752 // est inferieur en valeur absolue au seuil 'err_uzawa'.
6753 // Pour des raisons de temps CPU, l'algorithme s'arrete egalement si
6754 // le nombre d'iterations est superieur a 'nb_iter_max'.
6755 // En pratique, les valeurs par defaut sont 'err_uzawa=1e-8' et 'nb_iter_max=30'.
6756 // Dans certains cas, par exemple pour des maillages tres grossiers, il a ete
6757 // observe que ce choix conduit a quelques differences sequentiel/parallele.
6758 // On recommande alors de diminuer le seuil et d'augmenter le nombre
6759 // d'iteration pour ameliorer la convergence de l'algorithme, au risque d'augmenter
6760 // le temps CPU.
6761 x_ibc = 0. ;
6762 while( deplacement_relatif > err_uzawa && nb_iter <= nb_iter_max )
6763 {
6764 // Calcul de la solution a l'etape k
6765 x_ibc = 0. ;
6766 distance_old = distance ;
6767 for (int i=0; i<x_ibc.dimension(0); i++)
6768 {
6769 for (int j=0; j<lambda.dimension(0); j++)
6770 {
6771 x_ibc(i) -= 0.5 * C(j,i) * lambda(j) ;
6772 }
6773 x_ibc(i) += x[i] ;
6774 }
6775
6776 // Calcul du multiplicateur de lagrange a l'etape k+1
6777 for (int i=0; i<lambda.dimension(0); i++)
6778 {
6779 //Parametre xx = C*x_ibc-f
6780 double xx = 0. ;
6781
6782 for (int j=0; j<x_ibc.dimension(0); j++)
6783 {
6784 xx += C(i,j)*x_ibc(j) ;
6785 }
6786 xx -= f(i) ;
6787 if ( d > 0 )
6788 {
6789 // cote solide
6790 lambda(i) = std::max( lambda(i) + rho * xx , 0. ) ;
6791 }
6792 else
6793 {
6794 //cote fluide
6795 lambda(i) = std::min( lambda(i) + rho * xx , 0. ) ;
6796 }
6797 }
6798 // Calcul et mise a jour de la condition du while
6799 distance = ( x_ibc(0) - x[0] ) * ( x_ibc(0) - x[0] )
6800 + ( x_ibc(1) - x[1] ) * ( x_ibc(1) - x[1] ) ;
6801 if (Objet_U::dimension==3)
6802 distance += ( x_ibc(2) - x[2] ) * ( x_ibc(2) - x[2] ) ;
6803
6804 deplacement_relatif = std::fabs(distance - distance_old) ;
6805 nb_iter++ ;
6806
6807 }
6808
6809}
6810
6811void Transport_Interfaces_FT_Disc::projete_point_face_fluide( int& nb_proj_modif,const int dimfa7,
6812 const DoubleTab& indicatrice_face, const DoubleTab& indicatrice,
6813 const DoubleTab& dist_face,const double t,const double dt,
6814 DoubleTab& Tab100,DoubleTab& Tab101,DoubleTab& Tab102,DoubleTab& Tab103,
6815 IntTab& Tab12,IntTab& CptFacette,DoubleTab& v_imp,DoubleTab& Vertex,Parser& parser_x, Parser& parser_y, Parser& parser_z )
6816{
6817 const int dim = Objet_U::dimension;
6818 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6819 const Domaine_VDF * zvdf = 0;
6820 if (sub_type(Domaine_VDF, mon_dom_dis))
6821 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis) ;
6822 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
6823 const IntVect& orientation = domaine_vdf.orientation();
6824 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6825 const IntTab& elem_faces = domaine_vf.elem_faces();
6826 const IntTab& faces_elem = domaine_vf.face_voisins();
6827 const int nfaces = faces_elem.dimension(0) ;
6828 const DoubleTab& xv = domaine_vf.xv();
6829 const double invalid_test = -1.e30;
6830
6831 Cerr << "CALCUL DU PROJETE POUR LES FACES FLUIDE ET d > invalid_test" << finl ;
6832
6833 for (int i_face = 0; i_face < nfaces; i_face++)
6834 {
6835 double d = dist_face(i_face) ;
6836 if (indicatrice_face(i_face) == 0. && d > invalid_test)
6837 {
6838 DoubleList mat_0, mat_1, mat_2, mat_3 ;
6839 ArrOfBit fa7(dimfa7);
6840 fa7=0;
6841 int nb_facettes_to_uzawa = 0 ;
6842 // On travaille sur les elements voisins de chaque face 'i_face'
6843 for( int ii=0; ii<2; ii++ )
6844 {
6845 const int elem = faces_elem(i_face,ii) ;
6846 // Si cet element voisin existe
6847 if( elem >-1 )
6848 {
6849 // alors on parcourt ses autres faces
6850 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
6851 {
6852 const int autre_face = elem_faces(elem,face_loc) ;
6853
6854 if (indicatrice_face(autre_face) != 0. && indicatrice_face(autre_face) != 1.)
6855 {
6856 // on identifie les elements auxquels appartient autre_face
6857 // et qui sont traverses par l'interface
6858 for(int ii2=0 ; ii2<2; ii2++)
6859 {
6860 const int elem_voisin = faces_elem(autre_face,ii2) ;
6861
6862 // On veut que l'element existe, qu'il soit lui-meme
6863 // traverse par une interface
6864 if( elem_voisin>-1 && indicatrice(elem_voisin) != 0.
6865 && indicatrice(elem_voisin) != 1. )
6866 {
6867
6868 for( int i=0 ; i< CptFacette(elem_voisin) ; i++)
6869 {
6870 if( !fa7.testsetbit( Tab12(elem_voisin,i) ) )
6871 {
6872 nb_facettes_to_uzawa++ ;
6873 mat_0.add( Tab100(elem_voisin,i) ) ;
6874 mat_1.add( Tab101(elem_voisin,i) ) ;
6875 mat_2.add( Tab102(elem_voisin,i) ) ;
6876 mat_3.add( Tab103(elem_voisin,i) ) ;
6877 }
6878 }
6879 }
6880 }
6881 }
6882 }
6883 }
6884 }
6885 if( nb_facettes_to_uzawa > 0 )
6886 {
6887 DoubleTab matrice_plans(nb_facettes_to_uzawa, dim) ;
6888 DoubleTab x(dim) ;
6889 DoubleTab secmem(nb_facettes_to_uzawa) ;
6890
6891 for( int i_facette=0 ; i_facette<nb_facettes_to_uzawa ; i_facette++ )
6892 {
6893 matrice_plans(i_facette,0) = mat_0[i_facette] ;
6894 matrice_plans(i_facette,1) = mat_1[i_facette] ;
6895 if (dim==3)
6896 matrice_plans(i_facette,2) = mat_2[i_facette] ;
6897 secmem[i_facette] = -mat_3[i_facette] ;
6898 }
6899
6900 for (int i_coord=0; i_coord<dim; i_coord++)
6901 {
6902 x(i_coord) = xv(i_face,i_coord) ;
6903 }
6904
6905 // Calcul des coordonnees du projete 'coord_projete'
6906 DoubleTab coord_projete(dim) ;
6907 coord_projete = 0. ;
6908 uzawa(d,matrice_plans,x,secmem,coord_projete) ;
6909
6910 if (variables_internes_->type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
6911 {
6912 DoubleTab V(dim) ;
6913 for (int i_coord=0; i_coord<dim; i_coord++)
6914 {
6915 V(i_coord) = Vertex(i_face,i_coord) ;
6916 }
6917 int cpt = 0 ;
6918 double Lref =0. ;
6919 const int ori = orientation[i_face] ;
6920 const int voisin0 = faces_elem(i_face,0) ;
6921 const int voisin1 = faces_elem(i_face,1) ;
6922 const int monophasique = 1 ;
6923 calcul_tolerance_projete_monophasique(i_face,ori,voisin0,voisin1,indicatrice_face,indicatrice,Lref) ;
6924 verifprojete(monophasique,Lref,d,x,V,coord_projete,cpt) ;
6925 if( cpt > 0 )
6926 nb_proj_modif++ ;
6927 }
6928
6929 //Calcul de la vitesse du projete
6930 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
6931 {
6932 for (int j = 0; j < dim; j++)
6933 {
6934 parser_x.setVar(j, coord_projete(j)) ;
6935 parser_y.setVar(j, coord_projete(j)) ;
6936 if (dim==3)
6937 parser_z.setVar(j, coord_projete(j)) ;
6938 }
6939 if (zvdf)
6940 {
6941 switch(zvdf->orientation(i_face))
6942 {
6943 case 0:
6944 v_imp(i_face) = parser_x.eval() ;
6945 break ;
6946 case 1:
6947 v_imp(i_face) = parser_y.eval() ;
6948 break ;
6949 case 2:
6950 v_imp(i_face) = parser_z.eval() ;
6951 break ;
6952 }
6953 }
6954 }
6955 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE )
6956 {
6957 ArrOfDouble v(dim) ;
6958 v = variables_internes_->loi_horaire_->vitesse(t+dt,coord_projete);
6959 if (zvdf)
6960 v_imp(i_face)=v[zvdf->orientation(i_face)];
6961 }
6962 }
6963 }
6964 }
6965}
6966
6967void Transport_Interfaces_FT_Disc::projete_point_face_interface( int& nb_proj_modif, const int dimfa7, const DoubleTab& indicatrice_face,
6968 const DoubleTab& indicatrice, const DoubleTab& dist_face,
6969 const double t, const double dt, DoubleTab& Tab100,
6970 DoubleTab& Tab101, DoubleTab& Tab102,DoubleTab& Tab103,
6971 IntTab& Tab12,IntTab& CptFacette, DoubleTab& v_imp,
6972 DoubleTab& Vertex,Parser& parser_x, Parser& parser_y,
6973 Parser& parser_z )
6974{
6975 const int dim = Objet_U::dimension;
6976 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6977 const Domaine_VDF * zvdf = 0 ;
6978 if (sub_type(Domaine_VDF, mon_dom_dis))
6979 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
6980 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
6981 const IntVect& orientation = domaine_vdf.orientation();
6982 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6983 const IntTab& elem_faces = domaine_vf.elem_faces();
6984 const IntTab& faces_elem = domaine_vf.face_voisins();
6985 const int nfaces = faces_elem.dimension(0) ;
6986 const DoubleTab& xv = domaine_vf.xv() ;
6987 const double invalid_test = -1.e30;
6988
6989 for( int i_face=0 ; i_face<nfaces ; i_face++ )
6990 {
6991 double d = dist_face(i_face) ;
6992 const int diphasique_tmp = (indicatrice_face(i_face) != 0. &&
6993 (indicatrice_face(i_face) != 1. || (indicatrice_face(i_face) == 1. && d<=0. && d> invalid_test)));
6994 const int diphasique = ( variables_internes_->is_extra_diphasique_solide ? diphasique_tmp : (diphasique_tmp && d <= 0.) ) ;
6995 const int fluide = ( indicatrice_face(i_face) == 0. ) ;
6996 const int solide = ( variables_internes_->is_extra_solide && (d>0. || (indicatrice_face(i_face) == 1. && d<-1.e20)) ) ;
6997 const int monophasique = ( fluide || solide ) ;
6998
6999 if (diphasique || (monophasique && d> invalid_test ))
7000 {
7001 DoubleList mat_0, mat_1, mat_2, mat_3 ;
7002 ArrOfBit fa7(dimfa7);
7003 fa7=0;
7004 int nb_facettes_to_uzawa = 0 ;
7005
7006 // Coordonnes du projet 'coord_projete'
7007 DoubleTab coord_projete(dim) ;
7008 coord_projete = 0. ;
7009 int projete_calcule = 0 ;
7010
7011 // Si la face a une indicatrice de 0.5 celui implique
7012 // qu'elle est parfaitement traverse par au moins une facette.
7013 // Dans ce cas, le projet du barycentre de la face sur le
7014 // plan des facettes est lui-mme.
7015 if( indicatrice_face(i_face) == 0.5 )
7016 {
7017 int voisin = -1 ;
7018 if( faces_elem(i_face,0) > -1 )
7019 voisin = faces_elem(i_face,0) ;
7020 else
7021 voisin = faces_elem(i_face,1) ;
7022
7023 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
7024 {
7025 for( int j=0 ; j<dim ; j++)
7026 {
7027 coord_projete(j)=xv(i_face,j) ;
7028 }
7029 projete_calcule = 1 ;
7030 }
7031 }
7032
7033 if( projete_calcule == 0 )
7034 {
7035 if( d == 0. )
7036 {
7037 for( int j=0 ; j<dim ; j++)
7038 {
7039 coord_projete(j)=xv(i_face,j) ;
7040 }
7041 }
7042 else
7043 {
7044 // on identifie les elements auxquels appartient i_face
7045 // et qui sont traverses par l'interface
7046 for(int ii=0 ; ii<2; ii++)
7047 {
7048 const int elem_voisin = faces_elem(i_face,ii) ;
7049
7050
7051 // On veut que l'element existe, qu'il soit lui-meme
7052 // traversepar une interface
7053 // YG : ce test a ete scinde en deux. Dans le cas d une indicatrice
7054 // modifiee, il peut arriver qu aucun des voisins ait une indicatrice
7055 // element !=0. Pour autant, on a envie de regarder les voisins des
7056 // voisins pour chercher des facettes. Idem pour le cas monophasique!
7057 if( elem_voisin>-1)
7058 {
7059 if (indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
7060 {
7061 for( int i=0 ; i< CptFacette(elem_voisin) ; i++)
7062 {
7063 if( !fa7.testsetbit( Tab12(elem_voisin,i) ) )
7064 {
7065 nb_facettes_to_uzawa++ ;
7066 mat_0.add( Tab100(elem_voisin,i) ) ;
7067 mat_1.add( Tab101(elem_voisin,i) ) ;
7068 mat_2.add( Tab102(elem_voisin,i) ) ;
7069 mat_3.add( Tab103(elem_voisin,i) ) ;
7070 }
7071 }
7072 }
7073 // On identifie ensuite les elements voisins (elem_voisin_voisin)
7074 // traverses par l'IBC.
7075 for(int j=0 ; j<2*dim ; j++)
7076 {
7077 const int elem_voisin_voisin = faces_elem(elem_faces(elem_voisin,j),0)
7078 + faces_elem(elem_faces(elem_voisin,j),1) - elem_voisin ;
7079
7080 if( elem_voisin_voisin>-1 && indicatrice(elem_voisin_voisin) != 0.
7081 && indicatrice(elem_voisin_voisin) != 1.
7082 && elem_voisin_voisin!=faces_elem(i_face,0)
7083 && elem_voisin_voisin!=faces_elem(i_face,1) )
7084 {
7085 for( int i=0 ; i< CptFacette(elem_voisin_voisin) ; i++)
7086 {
7087 if( !fa7.testsetbit( Tab12(elem_voisin_voisin,i) ) )
7088 {
7089 nb_facettes_to_uzawa++ ;
7090 mat_0.add( Tab100(elem_voisin_voisin,i) ) ;
7091 mat_1.add( Tab101(elem_voisin_voisin,i) ) ;
7092 mat_2.add( Tab102(elem_voisin_voisin,i) ) ;
7093 mat_3.add( Tab103(elem_voisin_voisin,i) ) ;
7094 }
7095 }
7096 }
7097 }
7098 }
7099 }
7100
7101 if( nb_facettes_to_uzawa == 0 && diphasique )
7102 {
7103 Cerr << "erreur concernant la face : "<< i_face << " I_f = "<<indicatrice_face(i_face)<<finl ;
7104 Cerr << "aucune facette detecte "<< finl ;
7105 Process::exit() ;
7106 }
7107 else if (nb_facettes_to_uzawa >0)
7108 {
7109
7110 DoubleTab matrice_plans(nb_facettes_to_uzawa, dim) ;
7111 DoubleTab x(dim) ;
7112 DoubleTab secmem(nb_facettes_to_uzawa) ;
7113
7114 for( int i_facette=0 ; i_facette<nb_facettes_to_uzawa ; i_facette++ )
7115 {
7116 matrice_plans(i_facette,0) = mat_0[i_facette] ;
7117 matrice_plans(i_facette,1) = mat_1[i_facette] ;
7118 if (dim==3)
7119 matrice_plans(i_facette,2) = mat_2[i_facette] ;
7120 secmem[i_facette] = -mat_3[i_facette] ;
7121 }
7122 for (int i_coord=0; i_coord<dim; i_coord++)
7123 {
7124 x(i_coord) = xv(i_face,i_coord) ;
7125 }
7126 coord_projete = 0. ;
7127 uzawa(d,matrice_plans,x,secmem,coord_projete) ;
7128
7129 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
7130 {
7131 DoubleTab V(dim) ;
7132 for (int i_coord=0; i_coord<dim; i_coord++)
7133 {
7134 V(i_coord) = Vertex(i_face,i_coord) ;
7135 }
7136 int cpt = 0 ;
7137 double Lref = 0. ;
7138 const int ori = orientation[i_face] ;
7139 const int voisin0 = faces_elem(i_face,0) ;
7140 const int voisin1 = faces_elem(i_face,1) ;
7141 const int monophasique2 = 0 ;
7142 calcul_tolerance_projete_diphasique(i_face,ori,voisin0,voisin1,indicatrice,Lref) ;
7143 verifprojete(monophasique2,Lref,d,x,V,coord_projete,cpt) ;
7144 if( cpt > 0 )
7145 nb_proj_modif++ ;
7146 }
7147 }
7148 }
7149 }
7150
7151 const int test = (diphasique || fluide || solide ) ;
7152
7153
7154 if(test)
7155 {
7156 // Calcul de la vitesse du projete
7157 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
7158 {
7159 for (int j = 0; j < dim; j++)
7160 {
7161 parser_x.setVar(j, coord_projete(j)) ;
7162 parser_y.setVar(j, coord_projete(j)) ;
7163 if (dim==3)
7164 parser_z.setVar(j, coord_projete(j)) ;
7165 }
7166 if (zvdf)
7167 {
7168 switch(zvdf->orientation(i_face))
7169 {
7170 case 0:
7171 v_imp(i_face) = parser_x.eval() ;
7172 break ;
7173 case 1:
7174 v_imp(i_face) = parser_y.eval() ;
7175 break ;
7176 case 2:
7177 v_imp(i_face) = parser_z.eval() ;
7178 break ;
7179 }
7180 }
7181 }
7182 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE )
7183 {
7184 ArrOfDouble v(dim);
7185 v = variables_internes_->loi_horaire_->vitesse(t+dt,coord_projete);
7186 if (zvdf)
7187 v_imp(i_face)=v[zvdf->orientation(i_face)];
7188 }
7189 }
7190 }
7191 }
7192}
7193
7194/*! @brief Deplace le maillage a l'aide du champ de vitesse impose entre l'instant maillage.
7195 *
7196 * temps() et l'instant "temps".
7197 * La nouvelle position des sommets est obtenue par integration des lignes de courant de ce champ,
7198 * par un schema RK3 (en un pas de temps) qui prend en compte la dependance en temps des vitesses imposees.
7199 * On "nettoie" et on change le temps du maillage. Pas de remaillage. maillage MINIMAL en sortie.
7200 *
7201 */
7202static void deplacer_maillage_ft_v_impose(Noms expression_vitesse,
7203 Maillage_FT_Disc& maillage, double temps)
7204{
7205 const double dt = temps - maillage.temps();
7206 Parser parser_x, parser_y, parser_z;
7207 init_parser_v_impose(expression_vitesse,
7208 parser_x, parser_y, parser_z, temps);
7209
7210 const DoubleTab& sommets = maillage.sommets();
7211 const int dim = sommets.dimension(1);
7212 const int dimension3 = (dim == 3);
7213 int i;
7214 const int nb_sommets = maillage.nb_sommets();
7215 DoubleTabFT deplacement(nb_sommets, dim);
7216 for (i = 0; i < nb_sommets; i++)
7217 {
7218 const double x0 = sommets(i, 0);
7219 const double y0 = sommets(i, 1);
7220 const double z0 = dimension3 ? sommets(i, 2) : 0.;
7221 double x = x0, y = y0, z = z0;
7222 integrer_vitesse_imposee(parser_x, parser_y, parser_z,
7223 temps, dt, x, y, z);
7224 deplacement(i, 0) = x - x0;
7225 deplacement(i, 1) = y - y0;
7226 if (dimension3)
7227 deplacement(i, 2) = z - z0;
7228 }
7229 maillage.transporter(deplacement);
7230 maillage.nettoyer_elements_virtuels();
7231 maillage.changer_temps(temps);
7232}
7233
7234// Calcul d'une vitesse de deplacement minimisant les deplacements relatifs
7235// des sommets d'interface dans le repere local (donc minimisant les remaillages locaux)
7236// On veut que, dans le repere mobile associe au centre de gravite de l'interface,
7237// le deplacement tangentiel soit nul.
7238void Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local(const Maillage_FT_Disc& maillage, DoubleTab& deplacement,DoubleTab& Positions,DoubleTab& Vitesses) const
7239{
7240 // const Maillage_FT_Disc & maillage = maillage_interface();
7241 //vitesse des centres d'aire
7242 const int nb_facettes=maillage.nb_facettes();
7243 const IntTab& facettes=maillage.facettes ();
7244 const int dim3 = (deplacement.line_size() == 3);
7245 ArrOfInt compo_connexe_facettes(nb_facettes); // Init a zero
7246 int n = search_connex_components_local_FT(maillage, compo_connexe_facettes);
7247 int nb_compo_tot=compute_global_connex_components_FT(maillage, compo_connexe_facettes, n);
7248
7249 DoubleTabFT normale;
7250 calculer_normale_sommets_interface(maillage, normale);
7251 Positions.resize(nb_compo_tot,dimension);
7252 Vitesses.resize(nb_compo_tot,dimension);
7253
7254 calculer_vmoy_composantes_connexes(maillage, compo_connexe_facettes, nb_compo_tot,
7255 deplacement, Vitesses, Positions);
7256
7257 // Calcul de la composante connexe des sommets
7258 // Attention un sommet peut n'etre rattache a aucune facette sur le meme processeur !
7259 // (il faudrait calculer les compo connexes sur les sommets, et ensuite passer aux faces
7260 // ce serait plus simple, voire calculer les deux en meme temps)
7261 IntVect compo_sommets;
7262 maillage.creer_tableau_sommets(compo_sommets, RESIZE_OPTIONS::NOCOPY_NOINIT);
7263 compo_sommets = -1;
7264 {
7265 const int dim = deplacement.dimension(1);
7266 for (int iface = 0; iface < nb_facettes; iface++)
7267 {
7268 const int compo = compo_connexe_facettes[iface];
7269 for (int j = 0; j < dim; j++)
7270 compo_sommets[facettes(iface, j)] = compo;
7271 }
7272 // On prend le max sur tous les processeurs qui partagent le sommet pour les sommets isoles
7273 // (max calcule uniquement pour les sommets reels, sommets virtuels faux)
7275 // Inutile de synchroniser, on utilise uniquement les sommets reels
7276 }
7277
7278 const int nb_sommets_tot = compo_sommets.size_totale();
7279 for (int som = 0; som < nb_sommets_tot; som++)
7280 {
7281 if (maillage.sommet_virtuel(som))
7282 {
7283 // Valeur pipo pour dire qu'on initialise pas
7284 deplacement(som, 0) = 100.;
7285 deplacement(som, 1) = 100.;
7286 continue;
7287 }
7288
7289 const int compo = compo_sommets[som];
7290
7291 // (v-vmoy) doit etre normal a l'interface
7292 // Donc on fait v_corrige = v_initial - composante_tangentielle_de(v_initial-vmoy)
7293 // Demonstration que (v_corrige - vmoy) est normal a l'interface :
7294 // On note ct() = composante_tangentielle_de()
7295 // ct(v_corrige - vmoy)
7296 // = ct(v_corrige) - ct(vmoy) car ct est lineaire
7297 // = ct(v_initial - ct(v_initial) + ct(vmoy)) - ct(vmoy) car ct est lineaire
7298 // = ct(v_initial) - ct(v_initial) + ct(vmoy) - ct(vmoy) cat ct(ct(x)) = ct(x) et linearite
7299 // = 0
7300
7301 // v_corrige = cn(v_initial - vmoy) + vmoy
7302 // v_corrige = cn(v_initial) - cn(vmoy) + vmoy
7303 // v_corrige = cn(v_initial) + ct(vmoy)
7304 // v_corrige = v_initial - ct(v_inital) + ct(vmoy)
7305 // v_corrige = v_initial - ct(v_initial - vmoy)
7306
7307 double nx = 0., ny = 0., nz = 0.;
7308 double vi_x = 0., vi_y = 0., vi_z = 0.;
7309
7310 nx = normale(som, 0);
7311 ny = normale(som, 1);
7312
7313 vi_x = deplacement(som, 0);
7314 vi_y = deplacement(som, 1);
7315 if (dim3)
7316 {
7317 vi_z = deplacement(som, 2);
7318 nz=normale(som, 2);
7319 }
7320
7321 double prodscal =
7322 (vi_x - Vitesses(compo, 0)) * nx
7323 + (vi_y - Vitesses(compo, 1)) * ny;
7324 if (dim3)
7325 prodscal += (vi_z - Vitesses(compo, 2)) * nz;
7326 double norme_carre = nx * nx + ny * ny + nz * nz;
7327
7328 int is_solid_particle = get_is_solid_particle() ? 1 : 0;
7329 if (norme_carre != 0.)
7330 {
7331 prodscal /= norme_carre;
7332 deplacement(som, 0) = nx * prodscal* (1-is_solid_particle) + Vitesses(compo, 0);
7333 deplacement(som, 1) = ny * prodscal* (1-is_solid_particle) + Vitesses(compo, 1);
7334 if (dim3)
7335 deplacement(som, 2) = nz * prodscal* (1-is_solid_particle) + Vitesses(compo, 2); // BugFix reported from baltik TCL on 2020/10/26
7336 }
7337 }
7338}
7339
7340// This method is called by mettre_a_jour(), so it is done in a loop that depends on the order of equations.
7341// NS is forced as first, always.
7342// Therefore, NS has turned the wheel (tourner la roue) before getting here.
7343// To make a really explicit scheme, we want to use u^n, not u^n+1.
7344// Because of the wheel turns in equation(0).mettre_a_jour() (which is NS), u^n is currently in .futur() and NOT in .present() (or .valeur() which is synonymous)
7346{
7347 DoubleTab& deplacement = variables_internes_->deplacement_sommets;
7348 const Navier_Stokes_std& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
7349 // Method is called by mettre_a_jour()
7350 // The option explicit_u_NS_ = 0 enables corresponds to the historical scheme in TrioCFD, which was apparently semi-implicit.
7351 // Set to explicit_u_NS_ = 1, you get a real explicit scheme.
7352 // WARNING : read comment above method explaining why "explicit" should use ".futur()"!!!
7353 // This option affects the calculation directly in calculer_vitesse_transport_interpolee
7354 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
7356 // Calcul de la vitesse de deplacement des sommets par interpolation
7357 // (deplacement contient en fait la vitesse en m/s)
7358 int flag = 1;
7359 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
7360 {
7361 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
7363 flag=0;
7364 }
7366 maillage,
7367 deplacement, 1 /* recalculer le champ de vitesse L2 */,
7368 flag /* Interpolation Multi-lineaire en VDF */,
7369 true /* la_roue_de_vitesse_a_deja_tournee */);
7370
7371#if DEBUG_CONSERV_VOLUME
7372 int n = maillage.nb_sommets();
7373 double dmin=0.;
7374 double dmax=0.;
7375 double dmean = 0.;
7376 DoubleTab norm_deplacement(n);
7377 if (n>0)
7378 {
7379 for (int i=0; i<n; i++)
7380 {
7381 double x = 0.;
7382 for (int j=0; j<deplacement.dimension(1); j++)
7383 x += deplacement(i,j)*deplacement(i,j);
7384 norm_deplacement[i] = sqrt(x);
7385 dmean +=sqrt(x);
7386 }
7387 dmean /=n;
7388 dmin = min_array(norm_deplacement);
7389 dmax = max_array(norm_deplacement);
7390 }
7391#endif
7392 // On recupere et ajoute a deplacement le saut de vitesse a l'interface si changement de phase
7394 true /* la_roue_de_vitesse_a_deja_tournee */);
7395
7396#if DEBUG_CONSERV_VOLUME
7397 if (n>0)
7398 {
7399 double dmean_wpch = 0.;
7400 for (int i=0; i<n; i++)
7401 {
7402 double x = 0.;
7403 for (int j=0; j<deplacement.dimension(1); j++)
7404 x += deplacement(i,j)*deplacement(i,j);
7405 norm_deplacement[i] = sqrt(x);
7406 dmean_wpch +=sqrt(x);
7407 }
7408 dmean_wpch /=n;
7409 double dmin_wpch = min_array(norm_deplacement);
7410 double dmax_wpch = max_array(norm_deplacement);
7411 Cerr << "Interfacial_velocity before/after pch [min/mean/max]. Time: "
7413 << " Without-pch: " << dmin << " " << dmean<< " " << dmax
7414 << " With-pch: " << dmin_wpch << " " << dmean_wpch << " " << dmax_wpch
7415 << " [Warning, values invalid in //] " << finl;
7416 }
7417#endif
7418
7419 if (interpolation_repere_local_)
7420 {
7421 DoubleTab Positions,Vitesses;
7422
7423 calculer_vitesse_repere_local(maillage, deplacement,Positions,Vitesses);
7424 assert(Positions.dimension(0)==Vitesses.dimension(0));
7426 {
7427 ofstream fout;
7428 fout.open("composantes_connexes.txt",ios::app);
7429 fout << "TEMPS: " << temps << std::endl;
7430 const int nb_bulles=Positions.dimension(0);
7431
7432 for(int bulle=0; bulle<nb_bulles; bulle++)
7433 {
7434 fout << "composante " << bulle << " position " ;
7435 for (int i=0; i <Positions.dimension(1); i++) fout << " " << Positions(bulle,i);
7436 fout << " vitesse " ;
7437 for (int i=0; i <Vitesses.dimension(1); i++) fout << " " << Vitesses(bulle,i);
7438 fout << std::endl;
7439 }
7440 fout.close();
7441 }
7442 }
7443
7444 const double delta_t = temps - maillage.temps();
7445 // Calcul du deplacement :
7446 deplacement *= delta_t;
7447
7448// Debug GB 2020.03.20 Conservation de volume
7449#if DEBUG_CONSERV_VOLUME
7450 double volume_avt = remaillage_interface().calculer_volume_mesh(maillage);
7451#endif
7452 if (variables_internes_->VOFlike_correction_volume > 0)
7453 {
7454 // Transport avec correction du volume des phases :
7455 // Sauvegarde de la position actuelle des sommets :
7456 DoubleTabFT position_precedente = maillage.sommets();
7457 maillage.preparer_tableau_avant_transport(position_precedente,
7458 maillage.desc_sommets());
7459 // Calcul de la variation de volume exacte a obtenir a partir du
7460 // champ de vitesse eulerien :
7461 ArrOfDoubleFT var_volume;
7462 {
7463 // Desole pour le ref_cast_non_const, il y a probablement plus propre mais je ne sais pas faire.
7464 // En l'etat, 'ns' doit etre non-const car il fait appel a get_update...normale et get_compute_indicatrice_faces
7465 // qui modifient l'objet Transport_... dans lequel nous sommes!
7466 Navier_Stokes_FT_Disc& ns = ref_cast_non_const(Navier_Stokes_FT_Disc, eqn_hydraulique);
7467
7468 DoubleVect dI_dt;
7470 // Here, the velocity given is either explicit or semi-impli depending on the choice for : explicit_u_NS_
7471 const DoubleTab& val_champ_vitesse = (bool)(explicit_u_NS_) ? champ_vitesse.futur() : champ_vitesse.valeurs();
7472 ns.calculer_dI_dt(dI_dt, val_champ_vitesse);
7473 dI_dt.echange_espace_virtuel();
7474#if DEBUG_CONSERV_VOLUME
7475 const int nb_elem = domaine_dis().nb_elem();
7476 double sum_before_rm = 0.;
7477 double sum_before_rm_dvol = 0.;
7478 for (int i = 0; i < nb_elem; i++)
7479 sum_before_rm +=-dI_dt[i]; // It's already homogeneous to *volumes[i];
7480
7481 sum_before_rm_dvol +=sum_before_rm*delta_t;
7482#endif
7483 // if (!ns.is_shift_secmem2_activated()) even modifiee is used, the indicatrice at cell-face is not exactly well reconstructed
7484 // still need ramasse_miettes to get good dI_dt
7485 // ONEDAY, indicatrice at cell-face are well construire, this can be comment
7486 ramasse_miettes(maillage, variables_internes_->tmp_flux->valeurs(), dI_dt);
7487 transfert_conservatif_eulerien_vers_lagrangien_sommets(maillage, dI_dt, var_volume);
7488
7489#if DEBUG_CONSERV_VOLUME
7490 double sum = 0.;
7491 for (int i = 0; i < nb_elem; i++)
7492 sum +=-dI_dt[i]; // It's already homogeneous to *volumes[i];
7493
7494 const double dvoldt_totale = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7495 const double sum_dvol =sum*delta_t;
7496 Cerr << " time " << temps << " sum_dI_dt " << sum << " sum_dvol " << sum_dvol
7497 << " sum_before_rm_dI_dt " << sum_before_rm << " sum_before_rm_dvol " << sum_before_rm_dvol
7498 << " V_lagrangien= " << dvoldt_totale <<finl;
7499#endif
7500 }
7501 // var_volume est une derivee par rapport au temps.
7502 // calcul de l'integrale pendant le pas de temps ...
7503 // et changement de signe car on veut la variation de volume de la phase 0
7504 // (et non celle de la phase 1)
7505 var_volume *= -delta_t;
7506// Debug GB 2019.02.08 Conservation de volume
7507#if DEBUG_CONSERV_VOLUME
7508 double dvol_theo_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7509#endif
7510 maillage.preparer_tableau_avant_transport(var_volume,
7511 maillage.desc_sommets());
7512 // Transport avec le deplacement interpole :
7514 maillage.transporter(deplacement);
7515 maillage.update_tableau_apres_transport(position_precedente,
7516 maillage.nb_sommets(),
7517 maillage.desc_sommets());
7518 maillage.update_tableau_apres_transport(var_volume,
7519 maillage.nb_sommets(),
7520 maillage.desc_sommets());
7521
7522 // Calcul de la variation de volume obtenue par ce deplacement :
7523 ArrOfDoubleFT var_volume_deplacement;
7525 position_precedente,
7526 var_volume_deplacement);
7527#if DEBUG_CONSERV_VOLUME
7528 double volume_apres = remaillage_interface().calculer_volume_mesh(maillage);
7529 double dvol_reel_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume_deplacement);
7530 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local " << finl
7531 << " volume avt= " << volume_avt << finl
7532 << " apres= " << volume_apres << finl
7533 << " dvol_theo_depl= " << dvol_theo_depl << finl
7534 << " dvol_reel_depl= " << dvol_reel_depl << finl
7535 << finl;
7536#endif
7537 // Calcul de la variation de volume de la phase 0 a imposer lors de la correction
7538 // de volume :
7539 var_volume -= var_volume_deplacement;
7540
7541 // Si volume de phase_1 imposee : on calcule une deuxieme correction
7542 if (variables_internes_->volume_impose_phase_1 > 0.)
7543 {
7544 DoubleVect values(3);
7545 values=0.;
7546// volume_phase_1 -> values(0)
7547// volume_sous_domaine -> values(1)
7548// volume_phase_0 -> values(2)
7549 if (variables_internes_->nom_domaine_volume_impose_ == "??")
7550 values(0) = calculer_integrale_indicatrice(indicatrice_->valeurs(), values(2));
7551 else
7552 {
7553 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7554 const DoubleVect& volumes = domaine_vf.volumes();
7555 const Sous_Domaine& sous_domaine = domaine_dis().domaine().ss_domaine(variables_internes_->nom_domaine_volume_impose_);
7556 const int nb_elem_sous_domaine = sous_domaine.nb_elem_tot();
7557 const DoubleTab& indic = indicatrice_->valeurs();
7558 const int nb_elem = domaine_vf.nb_elem();
7559 for (int i = 0; i < nb_elem_sous_domaine; i++)
7560 {
7561 const int elem = sous_domaine[i];
7562 if (elem < nb_elem)
7563 {
7564 values(0) += indic(elem) * volumes(elem);
7565 values(1) += volumes(elem);
7566 values(2) += (1.-indic(elem)) * volumes(elem);
7567 }
7568 }
7569 mp_sum_for_each_item(values);
7570 /* Cerr << "Volume_sous_domaine " << variables_internes_->nom_domaine_volume_impose_ <<
7571 mp_sum(volume_sous_domaine) << finl;
7572 volume_phase_1 = mp_sum(volume_phase_1); */
7573 Cerr << "Volume_sous_domaine " << variables_internes_->nom_domaine_volume_impose_ <<
7574 values(1) << finl;
7575
7576 }
7577 const double erreur_volume = variables_internes_->volume_impose_phase_1 - values(0);
7578 Journal() << "Transport_Interfaces_FT_Disc::mettre_a_jour "
7579 << "correction_volume_impose_phase_1= " << erreur_volume << finl;
7580 // Calcul de la correction de volume a imposer a chaque sommet
7581 // Surface totale d'interface:
7582 double surface_tot = 0.;
7583 {
7584 int i;
7585 const int nb_facettes = maillage.nb_facettes();
7586 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
7587
7588 for (i = 0; i < nb_facettes; i++)
7589 surface_tot += surfaces[i];
7590
7591 surface_tot = mp_sum(surface_tot) * 3.;
7592 if (surface_tot > 0.)
7593 {
7594 const double inv_surface_tot = 1. / surface_tot;
7595 const IntTab& facettes = maillage.facettes();
7596 const int nb_som_facette = facettes.dimension(1);
7597 for (i = 0; i < nb_facettes; i++)
7598 {
7599 int j;
7600 const double dvolume = erreur_volume * surfaces[i] * inv_surface_tot;
7601 for (j = 0; j < nb_som_facette; j++)
7602 {
7603 int isom = facettes(i,j);
7604 // var_volume est la variation de volume de phase 0, donc signe "moins"
7605 var_volume[isom] -= dvolume;
7606 }
7607 }
7608 }
7609 }
7610 }
7611 // Correction de volume :
7612 // GB. 2019.05.13. Pourquoi utiliser iterations_correction_volume pour le nombre de lissage de dvol?
7613 // remaillage_interface().lisser_dvolume(maillage, var_volume,
7614 // variables_internes_->iterations_correction_volume);
7615 // 2019.05.13. Nouveau code :
7616 remaillage_interface().lisser_dvolume(maillage, var_volume,
7617 variables_internes_->nb_lissage_correction_volume);
7618
7619#if DEBUG_CONSERV_VOLUME
7620 double volume_before = remaillage_interface().calculer_volume_mesh(maillage);
7621 double dvol_total_before = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7622 Cerr << " dvol_error_before= " << dvol_total_before << " Volume_before= " << volume_before << " time " << temps << finl;
7623#endif
7624 // GB. 2019.05.13. Pourquoi utiliser nb_iter_bary_volume_seul_ plutot que iterations_correction_volume?
7625 //remaillage_interface().corriger_volume(maillage, var_volume);
7626 // 2019.05.13. Nouveau code :
7627 remaillage_interface().corriger_volume_(maillage, var_volume,
7628 variables_internes_->nb_iterations_correction_volume);
7629#if DEBUG_CONSERV_VOLUME
7630 double volume_after = remaillage_interface().calculer_volume_mesh(maillage);
7631 double dvol_total_after = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7632 Cerr << " dvol_error_after= " << dvol_total_after << " Volume_after= " << volume_after << " time " << temps << finl;
7633#endif
7634 }
7635 else
7636 {
7637#if DEBUG_CONSERV_VOLUME
7638 // Sauvegarde de la position actuelle des sommets :
7639 DoubleTabFT position_precedente = maillage.sommets();
7640 maillage.preparer_tableau_avant_transport(position_precedente,
7641 maillage.desc_sommets());
7642#endif
7643 // Transport par interpolation de vitesse seule :
7645 maillage.transporter(deplacement);
7646#if DEBUG_CONSERV_VOLUME
7647 // Calcul de la variation de volume obtenue par ce deplacement :
7648 ArrOfDoubleFT var_volume_deplacement;
7650 position_precedente,
7651 var_volume_deplacement);
7652
7653 maillage.update_tableau_apres_transport(position_precedente,
7654 maillage.nb_sommets(),
7655 maillage.desc_sommets());
7656 double volume_apres = remaillage_interface().calculer_volume_mesh(maillage);
7657 double dvol_reel_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume_deplacement);
7658 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local " << finl
7659 << " volume avt= " << volume_avt << finl
7660 << " apres= " << volume_apres << finl;
7661// pas calcule Cerr << " dvol_theo_depl= " << dvol_theo_depl << finl;
7662 Cerr << " dvol_reel_depl= " << dvol_reel_depl << finl
7663 << " dt= " << delta_t << finl;
7664#endif
7665 }
7667 maillage.changer_temps(temps);
7668
7669 if (collision_model_ && nb_particles_tot_>1)
7671
7672 maillage.compute_gravity_center_fa7();
7673}
7674
7675void Transport_Interfaces_FT_Disc::ajouter_contribution_saut_vitesse(DoubleTab& deplacement, const bool la_roue_de_vitesse_a_deja_tournee) const
7676{
7677 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
7678 const Champ_base *u0_ptr = 0;
7679
7680 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
7681 {
7682 // assert(la_roue_de_vitesse_a_deja_tournee); // TODO : supprimer le param car il n'est jamais usite en false
7683 // Je ne vois pas qui tourne le roue pour delta_u??? // TODO Supprimer le champ_inc
7684 // On recupere le saut de vitesse a l'interface (changement de phase)
7685 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
7686 u0_ptr = ns.get_delta_vitesse_interface();
7687 if (u0_ptr)
7688 {
7689 const Champ_base& u0 = *u0_ptr;
7690 DoubleTabFT d2(deplacement);
7691 // If ns.get_new_mass_source() == 0, we use a standard multi-linear interpolation.
7692 // If ns.get_new_mass_source() == 1, we use the new method (1D-interpolation of each velocity component in its direction)
7695 d2, 1 /* recalculer le champ de vitesse L2 */,
7696 1-ns.get_new_mass_source(),
7697 la_roue_de_vitesse_a_deja_tournee);
7698
7699 const int n = d2.dimension(0);
7700 const int dim = d2.line_size();
7701 for (int i = 0; i < n; i++)
7702 {
7703 for (int j = 0; j < dim; j++)
7704 {
7705 const double depl2 = d2(i,j);
7706 deplacement(i,j) -= depl2;
7707 }
7708 }
7709 }
7710 }
7711}
7712
7714{
7715 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7716 const DoubleTab& indicatrice = get_indicatrice().valeurs();
7717 const int nb_compo = topologie_interface().calculer_composantes_connexes_pour_suppression(domaine_vf, indicatrice, num_compo);
7718 return nb_compo;
7719}
7720
7721double Transport_Interfaces_FT_Disc::suppression_interfaces(const IntVect& num_compo, const ArrOfInt& flags_compo_a_supprimer)
7722{
7724 const double volume = topologie_interface().suppression_interfaces(num_compo,
7725 flags_compo_a_supprimer, maillage,
7726 variables_internes_->indicatrice_cache->valeurs());
7727 return volume;
7728}
7729
7731{
7732 bool indic_updated = false;
7734 return false;
7735
7736 const Sous_Domaine& sous_domaine = domaine_dis().domaine().ss_domaine(suppression_interfaces_sous_domaine_);
7738 indic_updated = true;
7739 const DoubleTab& indicatrice = get_indicatrice().valeurs();
7740 // Construction de la liste des elements de la sous-domaine contenant la phase a supprimer
7741 ArrOfInt liste_elems_sous_domaine;
7742 int i;
7743 const double phase_continue = topologie_interface().get_phase_continue();
7744
7745 const int nb_elems_sous_domaine = sous_domaine.nb_elem_tot();
7746 for (i = 0; i < nb_elems_sous_domaine; i++)
7747 {
7748 const int i_elem = sous_domaine[i];
7749 const double indic = indicatrice[i_elem];
7750 if (indic != phase_continue)
7751 liste_elems_sous_domaine.append_array(i_elem);
7752 }
7753 const int sz_liste_elems_sous_domaine = liste_elems_sous_domaine.size_array();
7754 if (mp_sum(sz_liste_elems_sous_domaine) > 0)
7755 {
7756 IntVect num_compo;
7757 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7758 const int nb_compo = topologie_interface().calculer_composantes_connexes_pour_suppression(domaine_vf, indicatrice, num_compo);
7759 // Tableau initialise a zero:
7760 ArrOfInt flags_compo_a_supprimer(nb_compo);
7761 for (i = 0; i < sz_liste_elems_sous_domaine; i++)
7762 {
7763 const int elem = liste_elems_sous_domaine[i];
7764 const int compo = num_compo[elem];
7765 flags_compo_a_supprimer[compo] = 1;
7766 }
7767 mp_sum_for_each_item(flags_compo_a_supprimer);
7769 topologie_interface().suppression_interfaces(num_compo, flags_compo_a_supprimer, maillage,
7770 variables_internes_->indicatrice_cache->valeurs());
7771
7772 if (max_array(flags_compo_a_supprimer))
7773 {
7775 indic_updated = true;
7776 // Parcours de toutes les equations du probleme,
7777 // Pour les equations "temperature FT" on appelle la methode "suppression_interfaces"
7778 Probleme_base& pb = probleme();
7779 const int n = pb.nombre_d_equations();
7780 for (int ii = 0; ii < n; ii++)
7781 {
7782 Equation_base& eq = pb.equation(ii);
7784 {
7787 const int i_phase_continue = (phase_continue < 0.5) ? 0 : 1;
7788 eq_temp.suppression_interfaces(num_compo, flags_compo_a_supprimer,
7789 i_phase_continue /* phase qui remplace l'ancienne */);
7790 }
7791 }
7792 }
7793 }
7794 return indic_updated;
7795}
7796
7797//Integration des trajectoires de particules
7798// La methode est une version simplifiee de deplacer_maillage_ft_v_fluide(...)
7799// -Interpolation du champ de vitesse de l equation de qdm
7800// -Calcul du deplacement a appliquer aux particules
7801// -Transport des particules en fonction du deplacement calcule
7802// -Mise a jour du temps de l objet ensemble de points meme si t<t_debut_integr
7803// Rq : t_debut_integr est fixe par defaut a t_init mais peut etre specifie par l utilisateur
7805{
7806 Cerr<<"The method Transport_Interfaces_FT_Disc::integrer_ensemble_lagrange"<<finl;
7807 Cerr<<"must be overloaded."<<finl;
7808 Process::exit();
7809}
7810
7812{
7813 Process::Journal() << "Transport_Interfaces_FT_Disc::mettre_a_jour " << le_nom() << " temps= "<< temps << finl;
7814 // Effectue le deplacement de l'interface:
7815 bool is_indic_up_to_date = mettre_a_jour_deplacement(temps);
7816
7817 // Remaillage de l'interface:
7818 const int mtag = maillage_interface().get_mesh_tag();
7820 // L'indicatrice ne peut etre "encore" a jour a l'issu du remaillage que si celui-ci n'a pas change le mesh_tag!
7821 is_indic_up_to_date = (mtag == maillage_interface().get_mesh_tag()) && is_indic_up_to_date;
7822
7823 // Effectue la mise a jour de l'inconnue, des indicatrices et de tous les champs auxiliaires:
7824 bool update_indic = !is_indic_up_to_date;
7825 mettre_a_jour_hors_deplacement(temps, true, update_indic);
7826}
7827
7829{
7830 deplacer_maillage(temps);
7831 bool is_indicatrice_up_to_date = injecter_supprimer_interfaces(temps);
7832 return is_indicatrice_up_to_date;
7833}
7834
7836{
7838 switch (variables_internes_->methode_transport)
7839 {
7841 {
7842 deplacer_maillage_ft_v_impose(variables_internes_->expression_vitesse_imposee, maillage, temps);
7843 break;
7844 }
7846 {
7848 break;
7849 }
7851 {
7852 // Le deplacement de l'interface est donne par l'expression de la loi horaire
7853 const double dt = temps - maillage.temps();
7854 // Le temps auquel est evalue la vitesse:
7855 // pour obtenir un deplacement precis a l'ordre 2, on evalue la vitesse au temps suivant:
7856 const double t = maillage.temps() + dt * 0.5;
7858 {
7859 Cerr << "Transport_Interfaces_FT_Disc::mettre_a_jour imposed motion by a time law at t:" << t << finl;
7860 }
7861 const int nb_sommets = maillage.nb_sommets();
7862 DoubleTabFT deplacement(nb_sommets, Objet_U::dimension);
7863
7864 const DoubleTab& sommets = maillage.sommets();
7865
7866 const int dim = Objet_U::dimension;
7867 ArrOfDouble coord(dim);
7868 ArrOfDouble coord_barycentre(dim); // Coordonnes du barycentre des points de l'interface
7869 int nb_sommets_reels=0;
7870 for (int i = 0; i < nb_sommets; i++)
7871 {
7872 // Determination si le sommet de l'interface est reel ou virtuel
7873 int est_un_sommet_reel=0;
7874 if (!maillage.sommet_virtuel(i))
7875 {
7876 nb_sommets_reels++;
7877 est_un_sommet_reel=1;
7878 }
7879 // Coordonnees coord du ieme sommet de l'interface a l'instant t
7880 for (int j = 0; j < dim; j++)
7881 {
7882 double pos = sommets(i, j);
7883 coord[j] = pos;
7884 if (est_un_sommet_reel)
7885 coord_barycentre[j] += pos;
7886 }
7887 // Calcul de ses nouvelles coordonnees a t+dt
7888 coord = variables_internes_->loi_horaire_->position(t+dt,t,coord);
7889
7890 // Calcul du tableau deplacement
7891 for (int j = 0; j < dim; j++)
7892 deplacement(i, j) = coord[j] - sommets(i,j);
7893 }
7894 // Calcul du barycentre des noeuds de l'interface
7895 // en tenant compte du parallelisme
7896 nb_sommets_reels=Process::check_int_overflow(mp_sum(nb_sommets_reels));
7897 /* for (int j = 0; j < dim; j++)
7898 {
7899 coord_barycentre(j)=mp_sum(coord_barycentre(j))/nb_sommets_reels;
7900 } */
7901 mp_sum_for_each_item(coord_barycentre);
7902 for (int j = 0; j < dim; j++)
7903 {
7904 coord_barycentre[j]=coord_barycentre[j]/nb_sommets_reels;
7905 }
7906 // Impression eventuelle de la loi horaire et du centre de gravite "discret" de l'interface
7907 if (schema_temps().limpr())
7908 variables_internes_->loi_horaire_->imprimer(schema_temps(),coord_barycentre);
7909
7910 maillage.transporter(deplacement);
7911 maillage.nettoyer_elements_virtuels();
7912 maillage.completer_maillage();
7913 maillage.changer_temps(temps);
7914 break;
7915 }
7916 default:
7917 Cerr << "Error for the method Transport_Interfaces_FT_Disc::mettre_a_jour :\n"
7918 << " the requested transport mehod is not developped" << finl;
7919 Process::exit();
7920 }
7921}
7922
7924{
7926 maillage.nettoyer_elements_virtuels();
7927 maillage.completer_maillage();
7928 maillage.changer_temps(temps);
7929}
7930
7932{
7933 bool indic_updated = injecter_interfaces_par_ajout_phase(temps);
7934 indic_updated = injecter_interfaces_pour_TCL(temps) || indic_updated;
7935
7936// Traitement des domaines de suppression
7937 indic_updated = test_suppression_interfaces_sous_domaine() || indic_updated;
7938 return indic_updated;
7939}
7940
7942{
7943 bool indic_updated = false;
7944 // injection des interfaces
7945 if (variables_internes_->injection_interfaces_temps_.size_array() > 0)
7946 {
7947 const ArrOfDouble& tps = variables_internes_->injection_interfaces_temps_;
7948 const int n = tps.size_array();
7949 const Noms& expr = variables_internes_->injection_interfaces_expressions_;
7950 assert(expr.size() == n);
7951 // Recherche du prochain temps d'injection:
7952 const double last_time = variables_internes_->injection_interfaces_last_time_;
7953 int i;
7954 for (i = 0; i < n; i++)
7955 if (tps[i] > last_time)
7956 break;
7957 for (; i < n && tps[i] <= temps; i++)
7958 {
7959 variables_internes_->injection_interfaces_last_time_=tps[i];
7960 // On essaye d'injecter l'interface
7961 Maillage_FT_Disc maillage_tmp;
7962 maillage_tmp.associer_equation_transport(*this);
7963 Maillage_FT_Disc::AjoutPhase phase = variables_internes_->injection_interfaces_phase_[i]
7965 DoubleTab sauvegarde(variables_internes_->indicatrice_cache->valeurs());
7966 const int ok = marching_cubes().construire_iso(expr[i],
7967 0., maillage_tmp,
7968 variables_internes_->indicatrice_cache->valeurs(),
7969 phase,
7970 variables_internes_->distance_interface_sommets);
7971
7972
7973
7974 Cerr << "Injection_interface time " << temps << " " << expr[i];
7975 if (ok)
7976 {
7977 maillage_interface().ajouter_maillage(maillage_tmp);
7979 indic_updated = true;
7980 double unused_vol_phase_0 = 0.;
7981 const double volume_phase_1_old = calculer_integrale_indicatrice(sauvegarde, unused_vol_phase_0);
7982 unused_vol_phase_0= 0.;
7983 const double volume_phase_1 = calculer_integrale_indicatrice(variables_internes_->indicatrice_cache->valeurs(), unused_vol_phase_0);
7984 double volume = volume_phase_1-volume_phase_1_old;
7985 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
7986 volume*=pow(-1.,1-phase);
7987 Cerr << " volume " << volume << finl;
7988 }
7989 else
7990 {
7991 Cerr << " failure: collision" << finl;
7992 variables_internes_->indicatrice_cache->valeurs() = sauvegarde;
7993 indic_updated = false;
7994 }
7995 }
7996 if (i == n)
7997 {
7998 Cerr << "The injection list is fulfilled !"
7999 << " (if it is wished, add an interface at a large time in the file)"
8000 << finl;
8001 barrier();
8002 Process::exit();
8003 }
8004 }
8005 return indic_updated;
8006}
8007
8009{
8010 bool indic_updated = false;
8011 Probleme_base& pb = probleme();
8012 if (sub_type(Probleme_FT_Disc_gen,pb))
8013 {
8014 Probleme_FT_Disc_gen& pb_ft = ref_cast_non_const(Probleme_FT_Disc_gen, pb);
8015 // injection des interfaces with temperature of activation
8016 if (pb_ft.tcl().reinjection_tcl() && pb_ft.tcl().ready_inject_tcl())
8017 {
8018 const double thetac = pb_ft.tcl().thetaC_tcl();
8019 const double Rc = pb_ft.tcl().Rc_inject();
8020
8021 // const Nom expr = "x^2+(y-8e-05*cos(50.0*pi/180.0))^2-8e-05^2";
8022 const Nom expr = Nom("x^2+(y-") + Nom(Rc)
8023 + Nom("*cos(") + Nom(thetac)
8024 + Nom("*pi/180.0))^2-") + Nom(Rc)
8025 + Nom("^2");
8026
8027 // On essaye d'injecter l'interface
8028 Maillage_FT_Disc maillage_tmp;
8029 maillage_tmp.associer_equation_transport (*this);
8030
8031 // By default, inject vapeur, phase 0
8033 0 ?
8035
8036 DoubleTab sauvegarde (
8037 variables_internes_->indicatrice_cache.valeur ().valeurs ());
8038
8039 const int ok = marching_cubes ().construire_iso (
8040 expr, 0., maillage_tmp,
8041 variables_internes_->indicatrice_cache.valeur ().valeurs (), phase,
8042 variables_internes_->distance_interface_sommets);
8043
8044 Cerr << "Injection_interface time " << temps << " " << expr;
8045 if (ok)
8046 {
8047 maillage_interface().ajouter_maillage (maillage_tmp);
8049 indic_updated = true;
8050 double unused_vol_phase_0 = 0.;
8051 const double volume_phase_1_old = calculer_integrale_indicatrice (
8052 sauvegarde, unused_vol_phase_0);
8053 unused_vol_phase_0 = 0.;
8054 const double volume_phase_1 = calculer_integrale_indicatrice (
8055 variables_internes_->indicatrice_cache.valeur ().valeurs (),
8056 unused_vol_phase_0);
8057 double volume = volume_phase_1 - volume_phase_1_old;
8058 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
8059 volume *= pow (-1., 1 - phase);
8060 Cerr << " volume " << volume << finl;
8061
8062 Schema_Temps_base& sch_tps = schema_temps();
8063 const double t_present_ = sch_tps.temps_courant();
8064 double& t_injection_ = pb_ft.tcl().t_injection();
8065 t_injection_ = t_present_;
8066 }
8067 else
8068 {
8069 Cerr << " failure: collision" << finl;
8070 variables_internes_->indicatrice_cache.valeur ().valeurs () =
8071 sauvegarde;
8072 indic_updated = false;
8073 }
8074 }
8075 }
8076
8077 // PARA re_injection bublle seed
8078 const int n = pb.nombre_d_equations();
8079 for (int ii = 0; ii < n; ii++)
8080 {
8081 Equation_base& eq = pb.equation(ii);
8083 {
8086
8087
8088 if (eq_temp.is_reinject_activated() && eq_temp.ready_injection())
8089 {
8090 const double thetac = eq_temp.get_thetaC();
8091 const double Rc = eq_temp.get_Rc_inject();
8092
8093 // const Nom expr = "x^2+(y-8e-05*cos(50.0*pi/180.0))^2-8e-05^2";
8094 const Nom expr = Nom("x^2+(y-") + Nom(Rc)
8095 + Nom("*cos(") + Nom(thetac)
8096 + Nom("*pi/180.0))^2-") + Nom(Rc)
8097 + Nom("^2");
8098
8099 // On essaye d'injecter l'interface
8100 Maillage_FT_Disc maillage_tmp;
8101 maillage_tmp.associer_equation_transport (*this);
8102
8103 // By default, inject vapeur, phase 0
8105 0 ?
8107
8108 DoubleTab sauvegarde (
8109 variables_internes_->indicatrice_cache.valeur ().valeurs ());
8110
8111 const int ok = marching_cubes ().construire_iso (
8112 expr, 0., maillage_tmp,
8113 variables_internes_->indicatrice_cache.valeur ().valeurs (), phase,
8114 variables_internes_->distance_interface_sommets);
8115
8116 Cerr << "Injection_interface time " << temps << " " << expr;
8117 if (ok)
8118 {
8119 maillage_interface().ajouter_maillage (maillage_tmp);
8121 indic_updated = true;
8122 double unused_vol_phase_0 = 0.;
8123 const double volume_phase_1_old = calculer_integrale_indicatrice (
8124 sauvegarde, unused_vol_phase_0);
8125 unused_vol_phase_0 = 0.;
8126 const double volume_phase_1 = calculer_integrale_indicatrice (
8127 variables_internes_->indicatrice_cache.valeur ().valeurs (),
8128 unused_vol_phase_0);
8129 double volume = volume_phase_1 - volume_phase_1_old;
8130 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
8131 volume *= pow (-1., 1 - phase);
8132 Cerr << " volume " << volume << finl;
8133 const Probleme_base& pb2 = get_probleme_base();
8134 if (sub_type(Probleme_FT_Disc_gen,pb2))
8135 {
8136 Probleme_FT_Disc_gen& pb_ft = ref_cast_non_const(Probleme_FT_Disc_gen, pb);
8137 // injection des interfaces with temperature of activation
8138 if (pb_ft.tcl().lissage_tcl())
8139 {
8140 Schema_Temps_base& sch_tps = schema_temps();
8141 const double t_present_ = sch_tps.temps_courant();
8142 double& t_injection_ = pb_ft.tcl().t_injection();
8143 t_injection_ = t_present_;
8144 }
8145 }
8146 }
8147 else
8148 {
8149 Cerr << " failure: collision" << finl;
8150 variables_internes_->indicatrice_cache.valeur ().valeurs () =
8151 sauvegarde;
8152 indic_updated = false;
8153 }
8154 }
8155
8156 }
8157 }
8158 return indic_updated;
8159}
8160
8161void Transport_Interfaces_FT_Disc::mettre_a_jour_hors_deplacement(double temps, const bool update_statio
8162 , const bool update_indic)
8163{
8164 // The Eulerian fields normal and distance should be updated first (before indicatrice!!)
8165 // because the indicatrice calculation partly relies on the distance calculation.
8166 // Update normal and distance and indicatrice
8167 // Attention: get_indicatrice renvoie une ref a indicatrice_cache.
8168 // C'est ici qu'on copie le contenu de indicatrice_cache dans indicatrice :
8169 if (update_indic)
8171 // TODO GB 2024 : mettre_a_jour ferait un echange_EV en plus de changer temps. Mais l'echange EV est deja fait dans le update donc pas necessaire.
8172 variables_internes_->distance_interface->changer_temps(temps);
8173 variables_internes_->normale_interface->changer_temps(temps);
8174 indicatrice_->valeurs() = get_indicatrice().valeurs();
8175
8176 variables_internes_->indicatrice_cache->changer_temps(temps);
8177 indicatrice_->changer_temps(temps);
8178
8179 if (update_statio)
8181
8182 // Beaucoup de monde utilise l'indic aux faces. On la calcule tout le temps (tant pis si c'est pas perf-ideal)
8184 indicatrice_faces_->changer_temps(temps);
8185 // TODO: GB2024
8186 // if (???) variables_internes_->vitesse_filtree.changer_temps(temps);
8187 // if (???) variables_internes_->tmp_flux.changer_temps(temps);
8188 // if (???) variables_internes_->index_element.changer_temps(temps);
8189 // if (???) variables_internes_->nelem_par_direction.changer_temps(temps);
8190 // if (???) variables_internes_->distance_interface_faces.changer_temps(temps);
8191 // if (???) variables_internes_->distance_interface_faces_corrigee.changer_temps(temps);
8192 // if (???) variables_internes_->distance_interface_faces_difference.changer_temps(temps);
8193 // if (???) vitesse_imp_interp_.changer_temps(temps);
8194
8195 {
8196 double volume_phase_0 = 0.;
8197 const double volume_phase_1 = calculer_integrale_indicatrice(indicatrice_->valeurs(), volume_phase_0);
8199 {
8200 Cerr << "Volume_phase_0 " << Nom(volume_phase_0, "%20.14g") << " time " << temps << finl;
8201 Cerr << "Volume_phase_1 " << Nom(volume_phase_1, "%20.14g") << " time " << temps << finl;
8202 }
8203 }
8204
8206 // Affichage de la surface totale d'interfaces dans le fichier .err
8207 // Affichage du centre de gravite des phases 0 et 1
8208 {
8209 // Calcul de la somme des surfaces des facettes reelles:
8210 //const Maillage_FT_Disc& maillage = maillage_interface();
8211 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
8212 const int nb_facettes = maillage.nb_facettes();
8213 double s = 0.;
8214 int i;
8215 for (i = 0; i < nb_facettes; i++)
8216 {
8217 const int virt = maillage.facette_virtuelle(i);
8218 if (! virt)
8219 s += surfaces[i];
8220 }
8221 const double s_tot = mp_sum(s);
8223 {
8224 Cerr << "Surface_Totale_Interface " << le_nom()
8225 << " t= " << temps << " surface= " << s_tot << finl;
8226 }
8227 // Calcul du centre de gravite des phases 0 et 1 a partir de l'indicatrice
8228 // indicatrice de phase:
8229 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
8230 const DoubleTab& indic = indicatrice_->valeurs();
8231 // centre de gravite des elements euleriens:
8232 const DoubleTab& xp = domaine_vf.xp();
8233 // volumes des elements euleriens:
8234 const DoubleVect& volumes = domaine_vf.volumes();
8235
8236 const int nb_elem = domaine_vf.nb_elem();
8237 const int dim = xp.line_size();
8238 DoubleTrav values(3,dim);
8239 values=0.;
8240 // somme des volumes des phases:
8241// v0_tot -> values(2,0)
8242// v1_tot -> values(2,1)
8243 // centre de gravite de la phase 0:
8244// g0[j] -> values(0,j)
8245 // phase 1:
8246// g1[j] -> values(1,j)
8247 assert(indic.dimension(0) == nb_elem); // indicatrice aux elements
8248 // Boucle sur les elements reels
8249 for (i = 0; i < nb_elem; i++)
8250 {
8251 const double ind = indic(i);
8252 const double v = volumes(i);
8253 const double v1 = ind * v;
8254 const double v0 = (1. - ind) * v;
8255 values(2,0) += v0;
8256 values(2,1) += v1;
8257 int j;
8258 for (j = 0; j < dim; j++)
8259 {
8260 const double x = xp(i,j);
8261 values(0,j) += v0 * x;
8262 values(1,j) += v1 * x;
8263 }
8264 }
8265 // Somme sur tous les processeurs et calcul du centre de gravite
8266 double mp_g0[3] = {0., 0., 0.};
8267 double mp_g1[3] = {0., 0., 0.};
8268
8269 mp_sum_for_each_item(values);
8270 {
8271 int j;
8272 /* mp_vtot0 = mp_sum(v0_tot);
8273 mp_vtot1 = mp_sum(v1_tot);
8274 if (mp_vtot0 > 0.)
8275 for (j = 0; j < dim; j++)
8276 mp_g0[j] = mp_sum(g0[j]) / mp_vtot0;
8277 if (mp_vtot1 > 0.)
8278 for (j = 0; j < dim; j++)
8279 mp_g1[j] = mp_sum(g1[j]) / mp_vtot1; */
8280 if (values(2,0) > 0.)
8281 {
8282 {
8283 for ( j = 0; j<dim; j++)
8284 mp_g0[j] = values(0,j) / values(2,0);
8285 }
8286 if (values(2,1) > 0.)
8287 for ( j = 0; j<dim; j++)
8288 mp_g1[j] = values(1,j) / values(2,1);
8289 }
8290 }
8291 // Affichage
8292 if (je_suis_maitre())
8293 {
8294 Cerr << "Centre_gravite_phases " << le_nom() << " t= " << temps;
8295 Cerr << " phase0: " << mp_g0[0] << " " << mp_g0[1] << " " << mp_g0[2] ;
8296 Cerr << " phase1: " << mp_g1[0] << " " << mp_g1[1] << " " << mp_g1[2] << finl;
8297 }
8298 }
8299 //GB : Calcul de la surface d'interfaces par element
8300 {
8301 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
8302 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
8303 const ArrOfInt& index_elem = intersections.index_elem();
8304 DoubleTab& surface = variables_internes_->surface_interface->valeurs();
8305 const int nb_elements = surface.dimension(0);
8306 for (int element = 0; element < nb_elements; element++)
8307 {
8308 int index = index_elem[element];
8309 double surface_totale = 0.;
8310 // Boucle sur les faces qui traversent l'element:
8311 while (index >= 0)
8312 {
8313 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
8314 surface_totale += data.fraction_surface_intersection_ * surface_facettes[data.numero_facette_];
8315 index = data.index_facette_suivante_;
8316 }
8317 surface[element] = surface_totale;
8318 }
8319 surface.echange_espace_virtuel();
8320 variables_internes_->surface_interface->mettre_a_jour(temps);
8321 }
8322 // Fin de GB
8323
8324 //TF : Gestion de l avancee en temps de la derivee
8326 //Fin de TF
8328 {
8329 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
8330 if (sub_type(Navier_Stokes_FT_Disc,eqn_hydraulique))
8331 {
8332 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
8333 ns.compute_particles_eulerian_id_number(collision_model_);
8335 }
8336
8337 // the mesh has changed, we need to recompute the data located to the fa7
8338 post_process_hydro_forces_.drop_the_flag();
8339 post_process_hydro_forces_Stokes_.drop_the_flag();
8340 post_process_hydro_forces_.drop_the_flag_heat_transfer();
8341
8342 if (schema_temps().limpr())
8343 {
8345 if (post_process_hydro_forces_.get_is_compute_forces())
8346 post_process_hydro_forces_.compute_hydrodynamic_forces();
8347 if (post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
8348 post_process_hydro_forces_Stokes_.compute_hydrodynamic_forces();
8349 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
8350 post_process_hydro_forces_.compute_heat_transfer();
8351 }
8352
8353 }
8354
8355}
8356
8357// Deplace les sommets de l'interface du deplacement prescrit (vitesse * coeff)
8358// ou coeff est homogene a un temps en secondes.
8359// On met a jour le tableau vitesse en fonction des sommets qui sont
8360// passes d'un processeur a l'autre.
8361void Transport_Interfaces_FT_Disc::transporter_sans_changement_topologie(DoubleTab& vitesse, const double coeff,const double temps)
8362{
8364 DoubleTabFT deplacement(vitesse);
8365 deplacement *= coeff;
8366
8367 maillage.preparer_tableau_avant_transport(vitesse,
8368 maillage.desc_sommets());
8369
8370 maillage.transporter(deplacement);
8371
8372 // attention, creation de sommets virtuels... on fait update_...
8373 // seulement a la fin.
8374 maillage.parcourir_maillage();
8375
8376 maillage.update_tableau_apres_transport(vitesse,
8377 maillage.nb_sommets(),
8378 maillage.desc_sommets());
8379 //ajout pour postraiter ss pas de tps RK3_FT
8380 maillage.changer_temps(temps);
8382 indicatrice_->valeurs()=get_indicatrice().valeurs();
8383 variables_internes_->indicatrice_cache->changer_temps(temps);
8384 indicatrice_->changer_temps(temps);
8385 variables_internes_->distance_interface->changer_temps(temps);
8386 variables_internes_->normale_interface->changer_temps(temps);
8387}
8388
8389
8390// ************************************************************************
8391// ************************************************************************
8392// Un tas de routines vides ou presque qui ne font rien ou pas grand chose
8393// ************************************************************************
8394// ************************************************************************
8395
8397{
8398 // Si on veut creer un probleme contenant uniquement une equation Transport,
8399 // il faut un milieu sinon ca plante dans pb_base::discretiser !
8400 ref_milieu_ = un_milieu;
8401}
8402
8404{
8405 equation_ns_=ns;
8406}
8407
8409{
8410 if (!ref_milieu_)
8411 {
8412 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
8413 Process::exit();
8414 }
8415 return ref_milieu_.valeur();
8416}
8417
8419{
8420 if (!ref_milieu_)
8421 {
8422 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
8423 Process::exit();
8424 }
8425 return ref_milieu_.valeur();
8426}
8427
8429{
8430 return 0;
8431}
8432
8434{
8435 assert(0);
8436 Process::exit();
8437 throw;
8438}
8439
8441{
8442 assert(0);
8443 Process::exit();
8444 throw;
8445}
8446
8448{
8449 return indicatrice_;
8450}
8451
8453{
8454 return indicatrice_;
8455}
8456
8458{
8459 return variables_internes_->marching_cubes_;
8460}
8461
8463{
8464 return variables_internes_->marching_cubes_;
8465}
8466
8468{
8469 return variables_internes_->maillage_interface;
8470}
8471
8473{
8474 return variables_internes_->maillage_interface;
8475}
8477{
8478 return variables_internes_->remaillage_interface_;
8479}
8480
8482{
8483 return variables_internes_->remaillage_interface_;
8484}
8486{
8487 return variables_internes_->topologie_interface_;
8488}
8489
8491{
8492 return variables_internes_->topologie_interface_;
8493}
8494
8496{
8497 return variables_internes_->doubletab_pos;
8498}
8499
8501{
8502 return variables_internes_->intvect_elements;
8503}
8504
8506{
8507 return variables_internes_->deplacement_sommets;
8508}
8509
8511{
8512 return variables_internes_->proprietes_particules_;
8513}
8514
8516{
8517 return variables_internes_->proprietes_particules_;
8518}
8519
8521{
8522 return variables_internes_->maillage_inject_;
8523}
8524
8526{
8527 return variables_internes_->maillage_inject_;
8528}
8529
8531{
8532 return variables_internes_->proprietes_inject_;
8533}
8534
8536{
8537 return variables_internes_->proprietes_inject_;
8538}
8539
8541{
8542 proprietes_particules().nettoyer(som_utilises);
8543}
8544
8545/*! @brief for PDI IO: retrieve name and type and dimensions of the indicatrice tag
8546 *
8547 */
8549{
8550 std::vector<YAML_data> data = Equation_base::data_a_sauvegarder();
8551 std::vector<YAML_data> dvi = variables_internes_->data_a_sauvegarder();
8552 data.insert(data.end(), dvi.begin(), dvi.end());
8553 return data;
8554}
8555
8556/*! @brief
8557 *
8558 */
8560{
8561 int bytes = Equation_base::sauvegarder(os);
8562 {
8563 int special, afaire;
8564 const int format_xyz = EcritureLectureSpecial::is_ecriture_special(special, afaire);
8565 double temps=inconnue().temps();
8566 Nom mon_ident("variables_internes_transport");
8567 mon_ident += Nom(temps,"%e");
8568 variables_internes_->set_time(temps);
8569 if (format_xyz)
8570 {
8572 {
8573 os << mon_ident << finl;
8574 os << variables_internes_->que_suis_je() << finl;
8575 }
8576 }
8578 {
8579 os << mon_ident << finl;
8580 os << variables_internes_->que_suis_je() << finl;
8581 }
8582 bytes += variables_internes_->sauvegarder(os);
8584 {
8585 Cerr << "Backup of collision model" << finl;
8586 if (collision_model_) bytes += collision_model_.valeur().sauvegarder(os);
8587 // we save particles position and velocity as these data
8588 // are required for the computation of contact forces
8589 Cerr << "Backup of particles position and velocity" << finl;
8590 if (format_xyz)
8591 {
8593 {
8594 for (int i=0; i<particles_position_collision_.dimension(0); i++)
8595 for (int j=0; j<particles_position_collision_.dimension(1); j++)
8597 for (int i=0; i<particles_velocity_collision_.dimension(0); i++)
8598 for (int j=0; j<particles_velocity_collision_.dimension(1); j++)
8600 }
8601 }
8603 {
8604 Cerr << "Backup of collision model not supported with pdi format" << finl;
8605 Process::exit();
8606 }
8607 else
8608 {
8610 bytes += 8 * particles_position_collision_.size_array();
8612 bytes += 8 * particles_velocity_collision_.size_array();
8613 }
8614 }
8615 }
8616 os.flush();
8617
8618 return bytes;
8619}
8620
8622{
8623 Cerr << "Transport_Interfaces_FT_Disc::reprendre" << finl;
8625 {
8627 {
8628 Nom id, type_name;
8629 is >> id >> type_name;
8630 if ( (! id.debute_par("variables_internes_transport"))
8631 || type_name != variables_internes_->que_suis_je())
8632 {
8633 Cerr << "Error for the method Transport_Interfaces_FT_Disc::reprendre" << finl;
8634 Cerr << variables_internes_->que_suis_je() <<" was expected."<< finl;
8635 Process::exit();
8636 }
8637 }
8638 variables_internes_->maillage_interface.associer_equation_transport(*this);
8639 const Nom& restart_fname = get_probleme_base().restart_filename();
8640 variables_internes_->set_restart_fname(restart_fname);
8641 variables_internes_->set_time(schema_temps().temps_courant());
8642 variables_internes_->reprendre(is);
8643 variables_internes_->injection_interfaces_last_time_ = schema_temps().temps_courant();
8645 {
8646 if (collision_model_) collision_model_.valeur().reprendre(is);
8647 const int nb_particles_tot=collision_model_.valeur().get_nb_particles_tot();
8648 particles_position_collision_.resize(nb_particles_tot,dimension);
8649 particles_velocity_collision_.resize(nb_particles_tot,dimension);
8650 const int format_xyz = EcritureLectureSpecial::is_lecture_special();
8651 if (format_xyz)
8652 {
8653 for (int i=0; i<particles_position_collision_.dimension(0); i++)
8654 for (int j=0; j<particles_position_collision_.dimension(1); j++)
8656 for (int i=0; i<particles_velocity_collision_.dimension(0); i++)
8657 for (int j=0; j<particles_velocity_collision_.dimension(1); j++)
8659 return 1;
8660 }
8661 else if (TRUST_2_PDI::is_PDI_restart())
8662 {
8663 Cerr << "Backup of collision model not supported with pdi format" << finl;
8664 Process::exit();
8665 }
8666 else
8667 {
8670 }
8671 const Domaine& domain = domaine_dis().domaine();
8673 }
8674 }
8675 return 1;
8676}
8677
8679{
8680 return probleme_base_.valeur();
8681}
8682
8684{
8685 return variables_internes_->parcours_interface_;
8686}
8687
8689{
8690 return variables_internes_->connectivite_frontieres_;
8691}
8692
8694{
8695 return variables_internes_->algorithmes_transport_.valeur();
8696}
8697
8698
8699void Transport_Interfaces_FT_Disc::fill_map_post_FT(Transport_Interfaces_FT_Disc::
8700 my_map& map_post, DoubleTab *ftab) const
8701{
8702 const Motcle som = "sommets";
8703 const Motcle elem = "elements";
8704 const Motcle bi = "elements et sommets";
8705 const DoubleTab dummytab;
8706
8707 map_post.emplace(Postraitement_base::demande_description, map_element_post_FT(bi,&Transport_Interfaces_FT_Disc::
8708 fill_ftab_vertices_curvature, ftab, dummytab));
8709 map_post.emplace("courbure", map_element_post_FT(som,&Transport_Interfaces_FT_Disc::
8710 fill_ftab_vertices_curvature, ftab, dummytab));
8711 map_post.emplace("vitesse", map_element_post_FT (som,&Transport_Interfaces_FT_Disc::
8712 fill_ftab_velocity, ftab, dummytab));
8713 map_post.emplace("vitesse_repere_local", map_element_post_FT (som,&Transport_Interfaces_FT_Disc::
8715 map_post.emplace("normale_unitaire", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8716 fill_ftab_normal_unit, ftab, dummytab));
8717 map_post.emplace("pressure", map_element_post_FT(elem,&Transport_Interfaces_FT_Disc::
8718 fill_ftab_pressure, ftab, dummytab));
8719 map_post.emplace("pressure_force", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8720 fill_ftab_pressure_force, ftab, dummytab));
8721 map_post.emplace("friction_force", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8722 fill_ftab_friction_force, ftab, dummytab));
8723
8724 map_post.emplace("sigma_xx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8725 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xx_fa7()));
8726 map_post.emplace("sigma_xy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8727 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xy_fa7()));
8728 map_post.emplace("sigma_xz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8729 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xz_fa7()));
8730 map_post.emplace("sigma_yx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8731 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yx_fa7()));
8732 map_post.emplace("sigma_yy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8733 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yy_fa7()));
8734 map_post.emplace("sigma_yz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8735 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yz_fa7()));
8736 map_post.emplace("sigma_zx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8737 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zx_fa7()));
8738 map_post.emplace("sigma_zy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8739 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zy_fa7()));
8740 map_post.emplace("sigma_zz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8741 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zz_fa7()));
8742 map_post.emplace("pressure_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8743 fill_ftab_Stokes_pressure_interp, ftab, dummytab));
8744 map_post.emplace("pressure_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8745 fill_ftab_Stokes_pressure_th, ftab, dummytab));
8746 map_post.emplace("pressure_force_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8748 map_post.emplace("pressure_force_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8750 map_post.emplace("friction_force_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8752 map_post.emplace("friction_force_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8754
8755 map_post.emplace("sigma_xx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8756 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xx_fa7()));
8757 map_post.emplace("sigma_xy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8758 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xy_fa7()));
8759 map_post.emplace("sigma_xz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8760 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xz_fa7()));
8761 map_post.emplace("sigma_yx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8762 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yx_fa7()));
8763 map_post.emplace("sigma_yy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8764 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yy_fa7()));
8765 map_post.emplace("sigma_yz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8766 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yz_fa7()));
8767 map_post.emplace("sigma_zx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8768 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zx_fa7()));
8769 map_post.emplace("sigma_zy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8770 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zy_fa7()));
8771 map_post.emplace("sigma_zz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8772 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zz_fa7()));
8773
8774 map_post.emplace("sigma_xx_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8776 map_post.emplace("sigma_xy_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8778 map_post.emplace("sigma_xz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8780 map_post.emplace("sigma_yy_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8782 map_post.emplace("sigma_yz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8784 map_post.emplace("sigma_zz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8786
8787 map_post.emplace("dUdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8788 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdx_P1()));
8789 map_post.emplace("dUdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8790 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdy_P1()));
8791 map_post.emplace("dUdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8792 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdz_P1()));
8793 map_post.emplace("dVdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8794 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdx_P1()));
8795 map_post.emplace("dVdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8796 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdy_P1()));
8797 map_post.emplace("dVdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8798 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdz_P1()));
8799 map_post.emplace("dWdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8800 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdx_P1()));
8801 map_post.emplace("dWdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8802 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdy_P1()));
8803 map_post.emplace("dWdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8804 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdz_P1()));
8805
8806 map_post.emplace("dUdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8807 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdx_P2()));
8808 map_post.emplace("dUdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8809 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdy_P2()));
8810 map_post.emplace("dUdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8811 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdz_P2()));
8812 map_post.emplace("dVdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8813 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdx_P2()));
8814 map_post.emplace("dVdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8815 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdy_P2()));
8816 map_post.emplace("dVdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8817 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdz_P2()));
8818 map_post.emplace("dWdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8819 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdx_P2()));
8820 map_post.emplace("dWdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8821 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdy_P2()));
8822 map_post.emplace("dWdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8823 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdz_P2()));
8824
8825 map_post.emplace("dUdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8826 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P1()));
8827 map_post.emplace("dUdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8828 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdy_P1()));
8829 map_post.emplace("dUdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8830 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P1()));
8831 map_post.emplace("dVdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8832 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdx_P1()));
8833 map_post.emplace("dVdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8834 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdy_P1()));
8835 map_post.emplace("dVdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8836 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P1()));
8837 map_post.emplace("dWdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8838 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P1()));
8839 map_post.emplace("dWdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8840 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P1()));
8841 map_post.emplace("dWdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8842 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P1()));
8843
8844 map_post.emplace("dUdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8845 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P2()));
8846 map_post.emplace("dUdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8847 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdy_P2()));
8848 map_post.emplace("dUdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8849 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P2()));
8850 map_post.emplace("dVdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8851 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdx_P2()));
8852 map_post.emplace("dVdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8853 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdy_P2()));
8854 map_post.emplace("dVdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8855 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P2()));
8856 map_post.emplace("dWdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8857 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P2()));
8858 map_post.emplace("dWdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8859 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P2()));
8860 map_post.emplace("dWdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8861 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P2()));
8862
8863 map_post.emplace("dUdx_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8864 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P1_Stokes_th()));
8865 map_post.emplace("dUdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8866 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P1_Stokes_th()));
8867 map_post.emplace("dVdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8868 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P1_Stokes_th()));
8869 map_post.emplace("dWdx_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8870 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P1_Stokes_th()));
8871 map_post.emplace("dWdy_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8872 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P1_Stokes_th()));
8873 map_post.emplace("dWdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8874 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P1_Stokes_th()));
8875
8876 map_post.emplace("dUdx_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8877 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P2_Stokes_th()));
8878 map_post.emplace("dUdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8879 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P2_Stokes_th()));
8880 map_post.emplace("dVdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8881 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P2_Stokes_th()));
8882 map_post.emplace("dWdx_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8883 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P2_Stokes_th()));
8884 map_post.emplace("dWdy_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8885 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P2_Stokes_th()));
8886 map_post.emplace("dWdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8887 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P2_Stokes_th()));
8888
8889 map_post.emplace("U_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8890 fill_ftab_vector, ftab, post_process_hydro_forces_.get_U_P1()));
8891 map_post.emplace("U_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8892 fill_ftab_vector, ftab, post_process_hydro_forces_.get_U_P2()));
8893 map_post.emplace("U_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8894 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P1()));
8895 map_post.emplace("U_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8896 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P2()));
8897 map_post.emplace("U_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8898 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P1_Stokes_th()));
8899 map_post.emplace("U_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8900 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P2_Stokes_th()));
8901 map_post.emplace("heat_transfer", map_element_post_FT(elem, &Transport_Interfaces_FT_Disc::fill_ftab_scalar,
8903
8904}
8905
8906/*! @brief Cherche le champ discret aux interfaces dont le nom est "champ", et verifie qu'il peut etre postraite a la localisation demandee (loc).
8907 *
8908 * Si oui on renvoie 1 et, si ftab est non nul, on remplit le champ ftab
8909 * avec le champ demande.
8910 * Si non, on renvoie 0.
8911 * (la fonction est appelee avec ftab=0 lors de la lecture du postraitement,
8912 * car on n'a pas besoin de la valeur du champ, on veut seulement verifier
8913 * qu'il existe).
8914 *
8915 */
8917{
8918 int res = 1;
8919
8920 const Motcle som = "sommets"; // post-processing at the vertices only
8921 const Motcle elem = "elements"; // post-processing at the element only
8922 const Motcle bi = "elements et sommets"; // post-processing at both location
8923
8924 Transport_Interfaces_FT_Disc::my_map map_post;
8925 fill_map_post_FT(map_post,ftab);
8926
8927 Motcle the_key="key";
8928 Motcle the_loc="loc";
8929 map_element_post_FT::func_type the_function=&Transport_Interfaces_FT_Disc::fill_ftab_scalar;
8930 DoubleTab the_tab_values;
8931 bool elem_found=false;
8932
8933 // I didn't manage to use std::map::find properly, so I loop on map_post to find the element
8934 for (const auto& [key, value] : map_post)
8935 {
8936 if (key==champ)
8937 {
8938 the_key=key;
8939 the_loc=value.location_;
8940 the_function=value.function_;
8941 the_tab_values=value.values_;
8942 elem_found=true;
8943 break;
8944 }
8945 }
8946
8948 {
8949 Cerr<<"The real fields to be post-processed are :"<<finl;
8950 int i=0;
8951 for (const auto& [key, value] : map_post)
8952 {
8953 Cerr << " Fields("<<i<<") : " << key << ", Location : ";
8954
8955 Cerr << value.location_ << finl;
8956 i++;
8957 }
8958 res = 0;
8959 }
8960 else if (!elem_found) // existing field?
8961 res = 0; // inexisting field
8962 else if (! (the_loc==bi
8963 || (the_loc==som && loc==Postraitement_base::SOMMETS)
8964 || (the_loc==elem && loc==Postraitement_base::ELEMENTS)) ) // authorized location?
8965 res = 0; // unauthorized location
8966 else
8967 {
8968 if (ftab)
8969 {
8970 if(post_process_hydro_forces_.get_is_compute_forces())
8971 post_process_hydro_forces_.compute_hydrodynamic_forces();
8972 if(post_process_hydro_forces_.get_is_compute_forces_Stokes_th())
8973 post_process_hydro_forces_Stokes_.compute_hydrodynamic_forces();
8974 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
8975 post_process_hydro_forces_.compute_heat_transfer();
8976 (this->*the_function)(ftab,the_tab_values);
8977 }
8978 res = 1;
8979 }
8980
8981 return res;
8982}
8983
8984/*! @brief Voir l'autre get_champ_post_FT.
8985 *
8986 * Cette fonction est specifique aux champs d'entiers.
8987 *
8988 */
8990{
8991 int res = 1;
8992
8993 const Motcle som = "sommets"; //postraitement possible uniquement aux sommets
8994 const Motcle elem = "elements"; //postraitement possible uniquement aux elements
8995 const Motcle bi = "elements et sommets"; //postraitement possible aux sommets et aux elements
8996 const int nb_champs = 5;
8997 Motcles fields(nb_champs);
8998 {
9000 fields[1] = "pe"; // PE owner
9001 fields[2] = "numero"; // numero local du sommet/element
9002 fields[3] = "pe_local"; // PE local
9003 fields[4] = "compo_connexe";
9004 }
9005 Motcles localisations(nb_champs);
9006 {
9007 localisations[0] = bi;
9008 localisations[1] = bi;
9009 localisations[2] = bi;
9010 localisations[3] = bi;
9011 localisations[4] = elem;
9012 }
9013
9014 int rank=fields.search(champ), i;
9015
9016 if (rank==0)
9017 {
9018 Cerr<<"The integer fields to be post-processed are:"<<finl;
9019 for (i=1 ; i<nb_champs ; i++)
9020 {
9021 Cerr << " Fields("<<i<<") : "<< fields[i] << " # Localisations : " << localisations[i] << finl;
9022 }
9023 res = 0;
9024 }
9025 else if (rank==-1)
9026 {
9027 //champ inexistant
9028 res = 0;
9029 }
9030 else if (! (localisations[rank]==bi
9031 || (localisations[rank]==som && loc==Postraitement_base::SOMMETS)
9032 || (localisations[rank]==elem && loc==Postraitement_base::ELEMENTS)) ) //test localisation autorisee ?
9033 {
9034 //localisation non autorisee
9035 res = 0;
9036 }
9037 else
9038 {
9039 if (itab) // Pointeur non nul : calculer le champ
9040 {
9041
9043 const int n =
9045 ? maillage.nb_sommets()
9046 : maillage.nb_facettes();
9047 int i2;
9048 itab->resize(n);
9049
9050 switch (rank )
9051 {
9052 case 1:
9053 {
9055 {
9056 //TMP : tant que IntTabFt et IntTab n'ont pas fusionne :
9057 //*itab = maillage_interface_->sommet_PE_owner();
9058 const ArrOfInt& pe_som = maillage.sommet_PE_owner();
9059 for (i2=0 ; i2<n ; i2++)
9060 {
9061 (*itab)(i2) = pe_som[i2];
9062 }
9063 }
9064 else
9065 {
9066 ArrOfIntFT pe_fac;
9067 maillage.facette_PE_owner(pe_fac);
9068 for (i2=0 ; i2<n ; i2++)
9069 {
9070 (*itab)(i2) = pe_fac[i2];
9071 }
9072 }
9073 break;
9074 }
9075 case 2:
9076 {
9077 for (i2=0 ; i2<n ; i2++)
9078 {
9079 (*itab)(i2) = i2;
9080 }
9081 break;
9082 }
9083 case 3:
9084 {
9085 (*itab) = Process::me();
9086 break;
9087 }
9088 case 4:
9089 {
9090 maillage.intersections_elem_facettes();
9091 ArrOfIntFT compo(maillage.nb_facettes());
9092 compo = 0;
9093 int n2 = search_connex_components_local_FT(maillage, compo);
9094 compute_global_connex_components_FT(maillage, compo, n2);
9095 const int nbf = maillage.nb_facettes();
9096 for (int ii = 0; ii < nbf; ii++)
9097 (*itab)[ii] = compo[ii];
9098
9099 break;
9100 }
9101 default:
9102 Cerr << "Transport_Interfaces_FT_Disc::get_champ_post_FT : unexpected case" << finl;
9103 assert(0);
9104 Process::exit();
9105 }
9106 }
9107 }
9108 return res;
9109}
9110
9111/*! @brief Renvoie le maillage stocke specialement pour le postraitement (si on veut postraiter un etat intermediaire.
9112 *
9113 * ..)
9114 *
9115 */
9117{
9118 //return variables_internes_->maillage_pour_post;
9119 return maillage_interface();
9120}
9121
9123{
9124 return variables_internes_->n_iterations_distance;
9125}
9126
9127
9128/*! @brief Renvoi de la distance signee entre l'interface et les sommets du maillage eulerien.
9129 *
9130 * Si cette distance n'a pas encore ete calculee, appel a calculer_distance_interface_sommets.
9131 * C'est un DoubleTab parce qu'il n'existe pas (encore) de champ aux sommets en VDF ...
9132 *
9133 */
9135{
9136 // Si le tag du maillage et le tag du champ sont identiques, inutile de recalculer:
9137 const int tag = maillage_interface().get_mesh_tag();
9138 if (tag == variables_internes_->distance_sommets_cache_tag)
9139 {
9140 return variables_internes_->distance_interface_sommets;
9141 }
9142 variables_internes_->distance_sommets_cache_tag = tag;
9143 assert(tag == variables_internes_->distance_normale_cache_tag);
9144 const DoubleTab& dist_elem = get_distance_interface().valeurs();
9145 const DoubleTab& normale_elem = get_normale_interface().valeurs();
9146 DoubleTab& dist_som = variables_internes_->distance_interface_sommets;
9147 calculer_distance_interface_sommets(dist_elem, normale_elem, dist_som);
9148 return dist_som;
9149}
9150
9151/*! @brief Calcule dist_som, la distance entre l'interface et les sommets du maillage eulerien a partir de dist_elem et normale_elem,
9152 *
9153 * distance et normale a l'interface aux centres des elements euleriens.
9154 * Pour un element, on evalue la distance entre chaque sommet de l'element et l'interface
9155 * comme :
9156 * d = d1 + d2,
9157 * d2 = normale scalaire (position_sommet - centre_element)
9158 * d1 est la distance entre l'interface et le centre de l'element,
9159 * normale est la normale a l'interface evaluee au centre de l'element
9160 * Ensuite, la distance entre un sommet et l'interface est la moyenne de toutes
9161 * les distances calculee a l'aide des elements adjacents a ce sommet.
9162 * La distance est invalide au-dela d'une certaine epaisseur autour de l'interface
9163 * (voir iterations de lissage dans calculer_distance_interface).
9164 * Dans ce cas on met une distance de +1e30 si l'indicatrice est >0.5,
9165 * sinon on met -1e30 (ce choix permet d'utiliser la fonction
9166 * distance dans les marching-cubes sans avoir a calculer une vraie distance partout).
9167 * Parametre : dist_elem
9168 * Signification : tableau contenant pour chaque element reel et virtuel la distance
9169 * entre l'interface et le centre de l'element (calculee par
9170 * calculer_distance_interface). L'espace virtuel doit etre a jour.
9171 * Parametre : normale_elem
9172 * Signification : idem pour la normale a l'interface
9173 * Parametre : dist_som
9174 * Signification : tableau ou on stocke le resultat du calcul. Le tableau doit
9175 * avoir la bonne taille et un descripteur adequat (voir "discretiser",
9176 * a priori un tableau avec une epaisseur de joint de zero et uniquement
9177 * des items communs).
9178 *
9179 */
9181 const DoubleTab& dist_elem,
9182 const DoubleTab& normale_elem,
9183 DoubleTab& dist_som) const
9184{
9185 static const double distance_sommets_invalides = -1.e30;
9186
9187 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
9188 const IntTab& elem_som = domaine_vf.domaine().les_elems();
9189 const DoubleTab& xp = domaine_vf.xp();
9190 const DoubleTab& coord_som = domaine_vf.domaine().les_sommets();
9191
9192 const int nb_sommets = dist_som.dimension_tot(0);
9193 ArrOfInt ncontrib(nb_sommets);
9194 ncontrib = 0;
9195 dist_som = 0.;
9196
9197 const int dim = Objet_U::dimension;
9198 double centre[3] = {0., 0., 0.};
9199 double normale[3] = {0., 0., 0.};
9200 // Calcul de SOMME(d1+d2) pour tous les elements voisins de chaque sommet :
9201 int elem, i;
9202 const int nb_elem_tot = dist_elem.dimension_tot(0);
9203 const int nb_som_elem = elem_som.line_size();
9204
9205 for (elem = 0; elem < nb_elem_tot; elem++)
9206 {
9207 const double d1 = dist_elem(elem);
9208 // Si la distance est invalide, on passe:
9209 if (d1 < distance_sommets_invalides)
9210 continue;
9211 // Centre de l'element et normale a l'interface pour cet element :
9212 for (i = 0; i < dim; i++)
9213 {
9214 centre[i] = xp(elem, i);
9215 normale[i] = normale_elem(elem, i);
9216 }
9217 // Boucle sur les sommets de l'element
9218 for (i = 0; i < nb_som_elem; i++)
9219 {
9220 const int som = elem_som(elem, i);
9221 // dist_som ne contient que des sommets reels en general.
9222 // si le sommet n'est pas dans dist_som, on ne calcule pas.
9223 if (som < nb_sommets)
9224 {
9225 double d2 = 0.;
9226 int j;
9227 for (j = 0; j < dim; j++)
9228 {
9229 double position_sommet = coord_som(som, j);
9230 d2 += (position_sommet - centre[j]) * normale[j];
9231 }
9232 dist_som(som) += d1 + d2;
9233 ++(ncontrib[som]);
9234 }
9235 }
9236 }
9237 // Division par le nombre d'elements voisins
9238 const double valeur_invalide = distance_sommets_invalides * 1.1;
9239#ifdef __INTEL_COMPILER
9240#pragma novector // Desactive vectorisation sur Intel car crash sinon
9241#endif
9242 for (i = 0; i < nb_sommets; i++)
9243 {
9244 const int n = ncontrib[i];
9245 if (n > 0)
9246 dist_som(i) /= n;
9247 else
9248 dist_som(i) = valeur_invalide;
9249 }
9250 dist_som.echange_espace_virtuel();
9251 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface_sommets",dist_som);
9252}
9253
9254/*! @brief Calcul d'un champ scalaire aux elements contenant une distance signee entre le centre de l'element et l'interface.
9255 *
9256 * La distance est positive dans
9257 * la phase 1 et negative dans la phase 0.
9258 * On calcule aussi un champ vectoriel aux elements contenant une normale
9259 * a l'interface. Ce champ est evalue en resolvant moralement
9260 * laplacien(normale) = gradient(indicatrice)
9261 * ou gradient(indicatrice) est le gradient de l'indicatrice continue
9262 * c'est a dire un dirac localise a la surface de l'interface.
9263 * Pour l'instant, cette normale est calculee de facon approchee avec quelques
9264 * iterations d'un lisseur. Le support est donc limite au voisinage de l'interface.
9265 * Pour les autres elements, la distance vaut -1.e30
9266 * Precondition : le maillage doit etre parcouru
9267 *
9268 */
9270 const Maillage_FT_Disc& maillage,
9271 DoubleTab& distance_elements,
9272 DoubleTab& normale_elements,
9273 const int n_iter) const
9274{
9275 statistics().create_custom_counter("Calculer_distance_interface",3,"FrontTracking");
9276 statistics().begin_count("Calculer_distance_interface",statistics().get_last_opened_counter_level()+1);
9277
9278 static const double distance_sommets_invalides = -1.e30;
9279
9280 // Coordonnees des sommets du maillage eulerien:
9281 const Domaine_dis_base& mon_dom_dis = domaine_dis();
9282 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
9283 const DoubleTab& centre_element = domaine_vf.xp();
9284
9285 // Tableau contenant une approximation de la normale aux sommets du maillage
9286 // eulerien :
9287 distance_elements = distance_sommets_invalides * 1.1;
9288 normale_elements = 0.;
9289
9290 const int nb_elem = mon_dom_dis.domaine().nb_elem();
9291 const int dim = Objet_U::dimension;
9292
9293 // Calcul de la distance pour l'epaisseur 0 (sommets des elements traverses par
9294 // l'interface). Pour chaque element, on calcule le plan passant par
9295 // le centre de gravite des portions de facettes et dont la normale est
9296 // la moyenne des normales aux portions de facettes, ponderees par la surface
9297 // des portions de facettes. La distance interface/element est la distance
9298 // entre ce plan et le centre de l'element.
9299 {
9300 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
9301 const ArrOfInt& index_elem = intersections.index_elem();
9302 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
9303 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9304 const IntTab& facettes = maillage.facettes();
9305 const DoubleTab& sommets = maillage.sommets();
9306 // Boucle sur les elements
9307 for (int elem = 0; elem < nb_elem; elem++)
9308 {
9309 int index = index_elem[elem];
9310 // Moyenne ponderee des normales aux facettes qui traversent l'element
9311 double normale[3] = {0., 0., 0.};
9312 // Centre de gravite de l'intersection facettes/element
9313 double centre[3] = {0., 0., 0.};
9314 // Somme des poids
9315 double surface_tot = 0.;
9316 // Boucle sur les facettes qui traversent cet element
9317 while (index >= 0)
9318 {
9320 intersections.data_intersection(index);
9321
9322 const int num_facette = data.numero_facette_;
9323#ifdef AVEC_BUG_SURFACES
9324 const double surface = data.surface_intersection_;
9325#else
9326 const double surface = data.fraction_surface_intersection_ * surface_facettes[num_facette];
9327#endif
9328 surface_tot += surface;
9329 for (int i = 0; i < dim; i++)
9330 {
9331 normale[i] += surface * normale_facettes(num_facette, i);
9332 // Calcul du centre de gravite de l'intersection facette/element
9333 double g_i = 0.; // Composante i de la coordonnee du centre de gravite
9334 for (int j = 0; j < dim; j++)
9335 {
9336 const int som = facettes(num_facette, j);
9337 const double coord = sommets(som, i);
9338 const double coeff = data.barycentre_[j];
9339 g_i += coord * coeff;
9340 }
9341 centre[i] += surface * g_i;
9342 }
9343 index = data.index_facette_suivante_;
9344 }
9345 if (surface_tot > 0.)
9346 {
9347 // La normale stockee n'est pas normee : norme a peu pres egale a la surface
9348 // d'interface qui a servi a la calculer.
9349 // centre = somme(centre[facette] * surface) / somme(surface)
9350 const double inverse_surface_tot = 1. / surface_tot;
9351 double norme = 0.;
9352 int j;
9353 for (j = 0; j < dim; j++)
9354 {
9355 norme += normale[j] * normale[j];
9356 normale_elements(elem, j) = normale[j];
9357 centre[j] *= inverse_surface_tot;
9358 }
9359 if (norme > 0)
9360 {
9361 double i_norme = 1./sqrt(norme);
9362 double distance = 0.;
9363 for (j = 0; j < dim; j++)
9364 {
9365 double n_j = normale[j] * i_norme; // normale normee
9366 distance += (centre_element(elem, j) - centre[j]) * n_j;
9367 }
9368 distance_elements(elem) = distance;
9369 }
9370 }
9371 }
9372 normale_elements.echange_espace_virtuel();
9373 distance_elements.echange_espace_virtuel();
9374 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface",normale_elements);
9375 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface",distance_elements);
9376 }
9377
9378 DoubleTab terme_src(normale_elements);
9379 DoubleTab tmp(normale_elements);
9380
9381 const IntTab& face_voisins = domaine_vf.face_voisins();
9382 const IntTab& elem_faces = domaine_vf.elem_faces();
9383 const int nb_elem_voisins = elem_faces.line_size();
9384
9385 // Calcul d'une normale aux elements :
9386 int iteration;
9387 for (iteration = 0; iteration < n_iter; iteration++)
9388 {
9389 // Iteration du lisseur : moralement on fait
9390 // normale = normale + (terme_source - laplacien(normale)) * facteur
9391 // qui converge vers
9392 // laplacien(normale) = terme_source
9393 // mais le laplacien est pipo : en pratique on fait juste :
9394 // normale = moyenne(normale sur les elem voisins) + terme_source
9395
9396 const double un_sur_ncontrib = 1. / (1. + nb_elem_voisins);
9397 int elem, i, k;
9398 for (elem = 0; elem < nb_elem; elem++)
9399 {
9400 // La moyenne du vecteur normal sur les voisins:
9401 double n[3] = {0., 0., 0.};
9402 for (i = 0; i < dim; i++)
9403 n[i] = normale_elements(elem, i);
9404 for (k = 0; k < nb_elem_voisins; k++)
9405 {
9406 // On cherche l'element voisin par la face k
9407 const int face = elem_faces(elem, k);
9408 const int e_voisin = face_voisins(face, 0) + face_voisins(face, 1) - elem;
9409 if (e_voisin >= 0) // Si on n'est pas au bord...
9410 for (i = 0; i < dim; i++)
9411 n[i] += normale_elements(e_voisin, i);
9412 }
9413 for (i = 0; i < dim; i++)
9414 tmp(elem, i) = terme_src(elem, i) + n[i] * un_sur_ncontrib;
9415 }
9416 normale_elements = tmp;
9417 normale_elements.echange_espace_virtuel();
9418 }
9419 // On normalise la normale, et on cree une liste des elements pour lesquels
9420 // la normale est connue :
9421 ArrOfIntFT liste_elements;
9422 {
9423 int elem;
9424 for (elem = 0; elem < nb_elem; elem++)
9425 {
9426 double nx = normale_elements(elem, 0);
9427 double ny = normale_elements(elem, 1);
9428 double nz = (dim==3) ? normale_elements(elem, 2) : 0.;
9429 double norme2 = nx*nx + ny*ny + nz*nz;
9430 if (norme2 > 0.)
9431 {
9432 double i_norme = 1. / sqrt(norme2);
9433 normale_elements(elem, 0) = nx * i_norme;
9434 normale_elements(elem, 1) = ny * i_norme;
9435 if (dim==3)
9436 normale_elements(elem, 2) = nz * i_norme;
9437 liste_elements.append_array(elem);
9438 }
9439 }
9440 normale_elements.echange_espace_virtuel();//Manque cet echange (MB)
9441 }
9442 // Calcul d'une distance a l'interface :
9443 terme_src = distance_elements;
9444 tmp = distance_elements;
9445 for (iteration = 0; iteration < n_iter; iteration++)
9446 {
9447 int i_elem, elem;
9448 const int liste_elem_size = liste_elements.size_array();
9449 for (i_elem = 0; i_elem < liste_elem_size; i_elem++)
9450 {
9451 elem = liste_elements[i_elem];
9452 if (terme_src(elem) > distance_sommets_invalides)
9453 {
9454 // Pour les elements traverses par l'interface, la distance n'est pas recalculee.
9455 tmp(elem) = distance_elements(elem);
9456 }
9457 else
9458 {
9459 // Pour les autres, on calcule une distance pour chaque element voisin
9460 double ncontrib = 0.;
9461 double somme_distances = 0.;
9462 int k;
9463 for (k = 0; k < nb_elem_voisins; k++)
9464 {
9465 // On cherche l'element voisin par la face k
9466 const int face = elem_faces(elem, k);
9467 const int e_voisin = face_voisins(face, 0) + face_voisins(face, 1) - elem;
9468 if (e_voisin >= 0) // Si on n'est pas au bord...
9469 {
9470 const double distance_voisin = distance_elements(e_voisin);
9471 if (distance_voisin > distance_sommets_invalides)
9472 {
9473 // Calcul d'une normale moyenne entre l'element et le voisin
9474 double nx = normale_elements(elem, 0) + normale_elements(e_voisin, 0);
9475 double ny = normale_elements(elem, 1) + normale_elements(e_voisin, 1);
9476 double nz = (dim==3)
9477 ? normale_elements(elem, 2) + normale_elements(e_voisin, 2) : 0.;
9478 double norm2 = nx*nx + ny*ny + nz*nz;
9479 if (norm2 > 0.)
9480 {
9481 double i_norm = 1./sqrt(norm2);
9482 nx *= i_norm;
9483 ny *= i_norm;
9484 nz *= i_norm;
9485 }
9486 // Calcul du vecteur (element - element_voisin)
9487 double dx = centre_element(elem, 0) - centre_element(e_voisin, 0);
9488 double dy = centre_element(elem, 1) - centre_element(e_voisin, 1);
9489 double dz = (dim==3)
9490 ? centre_element(elem, 2) - centre_element(e_voisin, 2) : 0.;
9491 double d = nx * dx + ny * dy + nz * dz + distance_voisin;
9492 somme_distances += d;
9493 ncontrib++;
9494 }
9495 }
9496 }
9497 // Moyenne des distances obtenues avec les elements voisins.
9498 if (ncontrib > 0.)
9499 {
9500 double d = somme_distances / ncontrib;
9501 tmp(elem) = d;
9502 }
9503 }
9504 }
9505 distance_elements = tmp;
9506 distance_elements.echange_espace_virtuel();
9507 }
9508 statistics().end_count("Calculer_distance_interface");
9509}
9510
9512 const ArrOfInt& compo_connexes_facettes,
9513 const int nb_compo_tot,
9514 const DoubleTab& vitesse_sommets,
9515 DoubleTab& vitesses,
9516 DoubleTab& positions) const
9517{
9518 assert(nb_compo_tot == vitesses.dimension(0));
9519 assert(nb_compo_tot == positions.dimension(0));
9520
9521 const int dim = vitesses.line_size();
9522 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9523 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
9524 const IntTab& facettes = maillage.facettes();
9525 const DoubleTab& sommets = maillage.sommets();
9526 assert(facettes.line_size() == dim);
9527
9528 // Surface totale de chaque composante connexe, initialise a zero
9529 ArrOfDouble surfaces_compo(nb_compo_tot);
9530 positions = 0.;
9531
9532 // Calcul du centre de gravite de la composante connexe
9533 // (centre de gravite de la surface, pas du volume)
9534 const int nb_facettes_tot = facettes.dimension_tot(0);
9535 {
9536 for (int i = 0; i < nb_facettes_tot; i++)
9537 {
9538 if (maillage.facette_virtuelle(i))
9539 continue;
9540 const int compo = compo_connexes_facettes[i];
9541 const double surface = surface_facettes[i];
9542 surfaces_compo[compo] += surface;
9543 // Centre de gravite de la facette, pondere par la surface
9544 for (int j = 0; j < dim; j++)
9545 {
9546 // Indice du sommet
9547 const int s = facettes(i, j);
9548 for (int k = 0; k < dim; k++)
9549 // On divisera par dim a la fin:
9550 positions(compo, k) += surface * sommets(s, k);
9551 }
9552 }
9553 mp_sum_for_each_item(surfaces_compo);
9554 mp_sum_for_each_item(positions);
9555
9556 positions *= (1. / dim);
9557
9558 DoubleVect s; // tab_divide prend DoubleVect, pas ArrOfDouble...
9559 s.ref_array(surfaces_compo);
9560 tab_divide_any_shape(positions, s);
9561 }
9562 ArrOfInt som(3);
9563 // Calcul de la vitesse de deplacement moyenne
9564 vitesses = 0.;
9565 //calcul de la vitesse moyenne de deplacement de l'interface
9566 for (int fa7 = 0; fa7 < nb_facettes_tot; fa7++)
9567 {
9568
9569 if (maillage.facette_virtuelle(fa7))
9570 continue;
9571 const double si=surface_facettes[fa7];
9572 som=0;
9573
9574 for (int d=0; d<dim; d++)
9575 som[d]=facettes(fa7,d);
9576
9577 //calcul de ds_dt
9578 double ds_dt=0.;
9579
9580 if(dim==2)
9581 {
9582 const double n0=normale_facettes(fa7,0);
9583 const double n1=normale_facettes(fa7,1);
9584 ds_dt=-n1*vitesse_sommets(som[0],0)+n0*vitesse_sommets(som[0],1)+n1*vitesse_sommets(som[1],0)-n0*vitesse_sommets(som[1],1);
9585 }
9586 else
9587 {
9588 const double n0=normale_facettes(fa7,0)*0.5;
9589 const double n1=normale_facettes(fa7,1)*0.5;
9590 const double n2=normale_facettes(fa7,2)*0.5;
9591 double s2s1[3],d_surface[3];
9592
9593 for (int i = 0; i < 3; i++)
9594 {
9595 // La differentielle de surface pour un deplacement du sommet i
9596 // est le produit vectoriel de la normale par le vecteur
9597 // s2s1 = (sommet[(i+1)%3] - sommet[(i+2)%3]) * 0.5
9598 // (vecteur de norme "base du triangle * 0.5" et de direction
9599 // la hauteur du triangle)
9600 const int s0 = som[i];
9601 const int s1 = som[ (i+1)%3 ];
9602 const int s2 = som[ (i+2)%3 ];
9603
9604 s2s1[0] = sommets(s1,0) - sommets(s2,0);
9605 s2s1[1] = sommets(s1,1) - sommets(s2,1);
9606 s2s1[2] = sommets(s1,2) - sommets(s2,2);
9607
9608 d_surface[0] = s2s1[1] * n2 - s2s1[2] * n1;
9609 d_surface[1] = s2s1[2] * n0 - s2s1[0] * n2;
9610 d_surface[2] = s2s1[0] * n1 - s2s1[1] * n0;
9611
9612 ds_dt+=d_surface[0]*vitesse_sommets(s0,0) + d_surface[1]*vitesse_sommets(s0,1) +d_surface[2]*vitesse_sommets(s0,2);
9613 }
9614 }
9615
9616 const int compo = compo_connexes_facettes[fa7];
9617 for (int d=0; d<dim; d++)
9618 {
9619 double V=0.;
9620 double p=0.;
9621 for (int d1=0; d1<dim; d1++)
9622 {
9623 V+=vitesse_sommets(som[d1],d);
9624 p+=sommets(som[d1],d);
9625 }
9626 V /= dim;
9627 p /= dim;
9628 vitesses(compo, d) += si * V + (p-positions(compo, d)) * ds_dt;
9629 }
9630 }
9631
9632 mp_sum_for_each_item(vitesses);
9633 {
9634 DoubleVect s; // tab_divide prend DoubleVect, pas ArrOfDouble...
9635 s.ref_array(surfaces_compo);
9636 tab_divide_any_shape(vitesses, s);
9637 }
9638
9640 {
9643 const Domaine& domain = domaine_dis().domaine();
9645 }
9646
9647}
9648
9649
9650// Note added by L. Wei on 13/01/2025
9651// This subroutine advects [valeurs] from PURE cells (both liquid and vapor).
9652// into two of their neighboring cells: one along the x-direction and another along the y-direction.
9653// The neighboring cell is identified by the normal direction of the liquid-vapor interface.
9654// Factors such as the normal vector to the liquid-vapor (L-V) interface and the proportion of the surface in x and y-dir of pure cells are considered
9655// to determine the appropriate proportion to redistribute to each neighboring cell. [i.e., the final valeur of tmp_flux]
9656// It's important to note that when this subroutine is invoked, it performs the advection process exactly once for all cells
9657// within the area where the interface normal vector ('normale_interface') is defined and non-zero. [normally serveral cells thickness surronding the interface]
9659 DoubleVect& flux,
9660 DoubleVect& valeurs)
9661{
9662 // Calcul d'un flux a travers chaque face, proportionnel a
9663 // Surface_face * (normale_interface scalaire normale_face) * grandeur_amont_a_transporter
9664 const int dim = Objet_U::dimension;
9665 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
9666 const Domaine& domaine = domaine_vf.domaine();
9667 const IntTab& face_voisins = domaine_vf.face_voisins();
9668 const IntTab& elem_faces = domaine_vf.elem_faces();
9669 const int nb_faces_tot = domaine_vf.nb_faces_tot();
9670 //const int nb_elem = domaine.nb_elem();
9671 const int nb_elem_tot = domaine.nb_elem_tot();
9672 const int nb_faces_elem = domaine_vf.domaine().nb_faces_elem();
9673 const DoubleVect& indic = get_indicatrice().valeurs();
9674 const DoubleTab& normale_interface = get_normale_interface().valeurs(); // direction: from vapour toward liquid
9675 for (int i_face = 0; i_face < nb_faces_tot; i_face++)
9676 {
9677 double f;
9678 const int elem0 = face_voisins(i_face, 0);
9679 const int elem1 = face_voisins(i_face, 1);
9680 if (elem0 < 0 || elem1 < 0) // at teh boundary
9681 f = 0.;
9682 else
9683 {
9684 double prod_scal = 0.;
9685 // Le produit scalaire est fait avec la normale a l'interface evaluee
9686 // a la face (moyenne des normales n0 et n1 des deux elements voisins.
9687 // faces_normales() donne une normale de norme egale a la surface de la face
9688 for (int i = 0; i < dim; i++)
9689 {
9690 double n0 = normale_interface(elem0, i);
9691 double n1 = normale_interface(elem1, i);
9692 prod_scal += (n0 + n1) * 0.5 * domaine_vf.face_normales(i_face, i);
9693 }
9694 if (indic(elem0) == 1. || indic(elem1) == 1.)
9695 prod_scal = - prod_scal;
9696 // Si la face appartient a deux elements diphasiques alors
9697 // on annule le flux pour eviter les echanges entre ces cellules
9698 if (indic(elem0) != 0. && indic(elem0) != 1.)
9699 {
9700 if (indic(elem1) != 0. && indic(elem1) != 1.)
9701 {
9702 prod_scal=0.;
9703 }
9704 }
9705 f = prod_scal;
9706 }
9707 flux(i_face) = f;
9708 }
9709 //
9711 //
9712 // Renormalisation des flux de sorte que la somme des flux sortants de chaque
9713 // element vide completement cet element.
9714 // On travaille sur une copie du tableau flux pour eviter les interactions
9715 // entre les deux boucles qui suivent
9716 DoubleVect tmp_flux = flux;
9717 ArrOfInt flag(nb_faces_elem);
9718 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9719 {
9720 // Somme des flux sortants de l'element:
9721 double somme = 0.;
9722 for (int j = 0; j < nb_faces_elem; j++)
9723 {
9724 int i_face = elem_faces(i_elem, j);
9725 const int elem0 = face_voisins(i_face, 0);
9726 const int elem1 = face_voisins(i_face, 1);
9727 if (elem0 < 0 || elem1 < 0)
9728 continue;
9729 // Le flux est-il sortant ?
9730 const double signe = (elem0 == i_elem) ? 1. : -1.;
9731 const double f = flux(i_face);
9732 if (f * signe > 0.)
9733 {
9734 somme += f * signe; // oui
9735 flag[j] = 1;//
9736 }
9737 }
9738 // renormalisation des flux sortants et multiplication par la valeur a transporter:
9739 if (somme > 0.)
9740 {
9741 const double facteur = valeurs(i_elem) / somme;
9742 for (int j = 0; j < nb_faces_elem; j++)
9743 {
9744 int i_face = elem_faces(i_elem, j);
9745 if (flag[j])
9746 {
9747 tmp_flux[i_face] = tmp_flux[i_face] * facteur;
9748 flag[j] = 0;
9749 }
9750 }
9751 }
9752 }
9753 // Recopie de tmp_flux dans flux
9754 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9755 {
9756 for (int j = 0; j < nb_faces_elem; j++)
9757 {
9758 int i_face = elem_faces(i_elem, j);
9759 flux[i_face]=tmp_flux[i_face];
9760 }
9761 }
9762 // Application du flux calcule
9763 // nb_elem_tot a la place de nb_elem
9764 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9765 {
9766 double x = valeurs(i_elem);
9767 for (int j = 0; j < nb_faces_elem; j++)
9768 {
9769 int i_face = elem_faces(i_elem, j);
9770 double f = flux(i_face);
9771 double signe = (i_elem == face_voisins(i_face, 1)) ? 1. : -1.;
9772 x += f * signe;
9773 }
9774 valeurs(i_elem) = x;
9775
9776 }
9777 valeurs.echange_espace_virtuel();
9778}
9779
9780// Calcule des valeurs aux sommets du maillage ft a partir des valeurs euler qui sont supposees etre aux elements.
9781// Le transfert est conservatif: on suppose que les valeurs_euler sont des integrales sur chaque element.
9782// La somme de ces valeurs sera egale a la somme des valeurs associees aux sommets lagrangiens.
9784 const DoubleVect& valeurs_euler,
9785 ArrOfDouble& valeurs_lagrange)
9786{
9787 const int nb_sommets = maillage.nb_sommets();
9788 valeurs_lagrange.resize_array(nb_sommets);
9789 // Initialisation a zero car on va ajouter des contributions dans le desordre :
9790 valeurs_lagrange = 0.;
9791
9792 const int dim = Objet_U::dimension;
9793 const IntTab& facettes = maillage.facettes();
9794 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
9795 const ArrOfInt& index_elem = intersections.index_elem();
9796 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9797 const int nb_elements = valeurs_euler.size();
9798 assert(nb_elements == index_elem.size_array());
9799
9800 // Boucle sur les elements euleriens
9801 int element;
9802 for (element = 0; element < nb_elements; element++)
9803 {
9804
9805 // Si cet element n'est pas traverse par l'interface, ne pas calculer
9806 // la variation de volume.
9807 const int index_premiere_intersection = index_elem[element];
9808 if (index_premiere_intersection < 0) // Pas de facette dans cet element
9809 continue;
9810
9811 // Repartition conservative de la valeur_euler sur les noeuds
9812 // du maillage lagrangien :
9813
9814 // Premier passage : calcul de la surface totale d'intersection entre le
9815 // maillage lagrangien et l'element eulerien "element".
9816 double surface_totale = 0.;
9817 // Boucle sur les faces qui traversent l'element:
9818 int index = index_premiere_intersection;
9819 while (index >= 0)
9820 {
9821 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
9822 const int facette = data.numero_facette_;
9823 const double surface_facette = surface_facettes[facette];
9824 surface_totale += data.fraction_surface_intersection_ * surface_facette;
9825 index = data.index_facette_suivante_;
9826 }
9827
9828 const double valeur_euler = valeurs_euler[element];
9829
9830 // Deuxieme passage : repartition de la valeur_euler sur les sommets,
9831 // proportionnelle a la surface et a la coordonnee barycentrique du sommet :
9832 index = index_premiere_intersection;
9833 if (surface_totale > 0.)
9834 {
9835 const double inv_surface_tot = 1. / surface_totale;
9836 while (index >= 0)
9837 {
9838 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
9839 const int facette = data.numero_facette_;
9840 const double surface_facette = surface_facettes[facette];
9841 // Fraction de la surface d'intersection de cette facette a la surface totale
9842 // d'intersection avec l'element :
9843 const double fraction_surface = data.fraction_surface_intersection_ * surface_facette * inv_surface_tot;
9844 int i;
9845 for (i = 0; i < dim; i++)
9846 {
9847 const int sommet = facettes(facette, i);
9848 const double coeff = data.barycentre_[i];
9849 // La somme des "coeff" pour une intersection vaut 1
9850 // et la sommet des fraction_surface pour toutes les intersections
9851 // vaut 1, donc on distribue "valeur_euler" de facon conservative
9852 // sur les sommets du maillage lagrangien :
9853 const double valeur = coeff * fraction_surface * valeur_euler;
9854 // Certaines contributions sont ajoutees a des sommets virtuels,
9855 // on collecte le tout a la fin :
9856 valeurs_lagrange[sommet] += valeur;
9857 }
9858 index = data.index_facette_suivante_;
9859 }
9860 }
9861 }
9862
9864 // Mise a jour des espaces virtuels :
9865 maillage.desc_sommets().echange_espace_virtuel(valeurs_lagrange);
9866}
9867
9868void Transport_Interfaces_FT_Disc::compute_nb_particles_tot()
9869{
9871 const int nb_facettes=mesh.nb_facettes();
9872 ArrOfInt id_number_fa7(nb_facettes); // Init a zero
9873 int n = search_connex_components_local_FT(mesh, id_number_fa7);
9874 nb_particles_tot_= compute_global_connex_components_FT(mesh, id_number_fa7, n);
9875}
9876
9878{
9879 const Domaine& domain = domaine_dis().domaine();
9880 // computing the total number of particles
9881 // one cannot use Transport_Interfaces_FT_Disc::compute_nb_compo_tot()
9882 // because we need compo_connex_fa7 after
9884 const int nb_facettes=mesh.nb_facettes();
9885 ArrOfInt id_number_fa7(nb_facettes); // Init a zero
9886 int n = search_connex_components_local_FT(mesh, id_number_fa7);
9887 int nb_particles_tot=compute_global_connex_components_FT(mesh, id_number_fa7, n);
9888
9889 // particles dont't have initial velocity, their velocity is initialized with 0
9890 if ((particles_velocity_collision_.dimension(0) != nb_particles_tot) || (particles_velocity_collision_.dimension(1) != dimension))
9891 {
9892 Cerr << "WARNING, renumbering particles !" << finl;
9893 particles_position_collision_.resize(nb_particles_tot, dimension);
9894 particles_velocity_collision_.resize(nb_particles_tot, dimension);
9897
9898 const ArrOfDouble& surface_facettes = mesh.get_update_surface_facettes();
9899 const IntTab& facettes = mesh.facettes();
9900 const DoubleTab& sommets = mesh.sommets();
9901
9902 DoubleVect particles_surfaces(nb_particles_tot);
9903
9904 // computing surface gravity center
9905 const int nb_facettes_tot = facettes.dimension_tot(0);
9906 {
9907 for (int i = 0; i < nb_facettes_tot; i++)
9908 {
9909 if (mesh.facette_virtuelle(i)) continue;
9910
9911 const int id_number_lagrangian_vertice = id_number_fa7[i];
9912 const double surface = surface_facettes[i];
9913 particles_surfaces[id_number_lagrangian_vertice] += surface;
9914
9915 // computing the facet gravity surface weighted by its surface
9916 for (int j = 0; j < dimension; j++)
9917 {
9918 const int s = facettes(i, j);
9919 for (int k = 0; k < dimension; k++)
9920 particles_position_collision_(id_number_lagrangian_vertice, k) +=
9921 surface * sommets(s, k);
9922 }
9923 }
9924 mp_sum_for_each_item(particles_surfaces);
9926
9928 DoubleVect s;
9929 s.ref_array(particles_surfaces);
9930 tab_divide_any_shape(particles_position_collision_, s);
9931 }
9932 }
9934 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9935 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9937}
9938
9939/*! @brief WARNING, particles_position_collision_ and particles_velocity_collision_ are not used to transport particles
9940* but only for the computation of contact forces. Thus, be aware that tables Vitesses and Positions
9941* from the method calculer_vitesse_repere_local() are different from those of the present method.
9942* Indeed, it is not required to conserve the same lagrangian number to transport particles.
9943* To merge tables from both methods, one should modify the following methods: search_connex_components_local_FT
9944* and compute_global_connex_components_FT. If a particle is numbered 0 by proc 0, its global Lagrangian number will be 0.
9945* However, if it passes to proc 1 and is assigned the number 0, its global number will be 0 + the number of particles of proc 0.
9946* This method swap rows of particles_position_collision_ and particles_velocity_collision_ to conserve the particles
9947* lagrangian ID number between two successive times steps using the particles eulerian ID number. Indeed, after calling
9948* the function search_connex_components_local_FT and compute_global_connex_components_FT, their lagrangian number has changed.
9949* The method is base on the assumption that the element in which the gravity center of a given particle conserve its
9950* eulerian ID number between two successive time steps, which is always verified for resolved particles.
9951* We then attribute the eulerian ID number of this elem to the lagrangian particle ID number by swapping table rows.
9952* /!\ /!\ /!\ At the moment, this method is performed sequentially only
9953* All processors know the tables particles_position_collision_ and particles_velocity_collision_
9954*/
9956{
9957 const Domaine& domain = domaine_dis().domaine();
9958 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9959 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9960 int nb_particles_tot = particles_position_collision_.dimension(0);
9961 DoubleTab correct_particles_position(nb_particles_tot, dimension);
9962 DoubleTab correct_particles_velocity(nb_particles_tot, dimension);
9963 IntVect particles_correct_id_number(nb_particles_tot);
9964
9965 // Step 1: Identification of the elements which contain particles gravity center
9967 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
9968
9969 // Step 2: Identification of the permutations required to conserve the Lagrangian number
9970 for (int wrong_id_number=0; wrong_id_number<nb_particles_tot; wrong_id_number++)
9971 {
9972 int particle_gravity_center_elem=gravity_center_elem_[wrong_id_number];
9973 int correct_id_number;
9974 if (particle_gravity_center_elem==-1) correct_id_number =-1;
9975 else correct_id_number = particles_eulerian_id_number[particle_gravity_center_elem];
9976 particles_correct_id_number(wrong_id_number)=correct_id_number;
9977 }
9978 mp_max_for_each_item(particles_correct_id_number);
9979 int isduplicateValue = collision_model_.valeur().check_for_duplicates(particles_correct_id_number);
9980 if (isduplicateValue == 1) Process::exit("Transport_Interfaces_FT_Disc::swap_particles_position_velocity "
9981 "ERROR: duplicate value of the particles lagrangian ID number");
9982
9983 // Step3:Swapping table rows
9984 for (int wrong_id_number = 0; wrong_id_number < nb_particles_tot; wrong_id_number++)
9985 {
9986 int good_id_number = particles_correct_id_number[wrong_id_number];
9987 for (int d = 0; d < dimension; d++)
9988 {
9989 correct_particles_position(good_id_number, d) = particles_position_collision_(wrong_id_number, d);
9990 correct_particles_velocity(good_id_number, d) = particles_velocity_collision_(wrong_id_number, d);
9991 }
9992 }
9993 particles_position_collision_ = correct_particles_position;
9994 particles_velocity_collision_ = correct_particles_velocity;
9995}
9996
9998{
9999 const Domaine_VF& domain_vf = ref_cast(Domaine_VF, domaine_dis());
10000 const DoubleVect& mesh_volumes = domain_vf.volumes();
10001 const IntTab& elem_faces = domain_vf.elem_faces();
10002 const DoubleTab& phase_indicator_function = indicatrice_->valeurs();
10003 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
10004 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
10005 const Fluide_Diphasique& two_phase_elem=ns.fluide_diphasique();
10006 const int id_solid_phase=1-two_phase_elem.get_id_fluid_phase();
10007 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
10008 const DoubleTab& tab_velocity=ns.inconnue().valeurs();
10009
10014
10015 for (int elem=0; elem<domain_vf.nb_elem(); elem++)
10016 {
10017 // the mean is realized on pure elem only
10018 if (phase_indicator_function(elem)==id_solid_phase)
10019 {
10020 const int particle= particles_eulerian_id_number(elem);
10021 particles_purely_solid_mesh_volume_(particle)+=mesh_volumes(elem);
10022 for (int dim=0; dim<dimension; dim++)
10023 {
10024 mean_particles_volumic_velocity_(particle,dim)+=0.5*(
10025 tab_velocity(elem_faces(elem,dim))+
10026 tab_velocity(elem_faces(elem,dim+dimension))
10027 )*mesh_volumes(elem);
10028
10030 0.5*(tab_velocity(elem_faces(elem,dim))+
10031 tab_velocity(elem_faces(elem,dim+dimension))
10032 )*mesh_volumes(elem),2);
10033 }
10034 }
10035 }
10036
10040 DoubleVect s_vparticles;
10042 tab_divide_any_shape(mean_particles_volumic_velocity_, s_vparticles);
10043 tab_divide_any_shape(mean_particles_volumic_squared_velocity_, s_vparticles);
10044
10045 for (int particle=0; particle<nb_particles_tot_; particle++)
10046 {
10047 for (int dim=0; dim<dimension; dim++)
10048 {
10049 rms_particles_volumic_velocity_(particle,dim)=
10050 sqrt(fabs(pow(mean_particles_volumic_velocity_(particle,dim),2)
10052 }
10053 }
10054
10055}
10056
10057void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
10058 const ArrOfDouble& values) const
10059{
10060 const int nb_fa7 = values.size_array();
10061 ftab->resize(nb_fa7, 1);
10062 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
10063 (*ftab)(fa7,0) = (float) values(fa7);
10064}
10065
10066void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
10067 const DoubleVect& values) const
10068{
10069 const int nb_fa7 = values.size_array();
10070 ftab->resize(nb_fa7, 1);
10071 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
10072 (*ftab)(fa7,0) = (float) values(fa7);
10073}
10074
10075void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
10076 const DoubleTab& values) const
10077{
10078 const int nb_fa7 = values.dimension(0);
10079 ftab->resize(nb_fa7, 1);
10080 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
10081 (*ftab)(fa7,0) = (float) values(fa7);
10082}
10083
10084void Transport_Interfaces_FT_Disc::fill_ftab_vector(DoubleTab *ftab, const DoubleTab& values) const
10085{
10086
10087 const int nb_fa7 = values.dimension(0);
10088 const int nb_compo = values.dimension(1);
10089 ftab->resize(nb_fa7, nb_compo);
10090 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
10091 for (int k=0 ; k<nb_compo ; k++)
10092 (*ftab)(fa7,k) = (float) values(fa7,k);
10093}
10094
10095void Transport_Interfaces_FT_Disc::fill_ftab_vertices_curvature(DoubleTab *ftab, const DoubleTab& dummytab) const
10096{
10098 fill_ftab_scalar(ftab,mesh.get_update_courbure_sommets());
10099}
10100
10101void Transport_Interfaces_FT_Disc::fill_ftab_velocity(DoubleTab *ftab,const DoubleTab& dummytab) const
10102{
10103 if (variables_internes_->refequation_vitesse_transport)
10104 {
10105 DoubleTabFT vit;
10106 // Calcul de la vitesse de deplacement des sommets par interpolation
10107 // (deplacement contient en fait la vitesse en m/s)
10108 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
10109 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
10110 int flag = 1;
10111 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
10112 {
10113 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
10115 flag=0;
10116 }
10118 0 /* ne pas recalculer le champ de vitesse L2 */, // GB 2020/03/20 -> Je suis surpris par cette option 0 en desaccord avec le moment du calcul
10119 // mais je ne prends pas la responsabilite de changer car je ne sais pas trop ce que ca represente (c'est du VEF uniquement?)
10120 flag /* Interpolation Multi-lineaire en VDF */,
10121 false /* la_roue_de_vitesse_a_deja_tournee => C'est vrai
10122 Mais en post, on veut afficher la valeur future de la vitesse qui sera appliquee lors du prochain dt,
10123 on l'obtient donc en regardant la case present */ );
10124 // Pour ajouter le saut de vitesse a l'interface :
10125 ajouter_contribution_saut_vitesse(vit, // TODO: a verifier. Je ne sais pas ce que l'on veut
10126 false /* la_roue_de_vitesse_a_deja_tournee => permet d'afficher la valeur future en expli */ ); // ici, l'interpolation depend de ns.get_new_mass_source()
10127 fill_ftab_vector(ftab,vit);
10128 }
10129 else
10130 {
10131 // Coder le postraitement d'une vitesse imposee
10132 Cerr << "Error : velocity nodes post-processing : to be developped." << finl;
10133 assert(0);
10134 Process::exit();
10135 }
10136
10137}
10138
10139void Transport_Interfaces_FT_Disc::fill_ftab_local_reference_frame_velocity(DoubleTab *ftab, const DoubleTab& dummytab) const
10140{
10141 if (variables_internes_->refequation_vitesse_transport)
10142 {
10143 DoubleTabFT vit;
10144 DoubleTab Positions,Vitesses;
10145 // Calcul de la vitesse de deplacement des sommets par interpolation
10146 // (deplacement contient en fait la vitesse en m/s)
10147 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
10148 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
10150 0 /* ne pas recalculer le champ de vitesse L2 */, // GB 2020/03/20 -> Je suis surpris par cette option 0 en desaccord avec le moment du calcul
10151 // mais je ne prends pas la responsabilite de changer car je ne sais pas trop ce que ca represente (c'est du VEF uniquement?)
10152 1 /* Interpolation Multi-lineaire en VDF */,
10153 false /* la_roue_de_vitesse_a_deja_tournee => C'est vrai
10154 Mais en post, on veut afficher la valeur future de la vitesse qui sera appliquee lors du prochain dt,
10155 on l'obtient donc en regardant la case present */ );
10156 // Pour ajouter le saut de vitesse a l'interface :
10157 ajouter_contribution_saut_vitesse(vit, // TODO: a verifier. Je ne sais pas ce que l'on veut
10158 false /* la_roue_de_vitesse_a_deja_tournee => permet d'afficher la valeur future en expli */ );// ici, l'interpolation depend de ns.get_new_mass_source()
10160 fill_ftab_vector(ftab,vit);
10161 }
10162 else
10163 {
10164 // Coder le postraitement d'une vitesse imposee
10165 Cerr << "Error : vitesse_repere_local nodes post-processing : to be developped." << finl;
10166 assert(0);
10167 Process::exit();
10168 }
10169}
10170
10171void Transport_Interfaces_FT_Disc::fill_ftab_normal_unit(DoubleTab *ftab,const DoubleTab& dummytab) const
10172{
10174 fill_ftab_vector(ftab,mesh.get_update_normale_facettes());
10175}
10176
10177void Transport_Interfaces_FT_Disc::fill_ftab_pressure_force(DoubleTab *ftab,const DoubleTab& dummytab) const
10178{
10179 if (post_process_hydro_forces_.get_is_post_process_pressure_force_fa7())
10180 fill_ftab_vector(ftab,post_process_hydro_forces_.get_pressure_force_fa7());
10181}
10182
10183void Transport_Interfaces_FT_Disc::fill_ftab_friction_force(DoubleTab *ftab,const DoubleTab& dummytab) const
10184{
10185 if (post_process_hydro_forces_.get_is_post_process_friction_force_fa7())
10186 fill_ftab_vector(ftab,post_process_hydro_forces_.get_friction_force_fa7());
10187}
10188
10189void Transport_Interfaces_FT_Disc::fill_ftab_Stokes(DoubleTab* ftab, const DoubleTab& values) const
10190{
10191 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10192 fill_ftab_vector(ftab,values);
10193}
10194
10195void Transport_Interfaces_FT_Disc::fill_ftab_pressure(DoubleTab *ftab,const DoubleTab& dummytab) const
10196{
10197 if(post_process_hydro_forces_.get_is_post_process_pressure_fa7())
10198 fill_ftab_scalar(ftab,post_process_hydro_forces_.get_pressure_fa7());
10199}
10200
10201void Transport_Interfaces_FT_Disc::fill_ftab_Stokes_pressure_interp(DoubleTab* ftab, const DoubleTab& dummytab) const
10202{
10203 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10204 fill_ftab_scalar(ftab,post_process_hydro_forces_Stokes_.get_pressure_fa7());
10205}
10206void Transport_Interfaces_FT_Disc::fill_ftab_Stokes_pressure_th(DoubleTab* ftab, const DoubleTab& dummytab) const
10207{
10208 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10209 fill_ftab_scalar(ftab,post_process_hydro_forces_Stokes_.get_pressure_fa7_Stokes_th());
10210}
10211
: classe Algorithmes_Transport_FT_Disc
int testsetbit(int_t i) const
Renvoie la valeur du bit e, puis met le bit e a 1.
Definition ArrOfBit.h:85
class Champ_Face_VDF Cette classe sert a representer un champ vectoriel dont on ne calcule
classe Champ_Fonc_Face_VDF
classe Champ_Fonc_P1NC
Classe Champ_Inc_base.
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
double changer_temps(const double temps) override
Fixe le temps du champ.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & futur(int i=1)
Definition Champ_Proto.h:47
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual const Domaine_dis_base & domaine_dis_base() const
virtual DoubleTab & valeur_aux_elems_passe(const DoubleTab &positions, const IntVect &les_polys, DoubleTab &tab_valeurs) const
Definition Champ_base.h:92
double temps() const
Renvoie le temps du champ.
virtual DoubleTab & valeur_aux_elems(const DoubleTab &positions, const IntVect &les_polys, DoubleTab &valeurs) const
provoque une erreur ! doit etre surchargee par les classes derivees
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
virtual void suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer, int nouvelle_phase)
Methode appelee par Transport_Interfaces_xxx::test_suppression_interfaces_sous_domaine() lorqu'une in...
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
void echange_espace_virtuel(ArrOfDouble &tab) const
classe Discretisation_base Cette classe represente un schema de discretisation en espace,...
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
void construire_elem_virt_pe_num()
Definition Domaine.cpp:704
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
SmallArrOfTID_t & chercher_elements(const DoubleTab &pos, SmallArrOfTID_t &elem, int reel=0) const
Recherche des elements contenant les points dont les coordonnees sont specifiees.
Definition Domaine.cpp:405
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
DoubleTab_t & les_sommets()
Definition Domaine.h:113
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
class Domaine_VDF
Definition Domaine_VDF.h:64
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
double distance_face(int, int, int k) const
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
int nb_joints() const
Definition Domaine_VF.h:65
const Joint & joint(int i) const
Definition Domaine_VF.h:105
double volumes(int i) const
Definition Domaine_VF.h:113
void construire_face_virt_pe_num()
Remplissage du tableau face_virt_pe_num_ (voir commentaire dans Domaine_VF.
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
int moments_a_imprimer() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
virtual IntTab & face_voisins()
int nb_elem_tot() const
const Domaine & domaine() const
Lecture dans un fichier d'objets ecrits au format binaire.
Definition EFichierBin.h:30
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Definition EFichier.h:29
static Nom & get_Output()
Renvoie le mode d'ecriture utilise (pour pouvoir le modifier).
static int is_ecriture_special(int &special, int &a_faire)
indique si le format special a ete demande en lecture active par sauvegarde xyz .
static int is_lecture_special()
indique si le format special a ete demande en lecture active par reprise xyz .
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual void set_param(Param &titi) const override
const Nom & le_nom() const override
Renvoie le nom de l'equation.
int reprendre(Entree &) override
On reprend l'inconnue a partir d'un flot d'entree.
virtual std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name, type and dimensions of the data to save/restore. This has to be overrode f...
virtual void associer_pb_base(const Probleme_base &)
S'associe au Probleme passe en parametre.
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual const Champ_Inc_base & inconnue() const =0
int calculate_time_derivative() const
virtual int nombre_d_operateurs() const =0
int sauvegarder(Sortie &) const override
On sauvegarde l'inconnue, puis les sources sur un flot de sortie.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
int limpr() const
Demande au schema en temps si il faut effectuer une impression.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
Champs_compris champs_compris_
virtual const Operateur & operateur(int) const =0
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const int & get_id_fluid_phase() const
: Classe de postraitement des champs euleriens au format lata
int ecrire_entete(const double temps_courant, const int reprise, const int est_le_premier_post) override
Ouvre le fichier maitre en mode ERASE et ecrit l'entete du fichier lata (sur le processeur maitre seu...
@ BINAIRE
int ecrire_domaine(const Domaine &domaine, const int est_le_premier_post) override
voir Format_Post_base::ecrire_domaine On accepte l'ecriture d'un domaine dans un pas de temps,...
int ecrire_temps(const double temps) override
commence l'ecriture d'un nouveau pas de temps En l'occurence pour le format LATA:
int ecrire_champ(const Domaine &domaine, const Noms &unite_, const Noms &noms_compo, int ncomp, double temps_, const Nom &id_du_champ, const Nom &id_du_domaine, const Nom &localisation, const Nom &nature, const DoubleTab &data) override
voir Format_Post_base::ecrire_champ
int initialize(const Nom &file_basename, const int format, const Nom &option_para) override
static Objet_U & objet(const Nom &)
Voir Interprete_bloc::objet_global() BM: la classe Interprete n'est pas le meilleur endroit pour cett...
: class Intersections_Elem_Facettes
const ArrOfInt & index_elem() const
Renvoie un tableau de taille domaine.
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 ...
const Joint_Items_t & joint_item(JOINT_ITEM type) const
Renvoie les informations de joint pour le type demande.
Definition Joint.cpp:128
const IntTab_t & renum_items_communs() const
Voir renum_items_communs_.
Cette classe implemente les operateurs et les methodes virtuelles de la classe EFichier de la facon s...
int get_sequential_items_flags(ArrOfBit &flags, int line_size=1) const
static void echange_espace_virtuel(IntVect &, Operations_echange opt=ECHANGE_EV, IsExchangeBlocking is_exchange_blocking=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
: class Maillage_FT_Disc Cette classe decrit un maillage:
virtual Entree & lire_param_maillage(Entree &is)
Cette fonction permet de lire les parametres pour le maillage des interfaces.
void mesh_tag_increase() const
int get_mesh_tag() const
return mesh_state_tag_
void set_is_solid_particle(const bool is_solid_particle)
void preparer_tableau_avant_transport(ArrOfDouble &tableau, const Desc_Structure_FT &descripteur) const
Prepare un tableau de donnees aux sommets ou aux facettes pour conserver les valeurs apres transport.
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,
void associer_equation_transport(const Equation_base &equation) override
on remplit refequation_transport_, schema_comm_domaine_ desc_sommets_.comm_group_ et desc_facettes_....
void update_tableau_apres_transport(ArrOfDouble &tableau, int nb_elements, const Desc_Structure_FT &descripteur) const
Voir preparer_tableau_avant_transport.
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
int facette_virtuelle(int i) const
Renvoie 0 si la facette m'appartient, 1 sinon.
double temps() const
return temps_physique_ (temps_physique_ ne sert a rien en interne.
const Desc_Structure_FT & desc_sommets() const
renvoie le descripteur des sommets (espace_distant/virtuel)
void completer_maillage()
Complete les structures de donnees du maillage.
virtual void ajouter_maillage(const Maillage_FT_Disc &maillage_tmp, int skip_facettes=0)
double changer_temps(double t)
return temps_physique_ = t
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...
void facette_PE_owner(ArrOfInt &facette_pe) const
pour postraitement, remplit le tableau en parametre avec le numero du PE proprietaire de chaque facet...
void parcourir_maillage()
Remplit la structure intersections_elem_facettes_.
const Schema_Comm & get_schema_comm_FT() const
int sommet_virtuel(int i) const
const ArrOfInt & sommet_PE_owner() const
pour postraitement, renvoie le numero du PE proprietaire des sommets
void calcul_indicatrice(DoubleVect &indicatrice, const DoubleVect &indicatrice_precedente) const
Calcul de la fonction indicatrice (on suppose que "indicatrice" a la structure d'un tableau de valeur...
virtual void transporter(const DoubleTab &deplacement)
Deplace les sommets de l'interface d'un vecteur "deplacement" fourni, Change eventuellement les somme...
const Intersections_Elem_Facettes & intersections_elem_facettes() const
void nettoyer_elements_virtuels()
Retire toutes les facettes virtuelles et tous les sommets qui ne sont pas utilises.
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...
virtual const ArrOfDouble & get_update_courbure_sommets() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau aux sommets du maillage Meme principe que Domaine::creer_tableau_sommets()
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
const ArrOfInt & sommet_elem() const
pour postraitement, renvoie sommet_elem_
int construire_iso(const DoubleVect &valeurs_sommets, double isovaleur, Maillage_FT_Disc &maillage, DoubleVect &indicatrice_approchee, const Maillage_FT_Disc::AjoutPhase phase, int ignorer_collision=0) const
Construction d'un maillage en segments ou en triangles comme l'isovaleur d'une fonction discretisee a...
void associer_domaine_vf(const Domaine_VF &domaine_vf)
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
virtual const Champ_base * get_delta_vitesse_interface() const
Si le champ de vitesse est discontinu (calcul avec changement de phase), renvoie un pointeur vers le ...
void compute_particles_eulerian_id_number(const OWN_PTR(Collision_Model_FT_base)&collision_model_ptr)
const DoubleTab & get_interfacial_area() const
virtual void calculer_dI_dt(DoubleVect &dI_dt, const DoubleTab &tab_vitesse)
virtual const Fluide_Diphasique & fluide_diphasique() const
const IntTab & get_particles_eulerian_id_number() const
void swap_particles_eulerian_id_number(const ArrOfInt &gravity_center_elem)
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual int finit_par(const char *const n) const
Definition Nom.cpp:324
virtual int find(const char *const n) const
Definition Nom.cpp:314
const std::string & getString() const
Definition Nom.h:92
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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 const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
static int bidim_axi
Definition Objet_U.h:102
virtual int reprendre(Entree &)
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:338
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur Classe generique de la hierarchie des operateurs.
Definition Operateur.h:39
double calculer_pas_de_temps() const
Calcule le prochain pas de temps.
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
void associer_connectivite_frontieres(const Connectivite_frontieres &connect)
void associer_domaine_dis(const Domaine_dis_base &domaine_dis)
Remplissage des variables persistantes de la classe (refdomaine_vf_, nb_faces_elem_,...
classe Paroi_FT_disc Condition aux limites d'angle de contact pour l'equation
Representation des donnees de la classe Parser.
Definition Parser.h:39
void addVar(const char *)
Definition Parser.cpp:565
virtual void setNbVar(int nvar)
Definition Parser.cpp:116
void setVar(const char *sv, double val)
Definition Parser.h:73
double eval()
Definition Parser.h:68
void setString(const std::string &s)
Definition Parser.h:102
virtual void parseString()
Definition Parser.cpp:124
static const char *const demande_description
const Triple_Line_Model_FT_Disc & tcl() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Nom & checkpoint_filename() const
bool is_dilatable() const
bool & reprise_effectuee()
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
const Nom & restart_filename() const
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:196
static double mp_min(double)
Definition Process.cpp:386
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:207
static double mp_max(double)
Definition Process.cpp:376
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Classe qui porte les proprietes de particules.
void nettoyer(const ArrOfInt &som_utilises)
: class Remaillage_FT Cette classe implemente les procedures de remaillage des interfaces pour le Fro...
int traite_decollement(Maillage_FT_Disc &maillage, const DoubleTab &deplacement) const
Cette fonction permet de gerer le decollement de l'interface de la paroi Si un sommet de bord n'a pas...
int traite_adherence(Maillage_FT_Disc &maillage) const
Cette fonction permet de gerer l'adherence de l'interface a la paroi Si une facette possede 3 sommets...
void associer_domaine(const Domaine_dis_base &domaine_dis)
Cette fonction stocke le domaine_dis dans refdomaine_dis_.
double calculer_variation_volume(const Maillage_FT_Disc &maillage, const DoubleTab &position_initiale, ArrOfDouble &varVolume) const
Cette fonction calcule le volume de phase 0 engendre par chaque sommet lors du deplacement de l'inter...
void set_is_solid_particle(const bool is_solid_particle)
void lisser_dvolume(const Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const int nb_iterations) const
Regularise le champ scalaire "var_volume" defini aux sommets du "maillage".
void corriger_volume_(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const int nb_iter_corrections_vol)
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
static void lire_xyz(Maillage_FT_Disc &mesh, const Domaine_VF *domaine_vf, Entree *fichier, const Domaine *domaine_src)
Remplissage du maillage mesh a partir d'un fichier de sauvegarde xyz (fichier) ou d'un domaine source...
static void init_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Create parallel descriptors for the vertex and element arrays of the domain (necessary because Scatte...
Definition Scatter.cpp:2742
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Definition Scatter.cpp:2757
class Schema_Temps_base
int nb_impr() const
Renvoie le nombre d'impressions effectuees.
double temps_courant() const
Renvoie le temps courant.
void imprimer_temps_courant(SFichier &) const
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual int nb_valeurs_temporelles() const =0
void update_critere_statio(const DoubleTab &tab_critere, Equation_base &equation)
//Actualisation de stationnaire_atteint_ et residu_ (critere residu_<seuil_statio_)
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual Sortie & flush()
Definition Sortie.cpp:138
int_t nb_elem_tot() const
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
_TYPE_ * addr()
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int est_vide() const
TRUSTList & add(_TYPE_)
insertion en queue
Definition TRUSTList.tpp:85
TRUSTList & add_if_not(_TYPE_)
Ajout d'un element a la liste ssi il n'existe pas deja.
int contient(_TYPE_) const
Verifie si un element appartient ou non a la liste.
int size() const
Definition TRUSTList.h:68
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
void ref_array(TRUSTArray< _TYPE_, _SIZE_ > &, _SIZE_ start=0, _SIZE_ sz=-1) override
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
classe TRUST_2_PDI Encapsulation of PDI methods (library used for IO operations). See the website pdi...
Definition TRUST_2_PDI.h:59
void read(const std::string &name, void *data)
static void set_PDI_restart(int r)
void get_type(const Nom &name, Nom &type)
Generic method to read the type of a TRUST object in the HDF5 file.
static void set_PDI_checkpoint(int c)
static int is_PDI_checkpoint()
static int is_PDI_restart()
void TRUST_start_sharing(const std::string &name, const void *data)
: class Topologie_Maillage_FT Cette classe implemente les procedures de remaillage des interfaces pou...
virtual int calculer_composantes_connexes_pour_suppression(const Domaine_VF &domaine_vf, const DoubleTab &indicatrice, IntVect &num_compo) const
Computes eulerian connex components of the phase indicator function "indicatrice" according to the ge...
virtual void remailler_interface(const double temps, Maillage_FT_Disc &maillage, Champ_base &indicatrice, Remaillage_FT &algo_remaillage_local)
Remaillage de l'interface: - amelioration petites et grandes facettes,.
virtual double suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer, Maillage_FT_Disc &maillage, DoubleTab &indicatrice)
Removes all interfaces contained in eulerian elements marked by the "flags_" array,...
std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name and type and dimensions of the indicatrice tag
OWN_PTR(Champ_Inc_base) indicatrice_cache
int reprendre(Entree &is) override
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
int sauvegarder(Sortie &os) const override
Sauvegarde d'un Objet_U sur un flot de sortie Methode a surcharger.
void set_param(Param &titi) const override
DoubleTab & derivee_en_temps_inco(DoubleTab &derivee) override
Calcul de la derivee en temps de l'inconnue : zero.
const Operateur & operateur(int i) const override
void fill_ftab_pressure_force(DoubleTab *ftab, const DoubleTab &dummytab) const
void fill_ftab_friction_force(DoubleTab *ftab, const DoubleTab &dummytab) const
virtual void get_expression_vitesse_imposee(DoubleTab &vitesse_imp)
const DoubleTab & get_mean_particles_volumic_squared_velocity() const
virtual void PPP_face_interface_voisin(const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &Vertex, DoubleTab &PPP)
void update_indicatrice_normale_distance()
Updates normals and distances to interface, then updates indicatrice.
virtual const Champ_base & get_indicatrice_faces()
void fill_ftab_normal_unit(DoubleTab *ftab, const DoubleTab &dummytab) const
virtual double suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer)
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...
void associer_equation_ns(const Navier_Stokes_FT_Disc &ns)
const DoubleTab & get_mean_particles_volumic_velocity() const
int preparer_calcul() override
Tout ce qui ne depend pas des autres problemes eventuels.
void fill_ftab_vertices_curvature(DoubleTab *ftab, const DoubleTab &dummytab) const
int sauvegarder(Sortie &) const override
On sauvegarde l'inconnue, puis les sources sur un flot de sortie.
virtual void remailler_interface()
Remaillage de l'interface : - amelioration petites et grandes facettes,.
virtual const DoubleTab & get_update_distance_interface_sommets() const
Renvoi de la distance signee entre l'interface et les sommets du maillage eulerien.
const Topologie_Maillage_FT & topologie_interface() const
int impr(Sortie &os) const override
Imprime les operateurs de l'equation sur un flot de sortie, de facon inconditionnelle.
void calcul_source(const DoubleTab &inco_val, const DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &source_val, const DoubleTab &vit_imposee, const DoubleTab &indicatrice_faces, const int is_QC, const double dt, const int is_explicite, const double eta)
void associer_milieu_base(const Milieu_base &milieu) override
void update_indicatrice() override
Recalcul du champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
void impr_effort_fluide_interface(DoubleTab &source_val, DoubleTab &pressure_part, DoubleTab &friction_part, DoubleTab &diff_part)
void calculer_scalaire_interpole(const Champ_base &ch_scal, const Maillage_FT_Disc &, DoubleTab &ch_scal_noeuds, int nv_calc) const
const DoubleTab & get_particles_purely_solid_mesh_volume() const
virtual void transporter_sans_changement_topologie(DoubleTab &vitesse, const double coeff, const double temps)
void calcul_indicatrice_faces(const DoubleTab &indicatrice, const IntTab &face_voisins)
void fill_ftab_Stokes(DoubleTab *ftab, const DoubleTab &values) const
const Proprietes_part_vol & proprietes_particules() const
virtual const Connectivite_frontieres & connectivite_frontieres() const
void mettre_a_jour(double temps) override
La valeur de l'inconnue sur le pas de temps a ete calculee.
void nettoyer_proprietes_particules(const ArrOfInt &som_utilises)
virtual void calcul_nb_traverse(const DoubleTab &xe, const double dx, const int dim, const int ori, Maillage_FT_Disc &maillage, int elem, int &traverse)
int verif_Cl() const override
Methode appelee par Equation_base::readOn On verifie que toutes les cl sont de type Paroi_FT_disc.
const DoubleTab & get_rms_particles_volumic_velocity() const
virtual void calculer_distance_interface(const Maillage_FT_Disc &maillage, DoubleTab &distance_elements, DoubleTab &normale_elements, const int n_iter) const
Calcul d'un champ scalaire aux elements contenant une distance signee entre le centre de l'element et...
virtual void calcul_tolerance_projete_monophasique(const int i_face, const int ori, const int voisin0, const int voisin1, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, double &tol)
void modifie_source(DoubleTab &so_modif, const DoubleTab &so_val, const DoubleTab &rho_faces, const int n, const int m, const int is_QC, const DoubleVect &vol_entrelaces, const Solveur_Masse_base &solv_masse)
virtual const Parcours_interface & parcours_interface() const
Post_Processing_Hydrodynamic_Forces_Stokes post_process_hydro_forces_Stokes_
virtual const Maillage_FT_Disc & maillage_interface_pour_post() const
Renvoie le maillage stocke specialement pour le postraitement (si on veut postraiter un etat intermed...
const Champ_Inc_base & inconnue() const override
const Champ_base & get_indicatrice() override
getter champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
virtual void calculer_distance_interface_faces(const DoubleTab &dist_elem, const DoubleTab &normale_elem, DoubleTab &dist_faces) const
void check_indicatrice_is_up_to_date() override
Checks if the indicator is up to date.
std::vector< YAML_data > data_a_sauvegarder() const override
for PDI IO: retrieve name and type and dimensions of the indicatrice tag
Transport_Interfaces_FT_Disc()
constructeur par defaut
void discretiser() override
Discretisation des champs: - indicatrice_ : champ scalaire discretise aux elements.
void swap_particles_lagrangian_position_velocity()
WARNING, particles_position_collision_ and particles_velocity_collision_ are not used to transport pa...
const Maillage_FT_Disc & maillage_inject() const
virtual void calculer_vitesse_transport_interpolee(const Champ_base &champ_vitesse, const Maillage_FT_Disc &m, DoubleTab &vitesse_noeuds, int nv_calc) const
void fill_ftab_pressure(DoubleTab *ftab, const DoubleTab &dummytab) const
const Probleme_base & get_probleme_base() const
double calculer_pas_de_temps() const override
Calcul du prochain pas de temps.
void integrer_ensemble_lagrange(const double temps) override
virtual const Champ_base & update_indicatrice_faces()
const Proprietes_part_vol & proprietes_inject() const
virtual void PPP_face_interface(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &Vertex)
virtual const Champ_base & get_normale_interface() const
virtual void RenumFa7(DoubleTab &Barycentre, DoubleTab &Tab110, DoubleTab &Tab111, DoubleTab &Tab112, IntTab &Tab12, IntTab &CptFacette, const int nb_facettes, const int nb_facettes_dim)
void fill_ftab_Stokes_pressure_th(DoubleTab *ftab, const DoubleTab &values) const
Post_Processing_Hydrodynamic_Forces post_process_hydro_forces_
virtual void PPP_face_voisin(const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &PPP)
virtual double calculer_integrale_indicatrice(const DoubleVect &indicatrice, double &v_ph0) const
const OWN_PTR(Collision_Model_FT_base) &get_ptr_collision_model() const
void associer_pb_base(const Probleme_base &probleme) override
S'associe au Probleme passe en parametre.
virtual const Algorithmes_Transport_FT_Disc & algorithmes_transport() const
virtual void plan_facette_existant(Maillage_FT_Disc &maillage, DoubleList A, DoubleList B, DoubleList C, DoubleList D, const int i_facette, int &test_liste)
virtual const Champ_base & get_update_distance_interface_faces() const
const Maillage_FT_Disc & maillage_interface() const
virtual void uzawa(const double d, const DoubleTab &matrice, const DoubleTab &x, const DoubleTab &secmem, DoubleTab &solution) const
virtual const Marching_Cubes & marching_cubes() const
virtual void calcul_eq_plan_facette(Maillage_FT_Disc &maillage, const int i_facette, double &a, double &b, double &c, double &d)
virtual void interpoler_vitesse_face(const DoubleTab &distance_interface, const int phase, const int stencil_width, DoubleTab &champ, DoubleTab &gradient, const double t, const double dt)
void fill_ftab_velocity(DoubleTab *ftab, const DoubleTab &dummytab) const
void ramasse_miettes(const Maillage_FT_Disc &maillage, DoubleVect &flux, DoubleVect &valeurs)
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
virtual void deplacer_maillage_ft_v_fluide(const double temps)
virtual void calcul_tolerance_projete_diphasique(const int i_face, const int ori, const int voisin0, const int voisin1, const DoubleTab &indicatrice, double &tol)
virtual void calcul_OutElemFa7(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const int nb_elem, int &nb_fa7_accepted, IntList &OutElem, IntList &OutFa7)
void verifprojete(const int monophasique, const double Lref, double d, const DoubleTab &x, const DoubleTab &V, DoubleTab &coord_projete, int &cpt)
virtual void calcul_maxfa7(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const int nb_elem, int &max_fa7, const int exec_planfa7existan)
void fill_ftab_local_reference_frame_velocity(DoubleTab *ftab, const DoubleTab &dummytab) const
static void transfert_conservatif_eulerien_vers_lagrangien_sommets(const Maillage_FT_Disc &maillage, const DoubleVect &valeurs_euler, ArrOfDouble &valeurs_lagrange)
virtual void StockageFa7(Maillage_FT_Disc &maillage, IntTab &CptFacette, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, DoubleTab &Tab110, DoubleTab &Tab111, DoubleTab &Tab112, IntTab &Tab12, DoubleTab &Barycentre, const DoubleTab &indicatrice, IntList &OutElem, ArrOfBit &fa7, const int exec_planfa7existant)
void mettre_a_jour_hors_deplacement(double temps, const bool update_statio=true, const bool update_indic=true)
Entree & lire_cond_init(Entree &is) override
Lecture des conditions initiales.
int reprendre(Entree &) override
On reprend l'inconnue a partir d'un flot d'entree.
void fill_ftab_Stokes_pressure_interp(DoubleTab *ftab, const DoubleTab &values) const
virtual void projete_point_face_interface(int &nb_proj_modif, const int dim_fa7, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, const DoubleTab &dist_face, const double t, const double dt, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, IntTab &Tab12, IntTab &CptFacette, DoubleTab &v_imp, DoubleTab &Vertex, Parser &parser_x, Parser &parser_y, Parser &parser_z)
virtual void BaryFa7(Maillage_FT_Disc &maillage, const int i_facette, DoubleTab &Barycentre)
OBS_PTR(Probleme_base) probleme_base_
virtual void calculer_vmoy_composantes_connexes(const Maillage_FT_Disc &maillage, const ArrOfInt &compo_connexes_facettes, const int nb_compo_tot, const DoubleTab &vitesse_sommets, DoubleTab &vitesses, DoubleTab &positions) const
virtual void calcul_vitesse(DoubleTab &vitesse_imp, const DoubleTab &champ_vitesse, const DoubleTab &vpoint, const double temps, const double dt)
virtual void calculer_vitesse_repere_local(const Maillage_FT_Disc &maillage, DoubleTab &deplacement, DoubleTab &Positions, DoubleTab &Vitesses) const
virtual void calculer_distance_interface_sommets(const DoubleTab &dist_elem, const DoubleTab &normale_elem, DoubleTab &dist_som) const
Calcule dist_som, la distance entre l'interface et les sommets du maillage eulerien a partir de dist_...
void update_normale_distance_interface() const
Calcule la normale et la distance a l'interface, evaluees sur une epaisseur egale a n_iterations_dist...
virtual void projete_point_face_fluide(int &nb_proj_modif, const int dim_fa7, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, const DoubleTab &dist_face, const double t, const double dt, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, IntTab &Tab12, IntTab &CptFacette, DoubleTab &v_imp, DoubleTab &Vertex, Parser &parser_x, Parser &parser_y, Parser &parser_z)
void calcul_effort_fluide_interface(const DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &source_val, const int is_explicite, const double eta)
virtual int calculer_composantes_connexes_pour_suppression(IntVect &num_compo)
void set_is_solid_particle(const bool is_solid_particle)
void ajouter_contribution_saut_vitesse(DoubleTab &deplacement, const bool la_roue_de_vitesse_a_deja_tournee) const
virtual const Champ_base & get_distance_interface() const
void modifier_vpoint_pour_imposer_vit(const DoubleTab &inco_val, DoubleTab &vpoint0, DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &terme_source, const double temps, const double dt, const int is_explicite, const double eta) override
virtual const int & get_n_iterations_distance() const
void assembler(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem) override
classe Transport_Interfaces_base Cette classe constitue la classe de base des equations de transport ...
classe YAML_data : collection of all needed information for data to save/restore in order to write th...
Definition YAML_data.h:26
void set_local(bool l)
Definition YAML_data.h:35