TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
IJK_Navier_Stokes_tools_cut_cell.cpp
1/****************************************************************************
2* Copyright (c) 2023, 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 <IJK_Navier_Stokes_tools_cut_cell.h>
17#include <Cut_field.h>
18#include <IJK_Interfaces.h>
19#include <Cut_cell_FT_Disc.h>
20
21extern "C" {
22 // LU decomoposition of a general matrix
23 void dgetrf_(int* M, int *N, double* A, int* lda, int* IPIV, int* INFO);
24
25 // generate inverse of a matrix given its LU decomposition
26 void dgetri_(int* N, double* A, int* lda, int* IPIV, double* WORK, int* lwork, int* INFO);
27}
28
29void inverse(double* A, int N)
30{
31 int *IPIV = new int[N];
32 int LWORK = N*N;
33 double *WORK = new double[LWORK];
34 int INFO;
35
36 dgetrf_(&N,&N,A,&N,IPIV,&INFO);
37 dgetri_(&N,A,&N,IPIV,WORK,&LWORK,&INFO);
38
39 delete[] IPIV;
40 delete[] WORK;
41}
42
44{
45 int index;
47};
48
49struct Sommet
50{
51 int sommet;
52 int fa7;
53 double value;
54 int count;
55};
56
64
72
73static const int max_number_of_involved_sommet = 512; // Note: Pour ce maximum, les sommets sont comptes une fois pour chaque facette et pour chaque cellule contenant cette facette
74
75static const int max_number_of_cell_candidates = 27;
76static const Int3 candidate_offset[max_number_of_cell_candidates] =
77{
78 {-1,-1,-1}, {-1,-1, 0}, {-1,-1,+1},
79 {-1, 0,-1}, {-1, 0, 0}, {-1, 0,+1},
80 {-1,+1,-1}, {-1,+1, 0}, {-1,+1,+1},
81 { 0,-1,-1}, { 0,-1, 0}, { 0,-1,+1},
82 { 0, 0,-1}, { 0, 0, 0}, { 0, 0,+1},
83 { 0,+1,-1}, { 0,+1, 0}, { 0,+1,+1},
84 {+1,-1,-1}, {+1,-1, 0}, {+1,-1,+1},
85 {+1, 0,-1}, {+1, 0, 0}, {+1, 0,+1},
86 {+1,+1,-1}, {+1,+1, 0}, {+1,+1,+1}
87};
88
89static const int max_number_of_candidates = max_number_of_involved_sommet + max_number_of_cell_candidates;
90
91template<typename T>
92Vecteur3 compute_lambda(int index_vertex0, int index_vertex1, int index_vertex2, int index_vertex3, T candidates[max_number_of_candidates], double xfact, double yfact, double zfact)
93{
94 double x_0 = candidates[index_vertex0].coord[0];
95 double y_0 = candidates[index_vertex0].coord[1];
96 double z_0 = candidates[index_vertex0].coord[2];
97
98 double x_1 = candidates[index_vertex1].coord[0];
99 double y_1 = candidates[index_vertex1].coord[1];
100 double z_1 = candidates[index_vertex1].coord[2];
101 double dx_1 = x_1 - x_0;
102 double dy_1 = y_1 - y_0;
103 double dz_1 = z_1 - z_0;
104
105 double x_2 = candidates[index_vertex2].coord[0];
106 double y_2 = candidates[index_vertex2].coord[1];
107 double z_2 = candidates[index_vertex2].coord[2];
108
109 double dx_2 = x_2 - x_0;
110 double dy_2 = y_2 - y_0;
111 double dz_2 = z_2 - z_0;
112
113 double x_3 = candidates[index_vertex3].coord[0];
114 double y_3 = candidates[index_vertex3].coord[1];
115 double z_3 = candidates[index_vertex3].coord[2];
116
117 double dx_3 = x_3 - x_0;
118 double dy_3 = y_3 - y_0;
119 double dz_3 = z_3 - z_0;
120
121 // En coordonnees barycentriques, puisque dX_0 = 0
122 //
123 // x_target_to_interpolate = dx_1 lambda_1 + dx_2 lamdba_2 + dx_3 lambda_3
124 // y_target_to_interpolate = dy_1 lambda_1 + dy_2 lamdba_2 + dy_3 lambda_3
125 // z_target_to_interpolate = dz_1 lambda_1 + dz_2 lamdba_2 + dz_3 lambda_3
126 // ---
127 // X_target_to_interpolate = Matrix * Lambda_vector
128 //
129 // Donc Lambda_vector = Matrix^-1 * X_target_to_interpolate
130 double Matrix[3*3] =
131 {
132 dx_1, dx_2, dx_3,
133 dy_1, dy_2, dy_3,
134 dz_1, dz_2, dz_3,
135 };
136
137 inverse(Matrix, 3);
138
139 double lambda_1 = Matrix[0] * (xfact - x_0) + Matrix[1] * (yfact - y_0) + Matrix[2] * (zfact - z_0);
140 double lambda_2 = Matrix[3] * (xfact - x_0) + Matrix[4] * (yfact - y_0) + Matrix[5] * (zfact - z_0);
141 double lambda_3 = Matrix[6] * (xfact - x_0) + Matrix[7] * (yfact - y_0) + Matrix[8] * (zfact - z_0);
142
143 Vecteur3 lambda_vec = {lambda_1, lambda_2, lambda_3};
144 return lambda_vec;
145}
146
147static void ijk_interpolate_cut_cell_for_given_index(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const Vecteur3& coordinates, IndexCoefficient tetrahedra_index_coefficient[4], int tolerate_not_within_tetrahedron, int skip_unknown_points, double value_for_bad_points, int& status)
148{
149 const int ghost = cut_cell_disc.get_ghost_size();
150 const int reduced_ghost = ghost - 1;
151
152 const double x = coordinates[0];
153 const double y = coordinates[1];
154 const double z = coordinates[2];
155
156 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
157 const int ni = geom.get_nb_items_local(Domaine_IJK::ELEM, 0);
158 const int nj = geom.get_nb_items_local(Domaine_IJK::ELEM, 1);
159 const int nk = geom.get_nb_items_local(Domaine_IJK::ELEM, 2);
160
161 const double dx = geom.get_constant_delta(DIRECTION_I);
162 const double dy = geom.get_constant_delta(DIRECTION_J);
163 const double dz = geom.get_constant_delta(DIRECTION_K);
164 // L'origine est sur un noeud. Donc que la premiere face en I est sur get_origin(DIRECTION_I)
165 double origin_x = geom.get_origin(DIRECTION_I);
166 double origin_y = geom.get_origin(DIRECTION_J);
167 double origin_z = geom.get_origin(DIRECTION_K);
168
169 const double x2 = (x - origin_x) / dx;
170 const double y2 = (y - origin_y) / dy;
171 const double z2 = (z - origin_z) / dz;
172
173 // Coordonnes barycentriques du points dans la cellule :
174 const double xfact = x2 - floor(x2);
175 const double yfact = y2 - floor(y2);
176 const double zfact = z2 - floor(z2);
177
178 // On travaille sur le maillage NS, on va donc corrige les indices de la periodicite.
179 // Note : on ne corrige que l'index et pas les coordonnees, car on n'utilise plus les coordonnees par la suite.
180 const int index_i = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_I, x, Domaine_IJK::ELEM);
181 const int index_j = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_J, y, Domaine_IJK::ELEM);
182 const int index_k = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_K, z, Domaine_IJK::ELEM);
183
184 // is point in the domain ? (ghost cells ok...)
185 bool ok = (index_i >= -reduced_ghost && index_i < ni + reduced_ghost) && (index_j >= -reduced_ghost && index_j < nj + reduced_ghost) && (index_k >= -reduced_ghost && index_k < nk + reduced_ghost);
186 bool close_to_edge = (index_i == -reduced_ghost || index_i == ni + reduced_ghost - 1) || (index_j == -reduced_ghost || index_j == nj + reduced_ghost - 1) || (index_k == -reduced_ghost || index_k == nk + reduced_ghost - 1);
187 if (!ok)
188 {
189 if (skip_unknown_points)
190 {
191 tetrahedra_index_coefficient[0] = {-1,value_for_bad_points};
192 tetrahedra_index_coefficient[1] = {-1,value_for_bad_points};
193 tetrahedra_index_coefficient[2] = {-1,value_for_bad_points};
194 tetrahedra_index_coefficient[3] = {-1,value_for_bad_points};
195 return;
196 }
197 else
198 {
199 // Error!
200 Cerr << "Error in ijk_interpolate_cut_cell_implementation: request cut-cell interpolation of point " << x << " " << y << " " << z << " which is outside of the domain on processor " << Process::me() << finl;
202 }
203 }
204
205 int number_of_candidates = 0;
206 Candidate candidates[max_number_of_candidates];
207 for (int i = 0; i < max_number_of_cell_candidates; i++)
208 {
209 int i_candidate_aperio = index_i + candidate_offset[i][0];
210 int j_candidate_aperio = index_j + candidate_offset[i][1];
211 int k_candidate_aperio = index_k + candidate_offset[i][2];
212
213 // Prise en compte de la periodicite
214 int i_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(0, i_candidate_aperio);
215 int j_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(1, j_candidate_aperio);
216 int k_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(2, k_candidate_aperio);
217
218 double old_indicatrice = cut_cell_disc.get_interfaces().I(i_candidate, j_candidate, k_candidate);
219 double next_indicatrice = cut_cell_disc.get_interfaces().In(i_candidate, j_candidate, k_candidate);
220 double indicatrice = next_time ? next_indicatrice : old_indicatrice;
221 if ((phase == 0 && indicatrice == 1.) || (phase == 1 && indicatrice == 0.))
222 {
223 // Point invalide
224 }
225 else
226 {
227 double candidate_x = (double)candidate_offset[i][0] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 0, phase, i_candidate, j_candidate, k_candidate));
228 double candidate_y = (double)candidate_offset[i][1] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 1, phase, i_candidate, j_candidate, k_candidate));
229 double candidate_z = (double)candidate_offset[i][2] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 2, phase, i_candidate, j_candidate, k_candidate));
230 double decalage_x = candidate_x - xfact;
231 double decalage_y = candidate_y - yfact;
232 double decalage_z = candidate_z - zfact;
233 candidates[number_of_candidates].index = number_of_candidates;
234 candidates[number_of_candidates].dist = sqrt(decalage_x*decalage_x + decalage_y*decalage_y + decalage_z*decalage_z);
235 candidates[number_of_candidates].coord[0] = candidate_x;
236 candidates[number_of_candidates].coord[1] = candidate_y;
237 candidates[number_of_candidates].coord[2] = candidate_z;
238
239 int n_candidate = cut_cell_disc.get_n(i_candidate, j_candidate, k_candidate);
240 if (n_candidate >= 0)
241 {
242 // Nothing to assert
243 }
244 else
245 {
246 assert((!next_time) || (cut_cell_disc.get_interfaces().In(i_candidate,j_candidate,k_candidate) == (double)phase));
247 assert((next_time) || (cut_cell_disc.get_interfaces().I(i_candidate,j_candidate,k_candidate) == (double)phase));
248 }
249 candidates[number_of_candidates].signed_independent_index = cut_cell_disc.get_domaine().get_signed_independent_index(phase, i_candidate, j_candidate, k_candidate);
250 number_of_candidates += 1;
251 }
252
253 }
254
255
256 assert(number_of_candidates <= max_number_of_candidates);
257 assert(number_of_candidates <= max_number_of_cell_candidates);
258 std::sort(candidates, candidates + number_of_candidates, [&](const Candidate& c1, const Candidate& c2)
259 {
260 return (c1.dist < c2.dist);
261 });
262
263 // On boucle d'abord sur n_neighbours, le nombre de points que l'on s'autorise a chercher
264 // dans la liste des voisins. Par exemple, n_neighbours=6 veut dire que l'on cherche a former
265 // des tetraedres a partir des 6 premiers voisins.
266 const bool limit_count = false;
267 const int max_count = 100;
268 int count = 0;
269 int closest_tetrahedron[4] = {-1,-1,-1,-1};
270 double closest_lambda_error = DMAXFLOAT;
271 for (int n_neighbours = 4; (n_neighbours < number_of_candidates && ((!limit_count) || count < max_count)); n_neighbours++)
272 {
273 int index_vertex0 = n_neighbours; // Le premier point est toujours fixe au dernier possible. Cela garanti que tous les tetraedres d'un nouveau n_neighbours sont nouveaux.
274
275 for (int index_vertex1 = 0; (index_vertex1 < index_vertex0-2 && ((!limit_count) || count < max_count)); index_vertex1++)
276 {
277 for (int index_vertex2 = index_vertex1+1; (index_vertex2 < index_vertex0-1 && ((!limit_count) || count < max_count)); index_vertex2++)
278 {
279 for (int index_vertex3 = index_vertex2+1; (index_vertex3 < index_vertex0 && ((!limit_count) || count < max_count)); index_vertex3++)
280 {
281 Vecteur3 lambda_vec = compute_lambda(index_vertex0, index_vertex1, index_vertex2, index_vertex3, candidates, xfact, yfact, zfact);
282 double lambda_1 = lambda_vec[0];
283 double lambda_2 = lambda_vec[1];
284 double lambda_3 = lambda_vec[2];
285
286 double lambda_0 = 1 - lambda_1 - lambda_2 - lambda_3;
287
288 int lambda_0_within_bounds = ((lambda_0 >= 0) && (lambda_0 <= 1));
289 int lambda_1_within_bounds = ((lambda_1 >= 0) && (lambda_1 <= 1));
290 int lambda_2_within_bounds = ((lambda_2 >= 0) && (lambda_2 <= 1));
291 int lambda_3_within_bounds = ((lambda_3 >= 0) && (lambda_3 <= 1));
292
293 int point_within_tetrahedron = lambda_0_within_bounds && lambda_1_within_bounds && lambda_2_within_bounds && lambda_3_within_bounds;
294
295 count++;
296 if (point_within_tetrahedron)
297 {
298 int signed_independent_index_0 = candidates[index_vertex0].signed_independent_index;
299 int signed_independent_index_1 = candidates[index_vertex1].signed_independent_index;
300 int signed_independent_index_2 = candidates[index_vertex2].signed_independent_index;
301 int signed_independent_index_3 = candidates[index_vertex3].signed_independent_index;
302
303 tetrahedra_index_coefficient[0] = {signed_independent_index_0, lambda_0};
304 tetrahedra_index_coefficient[1] = {signed_independent_index_1, lambda_1};
305 tetrahedra_index_coefficient[2] = {signed_independent_index_2, lambda_2};
306 tetrahedra_index_coefficient[3] = {signed_independent_index_3, lambda_3};
307
308 status = count;
309 return;
310 }
311 else
312 {
313 double lambda_error_0 = std::max((lambda_0 < 0)*(-lambda_0), (lambda_0 > 1)*(lambda_0 - 1));
314 double lambda_error_1 = std::max((lambda_1 < 0)*(-lambda_1), (lambda_1 > 1)*(lambda_1 - 1));
315 double lambda_error_2 = std::max((lambda_2 < 0)*(-lambda_2), (lambda_2 > 1)*(lambda_2 - 1));
316 double lambda_error_3 = std::max((lambda_3 < 0)*(-lambda_3), (lambda_3 > 1)*(lambda_3 - 1));
317
318 double lambda_error = std::max(lambda_error_0, std::max(lambda_error_1, std::max(lambda_error_2, lambda_error_3)));
319 assert(lambda_error > 0);
320
321 if (closest_lambda_error > lambda_error)
322 {
323 closest_tetrahedron[0] = index_vertex0;
324 closest_tetrahedron[1] = index_vertex1;
325 closest_tetrahedron[2] = index_vertex2;
326 closest_tetrahedron[3] = index_vertex3;
327 closest_lambda_error = lambda_error;
328 }
329 }
330 }
331 }
332 }
333 }
334
335 // Utilise le tetrahedre le plus proche selon les parametres de tolerance
336 if ((tolerate_not_within_tetrahedron == 2) || (tolerate_not_within_tetrahedron == 1 && closest_lambda_error < 1e-9))
337 {
338 Vecteur3 lambda_vec = compute_lambda(closest_tetrahedron[0], closest_tetrahedron[1], closest_tetrahedron[2], closest_tetrahedron[3], candidates, xfact, yfact, zfact);
339 double lambda_1 = lambda_vec[0];
340 double lambda_2 = lambda_vec[1];
341 double lambda_3 = lambda_vec[2];
342
343 double lambda_0 = 1 - lambda_1 - lambda_2 - lambda_3;
344
345 assert(!(((lambda_0 >= 0) && (lambda_0 <= 1)) && ((lambda_1 >= 0) && (lambda_1 <= 1)) && ((lambda_2 >= 0) && (lambda_2 <= 1)) && ((lambda_3 >= 0) && (lambda_3 <= 1))));
346
347 int signed_independent_index_0 = candidates[closest_tetrahedron[0]].signed_independent_index;
348 int signed_independent_index_1 = candidates[closest_tetrahedron[1]].signed_independent_index;
349 int signed_independent_index_2 = candidates[closest_tetrahedron[2]].signed_independent_index;
350 int signed_independent_index_3 = candidates[closest_tetrahedron[3]].signed_independent_index;
351
352 tetrahedra_index_coefficient[0] = {signed_independent_index_0, lambda_0};
353 tetrahedra_index_coefficient[1] = {signed_independent_index_1, lambda_1};
354 tetrahedra_index_coefficient[2] = {signed_independent_index_2, lambda_2};
355 tetrahedra_index_coefficient[3] = {signed_independent_index_3, lambda_3};
356
357 status = -1;
358 return;
359 }
360 else
361 {
362 Cerr << "Value of close_to_edge: " << (int)close_to_edge << finl;
363 Cerr << "Error in ijk_interpolate_cut_cell_for_given_index: no tetrahedron containing the point " << x << " " << y << " " << z << " on processor " << Process::me() << finl;
364 Cerr << "For information, closest_lambda_error=" << closest_lambda_error << finl;
365 // Note: While maybe not most likely, I noticed this error could occur if
366 // * the number of cells per particle diameter is too small <=3
367 // * ijk_splitting_ft_extension is not large enough
369 tetrahedra_index_coefficient[0] = {-1,-1.};
370 tetrahedra_index_coefficient[1] = {-1,-1.};
371 tetrahedra_index_coefficient[2] = {-1,-1.};
372 tetrahedra_index_coefficient[3] = {-1,-1.};
373 return;
374 }
375}
376
377static double ijk_interpolate_cut_cell_using_interface_for_given_index(bool next_time, int phase, const IJK_Field_double& field_ft, const Cut_field_double& field, const ArrOfDouble& interfacial_temperature, const Vecteur3& coordinates, int tolerate_not_within_tetrahedron, int skip_unknown_points, double value_for_bad_points, int& status)
378{
379 if (Process::me() > 0)
380 {
381 Cerr << "Error in ijk_interpolate_cut_cell_using_interface_for_given_index: Le calcul est parallele mais cette methode n'est pas correcte dans le cas parallele" << finl;
383 }
384
385 const Cut_cell_FT_Disc& cut_cell_disc = field.get_cut_cell_disc();
386
387 const Maillage_FT_IJK& mesh = next_time ? cut_cell_disc.get_interfaces().maillage_ft_ijk() : cut_cell_disc.get_interfaces().old_maillage_ft_ijk();
388 const IntTab& facettes = mesh.facettes();
389 const DoubleTab& sommets = mesh.sommets();
390 const ArrOfDouble& surface_facettes = mesh.get_update_surface_facettes();
392
393 //const int ghost = field.ghost();
394 const int ghost = cut_cell_disc.get_ghost_size();
395 assert(field.ghost() >= ghost);
396
397 const double x = coordinates[0];
398 const double y = coordinates[1];
399 const double z = coordinates[2];
400
401 const int ni_ft = field_ft.ni();
402 const int nj_ft = field_ft.nj();
403 const int nk_ft = field_ft.nk();
404
405 const Domaine_IJK& geom_ft = field_ft.get_domaine();
406
407 const double dx_ft = geom_ft.get_constant_delta(DIRECTION_I);
408 const double dy_ft = geom_ft.get_constant_delta(DIRECTION_J);
409 const double dz_ft = geom_ft.get_constant_delta(DIRECTION_K);
410 double origin_x_ft = geom_ft.get_origin(DIRECTION_I);
411 double origin_y_ft = geom_ft.get_origin(DIRECTION_J);
412 double origin_z_ft = geom_ft.get_origin(DIRECTION_K);
413
414 const double x2_ft = (x - origin_x_ft) / dx_ft;
415 const double y2_ft = (y - origin_y_ft) / dy_ft;
416 const double z2_ft = (z - origin_z_ft) / dz_ft;
417
418 const int index_i_ft = (int)(std::floor(x2_ft)) - geom_ft.get_offset_local(DIRECTION_I);
419 const int index_j_ft = (int)(std::floor(y2_ft)) - geom_ft.get_offset_local(DIRECTION_J);
420 const int index_k_ft = (int)(std::floor(z2_ft)) - geom_ft.get_offset_local(DIRECTION_K);
421
422 const int ni = field.ni();
423 const int nj = field.nj();
424 const int nk = field.nk();
425
426 const Domaine_IJK& geom = field.get_domaine();
427 const double dx = geom.get_constant_delta(DIRECTION_I);
428 const double dy = geom.get_constant_delta(DIRECTION_J);
429 const double dz = geom.get_constant_delta(DIRECTION_K);
430 //const Domaine_IJK::Localisation loc = field.pure_.get_localisation();
431 // L'origine est sur un noeud. Donc que la premiere face en I est sur get_origin(DIRECTION_I)
432 double origin_x = geom.get_origin(DIRECTION_I);
433 double origin_y = geom.get_origin(DIRECTION_J);
434 double origin_z = geom.get_origin(DIRECTION_K);
435
436 const double x2 = (x - origin_x) / dx;
437 const double y2 = (y - origin_y) / dy;
438 const double z2 = (z - origin_z) / dz;
439
440 // Coordonnes barycentriques du points dans la cellule :
441 const double xfact = x2 - floor(x2);
442 const double yfact = y2 - floor(y2);
443 const double zfact = z2 - floor(z2);
444
445 // On travaille sur le maillage NS, on va donc corrige les indices de la periodicite.
446 // Note : on ne corrige que l'index et pas les coordonnees, car on n'utilise plus les coordonnees par la suite.
447 const int index_i = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_I, x, Domaine_IJK::ELEM);
448 const int index_j = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_J, y, Domaine_IJK::ELEM);
449 const int index_k = cut_cell_disc.get_domaine().get_i_along_dir_perio(DIRECTION_K, z, Domaine_IJK::ELEM);
450
451 // is point in the domain ? (ghost cells ok...)
452 bool ok = (index_i >= -ghost && index_i < ni + ghost) && (index_j >= -ghost && index_j < nj + ghost) && (index_k >= -ghost && index_k < nk + ghost);
453 bool close_to_edge = (index_i == -ghost || index_i == ni + ghost - 1) || (index_j == -ghost || index_j == nj + ghost - 1) || (index_k == -ghost || index_k == nk + ghost - 1);
454 if (!ok)
455 {
456 if (skip_unknown_points)
457 {
458 return value_for_bad_points;
459 }
460 else
461 {
462 // Error!
463 Cerr << "Error in ijk_interpolate_cut_cell_implementation: request cut-cell interpolation of point " << x << " " << y << " " << z << " which is outside of the domain on processor " << Process::me() << finl;
465 }
466 }
467
468 Sommet involved_sommet[max_number_of_involved_sommet] = {};
469 for (int i = 0; i < max_number_of_involved_sommet; i++)
470 {
471 involved_sommet[i].sommet = -1;
472 involved_sommet[i].fa7 = -1;
473 involved_sommet[i].value = 0.;
474 involved_sommet[i].count = 0;
475 }
476 int number_of_involved_sommet = 0;
477
478 int number_of_candidates = 0;
479 Candidate_with_direct_value candidates[max_number_of_candidates];
480 for (int i = 0; i < max_number_of_cell_candidates; i++)
481 {
482 int i_candidate_aperio = index_i + candidate_offset[i][0];
483 int j_candidate_aperio = index_j + candidate_offset[i][1];
484 int k_candidate_aperio = index_k + candidate_offset[i][2];
485
486 // Prise en compte de la periodicite
487 int i_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(0, i_candidate_aperio);
488 int j_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(1, j_candidate_aperio);
489 int k_candidate = cut_cell_disc.get_domaine().correct_perio_i_local(2, k_candidate_aperio);
490
491 double old_indicatrice = cut_cell_disc.get_interfaces().I(i_candidate, j_candidate, k_candidate);
492 double next_indicatrice = cut_cell_disc.get_interfaces().In(i_candidate, j_candidate, k_candidate);
493 double indicatrice = next_time ? next_indicatrice : old_indicatrice;
494 if ((phase == 0 && indicatrice == 1.) || (phase == 1 && indicatrice == 0.))
495 {
496 // Point invalide
497 }
498 else
499 {
500 double candidate_x = (double)candidate_offset[i][0] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 0, phase, i_candidate, j_candidate, k_candidate));
501 double candidate_y = (double)candidate_offset[i][1] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 1, phase, i_candidate, j_candidate, k_candidate));
502 double candidate_z = (double)candidate_offset[i][2] + (cut_cell_disc.get_interfaces().get_barycentre(next_time, 2, phase, i_candidate, j_candidate, k_candidate));
503 double decalage_x = candidate_x - xfact;
504 double decalage_y = candidate_y - yfact;
505 double decalage_z = candidate_z - zfact;
506 candidates[number_of_candidates].index = number_of_candidates;
507 candidates[number_of_candidates].dist = sqrt(decalage_x*decalage_x + decalage_y*decalage_y + decalage_z*decalage_z);
508 candidates[number_of_candidates].coord[0] = candidate_x;
509 candidates[number_of_candidates].coord[1] = candidate_y;
510 candidates[number_of_candidates].coord[2] = candidate_z;
511
512 int n_candidate = cut_cell_disc.get_n(i_candidate, j_candidate, k_candidate);
513 if (n_candidate >= 0)
514 {
515 candidates[number_of_candidates].value = (phase == 0) ? field.diph_v_(n_candidate) : field.diph_l_(n_candidate);
516 }
517 else
518 {
519 assert((!next_time) || (cut_cell_disc.get_interfaces().In(i_candidate,j_candidate,k_candidate) == (double)phase));
520 assert((next_time) || (cut_cell_disc.get_interfaces().I(i_candidate,j_candidate,k_candidate) == (double)phase));
521 candidates[number_of_candidates].value = field.pure_(i_candidate,j_candidate,k_candidate);
522 }
523 assert(candidates[number_of_candidates].value != 0); // Suggests a bug, but not necessarily implies so
524 number_of_candidates += 1;
525 }
526
527 int i_candidate_ft = index_i_ft + candidate_offset[i][0];
528 int j_candidate_ft = index_j_ft + candidate_offset[i][1];
529 int k_candidate_ft = index_k_ft + candidate_offset[i][2];
530
531 if (i_candidate_ft < 0 || j_candidate_ft < 0 || k_candidate_ft < 0 || i_candidate_ft >= ni_ft || j_candidate_ft >= nj_ft || k_candidate_ft >= nk_ft)
532 {
533 continue; // Ne fait rien, car ces conditions semblent impliquer que le point est inutile.
534 }
535
536 const ArrOfInt& index_elem = intersec.index_elem();
537 const int num_elem = geom_ft.convert_ijk_cell_to_packed(i_candidate_ft,j_candidate_ft,k_candidate_ft);
538 int index = index_elem[num_elem];
539
540 // Boucle sur les facettes qui traversent cet element
541 while (index >= 0)
542 {
543 const Intersections_Elem_Facettes_Data& data = intersec.data_intersection(index);
544 const int fa7 = data.numero_facette_;
545
546 for (int som = 0; som < 3; som++)
547 {
548 // Note : Incomplet
549 // On ne prend en compte que les sommets reels
550 // car il semble difficile de prendre en compte les facettes que le PE ne connait pas
551 // et je suppose que l'on connait toutes les facettes associees a un sommet reel.
552 // Cela veut dire qu'il y aura une difference entre sequentiel et parallele.
553 if (!mesh.sommet_virtuel(facettes(fa7, som)))
554 {
555 assert(number_of_involved_sommet < max_number_of_involved_sommet);
556 involved_sommet[number_of_involved_sommet].sommet = facettes(fa7, som);
557 involved_sommet[number_of_involved_sommet].fa7 = fa7;
558 involved_sommet[number_of_involved_sommet].value = interfacial_temperature(fa7)/surface_facettes(fa7);
559 involved_sommet[number_of_involved_sommet].count = 1;
560 number_of_involved_sommet += 1;
561 }
562 }
563
564 index = data.index_facette_suivante_;
565 };
566 }
567
568 std::sort(involved_sommet, involved_sommet + number_of_involved_sommet, [&](const Sommet& s1, const Sommet& s2)
569 {
570 if(s1.sommet == s2.sommet)
571 return (s1.fa7 > s2.fa7);
572 else
573 return (s1.sommet > s2.sommet);
574 });
575
576 int initial_number_of_involved_sommet = number_of_involved_sommet;
577
578 int precedente_fa7 = -1;
579 int precedent_sommet = -1;
580 int premier_i_avec_ce_sommet = -1;
581 for (int i = 0; i < initial_number_of_involved_sommet; i++)
582 {
583 int sommet = involved_sommet[i].sommet;
584 int fa7 = involved_sommet[i].fa7;
585 assert(sommet != -1);
586 if (sommet == precedent_sommet)
587 {
588 assert(fa7 != -1);
589 if (fa7 == precedente_fa7)
590 {
591 // This is a duplicate, thus the information is destroyed (below).
592 }
593 else
594 {
595 // This is the contribution of a different facet,
596 // the information is moved to the first instance of the vertex, then destroyed (below).
597 involved_sommet[premier_i_avec_ce_sommet].value += involved_sommet[i].value;
598 involved_sommet[premier_i_avec_ce_sommet].count += 1;
599
600 precedente_fa7 = fa7;
601 }
602
603 involved_sommet[i].sommet = -1;
604 involved_sommet[i].fa7 = -1;
605 involved_sommet[i].value = 0.;
606 involved_sommet[i].count = 1;
607
608 number_of_involved_sommet -= 1;
609
610 }
611 else
612 {
613 premier_i_avec_ce_sommet = i;
614 precedent_sommet = sommet;
615 precedente_fa7 = -1;
616 }
617 }
618
619 for (int i = 0; i < initial_number_of_involved_sommet; i++)
620 {
621 involved_sommet[i].value /= involved_sommet[i].count;
622 involved_sommet[i].count = 1;
623 }
624
625 std::sort(involved_sommet, involved_sommet + initial_number_of_involved_sommet, [&](const Sommet& s1, const Sommet& s2)
626 {
627 if(s1.sommet == s2.sommet)
628 return (s1.fa7 > s2.fa7);
629 else
630 return (s1.sommet > s2.sommet);
631 });
632
633
634 for (int i = 0; i < number_of_involved_sommet; i++)
635 {
636 int sommet = involved_sommet[i].sommet;
637 if (i >= 1)
638 {
639 assert(sommet != involved_sommet[i-1].sommet);
640 }
641
642 double decalage_x = (sommets(sommet, 0) - x)/dx;
643 double decalage_y = (sommets(sommet, 1) - y)/dy;
644 double decalage_z = (sommets(sommet, 2) - z)/dz;
645 double candidate_x = decalage_x + xfact;
646 double candidate_y = decalage_y + yfact;
647 double candidate_z = decalage_z + zfact;
648
649 candidates[number_of_candidates].dist = sqrt(decalage_x*decalage_x + decalage_y*decalage_y + decalage_z*decalage_z);
650 candidates[number_of_candidates].coord[0] = candidate_x;
651 candidates[number_of_candidates].coord[1] = candidate_y;
652 candidates[number_of_candidates].coord[2] = candidate_z;
653 candidates[number_of_candidates].value = involved_sommet[i].value;
654 number_of_candidates += 1;
655 }
656
657 assert(number_of_candidates <= max_number_of_candidates);
658 std::sort(candidates, candidates + number_of_candidates, [&](const Candidate_with_direct_value& c1, const Candidate_with_direct_value& c2)
659 {
660 return (c1.dist < c2.dist);
661 });
662
663 // On boucle d'abord sur n_neighbours, le nombre de points que l'on s'autorise a chercher
664 // dans la liste des voisins. Par exemple, n_neighbours=6 veut dire que l'on cherche a former
665 // des tetraedres a partir des 6 premiers voisins.
666 const bool limit_count = false;
667 const bool force_use_fist_neighbour = true; // Force l'utilisation du voisin le plus proche. Avantage : garanti de rester proche de ce point si le premier voisin est tres proche.
668 const int max_count = 100;
669 int count = 0;
670 int closest_tetrahedron[4] = {-1,-1,-1,-1};
671 double closest_lambda_error = DMAXFLOAT;
672 for (int n_neighbours = 4; (n_neighbours < number_of_candidates && ((!limit_count) || count < max_count)); n_neighbours++)
673 {
674 int index_vertex0 = n_neighbours; // Le premier point est toujours fixe au dernier possible. Cela garanti que tous les tetraedres d'un nouveau n_neighbours sont nouveaux.
675
676 for (int index_vertex1 = 0; (index_vertex1 < (force_use_fist_neighbour ? 1 : index_vertex0-2) && ((!limit_count) || count < max_count)); index_vertex1++)
677 {
678 for (int index_vertex2 = index_vertex1+1; (index_vertex2 < index_vertex0-1 && ((!limit_count) || count < max_count)); index_vertex2++)
679 {
680 for (int index_vertex3 = index_vertex2+1; (index_vertex3 < index_vertex0 && ((!limit_count) || count < max_count)); index_vertex3++)
681 {
682 Vecteur3 lambda_vec = compute_lambda(index_vertex0, index_vertex1, index_vertex2, index_vertex3, candidates, xfact, yfact, zfact);
683 double lambda_1 = lambda_vec[0];
684 double lambda_2 = lambda_vec[1];
685 double lambda_3 = lambda_vec[2];
686
687 double lambda_0 = 1 - lambda_1 - lambda_2 - lambda_3;
688
689 int lambda_0_within_bounds = ((lambda_0 >= 0) && (lambda_0 <= 1));
690 int lambda_1_within_bounds = ((lambda_1 >= 0) && (lambda_1 <= 1));
691 int lambda_2_within_bounds = ((lambda_2 >= 0) && (lambda_2 <= 1));
692 int lambda_3_within_bounds = ((lambda_3 >= 0) && (lambda_3 <= 1));
693
694 int point_within_tetrahedron = lambda_0_within_bounds && lambda_1_within_bounds && lambda_2_within_bounds && lambda_3_within_bounds;
695
696 count++;
697 if (point_within_tetrahedron)
698 {
699 double field_0 = candidates[index_vertex0].value;
700 double field_1 = candidates[index_vertex1].value;
701 double field_2 = candidates[index_vertex2].value;
702 double field_3 = candidates[index_vertex3].value;
703 assert(field_0 != 0); // Suggests a bug, but not necessarily implies so
704 assert(field_1 != 0); // .
705 assert(field_2 != 0); // .
706 assert(field_3 != 0); // .
707
708 double r = field_0*lambda_0 + field_1*lambda_1 + field_2*lambda_2 + field_3*lambda_3;
709
710 status = count;
711 return r;
712 }
713 else
714 {
715 double lambda_error_0 = std::max((lambda_0 < 0)*(-lambda_0), (lambda_0 > 1)*(lambda_0 - 1));
716 double lambda_error_1 = std::max((lambda_1 < 0)*(-lambda_1), (lambda_1 > 1)*(lambda_1 - 1));
717 double lambda_error_2 = std::max((lambda_2 < 0)*(-lambda_2), (lambda_2 > 1)*(lambda_2 - 1));
718 double lambda_error_3 = std::max((lambda_3 < 0)*(-lambda_3), (lambda_3 > 1)*(lambda_3 - 1));
719
720 double lambda_error = std::max(lambda_error_0, std::max(lambda_error_1, std::max(lambda_error_2, lambda_error_3)));
721 assert(lambda_error > 0);
722
723 if (closest_lambda_error > lambda_error)
724 {
725 closest_tetrahedron[0] = index_vertex0;
726 closest_tetrahedron[1] = index_vertex1;
727 closest_tetrahedron[2] = index_vertex2;
728 closest_tetrahedron[3] = index_vertex3;
729 closest_lambda_error = lambda_error;
730 }
731 }
732 }
733 }
734 }
735 }
736
737 // Utilise le tetrahedre le plus proche selon les parametres de tolerance
738 if ((tolerate_not_within_tetrahedron == 2) || (tolerate_not_within_tetrahedron == 1 && closest_lambda_error < 5e-2))
739 {
740 Vecteur3 lambda_vec = compute_lambda(closest_tetrahedron[0], closest_tetrahedron[1], closest_tetrahedron[2], closest_tetrahedron[3], candidates, xfact, yfact, zfact);
741 double lambda_1 = lambda_vec[0];
742 double lambda_2 = lambda_vec[1];
743 double lambda_3 = lambda_vec[2];
744
745 double lambda_0 = 1 - lambda_1 - lambda_2 - lambda_3;
746
747 assert(!(((lambda_0 >= 0) && (lambda_0 <= 1)) && ((lambda_1 >= 0) && (lambda_1 <= 1)) && ((lambda_2 >= 0) && (lambda_2 <= 1)) && ((lambda_3 >= 0) && (lambda_3 <= 1))));
748
749 double field_0 = candidates[closest_tetrahedron[0]].value;
750 double field_1 = candidates[closest_tetrahedron[1]].value;
751 double field_2 = candidates[closest_tetrahedron[2]].value;
752 double field_3 = candidates[closest_tetrahedron[3]].value;
753
754 double r = field_0*lambda_0 + field_1*lambda_1 + field_2*lambda_2 + field_3*lambda_3;
755
756 status = -1;
757 return r;
758 }
759 else
760 {
761 Cerr << "Value of close_to_edge: " << (int)close_to_edge << finl;
762 Cerr << "Error in ijk_interpolate_cut_cell_using_interface_for_given_index: no tetrahedron containing the point " << x << " " << y << " " << z << " on processor " << Process::me() << finl;
763 Cerr << "For information, closest_lambda_error=" << closest_lambda_error << finl;
764 // Note: While maybe not most likely, I noticed this error could occur if
765 // * the number of cells per particle diameter is too small <=3
766 // * ijk_splitting_ft_extension is not large enough
768 return -1;
769 }
770}
771
772// Interpolate the "field" at the requested "coordinates" (array with 3 columns), and stores into "result"
773static void ijk_interpolate_cut_cell_implementation(bool next_time, int phase, const Cut_field_double& field, const DoubleTab& coordinates, ArrOfDouble& result, int skip_unknown_points, double value_for_bad_points)
774{
775 const int nb_coords = coordinates.dimension(0);
776 result.resize_array(nb_coords);
777 for (int idx = 0; idx < nb_coords; idx++)
778 {
779 Vecteur3 coordinates_for_given_index(coordinates(idx,0), coordinates(idx,1), coordinates(idx,2));
780 int tolerate_not_within_tetrahedron = 1;
781 int status = -2;
782 IndexCoefficient tetrahedra_index_coefficient[4];
783 ijk_interpolate_cut_cell_for_given_index(next_time, phase, field.get_cut_cell_disc(), coordinates_for_given_index, tetrahedra_index_coefficient, tolerate_not_within_tetrahedron, skip_unknown_points, value_for_bad_points, status);
784
785 double field_0 = field.from_signed_independent_index(tetrahedra_index_coefficient[0].index);
786 double field_1 = field.from_signed_independent_index(tetrahedra_index_coefficient[1].index);
787 double field_2 = field.from_signed_independent_index(tetrahedra_index_coefficient[2].index);
788 double field_3 = field.from_signed_independent_index(tetrahedra_index_coefficient[3].index);
789
790 double interpolated_value = field_0*tetrahedra_index_coefficient[0].coefficient + field_1*tetrahedra_index_coefficient[1].coefficient + field_2*tetrahedra_index_coefficient[2].coefficient + field_3*tetrahedra_index_coefficient[3].coefficient;
791 result[idx] = interpolated_value;
792 }
793}
794
795static void ijk_interpolate_cut_cell_implementation(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const DoubleTab& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient, int skip_unknown_points, double value_for_bad_points)
796{
797 const int nb_coords = coordinates.dimension(0);
798 signed_independent_index.resize(nb_coords, 4);
799 coefficient.resize(nb_coords, 4);
800 for (int idx = 0; idx < nb_coords; idx++)
801 {
802 Vecteur3 coordinates_for_given_index(coordinates(idx,0), coordinates(idx,1), coordinates(idx,2));
803 int tolerate_not_within_tetrahedron = 1;
804 int status = -2;
805 IndexCoefficient tetrahedra_index_coefficient[4];
806 ijk_interpolate_cut_cell_for_given_index(next_time, phase, cut_cell_disc, coordinates_for_given_index, tetrahedra_index_coefficient, tolerate_not_within_tetrahedron, skip_unknown_points, value_for_bad_points, status);
807
808 signed_independent_index(idx,0) = tetrahedra_index_coefficient[0].index;
809 signed_independent_index(idx,1) = tetrahedra_index_coefficient[1].index;
810 signed_independent_index(idx,2) = tetrahedra_index_coefficient[2].index;
811 signed_independent_index(idx,3) = tetrahedra_index_coefficient[3].index;
812 coefficient(idx,0) = tetrahedra_index_coefficient[0].coefficient;
813 coefficient(idx,1) = tetrahedra_index_coefficient[1].coefficient;
814 coefficient(idx,2) = tetrahedra_index_coefficient[2].coefficient;
815 coefficient(idx,3) = tetrahedra_index_coefficient[3].coefficient;
816 }
817}
818
819void ijk_interpolate_cut_cell_skip_unknown_points(bool next_time, int phase, const Cut_field_double& field, const DoubleTab& coordinates, ArrOfDouble& result, const double value_for_bad_points)
820{
821 ijk_interpolate_cut_cell_implementation(next_time, phase, field, coordinates, result, 1 /* yes:skip unknown points */, value_for_bad_points);
822}
823
824void ijk_interpolate_cut_cell(bool next_time, int phase, const Cut_field_double& field, const DoubleTab& coordinates, ArrOfDouble& result)
825{
826 ijk_interpolate_cut_cell_implementation(next_time, phase, field, coordinates, result, 0 /* skip unknown points=no */, 0.);
827}
828
829void ijk_interpolate_cut_cell_skip_unknown_points(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const DoubleTab& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient, const double value_for_bad_points)
830{
831 ijk_interpolate_cut_cell_implementation(next_time, phase, cut_cell_disc, coordinates, signed_independent_index, coefficient, 1 /* yes:skip unknown points */, value_for_bad_points);
832}
833
834void ijk_interpolate_cut_cell(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const DoubleTab& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient)
835{
836 ijk_interpolate_cut_cell_implementation(next_time, phase, cut_cell_disc, coordinates, signed_independent_index, coefficient, 0 /* skip unknown points=no */, 0.);
837}
838
839double ijk_interpolate_cut_cell_using_interface_skip_unknown_points(bool next_time, int phase, const IJK_Field_double& field_ft, const Cut_field_double& field, const ArrOfDouble& interfacial_temperature, const Vecteur3& coordinates, int tolerate_not_within_tetrahedron, const double value_for_bad_points, int& status)
840{
841 double interpolated_value = ijk_interpolate_cut_cell_using_interface_for_given_index(next_time, phase, field_ft, field, interfacial_temperature, coordinates, tolerate_not_within_tetrahedron, 1, value_for_bad_points, status);
842 return interpolated_value;
843}
844
845double ijk_interpolate_cut_cell_using_interface(bool next_time, int phase, const IJK_Field_double& field_ft, const Cut_field_double& field, const ArrOfDouble& interfacial_temperature, const Vecteur3& coordinates, int tolerate_not_within_tetrahedron, int& status)
846{
847 double interpolated_value = ijk_interpolate_cut_cell_using_interface_for_given_index(next_time, phase, field_ft, field, interfacial_temperature, coordinates, tolerate_not_within_tetrahedron, 0, 0., status);
848 return interpolated_value;
849}
850
851// Returns the indices and coefficients to interpolate the "field" at the requested coordinate
852static void ijk_interpolate_one_value(bool next_time, const Cut_cell_FT_Disc& cut_cell_disc, const Vecteur3& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient, int skip_unknown_points, double value_for_bad_points)
853{
854 const int ghost = cut_cell_disc.get_ghost_size();
855 const Domaine_IJK& geom = cut_cell_disc.get_domaine();
856 const int ni = geom.get_nb_items_local(Domaine_IJK::ELEM, 0);
857 const int nj = geom.get_nb_items_local(Domaine_IJK::ELEM, 1);
858 const int nk = geom.get_nb_items_local(Domaine_IJK::ELEM, 2);
859
860 const double dx = geom.get_constant_delta(DIRECTION_I);
861 const double dy = geom.get_constant_delta(DIRECTION_J);
862 const double dz = geom.get_constant_delta(DIRECTION_K);
863 // L'origine est sur un noeud. Donc que la premiere face en I est sur get_origin(DIRECTION_I)
864 double origin_x = geom.get_origin(DIRECTION_I);
865 double origin_y = geom.get_origin(DIRECTION_J);
866 double origin_z = geom.get_origin(DIRECTION_K);
867 const double x = coordinates[0];
868 const double y = coordinates[1];
869 const double z = coordinates[2];
870 const double x2 = (x - origin_x) / dx;
871 const double y2 = (y - origin_y) / dy;
872 const double z2 = (z - origin_z) / dz;
873 const int index_i = (int) (floor(x2)) - geom.get_offset_local(DIRECTION_I);
874 const int index_j = (int) (floor(y2)) - geom.get_offset_local(DIRECTION_J);
875 const int index_k = (int) (floor(z2)) - geom.get_offset_local(DIRECTION_K);
876 // Coordonnes barycentriques du points dans la cellule :
877 const double xfact = x2 - floor(x2);
878 const double yfact = y2 - floor(y2);
879 const double zfact = z2 - floor(z2);
880
881 // is point in the domain ? (ghost cells ok...)
882 bool ok = (index_i >= -ghost && index_i < ni + ghost - 1) && (index_j >= -ghost && index_j < nj + ghost - 1) && (index_k >= -ghost && index_k < nk + ghost - 1);
883 if (!ok)
884 {
885 if (skip_unknown_points)
886 {
887 }
888 else
889 {
890 // Error!
891 Cerr << "Error in ijk_interpolate_implementation: request interpolation of point " << x << " " << y << " " << z << " which is outside of the domain on processor " << Process::me()
892 << finl;
894 }
895 }
896
897 double indic_0 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i, index_j, index_k)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i, index_j, index_k));
898 double indic_1 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j, index_k)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j, index_k));
899 double indic_2 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i, index_j+1, index_k)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i, index_j+1, index_k));
900 double indic_3 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j+1, index_k)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j+1, index_k));
901 double indic_4 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i, index_j, index_k+1)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i, index_j, index_k+1));
902 double indic_5 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j, index_k+1)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j, index_k+1));
903 double indic_6 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i, index_j+1, index_k+1)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i, index_j+1, index_k+1));
904 double indic_7 = next_time ? (1 - cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j+1, index_k+1)) : (1 - cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j+1, index_k+1));
905 double indic_8 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i, index_j, index_k) : cut_cell_disc.get_interfaces().I_ft(index_i, index_j, index_k);
906 double indic_9 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j, index_k) : cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j, index_k);
907 double indic_10 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i, index_j+1, index_k) : cut_cell_disc.get_interfaces().I_ft(index_i, index_j+1, index_k);
908 double indic_11 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j+1, index_k) : cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j+1, index_k);
909 double indic_12 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i, index_j, index_k+1) : cut_cell_disc.get_interfaces().I_ft(index_i, index_j, index_k+1);
910 double indic_13 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j, index_k+1) : cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j, index_k+1);
911 double indic_14 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i, index_j+1, index_k+1) : cut_cell_disc.get_interfaces().I_ft(index_i, index_j+1, index_k+1);
912 double indic_15 = next_time ? cut_cell_disc.get_interfaces().In_ft(index_i+1, index_j+1, index_k+1) : cut_cell_disc.get_interfaces().I_ft(index_i+1, index_j+1, index_k+1);
913
914 int output_index = -1;
915
916 if (indic_0 != 0)
917 {
918 output_index += 1;
919 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i, index_j, index_k);
920 coefficient(output_index) = indic_0 * (1.-xfact) * (1.-yfact) * (1.-zfact);
921 }
922
923 if (indic_1 != 0)
924 {
925 output_index += 1;
926 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i+1, index_j, index_k);
927 coefficient(output_index) = indic_1 * (xfact) * (1.-yfact) * (1.-zfact);
928 }
929
930 if (indic_2 != 0)
931 {
932 output_index += 1;
933 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i, index_j+1, index_k);
934 coefficient(output_index) = indic_2 * (1.-xfact) * (yfact) * (1.-zfact);
935 }
936
937 if (indic_3 != 0)
938 {
939 output_index += 1;
940 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i+1, index_j+1, index_k);
941 coefficient(output_index) = indic_3 * (xfact) * (yfact) * (1.-zfact);
942 }
943
944 if (indic_4 != 0)
945 {
946 output_index += 1;
947 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i, index_j, index_k+1);
948 coefficient(output_index) = indic_4 * (1.-xfact) * (1.-yfact) * (zfact);
949 }
950
951 if (indic_5 != 0)
952 {
953 output_index += 1;
954 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i+1, index_j, index_k+1);
955 coefficient(output_index) = indic_5 * (xfact) * (1.-yfact) * (zfact);
956 }
957
958 if (indic_6 != 0)
959 {
960 output_index += 1;
961 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i, index_j+1, index_k+1);
962 coefficient(output_index) = indic_6 * (1.-xfact) * (yfact) * (zfact);
963 }
964
965 if (indic_7 != 0)
966 {
967 output_index += 1;
968 signed_independent_index(output_index) = geom.get_signed_independent_index(0, index_i+1, index_j+1, index_k+1);
969 coefficient(output_index) = indic_7 * (xfact) * (yfact) * (zfact);
970 }
971
972 if (indic_8 != 0)
973 {
974 output_index += 1;
975 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i, index_j, index_k);
976 coefficient(output_index) = indic_8 * (1.-xfact) * (1.-yfact) * (1.-zfact);
977 }
978
979 if (indic_9 != 0)
980 {
981 output_index += 1;
982 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i+1, index_j, index_k);
983 coefficient(output_index) = indic_9 * (xfact) * (1.-yfact) * (1.-zfact);
984 }
985
986 if (indic_10 != 0)
987 {
988 output_index += 1;
989 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i, index_j+1, index_k);
990 coefficient(output_index) = indic_10 * (1.-xfact) * (yfact) * (1.-zfact);
991 }
992
993 if (indic_11 != 0)
994 {
995 output_index += 1;
996 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i+1, index_j+1, index_k);
997 coefficient(output_index) = indic_11 * (xfact) * (yfact) * (1.-zfact);
998 }
999
1000 if (indic_12 != 0)
1001 {
1002 output_index += 1;
1003 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i, index_j, index_k+1);
1004 coefficient(output_index) = indic_12 * (1.-xfact) * (1.-yfact) * (zfact);
1005 }
1006
1007 if (indic_13 != 0)
1008 {
1009 output_index += 1;
1010 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i+1, index_j, index_k+1);
1011 coefficient(output_index) = indic_13 * (xfact) * (1.-yfact) * (zfact);
1012 }
1013
1014 if (indic_14 != 0)
1015 {
1016 output_index += 1;
1017 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i, index_j+1, index_k+1);
1018 coefficient(output_index) = indic_14 * (1.-xfact) * (yfact) * (zfact);
1019 }
1020
1021 if (indic_15 != 0)
1022 {
1023 output_index += 1;
1024 signed_independent_index(output_index) = geom.get_signed_independent_index(1, index_i+1, index_j+1, index_k+1);
1025 coefficient(output_index) = indic_15 * (xfact) * (yfact) * (zfact);
1026 }
1027
1028 signed_independent_index.resize(output_index+1);
1029 coefficient.resize(output_index+1);
1030}
1031
1032void ijk_interpolate_skip_unknown_points(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const Vecteur3& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient, const double value_for_bad_points)
1033{
1034 signed_independent_index.resize(16);
1035 coefficient.resize(16);
1036 ijk_interpolate_one_value(next_time, cut_cell_disc, coordinates, signed_independent_index, coefficient, 1 /* yes:skip unknown points */, value_for_bad_points);
1037}
1038
1039void ijk_interpolate(bool next_time, int phase, const Cut_cell_FT_Disc& cut_cell_disc, const Vecteur3& coordinates, IntTabFT& signed_independent_index, DoubleTabFT& coefficient)
1040{
1041 signed_independent_index.resize(16);
1042 coefficient.resize(16);
1043 ijk_interpolate_one_value(next_time, cut_cell_disc, coordinates, signed_independent_index, coefficient, 0 /* skip unknown points=no */, 0.);
1044}
1045
1046void euler_explicit_update_cut_cell_notransport(double timestep, bool next_time, const Cut_field_double& dv, Cut_field_double& v)
1047{
1048 const Cut_cell_FT_Disc& cut_cell_disc = v.get_cut_cell_disc();
1049 const double delta_t = timestep;
1050 const int imax = v.ni();
1051 const int jmax = v.nj();
1052 const int kmax = v.nk();
1053 for (int k = 0; k < kmax; k++)
1054 {
1055 for (int j = 0; j < jmax; j++)
1056 {
1057 for (int i = 0; i < imax; i++)
1058 {
1059 double nonzero_indicatrice_l = next_time ? cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1060 double nonzero_indicatrice_v = next_time ? cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1061
1062 int n = cut_cell_disc.get_n(i,j,k);
1063 if (n < 0)
1064 {
1065 double x = dv.pure_(i,j,k);
1066 double next_v_vol = v.pure_(i,j,k) + x * delta_t;
1067 v.pure_(i,j,k) = next_v_vol;
1068 }
1069 else
1070 {
1071 double x_l = dv.diph_l_(n);
1072 double x_v = dv.diph_v_(n);
1073
1074 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * delta_t;
1075 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * delta_t;
1076 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1077 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1078 }
1079 }
1080 }
1081 }
1082}
1083
1084void runge_kutta3_update_cut_cell_notransport(bool next_time, const Cut_field_double& dv, Cut_field_double& F, Cut_field_double& v, const int step, double dt_tot, const Cut_field_int& cellule_rk_restreint)
1085{
1086 const double coeff_a[3] = { 0., -5. / 9., -153. / 128. };
1087 // Fk[0] = 1; Fk[i+1] = Fk[i] * a[i+1] + 1
1088 const double coeff_Fk[3] = { 1., 4. / 9., 15. / 32. };
1089
1090 const double facteurF = coeff_a[step];
1091 const double intermediate_dt = compute_fractionnal_timestep_rk3(dt_tot, step);
1092 const double delta_t_divided_by_Fk = intermediate_dt / coeff_Fk[step];
1093 const int imax = v.ni();
1094 const int jmax = v.nj();
1095 const int kmax = v.nk();
1096 const Cut_cell_FT_Disc& cut_cell_disc = v.get_cut_cell_disc();
1097 switch(step)
1098 {
1099 case 0:
1100 // don't read initial value of F (no performance benefit because write to F causes the
1101 // processor to fetch the cache line, but we don't wand to use a potentially uninitialized value
1102 for (int k = 0; k < kmax; k++)
1103 {
1104 for (int j = 0; j < jmax; j++)
1105 {
1106 for (int i = 0; i < imax; i++)
1107 {
1108 double nonzero_indicatrice_l = next_time ? cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1109 double nonzero_indicatrice_v = next_time ? cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1110
1111 int n = cut_cell_disc.get_n(i,j,k);
1112 if (n < 0)
1113 {
1114 double x = dv.pure_(i,j,k);
1115 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1116 F.pure_(i,j,k) = x;
1117 v.pure_(i,j,k) = next_v_vol;
1118 }
1119 else
1120 {
1121 double x_l = dv.diph_l_(n);
1122 double x_v = dv.diph_v_(n);
1123
1124 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1125 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1126 F.diph_l_(n) = x_l;
1127 F.diph_v_(n) = x_v;
1128 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1129 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1130 }
1131 }
1132 }
1133 }
1134 break;
1135 case 1:
1136 // general case, read and write F
1137 for (int k = 0; k < kmax; k++)
1138 {
1139 for (int j = 0; j < jmax; j++)
1140 {
1141 for (int i = 0; i < imax; i++)
1142 {
1143 double nonzero_indicatrice_l = next_time ? cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1144 double nonzero_indicatrice_v = next_time ? cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1145
1146 int n = cut_cell_disc.get_n(i,j,k);
1147 if (n < 0)
1148 {
1149 if (cellule_rk_restreint.pure_(i,j,k) == 0)
1150 {
1151 double x = F.pure_(i, j, k) * facteurF + dv.pure_(i,j,k);
1152 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1153 F.pure_(i,j,k) = x;
1154 v.pure_(i,j,k) = next_v_vol;
1155 }
1156 else
1157 {
1158 double x = dv.pure_(i,j,k);
1159 double next_v_vol = v.pure_(i,j,k) + x * intermediate_dt;
1160 F.pure_(i,j,k) = x;
1161 v.pure_(i,j,k) = next_v_vol;
1162 }
1163 }
1164 else
1165 {
1166 if (cellule_rk_restreint.diph_v_(n) == 0)
1167 {
1168 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1169
1170 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1171 F.diph_v_(n) = x_v;
1172 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1173 }
1174 else
1175 {
1176 double x_v = dv.diph_v_(n);
1177
1178 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * intermediate_dt;
1179 F.diph_v_(n) = x_v;
1180 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1181 }
1182
1183 if (cellule_rk_restreint.diph_l_(n) == 0)
1184 {
1185 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1186
1187 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1188 F.diph_l_(n) = x_l;
1189 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1190 }
1191 else
1192 {
1193 double x_l = dv.diph_l_(n);
1194
1195 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * intermediate_dt;
1196 F.diph_l_(n) = x_l;
1197 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1198 }
1199 }
1200 }
1201 }
1202 }
1203 break;
1204 case 2:
1205 // do not write F
1206 for (int k = 0; k < kmax; k++)
1207 {
1208 for (int j = 0; j < jmax; j++)
1209 {
1210 for (int i = 0; i < imax; i++)
1211 {
1212 double nonzero_indicatrice_l = next_time ? cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1213 double nonzero_indicatrice_v = next_time ? cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k) : cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1214
1215 int n = cut_cell_disc.get_n(i,j,k);
1216 if (n < 0)
1217 {
1218 if (cellule_rk_restreint.pure_(i,j,k) == 0)
1219 {
1220 double x = F.pure_(i, j, k) * facteurF + dv.pure_(i,j,k);
1221 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1222 v.pure_(i,j,k) = next_v_vol;
1223 }
1224 else
1225 {
1226 double x = dv.pure_(i,j,k);
1227 double next_v_vol = v.pure_(i,j,k) + x * intermediate_dt;
1228 v.pure_(i,j,k) = next_v_vol;
1229 }
1230 }
1231 else
1232 {
1233 if (cellule_rk_restreint.diph_v_(n) == 0)
1234 {
1235 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1236
1237 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1238 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1239 }
1240 else
1241 {
1242 double x_v = dv.diph_v_(n);
1243
1244 double next_v_vol_v = v.diph_v_(n)*nonzero_indicatrice_v + x_v * intermediate_dt;
1245 v.diph_v_(n) = next_v_vol_v/nonzero_indicatrice_v;
1246 }
1247
1248 if (cellule_rk_restreint.diph_l_(n) == 0)
1249 {
1250 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1251
1252 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1253 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1254 }
1255 else
1256 {
1257 double x_l = dv.diph_l_(n);
1258
1259 double next_v_vol_l = v.diph_l_(n)*nonzero_indicatrice_l + x_l * intermediate_dt;
1260 v.diph_l_(n) = next_v_vol_l/nonzero_indicatrice_l;
1261 }
1262 }
1263 }
1264 }
1265 }
1266 break;
1267 default:
1268 Cerr << "Error in runge_kutta_update: wrong step" << finl;
1269 Process::exit();
1270 };
1271}
1272
1273void euler_explicit_update_cut_cell_transport(double timestep, const Cut_field_double& dv, Cut_field_double& v)
1274{
1275 const Cut_cell_FT_Disc& cut_cell_disc = v.get_cut_cell_disc();
1276 const double delta_t = timestep;
1277 const int imax = v.ni();
1278 const int jmax = v.nj();
1279 const int kmax = v.nk();
1280 for (int k = 0; k < kmax; k++)
1281 {
1282 for (int j = 0; j < jmax; j++)
1283 {
1284 for (int i = 0; i < imax; i++)
1285 {
1286 double old_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1287 double next_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k);
1288 double old_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1289 double next_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k);
1290
1291 int n = cut_cell_disc.get_n(i,j,k);
1292 if (n < 0)
1293 {
1294 double x = dv.pure_(i,j,k);
1295 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1296 double next_v_vol = v.pure_(i,j,k) + x * delta_t;
1297 v.pure_(i,j,k) = next_v_vol;
1298 }
1299 else
1300 {
1301 double x_l = dv.diph_l_(n);
1302 double x_v = dv.diph_v_(n);
1303
1304 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * delta_t;
1305 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * delta_t;
1306 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1307 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1308 }
1309 }
1310 }
1311 }
1312}
1313
1314void runge_kutta3_update_cut_cell_transport(const Cut_field_double& dv, Cut_field_double& F, Cut_field_double& v, const int step, double dt_tot, const Cut_field_int& cellule_rk_restreint)
1315{
1316 const double coeff_a[3] = { 0., -5. / 9., -153. / 128. };
1317 // Fk[0] = 1; Fk[i+1] = Fk[i] * a[i+1] + 1
1318 const double coeff_Fk[3] = { 1., 4. / 9., 15. / 32. };
1319
1320 const double facteurF = coeff_a[step];
1321 const double intermediate_dt = compute_fractionnal_timestep_rk3(dt_tot, step);
1322 const double delta_t_divided_by_Fk = intermediate_dt / coeff_Fk[step];
1323 const int imax = v.ni();
1324 const int jmax = v.nj();
1325 const int kmax = v.nk();
1326 const Cut_cell_FT_Disc& cut_cell_disc = v.get_cut_cell_disc();
1327 switch(step)
1328 {
1329 case 0:
1330 // don't read initial value of F (no performance benefit because write to F causes the
1331 // processor to fetch the cache line, but we don't wand to use a potentially uninitialized value
1332 for (int k = 0; k < kmax; k++)
1333 {
1334 for (int j = 0; j < jmax; j++)
1335 {
1336 for (int i = 0; i < imax; i++)
1337 {
1338 double old_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1339 double next_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k);
1340 double old_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1341 double next_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k);
1342
1343 int n = cut_cell_disc.get_n(i,j,k);
1344 if (n < 0)
1345 {
1346 double x = dv.pure_(i,j,k);
1347 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1348 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1349 F.pure_(i,j,k) = x;
1350 v.pure_(i,j,k) = next_v_vol;
1351 }
1352 else
1353 {
1354 double x_l = dv.diph_l_(n);
1355 double x_v = dv.diph_v_(n);
1356
1357 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1358 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1359 F.diph_l_(n) = x_l;
1360 F.diph_v_(n) = x_v;
1361
1362 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1363 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1364 }
1365 }
1366 }
1367 }
1368 break;
1369 case 1:
1370 // general case, read and write F
1371 for (int k = 0; k < kmax; k++)
1372 {
1373 for (int j = 0; j < jmax; j++)
1374 {
1375 for (int i = 0; i < imax; i++)
1376 {
1377 double old_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1378 double next_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k);
1379 double old_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1380 double next_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k);
1381
1382 int n = cut_cell_disc.get_n(i,j,k);
1383 if (n < 0)
1384 {
1385 if (cellule_rk_restreint.pure_(i,j,k) == 0)
1386 {
1387 double x = F.pure_(i, j, k) * facteurF + dv.pure_(i,j,k);
1388 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1389 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1390 F.pure_(i,j,k) = x;
1391 v.pure_(i,j,k) = next_v_vol;
1392 }
1393 else
1394 {
1395 double x = dv.pure_(i,j,k);
1396 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1397 double next_v_vol = v.pure_(i,j,k) + x * intermediate_dt;
1398 F.pure_(i,j,k) = x;
1399 v.pure_(i,j,k) = next_v_vol;
1400 }
1401 }
1402 else
1403 {
1404 if (cellule_rk_restreint.diph_v_(n) == 0)
1405 {
1406 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1407
1408 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1409 F.diph_v_(n) = x_v;
1410
1411 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1412 }
1413 else
1414 {
1415 double x_v = dv.diph_v_(n);
1416
1417 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * intermediate_dt;
1418 F.diph_v_(n) = x_v;
1419
1420 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1421 }
1422
1423 if (cellule_rk_restreint.diph_l_(n) == 0)
1424 {
1425 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1426
1427 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1428 F.diph_l_(n) = x_l;
1429
1430 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1431 }
1432 else
1433 {
1434 double x_l = dv.diph_l_(n);
1435
1436 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * intermediate_dt;
1437 F.diph_l_(n) = x_l;
1438
1439 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1440 }
1441 }
1442 }
1443 }
1444 }
1445 break;
1446 case 2:
1447 // do not write F
1448 for (int k = 0; k < kmax; k++)
1449 {
1450 for (int j = 0; j < jmax; j++)
1451 {
1452 for (int i = 0; i < imax; i++)
1453 {
1454 double old_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1455 double next_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k);
1456 double old_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1457 double next_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k);
1458
1459 int n = cut_cell_disc.get_n(i,j,k);
1460 if (n < 0)
1461 {
1462 if (cellule_rk_restreint.pure_(i,j,k) == 0)
1463 {
1464 double x = F.pure_(i, j, k) * facteurF + dv.pure_(i,j,k);
1465 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1466 double next_v_vol = v.pure_(i,j,k) + x * delta_t_divided_by_Fk;
1467 v.pure_(i,j,k) = next_v_vol;
1468 }
1469 else
1470 {
1471 double x = dv.pure_(i,j,k);
1472 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1473 double next_v_vol = v.pure_(i,j,k) + x * intermediate_dt;
1474 v.pure_(i,j,k) = next_v_vol;
1475 }
1476 }
1477 else
1478 {
1479 if (cellule_rk_restreint.diph_v_(n) == 0)
1480 {
1481 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1482
1483 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * delta_t_divided_by_Fk;
1484
1485 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1486 }
1487 else
1488 {
1489 double x_v = dv.diph_v_(n);
1490
1491 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v + x_v * intermediate_dt;
1492
1493 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1494 }
1495
1496 if (cellule_rk_restreint.diph_l_(n) == 0)
1497 {
1498 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1499
1500 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * delta_t_divided_by_Fk;
1501
1502 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1503 }
1504 else
1505 {
1506 double x_l = dv.diph_l_(n);
1507
1508 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l + x_l * intermediate_dt;
1509
1510 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1511 }
1512 }
1513 }
1514 }
1515 }
1516 break;
1517 default:
1518 Cerr << "Error in runge_kutta_update: wrong step" << finl;
1519 Process::exit();
1520 };
1521}
1522
1523void cut_cell_switch_field_time(Cut_field_double& v)
1524{
1525 const Cut_cell_FT_Disc& cut_cell_disc = v.get_cut_cell_disc();
1526 const int imax = v.ni();
1527 const int jmax = v.nj();
1528 const int kmax = v.nk();
1529 for (int k = 0; k < kmax; k++)
1530 {
1531 for (int j = 0; j < jmax; j++)
1532 {
1533 for (int i = 0; i < imax; i++)
1534 {
1535 double old_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().I_nonzero(1,i,j,k);
1536 double next_nonzero_indicatrice_l = cut_cell_disc.get_interfaces().In_nonzero(1,i,j,k);
1537 double old_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().I_nonzero(0,i,j,k);
1538 double next_nonzero_indicatrice_v = cut_cell_disc.get_interfaces().In_nonzero(0,i,j,k);
1539
1540 int n = cut_cell_disc.get_n(i,j,k);
1541 if (n < 0)
1542 {
1543 assert(old_nonzero_indicatrice_l == next_nonzero_indicatrice_l);
1544 double next_v_vol = v.pure_(i,j,k);
1545 v.pure_(i,j,k) = next_v_vol;
1546 }
1547 else
1548 {
1549 double next_v_vol_l = v.diph_l_(n)*old_nonzero_indicatrice_l;
1550 double next_v_vol_v = v.diph_v_(n)*old_nonzero_indicatrice_v;
1551
1552 v.diph_l_(n) = next_v_vol_l/next_nonzero_indicatrice_l;
1553 v.diph_v_(n) = next_v_vol_v/next_nonzero_indicatrice_v;
1554 }
1555 }
1556 }
1557 }
1558}
1559
1560void runge_kutta3_update_surfacic_fluxes(Cut_field_double& dv, Cut_field_double& F, const int step, const int k_layer, const int dir, double dt_tot, const Cut_field_int& cellule_rk_restreint)
1561{
1562 const double coeff_a[3] = { 0., -5. / 9., -153. / 128. };
1563 // Fk[0] = 1; Fk[i+1] = Fk[i] * a[i+1] + 1
1564 const double coeff_Fk[3] = { 1., 4. / 9., 15. / 32. };
1565
1566 int di = (dir == 0) ? -1 : 0;
1567 int dj = (dir == 1) ? -1 : 0;
1568 int dk = (dir == 2) ? -1 : 0;
1569
1570 const double facteurF = coeff_a[step];
1571 const double one_divided_by_Fk = 1. / coeff_Fk[step];
1572 const int imax = dv.ni();
1573 const int jmax = dv.nj();
1574 const int ghost = dv.ghost();
1575 const Cut_cell_FT_Disc& cut_cell_disc = dv.get_cut_cell_disc();
1576 switch(step)
1577 {
1578 case 0:
1579 // don't read initial value of F (no performance benefit because write to F causes the
1580 // processor to fetch the cache line, but we don't wand to use a potentially uninitialized value
1581 for (int j = -ghost; j < jmax+ghost; j++)
1582 {
1583 for (int i = -ghost; i < imax+ghost; i++)
1584 {
1585 int n = cut_cell_disc.get_n(i,j,k_layer);
1586 if (n < 0)
1587 {
1588 double x = dv.pure_(i,j,k_layer);
1589 dv.pure_(i,j,k_layer) = x * one_divided_by_Fk;
1590 F.pure_(i,j,k_layer) = x;
1591 }
1592 else
1593 {
1594 double x_l = dv.diph_l_(n);
1595 double x_v = dv.diph_v_(n);
1596
1597 dv.diph_l_(n) = x_l * one_divided_by_Fk;
1598 dv.diph_v_(n) = x_v * one_divided_by_Fk;
1599 F.diph_l_(n) = x_l;
1600 F.diph_v_(n) = x_v;
1601
1602 int n_decale = cut_cell_disc.get_n(i+di,j+dj,k_layer+dk);
1603 if (n_decale < 0)
1604 {
1605 int phase = IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.indic_pure(i+di,j+dj,k_layer+dk));
1606 dv.pure_(i,j,k_layer) = (phase == 0) ? dv.diph_v_(n) : dv.diph_l_(n);
1607 F.pure_(i,j,k_layer) = (phase == 0) ? F.diph_v_(n) : F.diph_l_(n);
1608 }
1609 }
1610 }
1611 }
1612 break;
1613 case 1:
1614 // general case, read and write F
1615 for (int j = -ghost; j < jmax+ghost; j++)
1616 {
1617 for (int i = -ghost; i < imax+ghost; i++)
1618 {
1619 int n = cut_cell_disc.get_n(i,j,k_layer);
1620 if (n < 0)
1621 {
1622 int phase = IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.indic_pure(i,j,k_layer));
1623 if ((cellule_rk_restreint.pure_(i,j,k_layer) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,phase) == 0))
1624 {
1625 double x = F.pure_(i, j, k_layer) * facteurF + dv.pure_(i,j,k_layer);
1626 dv.pure_(i,j,k_layer) = x * one_divided_by_Fk;
1627 F.pure_(i,j,k_layer) = x;
1628 }
1629 else
1630 {
1631 double x = dv.pure_(i,j,k_layer);
1632 dv.pure_(i,j,k_layer) = x;
1633 F.pure_(i,j,k_layer) = x;
1634 }
1635 }
1636 else
1637 {
1638 if ((cellule_rk_restreint.diph_v_(n) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,0) == 0))
1639 {
1640 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1641
1642 dv.diph_v_(n) = x_v * one_divided_by_Fk;
1643 F.diph_v_(n) = x_v;
1644 }
1645 else
1646 {
1647 double x_v = dv.diph_v_(n);
1648
1649 dv.diph_v_(n) = x_v;
1650 F.diph_v_(n) = x_v;
1651 }
1652
1653 if ((cellule_rk_restreint.diph_l_(n) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,1) == 0))
1654 {
1655 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1656
1657 dv.diph_l_(n) = x_l * one_divided_by_Fk;
1658 F.diph_l_(n) = x_l;
1659 }
1660 else
1661 {
1662 double x_l = dv.diph_l_(n);
1663
1664 dv.diph_l_(n) = x_l;
1665 F.diph_l_(n) = x_l;
1666 }
1667
1668 int n_decale = cut_cell_disc.get_n(i+di,j+dj,k_layer+dk);
1669 if (n_decale < 0)
1670 {
1671 int phase = IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.indic_pure(i+di,j+dj,k_layer+dk));
1672 dv.pure_(i,j,k_layer) = (phase == 0) ? dv.diph_v_(n) : dv.diph_l_(n);
1673 F.pure_(i,j,k_layer) = (phase == 0) ? F.diph_v_(n) : F.diph_l_(n);
1674 }
1675 }
1676 }
1677 }
1678 break;
1679 case 2:
1680 // do not write F
1681 for (int j = -ghost; j < jmax+ghost; j++)
1682 {
1683 for (int i = -ghost; i < imax+ghost; i++)
1684 {
1685 int n = cut_cell_disc.get_n(i,j,k_layer);
1686 if (n < 0)
1687 {
1688 int phase = IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.indic_pure(i,j,k_layer));
1689 if ((cellule_rk_restreint.pure_(i,j,k_layer) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,phase) == 0))
1690 {
1691 double x = F.pure_(i, j, k_layer) * facteurF + dv.pure_(i,j,k_layer);
1692 dv.pure_(i,j,k_layer) = x * one_divided_by_Fk;
1693 }
1694 else
1695 {
1696 double x = dv.pure_(i,j,k_layer);
1697 dv.pure_(i,j,k_layer) = x;
1698 }
1699 }
1700 else
1701 {
1702 if ((cellule_rk_restreint.diph_v_(n) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,0) == 0))
1703 {
1704 double x_v = F.diph_v_(n) * facteurF + dv.diph_v_(n);
1705
1706 dv.diph_v_(n) = x_v * one_divided_by_Fk;
1707 }
1708 else
1709 {
1710 double x_v = dv.diph_v_(n);
1711
1712 dv.diph_v_(n) = x_v;
1713 }
1714
1715 if ((cellule_rk_restreint.diph_l_(n) == 0) && (cellule_rk_restreint.from_ijk_and_phase(i+di,j+dj,k_layer+dk,1) == 0))
1716 {
1717 double x_l = F.diph_l_(n) * facteurF + dv.diph_l_(n);
1718
1719 dv.diph_l_(n) = x_l * one_divided_by_Fk;
1720 }
1721 else
1722 {
1723 double x_l = dv.diph_l_(n);
1724
1725 dv.diph_l_(n) = x_l;
1726 }
1727
1728 int n_decale = cut_cell_disc.get_n(i+di,j+dj,k_layer+dk);
1729 if (n_decale < 0)
1730 {
1731 int phase = IJK_Interfaces::convert_indicatrice_to_phase(cut_cell_disc.indic_pure(i+di,j+dj,k_layer+dk));
1732 dv.pure_(i,j,k_layer) = (phase == 0) ? dv.diph_v_(n) : dv.diph_l_(n);
1733 F.pure_(i,j,k_layer) = (phase == 0) ? F.diph_v_(n) : F.diph_l_(n);
1734 }
1735 }
1736 }
1737 }
1738 break;
1739 default:
1740 Cerr << "Error in runge_kutta_update: wrong step" << finl;
1741 Process::exit();
1742 };
1743}
1744
1745// Cette fonction sert ajouter la pente liee a la correction a la pente liee au schema principal
1746// Le facteur vol_over_dt_surface existe car le flux calcule dans les routines de correction n'a
1747// pas la bonne unite.
1748void add_flux_times_vol_over_dt_surface(double fractional_timestep, const Cut_field_vector3_double& cut_field_current_fluxes, Cut_field_vector3_double& cut_field_RK3_F_fluxes)
1749{
1750 const Domaine_IJK& geom = cut_field_current_fluxes[0].get_cut_cell_disc().get_domaine();
1751 assert(cut_field_current_fluxes[0].get_cut_cell_disc().get_domaine().is_uniform(0));
1752 assert(cut_field_current_fluxes[0].get_cut_cell_disc().get_domaine().is_uniform(1));
1753 assert(cut_field_current_fluxes[0].get_cut_cell_disc().get_domaine().is_uniform(2));
1754 const double dx = geom.get_constant_delta(DIRECTION_I);
1755 const double dy = geom.get_constant_delta(DIRECTION_J);
1756 const double dz = geom.get_constant_delta(DIRECTION_K);
1757 double vol = dx*dy*dz;
1758
1759 for (int dir = 0; dir < 3; dir++)
1760 {
1761 const int ni = cut_field_current_fluxes[dir].ni();
1762 const int nj = cut_field_current_fluxes[dir].nj();
1763 const int nk = cut_field_current_fluxes[dir].nk();
1764 for (int k = 0; k < nk; k++)
1765 {
1766 for (int j = 0; j < nj; j++)
1767 {
1768 for (int i = 0; i < ni; i++)
1769 {
1770 double vol_over_dt = vol/fractional_timestep;
1771
1772 cut_field_RK3_F_fluxes[dir].pure_(i,j,k) += cut_field_current_fluxes[dir].pure_(i,j,k)*vol_over_dt;
1773 }
1774 }
1775 }
1776
1777 const Cut_cell_FT_Disc& cut_cell_disc = cut_field_current_fluxes[dir].get_cut_cell_disc();
1778 for (int n = 0; n < cut_cell_disc.get_n_tot(); n++)
1779 {
1780 double vol_over_dt = vol/fractional_timestep;
1781
1782 const DoubleTabFT_cut_cell_vector3& indicatrice_surfacique = cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face();
1783 double indicatrice_surface = indicatrice_surfacique(n,dir);
1784
1785 cut_field_RK3_F_fluxes[dir].diph_l_(n) += (indicatrice_surface == 0.) ? 0. : cut_field_current_fluxes[dir].diph_l_(n)*vol_over_dt/indicatrice_surface;
1786 cut_field_RK3_F_fluxes[dir].diph_v_(n) += ((1 - indicatrice_surface) == 0.) ? 0. : cut_field_current_fluxes[dir].diph_v_(n)*vol_over_dt/(1 - indicatrice_surface);
1787 }
1788 }
1789}
1790
1791void set_rk_restreint(int rk_step, int rk_restriction_leniency, const Cut_cell_FT_Disc& cut_cell_disc, Cut_field_int& cellule_rk_restreint)
1792{
1793 if (rk_step == 0)
1794 {
1795 cellule_rk_restreint.set_to_uniform_value(0.);
1796 }
1797
1798 if (rk_restriction_leniency == 10)
1799 {
1800 cellule_rk_restreint.set_to_uniform_value(1.);
1801 }
1802
1803 if (rk_restriction_leniency == 11)
1804 {
1805 for (int n = 0; n < cut_cell_disc.get_n_tot(); n++)
1806 {
1807 Int3 ijk = cut_cell_disc.get_ijk(n);
1808 int i = ijk[0];
1809 int j = ijk[1];
1810 int k = ijk[2];
1811
1812 cellule_rk_restreint.pure_(i,j,k) = 1;
1813 cellule_rk_restreint.diph_v_(n) = 1;
1814 cellule_rk_restreint.diph_l_(n) = 1;
1815 }
1816 }
1817
1818 // Boucle sur les cellules qui disparaissent lors de ce sous pas de temps
1819 {
1820 int statut_diphasique = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::MOURRANT);
1821 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique);
1822 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique+1);
1823 for (int index = index_min; index < index_max; index++)
1824 {
1825 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
1826
1827 Int3 ijk = cut_cell_disc.get_ijk(n);
1828 int i = ijk[0];
1829 int j = ijk[1];
1830 int k = ijk[2];
1831
1832 if ((rk_restriction_leniency == 4) || (rk_restriction_leniency == 5))
1833 continue;
1834
1835 if ((rk_restriction_leniency == 1) || (rk_restriction_leniency == 3))
1836 {
1837 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
1838 int phase = 1 - IJK_Interfaces::convert_indicatrice_to_phase(next_indicatrice); // phase de la cellule mourrante
1839
1840 if (phase == 0)
1841 {
1842 cellule_rk_restreint.diph_v_(n) = 1;
1843 }
1844 else
1845 {
1846 cellule_rk_restreint.diph_l_(n) = 1;
1847 }
1848 }
1849 else if ((rk_restriction_leniency == 0) || (rk_restriction_leniency == 2))
1850 {
1851 cellule_rk_restreint.diph_v_(n) = 1;
1852 cellule_rk_restreint.diph_l_(n) = 1;
1853 }
1854 }
1855 }
1856
1857 // Boucle sur les cellules qui apparaissent ou bien qui sont petites lors de ce sous pas de temps
1858 {
1859 int statut_diphasique_naissant = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::NAISSANT);
1860 int statut_diphasique_petit = static_cast<int>(Cut_cell_FT_Disc::STATUT_DIPHASIQUE::DESEQUILIBRE_FINAL);
1861 assert(statut_diphasique_petit == statut_diphasique_naissant + 1);
1862 int index_min = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_naissant);
1863 int index_max = cut_cell_disc.get_statut_diphasique_value_index(statut_diphasique_petit+1);
1864 for (int index = index_min; index < index_max; index++)
1865 {
1866 int n = cut_cell_disc.get_n_from_statut_diphasique_index(index);
1867
1868 Int3 ijk = cut_cell_disc.get_ijk(n);
1869 int i = ijk[0];
1870 int j = ijk[1];
1871 int k = ijk[2];
1872
1873 if (rk_step == 0 && ((rk_restriction_leniency == 5) || (rk_restriction_leniency == 4) || (rk_restriction_leniency == 3) || (rk_restriction_leniency == 2)))
1874 continue;
1875
1876 if ((rk_restriction_leniency == 1) || (rk_restriction_leniency == 3) || (rk_restriction_leniency == 5))
1877 {
1878 double old_indicatrice = cut_cell_disc.get_interfaces().I(i,j,k);
1879 double next_indicatrice = cut_cell_disc.get_interfaces().In(i,j,k);
1880 int est_naissant = cut_cell_disc.get_interfaces().est_pure(old_indicatrice);
1881 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
1882
1883 if (phase == 0)
1884 {
1885 cellule_rk_restreint.diph_v_(n) = 1;
1886 }
1887 else
1888 {
1889 cellule_rk_restreint.diph_l_(n) = 1;
1890 }
1891 }
1892 else if ((rk_restriction_leniency == 0) || (rk_restriction_leniency == 2) || (rk_restriction_leniency == 4))
1893 {
1894 cellule_rk_restreint.diph_v_(n) = 1;
1895 cellule_rk_restreint.diph_l_(n) = 1;
1896 }
1897 }
1898 }
1899}
1900
const Domaine_IJK & get_domaine() const
const IJK_Interfaces & get_interfaces() const
int get_ghost_size() const
Int3 get_ijk(int n) const
double indic_pure(const int i, const int j, const 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
_TYPE_ & from_ijk_and_phase(int i, int j, int k, bool phase)
_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
void set_to_uniform_value(_TYPE_ valeur)
TRUSTTabFT_cut_cell< _TYPE_ > diph_l_
Definition Cut_field.h:49
_TYPE_ & from_signed_independent_index(int signed_independent_index)
TRUSTTabFT_cut_cell< _TYPE_ > diph_v_
Definition Cut_field.h:50
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.
int get_nb_items_local(Localisation loc, int direction) const
Returns the number of local items (on this processor) for the given localisation in the requested dir...
double get_constant_delta(int direction) const
Returns the size of cells in a direction.
int get_i_along_dir_perio(int direction, double coord_dir, Localisation loc) const
double get_origin(int direction) const
Returns the coordinate of the first node (global) of the mesh in the requested direction.
int get_signed_independent_index(int phase, int i, int j, int k) const
int correct_perio_i_local(int direction, int i) const
int convert_ijk_cell_to_packed(const FixedVector< int, 3 > ijk) const
Converts the ijk index of an element to a cell index.
const Domaine_IJK & get_domaine() const
const Domaine_IJK & get_domaine() const
const DoubleTabFT_cut_cell_vector3 & get_indicatrice_surfacique_efficace_face() const
const IJK_Field_double & I_ft() const
const IJK_Field_double & I() const
double In_nonzero(const int phase, const int i, const int j, const int k) const
double I_nonzero(const int phase, const int i, const int j, const int k) const
const IJK_Field_double & In() const
const Maillage_FT_IJK & old_maillage_ft_ijk() const
const Maillage_FT_IJK & maillage_ft_ijk() 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
const IJK_Field_double & In_ft() const
static int convert_indicatrice_to_phase(double indicatrice)
: class Intersections_Elem_Facettes
const ArrOfInt & index_elem() const
Renvoie un tableau de taille domaine.
const Intersections_Elem_Facettes_Data & data_intersection(int index) const
Renvoie les donnees de l'intersection stockee a l'indice "index" dans le tableau "data" ( 0 <= index ...
const DoubleTab & sommets() const
renvoie le tableau des sommets (reels et virtuels) dimension(0) = nombre de sommets,
int sommet_virtuel(int i) const
const Intersections_Elem_Facettes & intersections_elem_facettes() const
virtual const ArrOfDouble & get_update_surface_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
: class Maillage_FT_IJK
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133