TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Cut_cell_surface_efficace.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_surface_efficace.h>
17#include <IJK_Field_vector.h>
18#include <Cut_cell_FT_Disc.h>
19#include <IJK_Thermal_base.h>
20#include <Process.h>
21#include <IJK_Navier_Stokes_tools.h>
22#include <Perf_counters.h>
23#include <SolveurSys.h>
24#include <Matrice_Morse.h>
25#include <Matrice_Bloc.h>
26#include <Matrice_Dense.h>
27#include <EChaine.h>
28
29extern "C" {
30 void dgelsd_(int* M, int* N, int* NRHS, double* A, int* lda, double* B, int* ldb, double* S, double* RCOND, int* rank, double* WORK, int* lwork, int* iwork, int* INFO);
31}
32
33// Solve A.x = b using dgelsd_ from Lapack.
34// A has dimension (M,N) but is in column-major order
35// b has dimension (M)
36// x has dimension (N)
37// The result is overwritten within b.
38void dgelsd_resoudre_systeme(double* A, double* B, int M, int N)
39{
40 int NRHS = 1;
41 int INFO;
42 int LDB = std::max(N,M);
43 int rank;
44 double RCOND = -1.;
45
46 int NLVL = std::max(0, int(std::log2(std::min(N,M)/(2+1))) + 1);
47 int LIWORK = std::max(1, 3*std::min(N,M)*NLVL + 11*std::min(N,M));
48 int *IWORK = new int[LIWORK];
49
50 int S_size = std::min(N,M);
51 double *S = new double[S_size];
52
53 int LWORK = -1;
54 double LWORK_opt;
55
56 // Query LWORK size
57 dgelsd_(&M,&N,&NRHS,A,&M,B,&LDB,S,&RCOND,&rank,&LWORK_opt,&LWORK,IWORK,&INFO);
58
59 LWORK = (int)LWORK_opt;
60 double *WORK = new double[LWORK];
61
62 // Solve
63 dgelsd_(&M,&N,&NRHS,A,&M,B,&LDB,S,&RCOND,&rank,WORK,&LWORK,IWORK,&INFO);
64
65 delete[] WORK;
66}
67
68
70 int methode_explicite,
71 const IJK_Field_double& old_indicatrice_ns,
72 const IJK_Field_double& next_indicatrice_ns,
73 const IJK_Field_double& surface_interface_ns_old,
74 const IJK_Field_double& surface_interface_ns_next,
75 const IJK_Field_vector3_double& normal_of_interf_ns_old,
76 const IJK_Field_vector3_double& normal_of_interf_ns_next,
77 DoubleTabFT_cut_cell_vector3& normale_deplacement_interface,
78 DoubleTabFT_cut_cell_scalar& surface_efficace_interface,
79 DoubleTabFT_cut_cell_scalar& surface_efficace_interface_initial)
80{
81 const Cut_cell_FT_Disc& cut_cell_disc = surface_efficace_interface.get_cut_cell_disc();
82 for (int n = 0; n < cut_cell_disc.get_n_tot(); n++)
83 {
84 Int3 ijk = cut_cell_disc.get_ijk(n);
85 int i = ijk[0];
86 int j = ijk[1];
87 int k = ijk[2];
88
89 if (IJK_Interfaces::est_pure(.5*(old_indicatrice_ns(i, j, k) + next_indicatrice_ns(i, j, k))))
90 {
91 // Si la cellule est purement monophasique, il n'y a pas d'intersection avec l'interface
92 normale_deplacement_interface(n,0) = 0.;
93 normale_deplacement_interface(n,1) = 0.;
94 normale_deplacement_interface(n,2) = 0.;
95 surface_efficace_interface(n) = 0.;
96 surface_efficace_interface_initial(n) = 0.;
97 }
98 else
99 {
100 if (methode_explicite) // methode explicite : on se place a de S_n
101 {
102 if (IJK_Interfaces::devient_pure(old_indicatrice_ns(i, j, k), next_indicatrice_ns(i, j, k)))
103 {
104 surface_efficace_interface(n) = surface_interface_ns_old(i, j, k);
105 for (int dir = 0 ; dir < 3 ; dir++)
106 {
107 normale_deplacement_interface(n,dir) = normal_of_interf_ns_old[dir](i, j, k);
108 }
109 }
110 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i, j, k), next_indicatrice_ns(i, j, k)))
111 {
112 surface_efficace_interface(n) = surface_interface_ns_next(i, j, k);
113 for (int dir = 0 ; dir < 3 ; dir++)
114 {
115 normale_deplacement_interface(n,dir) = normal_of_interf_ns_next[dir](i, j, k);
116 }
117 }
118 else
119 {
120 surface_efficace_interface(n) = surface_interface_ns_old(i, j, k);
121 for (int dir = 0 ; dir < 3 ; dir++)
122 {
123 normale_deplacement_interface(n,dir) = normal_of_interf_ns_old[dir](i, j, k);
124 }
125 }
126 }
127 else // methode algebrique : on ne place au milieu de S_n et S_n+1
128 {
129 if (IJK_Interfaces::devient_pure(old_indicatrice_ns(i, j, k), next_indicatrice_ns(i, j, k)))
130 {
131 surface_efficace_interface(n) = (surface_interface_ns_old(i, j, k) + 3*surface_interface_ns_next(i, j, k)) * 0.25;
132 for (int dir = 0 ; dir < 3 ; dir++)
133 {
134 normale_deplacement_interface(n,dir) = normal_of_interf_ns_old[dir](i, j, k);
135 }
136 }
137 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i, j, k), next_indicatrice_ns(i, j, k)))
138 {
139 surface_efficace_interface(n) = (3*surface_interface_ns_old(i, j, k) + surface_interface_ns_next(i, j, k)) * 0.25;
140 for (int dir = 0 ; dir < 3 ; dir++)
141 {
142 normale_deplacement_interface(n,dir) = normal_of_interf_ns_next[dir](i, j, k);
143 }
144 }
145 else
146 {
147 surface_efficace_interface(n) = (surface_interface_ns_old(i, j, k) + surface_interface_ns_next(i, j, k)) * 0.5;
148 for (int dir = 0 ; dir < 3 ; dir++)
149 {
150 normale_deplacement_interface(n,dir) = (normal_of_interf_ns_old[dir](i, j, k) + normal_of_interf_ns_next[dir](i, j, k)) * 0.5;
151 }
152 }
153 }
154
155 double norm_normale = sqrt(normale_deplacement_interface(n,0)*normale_deplacement_interface(n,0) + normale_deplacement_interface(n,1)*normale_deplacement_interface(n,1) + normale_deplacement_interface(n,2)*normale_deplacement_interface(n,2));
156 normale_deplacement_interface(n,0) /= norm_normale;
157 normale_deplacement_interface(n,1) /= norm_normale;
158 normale_deplacement_interface(n,2) /= norm_normale;
159
160 surface_efficace_interface_initial(n) = surface_efficace_interface(n);
161 }
162 }
163}
164
166 const IJK_Field_vector3_double& velocity,
167 const IJK_Field_double& old_indicatrice_ns,
168 const IJK_Field_double& next_indicatrice_ns,
169 const IJK_Field_vector3_double& barycentre_phase1_ns_old,
170 const IJK_Field_vector3_double& barycentre_phase1_ns_next,
171 DoubleTabFT_cut_cell_vector3& coord_deplacement_interface,
172 DoubleTabFT_cut_cell_vector3& vitesse_deplacement_interface)
173{
174 const Cut_cell_FT_Disc& cut_cell_disc = vitesse_deplacement_interface.get_cut_cell_disc();
175 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
176
177 // Calculer la coordonnee correspondant au deplacement de l'interface :
178 // x_depl_interf = (I[new]*bary[new] - I[old]*bary[old])/(delta I)
179 // Bien sur, celle-ci ne depend pas de la phase consideree.
180 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
181 {
182 Int3 ijk = cut_cell_disc.get_ijk(n);
183 int i = ijk[0];
184 int j = ijk[1];
185 int k = ijk[2];
186
187 for (int dir = 0; dir < 3; dir++)
188 {
189 double delta_I = next_indicatrice_ns(i,j,k) - old_indicatrice_ns(i,j,k);
190
191 double bary_depl_interf;
192 if (delta_I == 0.)
193 {
194 bary_depl_interf = barycentre_phase1_ns_next[dir](i,j,k);
195 }
196 else
197 {
198 bary_depl_interf = (next_indicatrice_ns(i,j,k)*barycentre_phase1_ns_next[dir](i,j,k) - old_indicatrice_ns(i,j,k)*barycentre_phase1_ns_old[dir](i,j,k))/delta_I;
199
200 // Le calcul est pas correct (!), mais on evite de planter
201 if (bary_depl_interf <= 0)
202 {
203 bary_depl_interf = 1e-12;
204 }
205 else if (bary_depl_interf > 1)
206 {
207 bary_depl_interf = 1 - 1e-12;
208 }
209 }
210 assert((bary_depl_interf >= 0) && (bary_depl_interf <= 1));
211
212 // Passage a un systeme de coordonnees dimensionel et absolue
213 const int i_dir = select_dir(dir, i, j, k);
214 const int offset_dir = cut_cell_disc.get_domaine().get_offset_local(dir);
215 const double origin_dir = geom.get_origin(dir);
216 const double delta_dir = geom.get_constant_delta(dir);
217 const double coord_dir = origin_dir + (i_dir + offset_dir + bary_depl_interf) * delta_dir;
218
219 coord_deplacement_interface(n, dir) = coord_dir;
220 }
221 }
222
223 // Interpolation de la vitesse sur la coordonnee du deplacement de l'interface
224 ArrOfDouble vinterp_component(cut_cell_disc.get_n_loc());
225 for (int dir = 0; dir < 3; dir++)
226 {
227 ijk_interpolate_skip_unknown_points(velocity[dir], coord_deplacement_interface, vinterp_component, 1.e5 /* value for unknown points */);
228 for (int i = 0; i < cut_cell_disc.get_n_loc(); i++)
229 {
230 vitesse_deplacement_interface(i, dir) = vinterp_component[i];
231 }
232 }
233 vitesse_deplacement_interface.echange_espace_virtuel();
234}
235
237 double timestep,
238 const IJK_Field_vector3_double& velocity,
239 const IJK_Field_double& old_indicatrice_ns,
240 const IJK_Field_double& next_indicatrice_ns,
241 const DoubleTabFT_cut_cell_vector3& vitesse_deplacement_interface,
242 const DoubleTabFT_cut_cell_vector3& normale_deplacement_interface,
243 DoubleTabFT_cut_cell_scalar& surface_efficace_interface)
244{
245 statistics().create_custom_counter("cut_cell: calcul des surfaces efficaces interface",2,"IJK");
246 statistics().begin_count("cut_cell: calcul des surfaces efficaces interface",statistics().get_last_opened_counter_level()+1);
247
248 const Cut_cell_FT_Disc& cut_cell_disc = surface_efficace_interface.get_cut_cell_disc();
249 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
250
251 const double delta_x = geom.get_constant_delta(0);
252 const double delta_y = geom.get_constant_delta(1);
253 const int offset = cut_cell_disc.get_domaine().get_offset_local(DIRECTION_K);
254 const ArrOfDouble& delta_z_all = geom.get_delta(DIRECTION_K);
255
256 // Calcul de la correction de surface efficace de l'interface
257 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
258 {
259 Int3 ijk = cut_cell_disc.get_ijk(n);
260 int i = ijk[0];
261 int j = ijk[1];
262 int k = ijk[2];
263
264 const double delta_z = delta_z_all[k + offset];
265 const double volume = delta_x * delta_y * delta_z;
266
267 const double vitesse_interface = -vitesse_deplacement_interface(n,0)*normale_deplacement_interface(n,0) - vitesse_deplacement_interface(n,1)*normale_deplacement_interface(n,1) - vitesse_deplacement_interface(n,2)*normale_deplacement_interface(n,2);
268 const double surface_interface = surface_efficace_interface(n);
269
270 double delta_volume_cible = volume * (next_indicatrice_ns(i, j, k) - old_indicatrice_ns(i, j, k));
271 double delta_volume_interface = vitesse_interface * surface_interface * timestep;
272
273 double erreur_relative = delta_volume_cible == 0. ? delta_volume_interface/volume : std::fabs((delta_volume_interface - delta_volume_cible)/delta_volume_cible);
274
275 if (erreur_relative == 0)
276 {
277 }
278 else
279 {
280 surface_efficace_interface(n) = delta_volume_cible/(vitesse_interface * timestep);
281 }
282 }
283
284 surface_efficace_interface.echange_espace_virtuel();
285 statistics().end_count("cut_cell: calcul des surfaces efficaces interface");
286}
287
288// calcul_surface_face_efficace_initiale: version with DoubleTabFT_cut_cell output (use cut-cell structures)
290 int methode_explicite,
291 const IJK_Field_vector3_double& old_indicatrice_surfacique_face_ns,
292 const IJK_Field_vector3_double& next_indicatrice_surfacique_face_ns,
293 DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face,
294 DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face_initial)
295{
296 if (methode_explicite) // methode explicite : on se place a de S_n
297 {
298 const Cut_cell_FT_Disc& cut_cell_disc = indicatrice_surfacique_efficace_face.get_cut_cell_disc();
299 for (int n = 0; n < cut_cell_disc.get_n_tot(); n++)
300 {
301 Int3 ijk = cut_cell_disc.get_ijk(n);
302 int i = ijk[0];
303 int j = ijk[1];
304 int k = ijk[2];
305
306 for (int dir = 0; dir < 3; dir++)
307 {
308 if ((old_indicatrice_surfacique_face_ns[dir](i, j, k) == 1) && (next_indicatrice_surfacique_face_ns[dir](i, j, k) == 0))
309 {
310 indicatrice_surfacique_efficace_face(n, dir) = .5;
311 }
312 else if ((old_indicatrice_surfacique_face_ns[dir](i, j, k) == 0) && (next_indicatrice_surfacique_face_ns[dir](i, j, k) == 1))
313 {
314 indicatrice_surfacique_efficace_face(n, dir) = .5;
315 }
316 else if (IJK_Interfaces::devient_pure(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
317 {
318 indicatrice_surfacique_efficace_face(n, dir) = old_indicatrice_surfacique_face_ns[dir](i, j, k);
319 }
320 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
321 {
322 indicatrice_surfacique_efficace_face(n, dir) = next_indicatrice_surfacique_face_ns[dir](i, j, k);
323 }
324 else
325 {
326 indicatrice_surfacique_efficace_face(n, dir) = old_indicatrice_surfacique_face_ns[dir](i, j, k);
327 }
328 indicatrice_surfacique_efficace_face_initial(n, dir) = indicatrice_surfacique_efficace_face(n, dir);
329 }
330 }
331 }
332 else // methode algebrique : on ne place au milieu de S_n et S_n+1
333 {
334 const Cut_cell_FT_Disc& cut_cell_disc = indicatrice_surfacique_efficace_face.get_cut_cell_disc();
335 for (int n = 0; n < cut_cell_disc.get_n_tot(); n++)
336 {
337 Int3 ijk = cut_cell_disc.get_ijk(n);
338 int i = ijk[0];
339 int j = ijk[1];
340 int k = ijk[2];
341
342 for (int dir = 0; dir < 3; dir++)
343 {
344 if (IJK_Interfaces::devient_pure(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
345 {
346 indicatrice_surfacique_efficace_face(n, dir) = (old_indicatrice_surfacique_face_ns[dir](i, j, k) + 3*next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.25;
347 }
348 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
349 {
350 indicatrice_surfacique_efficace_face(n, dir) = (3*old_indicatrice_surfacique_face_ns[dir](i, j, k) + next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.25;
351 }
352 else
353 {
354 indicatrice_surfacique_efficace_face(n, dir) = (old_indicatrice_surfacique_face_ns[dir](i, j, k) + next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.5;
355 }
356 indicatrice_surfacique_efficace_face_initial(n, dir) = indicatrice_surfacique_efficace_face(n, dir);
357 }
358 }
359 }
360}
361
362// calcul_surface_face_efficace_initiale: version with IJK_Field output (does not use cut-cell structures)
364 int methode_explicite,
365 const IJK_Field_vector3_double& old_indicatrice_surfacique_face_ns,
366 const IJK_Field_vector3_double& next_indicatrice_surfacique_face_ns,
367 IJK_Field_vector3_double& indicatrice_surfacique_efficace_face,
368 IJK_Field_vector3_double& indicatrice_surfacique_efficace_face_initial)
369{
370 if (methode_explicite) // methode explicite : on se place a de S_n
371 {
372 for (int dir = 0; dir < 3; dir++)
373 {
374 const int ni = indicatrice_surfacique_efficace_face[dir].ni();
375 const int nj = indicatrice_surfacique_efficace_face[dir].nj();
376 const int nk = indicatrice_surfacique_efficace_face[dir].nk();
377 const int ghost = indicatrice_surfacique_efficace_face[dir].ghost();
378
379 for (int k = -ghost; k < nk+ghost; k++)
380 {
381 for (int j = -ghost; j < nj+ghost; j++)
382 {
383 for (int i = -ghost; i < ni+ghost; i++)
384 {
385 if ((old_indicatrice_surfacique_face_ns[dir](i, j, k) == 1) && (next_indicatrice_surfacique_face_ns[dir](i, j, k) == 0))
386 {
387 indicatrice_surfacique_efficace_face[dir](i, j, k) = .5;
388 }
389 else if ((old_indicatrice_surfacique_face_ns[dir](i, j, k) == 0) && (next_indicatrice_surfacique_face_ns[dir](i, j, k) == 1))
390 {
391 indicatrice_surfacique_efficace_face[dir](i, j, k) = .5;
392 }
393 else if (IJK_Interfaces::devient_pure(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
394 {
395 indicatrice_surfacique_efficace_face[dir](i, j, k) = old_indicatrice_surfacique_face_ns[dir](i, j, k);
396 }
397 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
398 {
399 indicatrice_surfacique_efficace_face[dir](i, j, k) = next_indicatrice_surfacique_face_ns[dir](i, j, k);
400 }
401 else
402 {
403 indicatrice_surfacique_efficace_face[dir](i, j, k) = old_indicatrice_surfacique_face_ns[dir](i, j, k);
404 }
405 indicatrice_surfacique_efficace_face_initial[dir](i, j, k) = indicatrice_surfacique_efficace_face[dir](i, j, k);
406 }
407 }
408 }
409 }
410 }
411 else // methode algebrique : on ne place au milieu de S_n et S_n+1
412 {
413 for (int dir = 0; dir < 3; dir++)
414 {
415 const int ni = indicatrice_surfacique_efficace_face[dir].ni();
416 const int nj = indicatrice_surfacique_efficace_face[dir].nj();
417 const int nk = indicatrice_surfacique_efficace_face[dir].nk();
418 const int ghost = indicatrice_surfacique_efficace_face[dir].ghost();
419
420 for (int k = -ghost; k < nk+ghost; k++)
421 {
422 for (int j = -ghost; j < nj+ghost; j++)
423 {
424 for (int i = -ghost; i < ni+ghost; i++)
425 {
426 if (IJK_Interfaces::devient_pure(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
427 {
428 indicatrice_surfacique_efficace_face[dir](i, j, k) = (old_indicatrice_surfacique_face_ns[dir](i, j, k) + 3*next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.25;
429 }
430 else if (IJK_Interfaces::devient_diphasique(old_indicatrice_surfacique_face_ns[dir](i, j, k), next_indicatrice_surfacique_face_ns[dir](i, j, k)))
431 {
432 indicatrice_surfacique_efficace_face[dir](i, j, k) = (3*old_indicatrice_surfacique_face_ns[dir](i, j, k) + next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.25;
433 }
434 else
435 {
436 indicatrice_surfacique_efficace_face[dir](i, j, k) = (old_indicatrice_surfacique_face_ns[dir](i, j, k) + next_indicatrice_surfacique_face_ns[dir](i, j, k)) * 0.5;
437 }
438 indicatrice_surfacique_efficace_face_initial[dir](i, j, k) = indicatrice_surfacique_efficace_face[dir](i, j, k);
439 }
440 }
441 }
442 }
443 }
444}
445
446
448 int verbosite_surface_efficace_face,
449 double timestep,
450 const Cut_field_vector3_double& velocity,
451 int& iteration_solver_surface_efficace_face,
452 const IJK_Field_double& old_indicatrice_ns,
453 const IJK_Field_double& next_indicatrice_ns,
454 const IJK_Field_vector3_double& old_indicatrice_surfacique_face_ns,
455 const IJK_Field_vector3_double& next_indicatrice_surfacique_face_ns,
456 DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face,
457 const DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face_initial,
458 DoubleTabFT_cut_cell_vector6& indicatrice_surfacique_efficace_face_correction,
459 DoubleTabFT_cut_cell_scalar& indicatrice_surfacique_efficace_face_absolute_error)
460{
461 statistics().create_custom_counter("cut_cell: calcul des surfaces efficaces",2,"IJK");
462 statistics().begin_count("cut_cell: calcul des surfaces efficaces",statistics().get_last_opened_counter_level()+1);
463 const Cut_cell_FT_Disc& cut_cell_disc = indicatrice_surfacique_efficace_face.get_cut_cell_disc();
464 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
465 const double delta_x = geom.get_constant_delta(0);
466 const double delta_y = geom.get_constant_delta(1);
467 const int offset = cut_cell_disc.get_domaine().get_offset_local(DIRECTION_K);
468 const ArrOfDouble& delta_z_all = geom.get_delta(DIRECTION_K);
469
470 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
471 {
472 indicatrice_surfacique_efficace_face_absolute_error(n) = 0.;
473 }
474
475 // Iteration du solveur de la surface efficace
476 const int maximum_iteration = 499;
477 const int iteration_impression_intermediaire = 600;
478 int solution_not_found = 0;
479 do
480 {
481 iteration_solver_surface_efficace_face += 1;
482 solution_not_found = 0;
483
484 int solution_locally_not_found = 0;
485
486 // Initialisation du tableau de correction de surface
487 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
488 {
489 Int3 ijk = cut_cell_disc.get_ijk(n);
490 int i = ijk[0];
491 int j = ijk[1];
492 int k = ijk[2];
493
494 for (int num_face = 0; num_face < 6; num_face++)
495 {
496 int dir = num_face%3;
497 int decalage = num_face/3;
498
499 int di = decalage*(dir == 0);
500 int dj = decalage*(dir == 1);
501 int dk = decalage*(dir == 2);
502
503 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
504 if (n_face >= 0)
505 {
506 indicatrice_surfacique_efficace_face_correction(n, num_face) = indicatrice_surfacique_efficace_face(n_face, dir);
507 }
508 else
509 {
510 assert((next_indicatrice_ns(i+di,j+dj,k+dk) == 0) || (next_indicatrice_ns(i+di,j+dj,k+dk) == 1));
511 indicatrice_surfacique_efficace_face_correction(n, num_face) = next_indicatrice_ns(i+di,j+dj,k+dk);
512 }
513 }
514 }
515
516 // Calcul de la correction de surface
517 // Note : Contrairement aux autres tableaux de surface, la correction est stockee sur
518 // les six faces de chaque cellule diphasique. On a donc pour chaque face deux informations
519 // de correction, qui correspondent a la correction calculee independamment pour les deux
520 // cellules contenant la face. On calcule dans un deuxieme temps la surface efficace
521 // a partir de ces deux corrections.
522 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
523 {
524 Int3 ijk = cut_cell_disc.get_ijk(n);
525 int i = ijk[0];
526 int j = ijk[1];
527 int k = ijk[2];
528
529 const double delta_z = delta_z_all[k + offset];
530 const double volume = delta_x * delta_y * delta_z;
531
532 const double fx = delta_y * delta_z * timestep;
533 const double fy = delta_x * delta_z * timestep;
534 const double fz = delta_x * delta_y * timestep;
535
536 double surface_efficace[6] = {0};
537 double surface_max[6] = {0};
538 double surface_min[6] = {0};
539 double flux_diphasique[6] = {0};
540 double delta_surface_max[6] = {0};
541
542 double delta_volume_total = 0;
543 double delta_volume_diphasique = 0;
544 for (int num_face = 0; num_face < 6; num_face++)
545 {
546 int dir = num_face%3;
547 int decalage = num_face/3;
548 int sign = decalage*2 -1;
549
550 int di = decalage*(dir == 0);
551 int dj = decalage*(dir == 1);
552 int dk = decalage*(dir == 2);
553
554 double f = select_dir(dir, fx, fy, fz);
555
556 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
557 if (n_face >= 0)
558 {
559 double surface_old = old_indicatrice_surfacique_face_ns[dir](i+di,j+dj,k+dk);
560 double surface_next = next_indicatrice_surfacique_face_ns[dir](i+di,j+dj,k+dk);
561 surface_max[num_face] = std::max(surface_old, surface_next);
562 surface_min[num_face] = std::min(surface_old, surface_next);
563 surface_efficace[num_face] = indicatrice_surfacique_efficace_face(n_face, dir);
564 flux_diphasique[num_face] = (indicatrice_surfacique_efficace_face(n_face, dir) == 1.) ? 0. : sign*f*indicatrice_surfacique_efficace_face(n_face, dir)*velocity[dir].diph_l_(n_face);
565 if (surface_efficace[num_face] == 0.)
566 {
567 assert(surface_max[num_face] == 0.);
568 }
569
570 delta_volume_total -= sign*f*surface_efficace[num_face]*velocity[dir].diph_l_(n_face);
571 delta_volume_diphasique -= flux_diphasique[num_face];
572
573 }
574 else
575 {
576 delta_volume_total -= sign*f*next_indicatrice_ns(i+di,j+dj,k+dk)*velocity[dir].pure_(i+di,j+dj,k+dk);
577 }
578
579 }
580
581 double delta_volume_cible = volume * (next_indicatrice_ns(i, j, k) - old_indicatrice_ns(i, j, k));
582 double delta_volume_pure = delta_volume_total - delta_volume_diphasique;
583 double delta_volume_diphasique_cible = delta_volume_cible - delta_volume_pure;
584
585 double erreur_absolue = std::fabs(delta_volume_total - delta_volume_cible);
586 double erreur_relative = delta_volume_cible == 0. ? delta_volume_total/volume : std::fabs((delta_volume_total - delta_volume_cible)/delta_volume_cible);
587 double ecart_volume_diphasique = delta_volume_diphasique - delta_volume_diphasique_cible;
588
589 indicatrice_surfacique_efficace_face_absolute_error(n) = erreur_absolue;
590
591 if (ecart_volume_diphasique == 0)
592 {
593 }
594 else
595 {
596 if (erreur_relative > 1e-5)
597 {
598 solution_locally_not_found = 1;
599 }
600
601 double somme_ratio_max_sur_requis = 0;
602 for (int num_face = 0; num_face < 6; num_face++)
603 {
604 if (flux_diphasique[num_face] != 0)
605 {
606 bool flux_et_ecart_meme_signe = ((flux_diphasique[num_face] < 0) == (ecart_volume_diphasique < 0));
607
608 delta_surface_max[num_face] = flux_et_ecart_meme_signe ? surface_max[num_face] - surface_efficace[num_face] : surface_efficace[num_face] - surface_min[num_face];
609
610 // Note : Le calcul de delta_surface_requis n'est pas fait si la surface est tres faible
611 // En effet, cela suggere que le flux_diphasique[num_face] est tres faible egalement, ce qui peut provoquer une 'Arithmetic exception'.
612 // De plus, modifier davantage la surface efficace dans ce cas n'est pas utile.
613 double delta_surface_requis = (std::abs(surface_efficace[num_face]) < 1e-80) ? 0. : std::fabs(ecart_volume_diphasique/flux_diphasique[num_face])*surface_efficace[num_face];
614 somme_ratio_max_sur_requis += (delta_surface_requis == 0.) ? 0. : delta_surface_max[num_face]/delta_surface_requis;
615 }
616 }
617
618 for (int num_face = 0; num_face < 6; num_face++)
619 {
620 if (flux_diphasique[num_face] != 0)
621 {
622 int dir = num_face%3;
623
624 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
625 assert(n_face >= 0);
626
627 bool flux_et_ecart_meme_signe = ((flux_diphasique[num_face] < 0) == (ecart_volume_diphasique < 0));
628 int sign = 2*flux_et_ecart_meme_signe - 1;
629
630 // Note : La correction est choisi telle que chaque surface contribue la meme fraction de delta_S_max^i.
631 // Normalement, cette fraction est toujours inferieur a 100%.
632 // La correction est :
633 // delta_S^i = delta_S_max^i / (somme delta_S_max/delta_S_requis),
634 // ce qui implique (delta_S^i/delta_S_max^i) est constant, et par ailleurs somme delta_S^i/delta_S_requis^i = 1
635 double correction = (somme_ratio_max_sur_requis == 0) ? 0. : sign*delta_surface_max[num_face]/somme_ratio_max_sur_requis;
636
637 indicatrice_surfacique_efficace_face_correction(n, num_face) = indicatrice_surfacique_efficace_face(n_face, dir) + correction;
638
639 {
640 double minimal_acceptable_surface = 1e-15;
641 if (indicatrice_surfacique_efficace_face_correction(n, num_face) < (surface_min[num_face] + minimal_acceptable_surface))
642 {
643 indicatrice_surfacique_efficace_face_correction(n, num_face) = std::min(surface_min[num_face] + minimal_acceptable_surface, .5*(surface_min[num_face] + surface_max[num_face]));
644 }
645 if (indicatrice_surfacique_efficace_face_correction(n, num_face) > (surface_max[num_face] - minimal_acceptable_surface))
646 {
647 indicatrice_surfacique_efficace_face_correction(n, num_face) = std::max(surface_max[num_face] - minimal_acceptable_surface, .5*(surface_min[num_face] + surface_max[num_face]));
648 }
649 }
650 }
651 }
652
653 }
654 }
655
656 indicatrice_surfacique_efficace_face_correction.echange_espace_virtuel();
657
658 // Mise a jour de la surface efficace
659 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
660 {
661 Int3 ijk = cut_cell_disc.get_ijk(n);
662 int i = ijk[0];
663 int j = ijk[1];
664 int k = ijk[2];
665
666 for (int dir = 0; dir < 3; dir++)
667 {
668 int di = (-1)*(dir == 0);
669 int dj = (-1)*(dir == 1);
670 int dk = (-1)*(dir == 2);
671
672 int n_face = cut_cell_disc.get_n(i+di, j+dj, k+dk);
673
674 if (n_face >= 0)
675 {
676 double new_surface = (indicatrice_surfacique_efficace_face_absolute_error(n_face) > indicatrice_surfacique_efficace_face_absolute_error(n)) ? indicatrice_surfacique_efficace_face_correction(n_face, dir+3) : indicatrice_surfacique_efficace_face_correction(n, dir);
677
678 // Si une des cellules disparait, on liu donne la priorite dans le calcul de la correction
679 bool centre_switch = (IJK_Interfaces::devient_pure(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k)) || (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k))));
680 bool decale_switch = (IJK_Interfaces::devient_pure(old_indicatrice_ns(i+di,j+dj,k+dk), next_indicatrice_ns(i+di,j+dj,k+dk)) || (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i+di,j+dj,k+dk), next_indicatrice_ns(i+di,j+dj,k+dk))));
681 if ((centre_switch) && (!decale_switch))
682 {
683 new_surface = indicatrice_surfacique_efficace_face_correction(n, dir);
684 }
685 else if ((!centre_switch) && (decale_switch))
686 {
687 new_surface = indicatrice_surfacique_efficace_face_correction(n_face, dir+3);
688 }
689
690 // Filtrage temporel de la correction
691 //indicatrice_surfacique_efficace_face(n, dir) = 0.25*(3*indicatrice_surfacique_efficace_face(n, dir) + new_surface);
692 indicatrice_surfacique_efficace_face(n, dir) = new_surface;
693 }
694 }
695 }
696
697 indicatrice_surfacique_efficace_face.echange_espace_virtuel();
698
699 if (iteration_solver_surface_efficace_face%iteration_impression_intermediaire == 0)
700 {
702 verbosite_surface_efficace_face,
703 iteration_solver_surface_efficace_face,
704 timestep,
705 velocity,
706 old_indicatrice_ns,
707 next_indicatrice_ns,
708 indicatrice_surfacique_efficace_face,
709 indicatrice_surfacique_efficace_face_initial);
710 }
711
712 solution_not_found = Process::mp_max(solution_locally_not_found);
713 }
714 while (solution_not_found && iteration_solver_surface_efficace_face < maximum_iteration);
715 statistics().end_count("cut_cell: calcul des surfaces efficaces");
716}
717
719 int verbosite_surface_efficace_interface,
720 double timestep,
721 const IJK_Field_vector3_double& velocity,
722 const IJK_Field_double& old_indicatrice_ns,
723 const IJK_Field_double& next_indicatrice_ns,
724 const DoubleTabFT_cut_cell_scalar& surface_efficace_interface,
725 const DoubleTabFT_cut_cell_scalar& surface_efficace_interface_initial,
726 const DoubleTabFT_cut_cell_vector3& normale_deplacement_interface,
727 const DoubleTabFT_cut_cell_vector3& vitesse_deplacement_interface)
728{
729 const Cut_cell_FT_Disc& cut_cell_disc = surface_efficace_interface.get_cut_cell_disc();
730 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
731 const double delta_x = geom.get_constant_delta(0);
732 const double delta_y = geom.get_constant_delta(1);
733 const int offset = cut_cell_disc.get_domaine().get_offset_local(DIRECTION_K);
734 const ArrOfDouble& delta_z_all = geom.get_delta(DIRECTION_K);
735
736 // Impression des resultats
737 int n_count = 0;
738 int n_count_surface = 0;
739 double moyenne_erreur_absolue = 0.;
740 double moyenne_erreur_relative = 0.;
741 double maximum_erreur_absolue = 0.;
742 double maximum_erreur_relative = 0.;
743 double moyenne_ecart_absolue_surface = 0.;
744 double moyenne_ecart_relatif_surface = 0.;
745 double maximum_ecart_absolue_surface = 0.;
746 double maximum_ecart_relatif_surface = 0.;
747 int switch_n_count = 0;
748 int switch_n_count_surface = 0;
749 double switch_moyenne_erreur_absolue = 0.;
750 double switch_moyenne_erreur_relative = 0.;
751 double switch_maximum_erreur_absolue = 0.;
752 double switch_maximum_erreur_relative = 0.;
753 double switch_moyenne_ecart_absolue_surface = 0.;
754 double switch_moyenne_ecart_relatif_surface = 0.;
755 double switch_maximum_ecart_absolue_surface = 0.;
756 double switch_maximum_ecart_relatif_surface = 0.;
757 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
758 {
759 Int3 ijk = cut_cell_disc.get_ijk(n);
760 int i = ijk[0];
761 int j = ijk[1];
762 int k = ijk[2];
763
764 bool centre_switch = (IJK_Interfaces::devient_pure(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k)) || (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k))));
765
766 const double delta_z = delta_z_all[k + offset];
767 const double volume = delta_x * delta_y * delta_z;
768
769 {
770 double erreur_relative;
771 if (surface_efficace_interface_initial(n) != 0.)
772 {
773 erreur_relative = std::fabs((surface_efficace_interface(n) - surface_efficace_interface_initial(n))/surface_efficace_interface_initial(n));
774 }
775 else
776 {
777 erreur_relative = 0.;
778 assert(surface_efficace_interface(n) == 0.);
779 }
780 double erreur_absolue = std::fabs(surface_efficace_interface(n) - surface_efficace_interface_initial(n));
781
782 moyenne_ecart_absolue_surface += erreur_absolue;
783 moyenne_ecart_relatif_surface += erreur_relative;
784 maximum_ecart_relatif_surface = erreur_relative > maximum_ecart_relatif_surface ? erreur_relative : maximum_ecart_relatif_surface;
785 maximum_ecart_absolue_surface = erreur_absolue > maximum_ecart_absolue_surface ? erreur_absolue : maximum_ecart_absolue_surface;
786
787 n_count_surface += 1;
788
789 if (centre_switch)
790 {
791 switch_moyenne_ecart_absolue_surface += erreur_absolue;
792 switch_moyenne_ecart_relatif_surface += erreur_relative;
793 switch_maximum_ecart_relatif_surface = erreur_relative > switch_maximum_ecart_relatif_surface ? erreur_relative : switch_maximum_ecart_relatif_surface;
794 switch_maximum_ecart_absolue_surface = erreur_absolue > switch_maximum_ecart_absolue_surface ? erreur_absolue : switch_maximum_ecart_absolue_surface;
795
796 switch_n_count_surface += 1;
797 }
798 }
799
800 const double vitesse_interface = -vitesse_deplacement_interface(n,0)*normale_deplacement_interface(n,0) - vitesse_deplacement_interface(n,1)*normale_deplacement_interface(n,1) - vitesse_deplacement_interface(n,2)*normale_deplacement_interface(n,2);
801 const double surface_interface = surface_efficace_interface(n);
802
803 double delta_volume_cible = volume * (next_indicatrice_ns(i, j, k) - old_indicatrice_ns(i, j, k));
804 double delta_volume_interface = vitesse_interface * surface_interface * timestep;
805
806 double erreur_relative = delta_volume_cible == 0. ? delta_volume_interface/volume : std::fabs((delta_volume_interface - delta_volume_cible)/delta_volume_cible);
807 double erreur_absolue = std::fabs(delta_volume_interface - delta_volume_cible);
808
809 if (IJK_Interfaces::est_pure(.5*(old_indicatrice_ns(i, j, k) + next_indicatrice_ns(i, j, k))))
810 {
811 // A failure of this assert suggests a non-zero velocity divergence
812 //assert(std::abs(erreur_relative) < 1e-12);
813 }
814 else
815 {
816 n_count += 1;
817 moyenne_erreur_relative += erreur_relative;
818 moyenne_erreur_absolue += erreur_absolue;
819 maximum_erreur_relative = erreur_relative > maximum_erreur_relative ? erreur_relative : maximum_erreur_relative;
820 maximum_erreur_absolue = erreur_absolue > maximum_erreur_absolue ? erreur_absolue : maximum_erreur_absolue;
821
822 if (centre_switch)
823 {
824 switch_n_count += 1;
825 switch_moyenne_erreur_relative += erreur_relative;
826 switch_moyenne_erreur_absolue += erreur_absolue;
827 switch_maximum_erreur_relative = erreur_relative > switch_maximum_erreur_relative ? erreur_relative : switch_maximum_erreur_relative;
828 switch_maximum_erreur_absolue = erreur_absolue > switch_maximum_erreur_absolue ? erreur_absolue : switch_maximum_erreur_absolue;
829 }
830 }
831 }
832 moyenne_erreur_absolue = Process::mp_sum(moyenne_erreur_absolue);
833 moyenne_erreur_relative = Process::mp_sum(moyenne_erreur_relative);
834 maximum_erreur_absolue = Process::mp_max(maximum_erreur_absolue);
835 maximum_erreur_relative = Process::mp_max(maximum_erreur_relative);
836 moyenne_ecart_absolue_surface = Process::mp_sum(moyenne_ecart_absolue_surface);
837 moyenne_ecart_relatif_surface = Process::mp_sum(moyenne_ecart_relatif_surface);
838 maximum_ecart_absolue_surface = Process::mp_max(maximum_ecart_absolue_surface);
839 maximum_ecart_relatif_surface = Process::mp_max(maximum_ecart_relatif_surface);
840 switch_moyenne_erreur_absolue = Process::mp_sum(switch_moyenne_erreur_absolue);
841 switch_moyenne_erreur_relative = Process::mp_sum(switch_moyenne_erreur_relative);
842 switch_maximum_erreur_absolue = Process::mp_max(switch_maximum_erreur_absolue);
843 switch_maximum_erreur_relative = Process::mp_max(switch_maximum_erreur_relative);
844 switch_moyenne_ecart_absolue_surface = Process::mp_sum(switch_moyenne_ecart_absolue_surface);
845 switch_moyenne_ecart_relatif_surface = Process::mp_sum(switch_moyenne_ecart_relatif_surface);
846 switch_maximum_ecart_absolue_surface = Process::mp_max(switch_maximum_ecart_absolue_surface);
847 switch_maximum_ecart_relatif_surface = Process::mp_max(switch_maximum_ecart_relatif_surface);
849 n_count_surface = Process::check_int_overflow(Process::mp_sum(n_count_surface));
850 switch_n_count = Process::check_int_overflow(Process::mp_sum(switch_n_count));
851 switch_n_count_surface = Process::check_int_overflow(Process::mp_sum(switch_n_count_surface));
852 assert(n_count_surface == n_count);
853 assert(switch_n_count_surface == switch_n_count);
854 if (n_count >= 1)
855 {
856 moyenne_erreur_relative /= n_count;
857 moyenne_erreur_absolue /= n_count;
858 moyenne_ecart_absolue_surface /= (n_count_surface);
859 moyenne_ecart_relatif_surface /= (n_count_surface);
860 }
861 if (switch_n_count >= 1)
862 {
863 switch_moyenne_erreur_relative /= switch_n_count;
864 switch_moyenne_erreur_absolue /= switch_n_count;
865 switch_moyenne_ecart_absolue_surface /= (switch_n_count_surface);
866 switch_moyenne_ecart_relatif_surface /= (switch_n_count_surface);
867 }
868
869 if (verbosite_surface_efficace_interface == 2)
870 {
871 Cerr << "Calcul surface efficace interface:" << finl;
872 Cerr << " moyenne_erreur: " << moyenne_erreur_absolue << " (relative: " << moyenne_erreur_relative << ") max_erreur: " << maximum_erreur_absolue << " (relative: " << maximum_erreur_relative << ")" << finl;
873 Cerr << " moyenne_ecart_surface: " << moyenne_ecart_absolue_surface << " (relatif: " << moyenne_ecart_relatif_surface << ") max_ecart_surface: " << maximum_ecart_absolue_surface << " (relatif: " << maximum_ecart_relatif_surface << ")" << finl;
874 Cerr << " switch moyenne_erreur: " << switch_moyenne_erreur_absolue << " (relative: " << switch_moyenne_erreur_relative << ") max_erreur: " << switch_maximum_erreur_absolue << " (relative: " << switch_maximum_erreur_relative << ")" << finl;
875 Cerr << " switch moyenne_ecart_surface: " << switch_moyenne_ecart_absolue_surface << " (relatif: " << switch_moyenne_ecart_relatif_surface << ") max_ecart_surface: " << switch_maximum_ecart_absolue_surface << " (relatif: " << switch_maximum_ecart_relatif_surface << ")" << finl;
876 }
877 else if (verbosite_surface_efficace_interface == 1)
878 {
879 Cerr << "Calcul surface efficace interface: mean_rel: " << moyenne_erreur_relative << " max_rel: " << maximum_erreur_relative << " switch_mean_rel: " << switch_moyenne_erreur_relative << " switch_max_rel: " << switch_maximum_erreur_relative << finl;
880 }
881 else
882 {
883 Cerr << "Cut_cell_surface_efficace::imprimer_informations_surface_efficace_interface non reconnu." << finl;
885 }
886}
887
889 int verbosite_surface_efficace_face,
890 int iteration_solver_surface_efficace_face,
891 double timestep,
892 const Cut_field_vector3_double& velocity,
893 const IJK_Field_double& old_indicatrice_ns,
894 const IJK_Field_double& next_indicatrice_ns,
895 const DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face,
896 const DoubleTabFT_cut_cell_vector3& indicatrice_surfacique_efficace_face_initial)
897{
898 const Cut_cell_FT_Disc& cut_cell_disc = indicatrice_surfacique_efficace_face.get_cut_cell_disc();
899 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
900 const double delta_x = geom.get_constant_delta(0);
901 const double delta_y = geom.get_constant_delta(1);
902 const int offset = cut_cell_disc.get_domaine().get_offset_local(DIRECTION_K);
903 const ArrOfDouble& delta_z_all = geom.get_delta(DIRECTION_K);
904
905 // Impression des resultats
906 int n_count = 0;
907 int n_count_surface = 0;
908 double moyenne_erreur_absolue = 0.;
909 double moyenne_erreur_relative = 0.;
910 double maximum_erreur_absolue = 0.;
911 double maximum_erreur_relative = 0.;
912 double moyenne_ecart_absolue_surface = 0.;
913 double moyenne_ecart_relatif_surface = 0.;
914 double maximum_ecart_absolue_surface = 0.;
915 double maximum_ecart_relatif_surface = 0.;
916 int switch_n_count = 0;
917 int switch_n_count_surface = 0;
918 double switch_moyenne_erreur_absolue = 0.;
919 double switch_moyenne_erreur_relative = 0.;
920 double switch_maximum_erreur_absolue = 0.;
921 double switch_maximum_erreur_relative = 0.;
922 double switch_moyenne_ecart_absolue_surface = 0.;
923 double switch_moyenne_ecart_relatif_surface = 0.;
924 double switch_maximum_ecart_absolue_surface = 0.;
925 double switch_maximum_ecart_relatif_surface = 0.;
926 for (int n = 0; n < cut_cell_disc.get_n_loc(); n++)
927 {
928 Int3 ijk = cut_cell_disc.get_ijk(n);
929 int i = ijk[0];
930 int j = ijk[1];
931 int k = ijk[2];
932
933 bool centre_switch = (IJK_Interfaces::devient_pure(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k)) || (IJK_Interfaces::devient_diphasique(old_indicatrice_ns(i,j,k), next_indicatrice_ns(i,j,k))));
934
935 const double delta_z = delta_z_all[k + offset];
936 const double volume = delta_x * delta_y * delta_z;
937
938 const double fx = delta_y * delta_z * timestep;
939 const double fy = delta_x * delta_z * timestep;
940 const double fz = delta_x * delta_y * timestep;
941
942 double delta_volume_total = 0;
943 for (int num_face = 0; num_face < 6; num_face++)
944 {
945 int dir = num_face%3;
946 int decalage = num_face/3;
947 int sign = decalage*2 -1;
948
949 int di = decalage*(dir == 0);
950 int dj = decalage*(dir == 1);
951 int dk = decalage*(dir == 2);
952
953 double f = select_dir(dir, fx, fy, fz);
954
955 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
956 if (n_face >= 0)
957 {
958 delta_volume_total -= sign*f*indicatrice_surfacique_efficace_face(n_face, dir)*velocity[dir].diph_l_(n_face);
959
960 {
961 double erreur_relative;
962 if (indicatrice_surfacique_efficace_face_initial(n_face, dir) != 0.)
963 {
964 erreur_relative = std::fabs((indicatrice_surfacique_efficace_face(n_face, dir) - indicatrice_surfacique_efficace_face_initial(n_face, dir))/indicatrice_surfacique_efficace_face_initial(n_face, dir));
965 }
966 else
967 {
968 erreur_relative = 0.;
969 assert(indicatrice_surfacique_efficace_face(n_face, dir) == 0.);
970 }
971 double erreur_absolue = std::fabs(indicatrice_surfacique_efficace_face(n_face, dir) - indicatrice_surfacique_efficace_face_initial(n_face, dir));
972
973 moyenne_ecart_absolue_surface += erreur_absolue;
974 moyenne_ecart_relatif_surface += erreur_relative;
975 maximum_ecart_relatif_surface = erreur_relative > maximum_ecart_relatif_surface ? erreur_relative : maximum_ecart_relatif_surface;
976 maximum_ecart_absolue_surface = erreur_absolue > maximum_ecart_absolue_surface ? erreur_absolue : maximum_ecart_absolue_surface;
977
978 //position_typique = (indicatrice_surfacique_efficace_face(n_face, dir) - surface_min)/(surface_max - surface_min);
979 n_count_surface += 1;
980
981 if (centre_switch)
982 {
983 switch_moyenne_ecart_absolue_surface += erreur_absolue;
984 switch_moyenne_ecart_relatif_surface += erreur_relative;
985 switch_maximum_ecart_relatif_surface = erreur_relative > switch_maximum_ecart_relatif_surface ? erreur_relative : switch_maximum_ecart_relatif_surface;
986 switch_maximum_ecart_absolue_surface = erreur_absolue > switch_maximum_ecart_absolue_surface ? erreur_absolue : switch_maximum_ecart_absolue_surface;
987
988 switch_n_count_surface += 1;
989 }
990 }
991 }
992 else
993 {
994 assert((next_indicatrice_ns(i+di,j+dj,k+dk) == 0) || (next_indicatrice_ns(i+di,j+dj,k+dk) == 1));
995 delta_volume_total -= sign*f*next_indicatrice_ns(i+di,j+dj,k+dk)*velocity[dir].pure_(i+di,j+dj,k+dk);
996 }
997
998 }
999
1000 double delta_volume_cible = volume * (next_indicatrice_ns(i, j, k) - old_indicatrice_ns(i, j, k));
1001
1002 double erreur_relative = delta_volume_cible == 0. ? delta_volume_total/volume : std::fabs((delta_volume_total - delta_volume_cible)/delta_volume_cible);
1003 double erreur_absolue = std::fabs(delta_volume_total - delta_volume_cible);
1004
1005 if (IJK_Interfaces::est_pure(.5*(old_indicatrice_ns(i, j, k) + next_indicatrice_ns(i, j, k))))
1006 {
1007 // A failure of this assert suggests a non-zero velocity divergence
1008 //assert(std::abs(erreur_relative) < 1e-12);
1009 }
1010 else
1011 {
1012 n_count += 1;
1013 moyenne_erreur_relative += erreur_relative;
1014 moyenne_erreur_absolue += erreur_absolue;
1015 maximum_erreur_relative = erreur_relative > maximum_erreur_relative ? erreur_relative : maximum_erreur_relative;
1016 maximum_erreur_absolue = erreur_absolue > maximum_erreur_absolue ? erreur_absolue : maximum_erreur_absolue;
1017
1018 if (centre_switch)
1019 {
1020 switch_n_count += 1;
1021 switch_moyenne_erreur_relative += erreur_relative;
1022 switch_moyenne_erreur_absolue += erreur_absolue;
1023 switch_maximum_erreur_relative = erreur_relative > switch_maximum_erreur_relative ? erreur_relative : switch_maximum_erreur_relative;
1024 switch_maximum_erreur_absolue = erreur_absolue > switch_maximum_erreur_absolue ? erreur_absolue : switch_maximum_erreur_absolue;
1025 }
1026 }
1027 }
1028 moyenne_erreur_absolue = Process::mp_sum(moyenne_erreur_absolue);
1029 moyenne_erreur_relative = Process::mp_sum(moyenne_erreur_relative);
1030 maximum_erreur_absolue = Process::mp_max(maximum_erreur_absolue);
1031 maximum_erreur_relative = Process::mp_max(maximum_erreur_relative);
1032 moyenne_ecart_absolue_surface = Process::mp_sum(moyenne_ecart_absolue_surface);
1033 moyenne_ecart_relatif_surface = Process::mp_sum(moyenne_ecart_relatif_surface);
1034 maximum_ecart_absolue_surface = Process::mp_max(maximum_ecart_absolue_surface);
1035 maximum_ecart_relatif_surface = Process::mp_max(maximum_ecart_relatif_surface);
1036 switch_moyenne_erreur_absolue = Process::mp_sum(switch_moyenne_erreur_absolue);
1037 switch_moyenne_erreur_relative = Process::mp_sum(switch_moyenne_erreur_relative);
1038 switch_maximum_erreur_absolue = Process::mp_max(switch_maximum_erreur_absolue);
1039 switch_maximum_erreur_relative = Process::mp_max(switch_maximum_erreur_relative);
1040 switch_moyenne_ecart_absolue_surface = Process::mp_sum(switch_moyenne_ecart_absolue_surface);
1041 switch_moyenne_ecart_relatif_surface = Process::mp_sum(switch_moyenne_ecart_relatif_surface);
1042 switch_maximum_ecart_absolue_surface = Process::mp_max(switch_maximum_ecart_absolue_surface);
1043 switch_maximum_ecart_relatif_surface = Process::mp_max(switch_maximum_ecart_relatif_surface);
1044 n_count = Process::check_int_overflow(Process::mp_sum(n_count));
1045 n_count_surface = Process::check_int_overflow(Process::mp_sum(n_count_surface));
1046 switch_n_count = Process::check_int_overflow(Process::mp_sum(switch_n_count));
1047 switch_n_count_surface = Process::check_int_overflow(Process::mp_sum(switch_n_count_surface));
1048 if (n_count >= 1)
1049 {
1050 moyenne_erreur_relative /= n_count;
1051 moyenne_erreur_absolue /= n_count;
1052 moyenne_ecart_absolue_surface /= (n_count_surface);
1053 moyenne_ecart_relatif_surface /= (n_count_surface);
1054 }
1055 if (switch_n_count >= 1)
1056 {
1057 switch_moyenne_erreur_relative /= switch_n_count;
1058 switch_moyenne_erreur_absolue /= switch_n_count;
1059 switch_moyenne_ecart_absolue_surface /= (switch_n_count_surface);
1060 switch_moyenne_ecart_relatif_surface /= (switch_n_count_surface);
1061 }
1062
1063 if (verbosite_surface_efficace_face == 2)
1064 {
1065 Cerr << "Calcul surface efficace face: #iteration: " << iteration_solver_surface_efficace_face << finl;
1066 Cerr << " moyenne_erreur: " << moyenne_erreur_absolue << " (relative: " << moyenne_erreur_relative << ") max_erreur: " << maximum_erreur_absolue << " (relative: " << maximum_erreur_relative << ")" << finl;
1067 Cerr << " moyenne_ecart_surface: " << moyenne_ecart_absolue_surface << " (relatif: " << moyenne_ecart_relatif_surface << ") max_ecart_surface: " << maximum_ecart_absolue_surface << " (relatif: " << maximum_ecart_relatif_surface << ")" << finl;
1068 Cerr << " switch moyenne_erreur: " << switch_moyenne_erreur_absolue << " (relative: " << switch_moyenne_erreur_relative << ") max_erreur: " << switch_maximum_erreur_absolue << " (relative: " << switch_maximum_erreur_relative << ")" << finl;
1069 Cerr << " switch moyenne_ecart_surface: " << switch_moyenne_ecart_absolue_surface << " (relatif: " << switch_moyenne_ecart_relatif_surface << ") max_ecart_surface: " << switch_maximum_ecart_absolue_surface << " (relatif: " << switch_maximum_ecart_relatif_surface << ")" << finl;
1070 }
1071 else if (verbosite_surface_efficace_face == 1)
1072 {
1073 Cerr << "Calcul surface efficace face: #" << iteration_solver_surface_efficace_face << " mean_rel: " << moyenne_erreur_relative << " max_rel: " << maximum_erreur_relative << " switch_mean_rel: " << switch_moyenne_erreur_relative << " switch_max_rel: " << switch_maximum_erreur_relative << finl;
1074 }
1075 else
1076 {
1077 Cerr << "Cut_cell_surface_efficace::imprimer_informations_surface_efficace_face: verbosite_surface_efficace_face non reconnu." << finl;
1078 Process::exit();
1079 }
1080}
1081
1082
1083void Cut_cell_surface_efficace::calcul_delta_volume_theorique_bilan(int compo, const DoubleTab& bounding_box_bulles, double timestep,
1084 const IJK_Field_double& indicatrice_avant_deformation,
1085 const IJK_Field_double& indicatrice_apres_deformation,
1086 const IJK_Field_vector3_double& indicatrice_surfacique_efficace_deformation_face,
1087 const Cut_field_vector3_double& deformation_velocity,
1088 IJK_Field_double& delta_volume_theorique_bilan)
1089{
1090 assert(&deformation_velocity[0].get_cut_cell_disc() == &deformation_velocity[1].get_cut_cell_disc());
1091 assert(&deformation_velocity[0].get_cut_cell_disc() == &deformation_velocity[2].get_cut_cell_disc());
1092 const Cut_cell_FT_Disc& cut_cell_disc = deformation_velocity[0].get_cut_cell_disc();
1093
1094 const int ni = delta_volume_theorique_bilan.ni();
1095 const int nj = delta_volume_theorique_bilan.nj();
1096 const int nk = delta_volume_theorique_bilan.nk();
1097
1098 const Domaine_IJK& geom = delta_volume_theorique_bilan.get_domaine();
1099 assert(geom.is_uniform(0));
1100 assert(geom.is_uniform(1));
1101 assert(geom.is_uniform(2));
1102
1103 const double delta_x = geom.get_constant_delta(DIRECTION_I);
1104 const double delta_y = geom.get_constant_delta(DIRECTION_J);
1105 const double delta_z = geom.get_constant_delta(DIRECTION_K);
1106
1107 double origin_x = geom.get_origin(DIRECTION_I);
1108 double origin_y = geom.get_origin(DIRECTION_J);
1109 double origin_z = geom.get_origin(DIRECTION_K);
1110
1111 const int offset_x = geom.get_offset_local(DIRECTION_I);
1112 const int offset_y = geom.get_offset_local(DIRECTION_J);
1113 const int offset_z = geom.get_offset_local(DIRECTION_K);
1114
1115 int imin = std::max(0, (int)((bounding_box_bulles(compo, 0, 0) - origin_x)/delta_x - offset_x - 2));
1116 int imax = std::min(ni, (int)((bounding_box_bulles(compo, 0, 1) - origin_x)/delta_x - offset_x + 2));
1117 int jmin = std::max(0, (int)((bounding_box_bulles(compo, 1, 0) - origin_y)/delta_y - offset_y - 2));
1118 int jmax = std::min(nj, (int)((bounding_box_bulles(compo, 1, 1) - origin_y)/delta_y - offset_y + 2));
1119 int kmin = std::max(0, (int)((bounding_box_bulles(compo, 2, 0) - origin_z)/delta_z - offset_z - 2));
1120 int kmax = std::min(nk, (int)((bounding_box_bulles(compo, 2, 1) - origin_z)/delta_z - offset_z + 2));
1121
1122 for (int k = kmin; k < kmax; k++)
1123 {
1124 for (int j = jmin; j < jmax; j++)
1125 {
1126 for (int i = imin; i < imax; i++)
1127 {
1128 bool apres_deformation_pure = ((indicatrice_apres_deformation(i,j,k) == 0.) || (indicatrice_apres_deformation(i,j,k) == 1.));
1129 if (apres_deformation_pure)
1130 {
1131 assert(delta_volume_theorique_bilan(i,j,k) == 0.);
1132 }
1133 else
1134 {
1135 const double fx = delta_y * delta_z * timestep;
1136 const double fy = delta_x * delta_z * timestep;
1137 const double fz = delta_x * delta_y * timestep;
1138
1139 double delta_volume_total[2] = {0};
1140
1141 for (int phase = 0 ; phase < 2 ; phase++)
1142 {
1143 for (int num_face = 0; num_face < 6; num_face++)
1144 {
1145 int dir = num_face%3;
1146 int decalage = num_face/3;
1147 int sign = decalage*2 -1;
1148
1149 int di = decalage*(dir == 0);
1150 int dj = decalage*(dir == 1);
1151 int dk = decalage*(dir == 2);
1152
1153 double surface_efficace = (phase == 0) ? 1 - indicatrice_surfacique_efficace_deformation_face[dir](i+di,j+dj,k+dk) : indicatrice_surfacique_efficace_deformation_face[dir](i+di,j+dj,k+dk);
1154
1155 double f = select_dir(dir, fx, fy, fz);
1156
1157 int n = cut_cell_disc.get_n(i, j, k);
1158 int n_face = cut_cell_disc.get_n_face(num_face, n, i, j, k);
1159 if (n_face >= 0)
1160 {
1161 const DoubleTabFT_cut_cell& deformation_diph_velocity = (phase == 0) ? deformation_velocity[dir].diph_v_ : deformation_velocity[dir].diph_l_;
1162
1163 assert(deformation_diph_velocity(n_face) != 6.3e32);
1164 delta_volume_total[phase] -= sign*f*surface_efficace*deformation_diph_velocity(n_face);
1165 }
1166 else
1167 {
1168 assert(deformation_velocity[dir].pure_(i+di,j+dj,k+dk) != 6.3e32);
1169 delta_volume_total[phase] -= sign*f*surface_efficace*deformation_velocity[dir].pure_(i+di,j+dj,k+dk);
1170 }
1171 }
1172 }
1173
1174
1175 // moyenne entre les deux phases de la prediction sur la variation de volume
1176 double delta_volume_cible = .5*(delta_volume_total[1] - delta_volume_total[0]); // la variation de la phase 0 est negative
1177
1178 assert(delta_volume_theorique_bilan(i,j,k) == 0.);
1179 delta_volume_theorique_bilan(i,j,k) = -delta_volume_cible; // signe negatif car on souhaite la variation de la phase 0
1180 }
1181 }
1182 }
1183 }
1184
1185 delta_volume_theorique_bilan.echange_espace_virtuel(delta_volume_theorique_bilan.ghost());
1186}
const Domaine_IJK & get_domaine() 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(int i, int j, int k) const
static void calcul_surface_interface_efficace(double timestep, const IJK_Field_vector3_double &velocity, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const DoubleTabFT_cut_cell_vector3 &vitesse_deplacement_interface, const DoubleTabFT_cut_cell_vector3 &normale_deplacement_interface, DoubleTabFT_cut_cell_scalar &surface_efficace_interface)
static void calcul_surface_interface_efficace_initiale(int methode_explicite, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const IJK_Field_double &surface_interface_ns_old, const IJK_Field_double &surface_interface_ns_next, const IJK_Field_vector3_double &normal_of_interf_ns_old, const IJK_Field_vector3_double &normal_of_interf_ns_next, DoubleTabFT_cut_cell_vector3 &normale_deplacement_interface, DoubleTabFT_cut_cell_scalar &surface_efficace_interface, DoubleTabFT_cut_cell_scalar &surface_efficace_interface_initial)
static void imprimer_informations_surface_efficace_interface(int verbosite_surface_efficace_interface, double timestep, const IJK_Field_vector3_double &velocity, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const DoubleTabFT_cut_cell_scalar &surface_efficace_interface, const DoubleTabFT_cut_cell_scalar &surface_efficace_interface_initial, const DoubleTabFT_cut_cell_vector3 &normale_deplacement_interface, const DoubleTabFT_cut_cell_vector3 &vitesse_deplacement_interface)
static void calcul_delta_volume_theorique_bilan(int compo, const DoubleTab &bounding_box_bulles, double timestep, const IJK_Field_double &indicatrice_avant_deformation, const IJK_Field_double &indicatrice_apres_deformation, const IJK_Field_vector3_double &indicatrice_surfacique_efficace_deformation_face, const Cut_field_vector3_double &deformation_velocity, IJK_Field_double &delta_volume_theorique_bilan)
static void imprimer_informations_surface_efficace_face(int verbosite_surface_efficace_face, int iteration_solver_surface_efficace_face, double timestep, const Cut_field_vector3_double &velocity, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face, const DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face_initial)
static void calcul_vitesse_interface(const IJK_Field_vector3_double &velocity, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const IJK_Field_vector3_double &barycentre_phase1_ns_old, const IJK_Field_vector3_double &barycentre_phase1_ns_next, DoubleTabFT_cut_cell_vector3 &coord_deplacement_interface, DoubleTabFT_cut_cell_vector3 &vitesse_deplacement_interface)
static void calcul_surface_face_efficace_initiale(int methode_explicite, const IJK_Field_vector3_double &old_indicatrice_surfacique_face_ns, const IJK_Field_vector3_double &next_indicatrice_surfacique_face_ns, DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face, DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face_initial)
static void calcul_surface_face_efficace_iteratif(int verbosite_surface_efficace_face, double timestep, const Cut_field_vector3_double &velocity, int &iteration_solver_surface_efficace_face, const IJK_Field_double &old_indicatrice_ns, const IJK_Field_double &next_indicatrice_ns, const IJK_Field_vector3_double &old_indicatrice_surfacique_face_ns, const IJK_Field_vector3_double &next_indicatrice_surfacique_face_ns, DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face, const DoubleTabFT_cut_cell_vector3 &indicatrice_surfacique_efficace_face_initial, DoubleTabFT_cut_cell_vector6 &indicatrice_surfacique_efficace_face_correction, DoubleTabFT_cut_cell_scalar &indicatrice_surfacique_efficace_face_absolute_error)
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
int get_offset_local(int direction) const
Returns the local offset in requested direction.
bool is_uniform(int direction) const
Method returns true if uniform in this direction.
double get_constant_delta(int direction) const
Returns the size of cells in a direction.
const ArrOfDouble & get_delta(int direction) const
Returns the array of mesh cell sizes in requested direction.
double get_origin(int direction) const
Returns the coordinate of the first node (global) of the mesh in the requested direction.
void echange_espace_virtuel(int ghost)
Exchange data over "ghost" number of cells.
const Domaine_IJK & get_domaine() const
static int devient_diphasique(double old_indicatrice, double next_indicatrice)
static int devient_pure(double old_indicatrice, double next_indicatrice)
static int est_pure(double indicatrice)
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static double mp_max(double)
Definition Process.cpp:376
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
const Cut_cell_FT_Disc & get_cut_cell_disc() const
void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname") override