TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Cut_cell_schema_auxiliaire.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 <Cut_cell_schema_auxiliaire.h>
17#include <Cut_cell_FT_Disc.h>
18#include <IJK_Thermal_base.h>
19#include <Process.h>
20#include <Probleme_FTD_IJK_cut_cell.h>
21
22#include <IJK_Navier_Stokes_tools.h>
23#include <IJK_Navier_Stokes_tools_cut_cell.h>
24#include <Param.h>
25
26Implemente_base_sans_constructeur(Cut_cell_schema_auxiliaire, "Cut_cell_schema_auxiliaire", Objet_U) ;
27
28Cut_cell_schema_auxiliaire::Cut_cell_schema_auxiliaire()
29{
31}
32
34{
35 return os;
36}
37
39{
40 Param param(que_suis_je());
41 set_param(param);
42 param.lire_avec_accolades(is);
43 return is;
44}
45
47{
48 param.ajouter("methode_valeur_remplissage", (int*)&methode_valeur_remplissage_);
49 param.dictionnaire("non_initialise",(int)METHODE_TEMPERATURE_REMPLISSAGE::NON_INITIALISE);
50 param.dictionnaire("copie_directe", (int)METHODE_TEMPERATURE_REMPLISSAGE::COPIE_DIRECTE);
51 param.dictionnaire("ponderation_voisin", (int)METHODE_TEMPERATURE_REMPLISSAGE::PONDERATION_VOISIN);
52 param.dictionnaire("ponderation_directionnelle_voisin", (int)METHODE_TEMPERATURE_REMPLISSAGE::PONDERATION_DIRECTIONNELLE_VOISIN);
53 param.dictionnaire("semi_lagrangien", (int)METHODE_TEMPERATURE_REMPLISSAGE::SEMI_LAGRANGIEN);
54 param.dictionnaire("semi_lagrangien_interpolate", (int)METHODE_TEMPERATURE_REMPLISSAGE::SEMI_LAGRANGIEN_INTERPOLATE);
55
56 param.ajouter("correction_petites_cellules", (int*)&correction_petites_cellules_);
57 param.dictionnaire("correction_directe", (int)CORRECTION_PETITES_CELLULES::CORRECTION_DIRECTE);
58 param.dictionnaire("direction_privilegiee", (int)CORRECTION_PETITES_CELLULES::DIRECTION_PRIVILEGIEE);
59 param.dictionnaire("direction_privilegiee_2", (int)CORRECTION_PETITES_CELLULES::DIRECTION_PRIVILEGIEE_2);
60 param.dictionnaire("correction_symetrique", (int)CORRECTION_PETITES_CELLULES::CORRECTION_SYMETRIQUE);
61 param.dictionnaire("direction_privilegiee_avec_limitation", (int)CORRECTION_PETITES_CELLULES::DIRECTION_PRIVILEGIEE_AVEC_LIMITATION);
62 param.dictionnaire("direction_privilegiee_avec_limitation_2", (int)CORRECTION_PETITES_CELLULES::DIRECTION_PRIVILEGIEE_AVEC_LIMITATION_2);
63 param.dictionnaire("correction_symetrique_avec_limitation", (int)CORRECTION_PETITES_CELLULES::CORRECTION_SYMETRIQUE_AVEC_LIMITATION);
64
65 param.ajouter("tolerate_not_within_tetrahedron", (int*)&tolerate_not_within_tetrahedron_);
66}
67
69{
70 temperature_remplissage_.associer_ephemere(cut_cell_disc);
71 flux_naive_.associer_ephemere(cut_cell_disc);
72}
73
74void Cut_cell_schema_auxiliaire::calcule_valeur_remplissage(double timestep, double lambda_liquid, double lambda_vapour, const IJK_Field_double& flux_interface_ns, const ArrOfDouble& interfacial_temperature, const IJK_Field_double& temperature_ft, const Cut_field_vector3_double& cut_field_total_velocity, const Cut_field_double& cut_field_temperature)
75{
76 if (methode_valeur_remplissage_ == METHODE_TEMPERATURE_REMPLISSAGE::COPIE_DIRECTE)
77 {
79 }
80 else if (methode_valeur_remplissage_ == METHODE_TEMPERATURE_REMPLISSAGE::PONDERATION_VOISIN)
81 {
82 calcule_valeur_remplissage_ponderation_voisin(false, cut_field_total_velocity, cut_field_temperature, temperature_remplissage_);
83 }
84 else if (methode_valeur_remplissage_ == METHODE_TEMPERATURE_REMPLISSAGE::PONDERATION_DIRECTIONNELLE_VOISIN)
85 {
86 calcule_valeur_remplissage_ponderation_voisin(true, cut_field_total_velocity, cut_field_temperature, temperature_remplissage_);
87 }
88 else if (methode_valeur_remplissage_ == METHODE_TEMPERATURE_REMPLISSAGE::SEMI_LAGRANGIEN)
89 {
90 calcule_valeur_remplissage_semi_lagrangien(timestep, lambda_liquid, lambda_vapour, flux_interface_ns, cut_field_temperature, temperature_remplissage_);
91 }
92 else if (methode_valeur_remplissage_ == METHODE_TEMPERATURE_REMPLISSAGE::SEMI_LAGRANGIEN_INTERPOLATE)
93 {
94 calcule_valeur_remplissage_semi_lagrangien_interpolate(timestep, interfacial_temperature, temperature_ft, cut_field_temperature, temperature_remplissage_);
95 }
96 else
97 {
98 Cerr << "Methode non reconnue pour le calcul de la valeur de remplissage." << finl;
100 }
101}
102
103void Cut_cell_schema_auxiliaire::compute_flux_dying_cells(const Cut_field_vector3_double& cut_field_total_velocity, const Cut_field_double& cut_field_temperature)
104{
105 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
106
107 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
108 const double delta_x = geom.get_constant_delta(0);
109 const double delta_y = geom.get_constant_delta(1);
110 const double delta_z = geom.get_constant_delta(2);
111 assert(cut_cell_disc.get_domaine().is_uniform(0));
112 assert(cut_cell_disc.get_domaine().is_uniform(1));
113 assert(cut_cell_disc.get_domaine().is_uniform(2));
114
115 int statut_diphasique = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::MOURRANT);
116 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique);
117 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique+1);
118 for (int index = index_min; index < index_max; index++)
119 {
120 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
121
122 Int3 ijk = cut_cell_disc.get_ijk(n);
123 int i = ijk[0];
124 int j = ijk[1];
125 int k = ijk[2];
126
127 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
128 continue;
129
130 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
131 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
132 assert(cut_cell_disc.get_interfaces().est_pure(next_indicatrice));
133 int phase = 1 - IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice); // phase de la cellule mourrante
134
135
136
137 double flux[6] = {0};
138 for (int num_face = 0; num_face < 6; num_face++)
139 {
140 int dir = num_face%3;
141 int decalage = num_face/3;
142 int sign = decalage*2 -1;
143
144 int di_decale = sign*(dir == 0);
145 int dj_decale = sign*(dir == 1);
146 int dk_decale = sign*(dir == 2);
147
148 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
149
150 double old_indicatrice_decale = cut_cell_disc.get_interfaces().I(i+di_decale,j+dj_decale,k+dk_decale);
151 bool decale_also_dying = (cut_cell_disc.get_interfaces().phase_mourrante(phase, i+di_decale,j+dj_decale,k+dk_decale));
152 bool decale_also_nascent = (cut_cell_disc.get_interfaces().phase_naissante(phase, i+di_decale,j+dj_decale,k+dk_decale));
153 bool decale_smaller = (phase == 0) ? (1 - old_indicatrice_decale) < (1 - old_indicatrice) : (old_indicatrice_decale) < (old_indicatrice);
154 if (decale_also_nascent || (decale_also_dying && decale_smaller))
155 {
156 flux[num_face] = 0;
157 }
158 else
159 {
160 flux[num_face] = f_dir*dying_cells_flux(num_face, phase, n, cut_field_total_velocity, cut_field_temperature);
161 }
162
163 flux_naive_(n,num_face) = flux[num_face];
164 }
165
166 // Correction du flux si aucun flux non-nul
167 if ((std::abs(flux[0]) + std::abs(flux[1]) + std::abs(flux[2]) + std::abs(flux[3]) + std::abs(flux[4]) + std::abs(flux[5])) == 0)
168 {
169 for (int num_face = 0; num_face < 6; num_face++)
170 {
171 int dir = num_face%3;
172 int decalage = num_face/3;
173 int sign = decalage*2 -1;
174
175 int di = decalage*(dir == 0);
176 int dj = decalage*(dir == 1);
177 int dk = decalage*(dir == 2);
178 int di_decale = sign*(dir == 0);
179 int dj_decale = sign*(dir == 1);
180 int dk_decale = sign*(dir == 2);
181
182 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
183
184 double old_indicatrice_decale = cut_cell_disc.get_interfaces().I(i+di_decale,j+dj_decale,k+dk_decale);
185 bool decale_also_dying = (cut_cell_disc.get_interfaces().phase_mourrante(phase, i+di_decale,j+dj_decale,k+dk_decale));
186 bool decale_also_nascent = (cut_cell_disc.get_interfaces().phase_naissante(phase, i+di_decale,j+dj_decale,k+dk_decale));
187 bool decale_smaller = (phase == 0) ? (1 - old_indicatrice_decale) < (1 - old_indicatrice) : (old_indicatrice_decale) < (old_indicatrice);
188 if (decale_also_nascent || (decale_also_dying && decale_smaller))
189 {
190 flux[num_face] = 0;
191 }
192 else
193 {
194 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
195 if (n_face >= 0)
196 {
197 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir) : cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir);
198 if (surface_efficace > 0)
199 {
200 flux[num_face] = f_dir*surface_efficace;
201 }
202 }
203 else
204 {
205 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().I(i+di,j+dj,k+dk) : cut_cell_disc.get_interfaces().I(i+di,j+dj,k+dk);
206 assert((surface_efficace == 0) || (surface_efficace == 1));
207 if (surface_efficace > 0)
208 {
209 flux[num_face] = f_dir*surface_efficace;
210 }
211 }
212 }
213
214 flux_naive_(n,num_face) = flux[num_face];
215 }
216 }
217 }
218}
219
220void Cut_cell_schema_auxiliaire::compute_flux_small_nascent_cells(const Cut_field_vector3_double& cut_field_total_velocity, Cut_field_double& cut_field_temperature)
221{
222 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
223
224 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
225 const double delta_x = geom.get_constant_delta(DIRECTION_I);
226 const double delta_y = geom.get_constant_delta(DIRECTION_J);
227 const double delta_z = geom.get_constant_delta(DIRECTION_K);
228 assert(geom.is_uniform(0));
229 assert(geom.is_uniform(1));
230 assert(geom.is_uniform(2));
231
232 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
233 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
234 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
235 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
236 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
237 for (int index = index_min; index < index_max; index++)
238 {
239 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
240
241 Int3 ijk = cut_cell_disc.get_ijk(n);
242 int i = ijk[0];
243 int j = ijk[1];
244 int k = ijk[2];
245
246 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
247 continue;
248
249 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
250 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
251 int est_naissant = cut_cell_disc.get_interfaces().est_pure(old_indicatrice);
252 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(old_indicatrice) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
253 assert(est_naissant || cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, cut_cell_disc.get_interfaces().I(i,j,k), next_indicatrice));
254
255
256
257 double flux[6] = {0};
258 for (int num_face = 0; num_face < 6; num_face++)
259 {
260 int dir = num_face%3;
261 int decalage = num_face/3;
262 int sign = decalage*2 -1;
263
264 int di_decale = sign*(dir == 0);
265 int dj_decale = sign*(dir == 1);
266 int dk_decale = sign*(dir == 2);
267
268 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
269
270 double old_indicatrice_decale = cut_cell_disc.get_interfaces().I(i+di_decale,j+dj_decale,k+dk_decale);
271 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
272 bool decale_also_dying = (cut_cell_disc.get_interfaces().phase_mourrante(phase, i+di_decale,j+dj_decale,k+dk_decale));
273 bool decale_nascent = (cut_cell_disc.get_interfaces().phase_naissante(phase, i+di_decale,j+dj_decale,k+dk_decale));
274 bool decale_small = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, old_indicatrice_decale, next_indicatrice_decale);
275 bool decale_smaller = (phase == 0) ? (1 - next_indicatrice_decale) < (1 - next_indicatrice) : (next_indicatrice_decale) < (next_indicatrice);
276 if (decale_also_dying || (est_naissant && decale_nascent && decale_smaller) || ((!est_naissant) && decale_nascent) || ((!est_naissant) && decale_small && decale_smaller))
277 {
278 flux[num_face] = 0;
279 }
280 else
281 {
282 flux[num_face] = f_dir*small_nascent_cells_flux(num_face, phase, n, cut_field_total_velocity, cut_field_temperature);
283 }
284
285 flux_naive_(n,num_face) = flux[num_face];
286 }
287
288 // Correction du flux si aucun flux non-nul
289 if ((std::abs(flux[0]) + std::abs(flux[1]) + std::abs(flux[2]) + std::abs(flux[3]) + std::abs(flux[4]) + std::abs(flux[5])) == 0)
290 {
291 for (int num_face = 0; num_face < 6; num_face++)
292 {
293 int dir = num_face%3;
294 int decalage = num_face/3;
295 int sign = decalage*2 -1;
296
297 int di = decalage*(dir == 0);
298 int dj = decalage*(dir == 1);
299 int dk = decalage*(dir == 2);
300 int di_decale = sign*(dir == 0);
301 int dj_decale = sign*(dir == 1);
302 int dk_decale = sign*(dir == 2);
303
304 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
305
306 double old_indicatrice_decale = cut_cell_disc.get_interfaces().I(i+di_decale,j+dj_decale,k+dk_decale);
307 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
308 bool decale_also_dying = (cut_cell_disc.get_interfaces().phase_mourrante(phase, i+di_decale,j+dj_decale,k+dk_decale));
309 bool decale_nascent = (cut_cell_disc.get_interfaces().phase_naissante(phase, i+di_decale,j+dj_decale,k+dk_decale));
310 bool decale_small = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, old_indicatrice_decale, next_indicatrice_decale);
311 bool decale_smaller = (phase == 0) ? (1 - next_indicatrice_decale) < (1 - next_indicatrice) : (next_indicatrice_decale) < (next_indicatrice);
312 if (decale_also_dying || (est_naissant && decale_nascent && decale_smaller) || ((!est_naissant) && decale_nascent) || ((!est_naissant) && decale_small && decale_smaller))
313 {
314 flux[num_face] = 0;
315 }
316 else
317 {
318 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
319 if (n_face >= 0)
320 {
321 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir) : cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir);
322 if (surface_efficace > 0)
323 {
324 flux[num_face] = f_dir*surface_efficace;
325 }
326 }
327 else
328 {
329 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk) : cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk);
330 assert((surface_efficace == 0) || (surface_efficace == 1));
331 if (surface_efficace > 0)
332 {
333 flux[num_face] = f_dir*surface_efficace;
334 }
335 }
336 }
337
338 flux_naive_(n,num_face) = flux[num_face];
339 }
340 }
341 }
342}
343
344void Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_copie_directe(const Cut_field_double& cut_field_temperature, DoubleTabFT_cut_cell_scalar& valeur_remplissage)
345{
346 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
347
348 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
349 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
350 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
351 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
352 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
353 for (int index = index_min; index < index_max; index++)
354 {
355 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
356
357 Int3 ijk = cut_cell_disc.get_ijk(n);
358 int i = ijk[0];
359 int j = ijk[1];
360 int k = ijk[2];
361
362 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
363 continue;
364
365 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
366 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
367 int est_naissant = cut_cell_disc.get_interfaces().est_pure(old_indicatrice);
368 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(old_indicatrice) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
369
370 valeur_remplissage(n) = (phase == 0) ? cut_field_temperature.diph_v_(n) : cut_field_temperature.diph_l_(n);
371 }
372}
373
374void Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_ponderation_voisin(bool est_directionnel, const Cut_field_vector3_double& cut_field_total_velocity, const Cut_field_double& cut_field_temperature, DoubleTabFT_cut_cell_scalar& valeur_remplissage)
375{
376 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
377
378 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
379 const double delta_x = geom.get_constant_delta(0);
380 const double delta_y = geom.get_constant_delta(1);
381 const double delta_z = geom.get_constant_delta(2);
382 assert(cut_cell_disc.get_domaine().is_uniform(0));
383 assert(cut_cell_disc.get_domaine().is_uniform(1));
384 assert(cut_cell_disc.get_domaine().is_uniform(2));
385
386 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
387 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
388 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
389 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
390 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
391 for (int index = index_min; index < index_max; index++)
392 {
393 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
394
395 Int3 ijk = cut_cell_disc.get_ijk(n);
396 int i = ijk[0];
397 int j = ijk[1];
398 int k = ijk[2];
399
400 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
401 continue;
402
403 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
404 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
405 int est_naissant = cut_cell_disc.get_interfaces().est_pure(old_indicatrice);
406 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(old_indicatrice) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
407 assert(est_naissant || cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, cut_cell_disc.get_interfaces().I(i,j,k), next_indicatrice));
408
409
410 double temp[6] = {0};
411 double flux[6] = {0};
412 double total_velocity[6] = {0};
413 for (int num_face = 0; num_face < 6; num_face++)
414 {
415 int dir = num_face%3;
416 int decalage = num_face/3;
417 int sign = decalage*2 -1;
418
419 int di = decalage*(dir == 0);
420 int dj = decalage*(dir == 1);
421 int dk = decalage*(dir == 2);
422 int di_decale = sign*(dir == 0);
423 int dj_decale = sign*(dir == 1);
424 int dk_decale = sign*(dir == 2);
425
426 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
427
428 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
429
430 double temperature_decale = -1e37;
431 int n_decale = cut_cell_disc.get_n(i+di_decale, j+dj_decale, k+dk_decale);
432 if (n_decale >= 0)
433 {
434 temperature_decale = (phase == 0) ? cut_field_temperature.diph_v_(n_decale) : cut_field_temperature.diph_l_(n_decale);
435 }
436 else
437 {
438 temperature_decale = (phase == (IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale)))*cut_field_temperature.pure_(i+di_decale,j+dj_decale,k+dk_decale);
439 }
440
441 total_velocity[num_face] = cut_field_total_velocity[dir].from_ijk_and_phase(i+di,j+dj,k+dk, phase);
442
443 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
444 if (n_face >= 0)
445 {
446 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir) : cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir);
447 double temperature = temperature_decale;
448 flux[num_face] = -sign*f_dir*surface_efficace*temperature*total_velocity[num_face];
449 if (est_directionnel)
450 {
451 flux[num_face] = (flux[num_face] < 0) ? 0. : flux[num_face];
452 }
453 temp[num_face] = temperature;
454 }
455 else
456 {
457 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk) : cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk);
458 assert((surface_efficace == 0) || (surface_efficace == 1));
459 double temperature = temperature_decale;
460 flux[num_face] = -sign*f_dir*surface_efficace*temperature*total_velocity[num_face];
461 if (est_directionnel)
462 {
463 flux[num_face] = (flux[num_face] < 0) ? 0. : flux[num_face];
464 }
465 temp[num_face] = temperature;
466 }
467 }
468
469 // Correction du flux si aucun flux non-nul
470 if ((std::abs(flux[0]) + std::abs(flux[1]) + std::abs(flux[2]) + std::abs(flux[3]) + std::abs(flux[4]) + std::abs(flux[5])) == 0)
471 {
472 for (int num_face = 0; num_face < 6; num_face++)
473 {
474 int dir = num_face%3;
475 int decalage = num_face/3;
476 int sign = decalage*2 -1;
477
478 int di = decalage*(dir == 0);
479 int dj = decalage*(dir == 1);
480 int dk = decalage*(dir == 2);
481 int di_decale = sign*(dir == 0);
482 int dj_decale = sign*(dir == 1);
483 int dk_decale = sign*(dir == 2);
484
485 double f_dir = select_dir(dir, delta_y*delta_z, delta_x*delta_z, delta_x*delta_y);
486
487 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
488
489 double temperature_decale = -1e37;
490 int n_decale = cut_cell_disc.get_n(i+di_decale, j+dj_decale, k+dk_decale);
491 if (n_decale >= 0)
492 {
493 temperature_decale = (phase == 0) ? cut_field_temperature.diph_v_(n_decale) : cut_field_temperature.diph_l_(n_decale);
494 }
495 else
496 {
497 temperature_decale = (phase == (IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale)))*cut_field_temperature.pure_(i+di_decale,j+dj_decale,k+dk_decale);
498 }
499
500 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
501 if (n_face >= 0)
502 {
503 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir) : cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir);
504 double temperature = temperature_decale;
505 flux[num_face] = f_dir*surface_efficace*temperature;
506 temp[num_face] = temperature;
507 }
508 else
509 {
510 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk) : cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk);
511 assert((surface_efficace == 0) || (surface_efficace == 1));
512 double temperature = temperature_decale;
513 flux[num_face] = f_dir*surface_efficace*temperature;
514 temp[num_face] = temperature;
515 }
516 }
517 }
518
519 if ((std::abs(total_velocity[0]) + std::abs(total_velocity[1]) + std::abs(total_velocity[2]) + std::abs(total_velocity[3]) + std::abs(total_velocity[4]) + std::abs(total_velocity[5])) == 0)
520 {
521 // All velocities are zero
522 valeur_remplissage(n) = DMINFLOAT+1; // Dummy value to indicate that no filling should be made.
523 }
524 if ((std::abs(temp[0]) + std::abs(temp[1]) + std::abs(temp[2]) + std::abs(temp[3]) + std::abs(temp[4]) + std::abs(temp[5])) < 1e-37)
525 {
526 // It looks like the input field is constant zero. In that case, the filling value should be zero as well.
527 valeur_remplissage(n) = 0;
528 }
529 else
530 {
531 double somme_T_flux = (temp[0]*std::abs(flux[0]) != 0.)*std::abs(flux[0]) + (temp[1]*std::abs(flux[1]) != 0.)*std::abs(flux[1]) + (temp[2]*std::abs(flux[2]) != 0.)*std::abs(flux[2]) + (temp[3]*std::abs(flux[3]) != 0.)*std::abs(flux[3]) + (temp[4]*std::abs(flux[4]) != 0.)*std::abs(flux[4]) + (temp[5]*std::abs(flux[5]) != 0.)*std::abs(flux[5]);
532 assert(somme_T_flux != 0.);
533 double val_remplissage = (temp[0]*std::abs(flux[0]) + temp[1]*std::abs(flux[1]) + temp[2]*std::abs(flux[2]) + temp[3]*std::abs(flux[3]) + temp[4]*std::abs(flux[4]) + temp[5]*std::abs(flux[5]))/somme_T_flux;
534 valeur_remplissage(n) = val_remplissage;
535 }
536 }
537}
538
539void Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_semi_lagrangien(double timestep, double lambda_liquid, double lambda_vapour, const IJK_Field_double& flux_interface_ns, const Cut_field_double& cut_field_temperature, DoubleTabFT_cut_cell_scalar& valeur_remplissage)
540{
541 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
542 const IJK_Field_double& surface_interface_old = cut_cell_disc.get_interfaces().get_surface_interface_old();
543
544 double dx = cut_cell_disc.get_domaine().get_constant_delta(0);
545 double dy = cut_cell_disc.get_domaine().get_constant_delta(1);
546 double dz = cut_cell_disc.get_domaine().get_constant_delta(2);
547
548 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
549 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
550 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
551 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
552 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
553 for (int index = index_min; index < index_max; index++)
554 {
555 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
556
557 Int3 ijk = cut_cell_disc.get_ijk(n);
558 int i = ijk[0];
559 int j = ijk[1];
560 int k = ijk[2];
561
562 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
563 continue;
564
565 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
566 int est_naissant = cut_cell_disc.get_interfaces().est_pure(cut_cell_disc.get_interfaces().I(i,j,k));
567 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.get_interfaces().I(i,j,k)) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
568
569 double normal_x = cut_cell_disc.get_interfaces().get_normale_deplacement_interface()(n,0);
570 double normal_y = cut_cell_disc.get_interfaces().get_normale_deplacement_interface()(n,1);
571 double normal_z = cut_cell_disc.get_interfaces().get_normale_deplacement_interface()(n,2);
572
573 double velocity_x = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,0);
574 double velocity_y = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,1);
575 double velocity_z = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,2);
576
577 double next_bary_x = dx*cut_cell_disc.get_interfaces().get_barycentre(true, 0, phase, i,j,k);
578 double next_bary_y = dy*cut_cell_disc.get_interfaces().get_barycentre(true, 1, phase, i,j,k);
579 double next_bary_z = dz*cut_cell_disc.get_interfaces().get_barycentre(true, 2, phase, i,j,k);
580
581 double next_bary_deplace_x = next_bary_x - velocity_x*timestep;
582 double next_bary_deplace_y = next_bary_y - velocity_y*timestep;
583 double next_bary_deplace_z = next_bary_z - velocity_z*timestep;
584
585 int i_old = i + static_cast <int>(std::floor(next_bary_deplace_x/dx));
586 int j_old = j + static_cast <int>(std::floor(next_bary_deplace_y/dy));
587 int k_old = k + static_cast <int>(std::floor(next_bary_deplace_z/dz));
588 assert(i-i_old >= -1 && i-i_old <= 1);
589 assert(j-j_old >= -1 && j-j_old <= 1);
590 assert(k-k_old >= -1 && k-k_old <= 1);
591
592 // En raison du seuil sur l'indicatrice, il est possible que la cellule_old corresponde a la cellule initiale
593 // bien que celle-ci soit consideree comme naissante.
594 // Dans ce cas, on utilise un voisin ; qui pourra fournir une temperature de reference.
595 if (est_naissant && (i_old == i) && (j_old == j) && (k_old == k))
596 {
597 double ecart_x = std::abs(next_bary_deplace_x/dx - std::round(next_bary_deplace_x/dx));
598 double ecart_y = std::abs(next_bary_deplace_y/dy - std::round(next_bary_deplace_y/dy));
599 double ecart_z = std::abs(next_bary_deplace_z/dz - std::round(next_bary_deplace_z/dz));
600 int direction_a_modifier = (ecart_x <= ecart_y && ecart_x <= ecart_z) ? 0 : ((ecart_y <= ecart_x && ecart_y <= ecart_z) ? 1 : 2);
601 double next_bary_deplace_normalise = select_dir(direction_a_modifier, next_bary_deplace_x/dx, next_bary_deplace_y/dy, next_bary_deplace_z/dz);
602 bool ajout_positif = std::floor(next_bary_deplace_normalise) > .5;
603
604 if (direction_a_modifier == 0)
605 {
606 i_old += (2*ajout_positif - 1);
607 }
608 else if (direction_a_modifier == 1)
609 {
610 j_old += (2*ajout_positif - 1);
611 }
612 else if (direction_a_modifier == 2)
613 {
614 k_old += (2*ajout_positif - 1);
615 }
616 }
617
618 int n_old = cut_cell_disc.get_n(i_old,j_old,k_old);
619
620 double old_bary_x = dx*((i_old - i) + cut_cell_disc.get_interfaces().get_barycentre(false, 0, phase, i_old,j_old,k_old));
621 double old_bary_y = dy*((j_old - j) + cut_cell_disc.get_interfaces().get_barycentre(false, 1, phase, i_old,j_old,k_old));
622 double old_bary_z = dz*((k_old - k) + cut_cell_disc.get_interfaces().get_barycentre(false, 2, phase, i_old,j_old,k_old));
623
624 if (n_old < 0)
625 {
626 Cerr << "Dans Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_semi_lagrangien, on a n_old < 0." << finl;
627 Cerr << "Ce cas est normalement pas possible mais pourrait peut-etre survenir a cause de la correction avec 'est_naissant && (i_old == i) && (j_old == j) && (k_old == k)'" << finl;
628 Cerr << "Verification : est_naissant=" << est_naissant << " i=" << i << " j=" << j << " k=" << k << " i_old=" << i_old << " j_old=" << j_old << " k_old=" << k_old << finl;
629 //Process::exit();
630 }
631
632 double temperature_old = (n_old < 0) ? cut_field_temperature.pure_(i_old,j_old,k_old) : ((phase == 0) ? cut_field_temperature.diph_v_(n_old) : cut_field_temperature.diph_l_(n_old));
633 double temperature_next = (phase == 0) ? cut_field_temperature.diph_v_(n) : cut_field_temperature.diph_l_(n);
634 if (temperature_next == 0.)
635 {
636 assert(temperature_old != 0);
637 }
638 assert(temperature_old != 0);
639
640 assert((flux_interface_ns(i,j,k) == 0.) || (surface_interface_old(i,j,k) != 0.)); // La surface ne devrait pas etre nulle si il y a un flux
641 double lambda = (phase == 0) ? lambda_vapour : lambda_liquid;
642 double dTdn = (flux_interface_ns(i,j,k) == 0.) ? 0. : flux_interface_ns(i,j,k)/(lambda * surface_interface_old(i,j,k));
643 assert((flux_interface_ns(i,j,k) == 0.) || (surface_interface_old(i,j,k) != 0));
644 valeur_remplissage(n) = temperature_old + dTdn * ((next_bary_deplace_x - old_bary_x)*normal_x + (next_bary_deplace_y - old_bary_y)*normal_y + (next_bary_deplace_z - old_bary_z)*normal_z);
645 }
646}
647
648void Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_semi_lagrangien_interpolate(double timestep, const ArrOfDouble& interfacial_temperature, const IJK_Field_double& temperature_ft, const Cut_field_double& cut_field_temperature, DoubleTabFT_cut_cell_scalar& valeur_remplissage)
649{
650 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
651
652 int count_status_not_found = 0;
653 int count_status_below_10 = 0;
654 int count_status_below_100 = 0;
655 int count_status_below_1000 = 0;
656 int count_status_below_10000 = 0;
657 int count_status_below_100000 = 0;
658 int count_status_below_1000000 = 0;
659 int count_status_above_1000000 = 0;
660
661 double dx = cut_cell_disc.get_domaine().get_constant_delta(0);
662 double dy = cut_cell_disc.get_domaine().get_constant_delta(1);
663 double dz = cut_cell_disc.get_domaine().get_constant_delta(2);
664
665 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
666 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
667 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
668 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
669 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
670 for (int index = index_min; index < index_max; index++)
671 {
672 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
673
674 Int3 ijk = cut_cell_disc.get_ijk(n);
675 int i = ijk[0];
676 int j = ijk[1];
677 int k = ijk[2];
678
679 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
680 continue;
681
682 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
683 int est_naissant = cut_cell_disc.get_interfaces().est_pure(cut_cell_disc.get_interfaces().I(i,j,k));
684 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.get_interfaces().I(i,j,k)) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
685
686 double velocity_x = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,0);
687 double velocity_y = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,1);
688 double velocity_z = cut_cell_disc.get_interfaces().get_vitesse_deplacement_interface()(n,2);
689
690 double next_bary_x = dx*cut_cell_disc.get_interfaces().get_barycentre(true, 0, phase, i,j,k);
691 double next_bary_y = dy*cut_cell_disc.get_interfaces().get_barycentre(true, 1, phase, i,j,k);
692 double next_bary_z = dz*cut_cell_disc.get_interfaces().get_barycentre(true, 2, phase, i,j,k);
693
694 double next_bary_deplace_x = next_bary_x - velocity_x*timestep;
695 double next_bary_deplace_y = next_bary_y - velocity_y*timestep;
696 double next_bary_deplace_z = next_bary_z - velocity_z*timestep;
697
698 double coordinates_x = next_bary_deplace_x + cut_cell_disc.get_domaine().get_coord_of_dof_along_dir(DIRECTION_I, i, Domaine_IJK::NODES);
699 double coordinates_y = next_bary_deplace_y + cut_cell_disc.get_domaine().get_coord_of_dof_along_dir(DIRECTION_J, j, Domaine_IJK::NODES);
700 double coordinates_z = next_bary_deplace_z + cut_cell_disc.get_domaine().get_coord_of_dof_along_dir(DIRECTION_K, k, Domaine_IJK::NODES);
701 Vecteur3 coordinates(coordinates_x, coordinates_y, coordinates_z);
702
703 int status = -2;
704 const int tolerate_not_within_tetrahedron = std::max(1, tolerate_not_within_tetrahedron_);
705 double temperature_interpolate = ijk_interpolate_cut_cell_using_interface(false, phase, temperature_ft, cut_field_temperature, interfacial_temperature, coordinates, tolerate_not_within_tetrahedron, status);
706 valeur_remplissage(n) = temperature_interpolate;
707
708 if (status == -1)
709 {
710 Cerr << "DEBUG status=-1 T_remplissage=" << valeur_remplissage(n) << finl;
711 }
712
713 assert(status > -2);
714 if (status == -1)
715 {
716 count_status_not_found++;
717 }
718 else if (status < 10)
719 {
720 count_status_below_10++;
721 }
722 else if (status < 100)
723 {
724 count_status_below_100++;
725 }
726 else if (status < 1000)
727 {
728 count_status_below_1000++;
729 }
730 else if (status < 10000)
731 {
732 count_status_below_10000++;
733 }
734 else if (status < 100000)
735 {
736 count_status_below_100000++;
737 }
738 else if (status < 1000000)
739 {
740 count_status_below_1000000++;
741 }
742 else if (status >= 1000000)
743 {
744 count_status_above_1000000++;
745 }
746 else
747 {
748 Cerr << "Un tel statut n'est pas possible." << finl;
750 }
751 }
752
753 Cerr << "Bilan des statuts pour Cut_cell_schema_auxiliaire::calcule_valeur_remplissage_semi_lagrangien_interpolate : " << finl;
754 Cerr << " -1 " << count_status_not_found << finl;
755 Cerr << " <10 " << count_status_below_10 << finl;
756 Cerr << " <100 " << count_status_below_100 << finl;
757 Cerr << " <1000 " << count_status_below_1000 << finl;
758 Cerr << " <10000 " << count_status_below_10000 << finl;
759 Cerr << " <100000 " << count_status_below_100000 << finl;
760 Cerr << " <1000000 " << count_status_below_1000000 << finl;
761 Cerr << ">=1000000 " << count_status_above_1000000 << finl;
762}
763
764void Cut_cell_schema_auxiliaire::add_dying_cells(const Cut_field_vector3_double& cut_field_total_velocity, Cut_field_double& cut_field_temperature, bool write_flux, Cut_field_vector3_double& cut_field_current_fluxes)
765{
766 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
767
768 assert(cut_cell_disc.get_domaine().is_uniform(0));
769 assert(cut_cell_disc.get_domaine().is_uniform(1));
770 assert(cut_cell_disc.get_domaine().is_uniform(2));
771
772 int statut_diphasique = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::MOURRANT);
773 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique);
774 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique+1);
775 for (int index = index_min; index < index_max; index++)
776 {
777 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
778
779 Int3 ijk = cut_cell_disc.get_ijk(n);
780 int i = ijk[0];
781 int j = ijk[1];
782 int k = ijk[2];
783
784 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
785 continue;
786
787 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
788 assert(cut_cell_disc.get_interfaces().est_pure(next_indicatrice));
789 int phase = 1 - IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice); // phase de la cellule mourrante
790
791 // Cette variable next_nonzero_indicatrice est utilisee plutot que old_indicatrice,
792 // par coherence avec l'indicatrice des cellules voisines, qui peut-etre est next mais
793 // peut-etre est egalement old si elle est egalement mourrante.
794 double next_nonzero_indicatrice = cut_cell_disc.get_interfaces().In_nonzero(phase,i,j,k);
795 assert(next_nonzero_indicatrice == ((phase == 0) ? 1 - cut_cell_disc.get_interfaces().I(i,j,k) : cut_cell_disc.get_interfaces().I(i,j,k)));
796
797 double temperature_centre = (phase == 0) ? cut_field_temperature.diph_v_(n) : cut_field_temperature.diph_l_(n);
798
799 if (std::abs(temperature_centre) < 1e-24)
800 {
801 continue;
802 }
803
804 // L'indicatrice precedente est utilisee. En effet, pour ne pas perdre d'information la temperature des cellules
805 // mortes reste associee a l'indicatrice precedente dans tous les cas.
806 double quantite_totale = (phase == 0) ? -next_nonzero_indicatrice*cut_field_temperature.diph_v_(n) : -next_nonzero_indicatrice*cut_field_temperature.diph_l_(n);
807
808
809 double flux[6] = {flux_naive_(n,0), flux_naive_(n,1), flux_naive_(n,2), flux_naive_(n,3), flux_naive_(n,4), flux_naive_(n,5)};
810
813 assert(somme_flux != 0.);
814
815
816 assert((flux[0] != 0) || (flux[1] != 0) || (flux[2] != 0) || (flux[3] != 0) || (flux[4] != 0) || (flux[5] != 0));
817
818 for (int num_face = 0; num_face < 6; num_face++)
819 {
820 if (flux[num_face] != 0.)
821 {
822 int dir = num_face%3;
823 int decalage = num_face/3;
824 int sign = decalage*2 -1;
825
826 int di_decale = sign*(dir == 0);
827 int dj_decale = sign*(dir == 1);
828 int dk_decale = sign*(dir == 2);
829
830 int n_decale = cut_cell_disc.get_n(i+di_decale, j+dj_decale, k+dk_decale);
831 double next_nonzero_indicatrice_decale = cut_cell_disc.get_interfaces().In_nonzero(phase,i+di_decale,j+dj_decale,k+dk_decale);
832 if (n_decale >= 0)
833 {
834 // Si la cellule voisine est egalement morte, on utilise l'indicatrice precedente pour calculer
835 // la variation de la temperature, sinon, on utilise l'indicatrice du pas de temps actuel/suivant.
836 if (phase == 0)
837 {
838 cut_field_temperature.diph_v_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice_decale;
839 cut_field_temperature.diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice;
840 }
841 else
842 {
843 cut_field_temperature.diph_l_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice_decale;
844 cut_field_temperature.diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice;
845 }
846 }
847 else
848 {
849 cut_field_temperature.pure_(i+di_decale,j+dj_decale,k+dk_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
850 if (phase == 0)
851 {
852 cut_field_temperature.diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice;
853 }
854 else
855 {
856 cut_field_temperature.diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale/next_nonzero_indicatrice;
857 }
858 }
859
860
861 if (write_flux)
862 {
863 if (num_face < 3)
864 {
865 if (phase == 0)
866 {
867 cut_field_current_fluxes[dir].diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale;
868 }
869 else
870 {
871 cut_field_current_fluxes[dir].diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale;
872 }
873 }
874 else
875 {
876 if (n_decale >= 0)
877 {
878 if (phase == 0)
879 {
880 cut_field_current_fluxes[dir].diph_v_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
881 }
882 else
883 {
884 cut_field_current_fluxes[dir].diph_l_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
885 }
886 }
887 else
888 {
889 cut_field_current_fluxes[dir].pure_(i+di_decale,j+dj_decale,k+dk_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
890 }
891 }
892 }
893 }
894 }
895 }
896
897 if (write_flux)
898 {
899 cut_field_current_fluxes[0].echange_espace_virtuel(1);
900 cut_field_current_fluxes[1].echange_espace_virtuel(1);
901 cut_field_current_fluxes[2].echange_espace_virtuel(1);
902 }
903}
904
905void Cut_cell_schema_auxiliaire::add_small_nascent_cells(const Cut_field_vector3_double& cut_field_total_velocity, Cut_field_double& cut_field_temperature, bool write_flux, Cut_field_vector3_double& cut_field_current_fluxes)
906{
907 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_temperature.get_cut_cell_disc();
908
909 assert(cut_cell_disc.get_domaine().is_uniform(0));
910 assert(cut_cell_disc.get_domaine().is_uniform(1));
911 assert(cut_cell_disc.get_domaine().is_uniform(2));
912
913 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
914 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
915 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
916 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
917 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
918 for (int index = index_min; index < index_max; index++)
919 {
920 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
921
922 Int3 ijk = cut_cell_disc.get_ijk(n);
923 int i = ijk[0];
924 int j = ijk[1];
925 int k = ijk[2];
926
927 if (!cut_cell_disc.get_domaine().within_ghost(i, j, k, 1, 1))
928 continue;
929
930 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
931 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
932 int est_naissant = cut_cell_disc.get_interfaces().est_pure(old_indicatrice);
933 int phase = est_naissant ? 1 - IJK_Interfaces::convert_indicatrice_to_phase(old_indicatrice) : ((cut_cell_disc.get_interfaces().below_small_threshold(next_indicatrice)) ? 1 : 0); // phase de la cellule petite ou naissante
934 assert(est_naissant || cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, cut_cell_disc.get_interfaces().I(i,j,k), next_indicatrice));
935
936
937 double temperature_centre = (phase == 0) ? cut_field_temperature.diph_v_(n) : cut_field_temperature.diph_l_(n);
938 double val_remplissage = temperature_remplissage_(n);
939 double quantite_totale = (phase == 0) ? (1 - next_indicatrice)*(val_remplissage - temperature_centre) : next_indicatrice*(val_remplissage - temperature_centre);
940
941 // The dummy value DMINFLOAT+1 indicates that no filling should be made.
942 if (val_remplissage == DMINFLOAT+1)
943 {
944 if (phase == 0)
945 {
946 assert((cut_field_total_velocity[0].from_ijk_and_phase(i,j,k, 0) == 0) && (cut_field_total_velocity[1].from_ijk_and_phase(i,j,k, 0) == 0) && (cut_field_total_velocity[2].from_ijk_and_phase(i,j,k, 0) == 0));
947 }
948 else
949 {
950 assert((cut_field_total_velocity[0].from_ijk_and_phase(i,j,k, 1) == 0) && (cut_field_total_velocity[1].from_ijk_and_phase(i,j,k, 1) == 0) && (cut_field_total_velocity[2].from_ijk_and_phase(i,j,k, 1) == 0));
951 }
952 continue;
953 }
954
955 if (std::abs(temperature_centre - val_remplissage) < 1e-24)
956 {
957 continue;
958 }
959
960 // Note: std::abs(val_remplissage) is compared to std::numeric_limits<double>::min(), as a naive std::abs(val_remplissage) > 0 does not prevent arithmetic errors upon division.
961 if ((std::abs(val_remplissage) > std::numeric_limits<double>::min()) && (std::abs(temperature_centre - val_remplissage)/val_remplissage) < 1e-24)
962 {
963 continue;
964 }
965
966 double flux[6] = {flux_naive_(n,0), flux_naive_(n,1), flux_naive_(n,2), flux_naive_(n,3), flux_naive_(n,4), flux_naive_(n,5)};
967
968 // Calcul du flux maximum pour la limitation des flux
969 double flux_max[6] = {0};
970 double total_velocity[6] = {0};
971 for (int num_face = 0; num_face < 6; num_face++)
972 {
973 int dir = num_face%3;
974 int decalage = num_face/3;
975 int sign = decalage*2 -1;
976
977 int di = decalage*(dir == 0);
978 int dj = decalage*(dir == 1);
979 int dk = decalage*(dir == 2);
980 int di_decale = sign*(dir == 0);
981 int dj_decale = sign*(dir == 1);
982 int dk_decale = sign*(dir == 2);
983
984 double old_indicatrice_decale = cut_cell_disc.get_interfaces().I(i+di_decale,j+dj_decale,k+dk_decale);
985 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
986 bool decale_also_dying = (cut_cell_disc.get_interfaces().phase_mourrante(phase, i+di_decale,j+dj_decale,k+dk_decale));
987 bool decale_nascent = (cut_cell_disc.get_interfaces().phase_naissante(phase, i+di_decale,j+dj_decale,k+dk_decale));
988 bool decale_small = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, old_indicatrice_decale, next_indicatrice_decale);
989 bool decale_smaller = (phase == 0) ? (1 - next_indicatrice_decale) < (1 - next_indicatrice) : (next_indicatrice_decale) < (next_indicatrice);
990 if (decale_also_dying || (est_naissant && decale_nascent && decale_smaller) || ((!est_naissant) && decale_nascent) || ((!est_naissant) && decale_small && decale_smaller))
991 {
992 flux_max[num_face] = 0;
993 }
994 else
995 {
996 double temperature_decale = -1e37;
997 int n_decale = cut_cell_disc.get_n(i+di_decale, j+dj_decale, k+dk_decale);
998 if (n_decale >= 0)
999 {
1000 temperature_decale = (phase == 0) ? cut_field_temperature.diph_v_(n_decale) : cut_field_temperature.diph_l_(n_decale);
1001 }
1002 else
1003 {
1004 temperature_decale = (phase == (IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale)))*cut_field_temperature.pure_(i+di_decale,j+dj_decale,k+dk_decale);
1005 }
1006
1007 total_velocity[num_face] = cut_field_total_velocity[dir].from_ijk_and_phase(i+di,j+dj,k+dk, phase);
1008
1009 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
1010 if (n_face >= 0)
1011 {
1012 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir) : cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face()(n_face, dir);
1013 if (surface_efficace > 0)
1014 {
1015 double next_volume_decale = (phase == 0) ? 1 - next_indicatrice_decale : next_indicatrice_decale;
1016 double next_volume = (phase == 0) ? 1 - next_indicatrice : next_indicatrice;
1017 flux_max[num_face] = (temperature_decale - temperature_centre)/(1/next_volume_decale + 1/next_volume);
1018 flux_max[num_face] = flux[num_face] >= 0 ? std::max(0., flux_max[num_face]) : std::max(0., -flux_max[num_face]);
1019 }
1020 }
1021 else
1022 {
1023 double surface_efficace = (phase == 0) ? 1 - cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk) : cut_cell_disc.get_interfaces().In(i+di,j+dj,k+dk);
1024 assert((surface_efficace == 0) || (surface_efficace == 1));
1025 if (surface_efficace > 0)
1026 {
1027 double next_volume_decale = (phase == 0) ? 1 - next_indicatrice_decale : next_indicatrice_decale;
1028 double next_volume = (phase == 0) ? 1 - next_indicatrice : next_indicatrice;
1029 flux_max[num_face] = (temperature_decale - temperature_centre)/(1/next_volume_decale + 1/next_volume);
1030 flux_max[num_face] = flux[num_face] >= 0 ? std::max(0., flux_max[num_face]) : std::max(0., -flux_max[num_face]);
1031 }
1032 }
1033 }
1034 }
1035
1037 {
1038 if ((std::abs(total_velocity[0]) + std::abs(total_velocity[1]) + std::abs(total_velocity[2]) + std::abs(total_velocity[3]) + std::abs(total_velocity[4]) + std::abs(total_velocity[5])) == 0)
1039 {
1040 continue;
1041 }
1042 }
1043
1046 assert(somme_flux != 0.);
1047 if (somme_flux == 0.)
1048 {
1049 continue;
1050 }
1051
1053
1054 assert((flux[0] != 0) || (flux[1] != 0) || (flux[2] != 0) || (flux[3] != 0) || (flux[4] != 0) || (flux[5] != 0));
1055
1056 for (int num_face = 0; num_face < 6; num_face++)
1057 {
1058 if (flux[num_face] != 0.)
1059 {
1060 int dir = num_face%3;
1061 int decalage = num_face/3;
1062 int sign = decalage*2 -1;
1063
1064 int di_decale = sign*(dir == 0);
1065 int dj_decale = sign*(dir == 1);
1066 int dk_decale = sign*(dir == 2);
1067
1068 int n_decale = cut_cell_disc.get_n(i+di_decale, j+dj_decale, k+dk_decale);
1069 double next_indicatrice_decale = cut_cell_disc.get_interfaces().In(i+di_decale,j+dj_decale,k+dk_decale);
1070 if (n_decale >= 0)
1071 {
1072 if (phase == 0)
1073 {
1074 cut_field_temperature.diph_v_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale/(1 - next_indicatrice_decale);
1075 cut_field_temperature.diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale/(1 - cut_cell_disc.get_interfaces().In(i,j,k));
1076 }
1077 else
1078 {
1079 cut_field_temperature.diph_l_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale/next_indicatrice_decale;
1080 cut_field_temperature.diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale/cut_cell_disc.get_interfaces().In(i,j,k);
1081 }
1082 }
1083 else
1084 {
1085 assert((int)next_indicatrice_decale == 1 - (int)(1 - next_indicatrice_decale));
1086 assert(phase == IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale));
1087 cut_field_temperature.pure_(i+di_decale,j+dj_decale,k+dk_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
1088 if (phase == 0)
1089 {
1090 cut_field_temperature.diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale/(1 - cut_cell_disc.get_interfaces().In(i,j,k));
1091 }
1092 else
1093 {
1094 cut_field_temperature.diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale/cut_cell_disc.get_interfaces().In(i,j,k);
1095 }
1096 }
1097
1098
1099 if (write_flux)
1100 {
1101 if (num_face < 3)
1102 {
1103 if (phase == 0)
1104 {
1105 cut_field_current_fluxes[dir].diph_v_(n) += (flux[num_face]/somme_flux)*quantite_totale;
1106 if (n_decale < 0)
1107 {
1108 assert(phase == IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale));
1109 cut_field_current_fluxes[dir].pure_(i,j,k) += (flux[num_face]/somme_flux)*quantite_totale;
1110 }
1111 }
1112 else
1113 {
1114 cut_field_current_fluxes[dir].diph_l_(n) += (flux[num_face]/somme_flux)*quantite_totale;
1115 if (n_decale < 0)
1116 {
1117 assert(phase == IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice_decale));
1118 cut_field_current_fluxes[dir].pure_(i,j,k) += (flux[num_face]/somme_flux)*quantite_totale;
1119 }
1120 }
1121 }
1122 else
1123 {
1124 if (n_decale >= 0)
1125 {
1126 if (phase == 0)
1127 {
1128 cut_field_current_fluxes[dir].diph_v_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
1129 }
1130 else
1131 {
1132 cut_field_current_fluxes[dir].diph_l_(n_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
1133 }
1134 }
1135 else
1136 {
1137 cut_field_current_fluxes[dir].pure_(i+di_decale,j+dj_decale,k+dk_decale) -= (flux[num_face]/somme_flux)*quantite_totale;
1138 }
1139 }
1140 }
1141 }
1142 }
1143 }
1144
1145 if (write_flux)
1146 {
1147 cut_field_current_fluxes[0].echange_espace_virtuel(1);
1148 cut_field_current_fluxes[1].echange_espace_virtuel(1);
1149 cut_field_current_fluxes[2].echange_espace_virtuel(1);
1150 }
1151}
const Domaine_IJK & get_domaine() const
const IJK_Interfaces & get_interfaces() const
Int3 get_ijk(int n) const
int get_n_face(int num_face, int n, int i, int j, int k) const
int get_n_from_statut_diphasique_index(int index) const
int get_statut_diphasique_value_index(int statut_diphasique) const
int get_n(int i, int j, int k) const
static void modification_flux_petites_cellules(CORRECTION_PETITES_CELLULES correction_petites_cellules, double quantite_totale, double flux[6])
static void limitation_flux_avec_flux_max(CORRECTION_PETITES_CELLULES correction_petites_cellules, double quantite_totale, double somme_flux, double flux_max[6], double flux[6])
CORRECTION_PETITES_CELLULES correction_petites_cellules_
virtual double small_nascent_cells_flux(int num_face, int phase, int n, const Cut_field_vector3_double &cut_field_total_velocity, const Cut_field_double &cut_field_temperature)=0
DoubleTabFT_cut_cell_scalar temperature_remplissage_
void set_param(Param &param) const override
void compute_flux_dying_cells(const Cut_field_vector3_double &cut_field_total_velocity, const Cut_field_double &cut_field_temperature)
void add_dying_cells(const Cut_field_vector3_double &cut_field_total_velocity, Cut_field_double &cut_field_temperature, bool write_flux, Cut_field_vector3_double &cut_field_current_fluxes)
METHODE_TEMPERATURE_REMPLISSAGE methode_valeur_remplissage_
void initialise(Cut_cell_FT_Disc &cut_cell_disc)
virtual double dying_cells_flux(int num_face, int phase, int n, const Cut_field_vector3_double &cut_field_total_velocity, const Cut_field_double &cut_field_temperature)=0
void compute_flux_small_nascent_cells(const Cut_field_vector3_double &cut_field_total_velocity, Cut_field_double &cut_field_temperature)
void calcule_valeur_remplissage_semi_lagrangien_interpolate(double timestep, const ArrOfDouble &interfacial_temperature, const IJK_Field_double &temperature_ft, const Cut_field_double &cut_field_temperature, DoubleTabFT_cut_cell_scalar &valeur_remplissage)
DoubleTabFT_cut_cell_vector6 flux_naive_
void calcule_valeur_remplissage_copie_directe(const Cut_field_double &cut_field_temperature, DoubleTabFT_cut_cell_scalar &valeur_remplissage)
void calcule_valeur_remplissage_semi_lagrangien(double timestep, double lambda_liquid, double lambda_vapour, const IJK_Field_double &flux_interface_ns, const Cut_field_double &cut_field_temperature, DoubleTabFT_cut_cell_scalar &valeur_remplissage)
void calcule_valeur_remplissage(double timestep, double lambda_liquid, double lambda_vapour, const IJK_Field_double &flux_interface_ns, const ArrOfDouble &interfacial_temperature, const IJK_Field_double &temperature_ft, const Cut_field_vector3_double &cut_field_total_velocity, const Cut_field_double &cut_field_temperature)
void calcule_valeur_remplissage_ponderation_voisin(bool est_directionnel, const Cut_field_vector3_double &cut_field_total_velocity, const Cut_field_double &cut_field_temperature, DoubleTabFT_cut_cell_scalar &valeur_remplissage)
void add_small_nascent_cells(const Cut_field_vector3_double &cut_field_total_velocity, Cut_field_double &cut_field_temperature, bool write_flux, Cut_field_vector3_double &cut_field_current_fluxes)
_TYPE_ & pure_(int i, int j, int k)
Definition Cut_field.h:116
const Cut_cell_FT_Disc & get_cut_cell_disc() const
Definition Cut_field.h:78
TRUSTTabFT_cut_cell< _TYPE_ > diph_l_
Definition Cut_field.h:49
TRUSTTabFT_cut_cell< _TYPE_ > diph_v_
Definition Cut_field.h:50
void echange_espace_virtuel(int ghost)
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
bool within_ghost(int i, int j, int k, int negative_ghost_size, int positive_ghost_size) const
bool is_uniform(int direction) const
Method returns true if uniform in this direction.
double get_coord_of_dof_along_dir(int dir, int i, Localisation loc) const
double get_constant_delta(int direction) const
Returns the size of cells in a direction.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const DoubleTabFT_cut_cell_vector3 & get_indicatrice_surfacique_efficace_face() const
const DoubleTabFT_cut_cell_vector3 & get_vitesse_deplacement_interface() const
const IJK_Field_double & I() const
double In_nonzero(const int phase, const int i, const int j, const int k) const
const IJK_Field_double & In() const
const IJK_Field_double & get_surface_interface_old() const
int next_below_small_threshold_for_phase(int phase, double old_indicatrice, double next_indicatrice) const
static int est_pure(double indicatrice)
double get_barycentre(bool next_time, int bary_compo, int phase, int i, int j, int k) const
static int convert_indicatrice_to_phase(double indicatrice)
const DoubleTabFT_cut_cell_vector3 & get_normale_deplacement_interface() const
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void dictionnaire(const char *option_name, int value)
Add an (option name, integer value) entry to the dictionary attached to a previously registered integ...
Definition Param.cpp:293
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52