16#ifndef OpConvQuickIJKScalar_cut_cell_TPP_included
17#define OpConvQuickIJKScalar_cut_cell_TPP_included
19#include <OpConvQuickIJKScalar_cut_cell.h>
21#ifndef OpConvQuickIJKScalar_cut_cell_included
22#error __FILE__ should only be included from corresponding header
25#include <ConstIJK_ptr.h>
26#include <Cut_cell_FT_Disc.h>
28#include <Domaine_IJK.h>
30#include <EntreeSortie.h>
31#include <IJK_Field_local_template.h>
32#include <IJK_Interfaces.h>
34#include <Operateur_IJK_base.h>
36#include <Simd_template.h>
37#include <TRUSTTabFT_cut_cell.h>
44#include <IJK_Field_vector.h>
46#include <Cut_cell_convection_auxiliaire.h>
47#include <simd_tools.h>
49template <DIRECTION _DIR_>
50void OpConvQuickIJKScalar_cut_cell_double::compute_flux_(IJK_Field_local_double& resu,
const int k_layer)
52 if (_DIR_==DIRECTION::Z)
64 ConstIJK_double_ptr input_field(*
input_field_, 0, 0, k_layer);
67 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
72 const double surface =
channel_data_.get_surface(k_layer, 1, (
int)_DIR_);
73 if (_DIR_==DIRECTION::Z)
76 const int global_k_layer = k_layer +
channel_data_.offset_to_global_k_layer();
79 const int first_global_k_layer = 0;
80 const int last_global_k_layer =
channel_data_.nb_elem_k_tot();
86 if (!
perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
94 const double delta_xyz_squared_over_8 = delta_xyz * delta_xyz * 0.125;
98 const Simd_double zero = 0.;
99 for (
int j = 0; ; j++)
101 for (
int i = 0; i < imax; i += vsize)
103 Simd_double velocity;
104 velocity_dir.get_center(i, velocity);
106 Simd_double fram0, fram1;
107 Simd_double curv0, curv1;
108 input_field.get_left_center(_DIR_, i, T0, T1);
109 fram_values.get_left_center(_DIR_, i, fram0, fram1);
110 curv_values.get_left_center(_DIR_, i, curv0, curv1);
111 Simd_double fram = max(fram0, fram1);
112 Simd_double curv = select_double(velocity, zero, curv1, curv0);
113 Simd_double T_amont = select_double(velocity, zero, T1 , T0 );
114 Simd_double flux = (T0 + T1) * 0.5 - delta_xyz_squared_over_8 * curv;
115 flux = ((1. - fram) * flux + fram * T_amont) * velocity * surface;
116 resu_ptr.put_val(i, flux);
121 input_field.next_j();
122 velocity_dir.next_j();
123 fram_values.next_j();
124 curv_values.next_j();
128 if (_DIR_==DIRECTION::Z)
154template <DIRECTION _DIR_>
155double OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_(
int i,
int j,
int k)
157 const int dir_i = (_DIR_ == DIRECTION::X);
158 const int dir_j = (_DIR_ == DIRECTION::Y);
159 const int dir_k = (_DIR_ == DIRECTION::Z);
162 const IJK_Field_local_double& input_field = *
input_field_;
165 const double surface =
channel_data_.get_surface(k, 1, (
int)_DIR_);
167 if (flux_determined_by_wall_<_DIR_>(k))
173 double velocity = velocity_dir(i,j,k);
174 double input_left_left = input_field(i-2*dir_i,j-2*dir_j,k-2*dir_k);
175 double input_left = input_field(i-dir_i,j-dir_j,k-dir_k);
176 double input_centre = input_field(i,j,k);
177 double input_right = input_field(i+dir_i,j+dir_j,k+dir_k);
179 double flux = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(k, delta_xyz, surface, velocity, input_left_left, input_left, input_centre, input_right);
184template <DIRECTION _DIR_>
185double OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_(
int k_layer,
double delta_xyz,
double surface,
double velocity,
double input_left_left,
double input_left,
double input_centre,
double input_right)
187 const int dir_k = (_DIR_ == DIRECTION::Z);
189 const double delta_xyz_squared_over_8 = delta_xyz * delta_xyz * 0.125;
191 Vecteur3 curv_fram_left = compute_curv_fram_local_<_DIR_>(k_layer-dir_k, input_left_left, input_left, input_centre);
192 double curv_left = curv_fram_left[0];
193 double fram_left = curv_fram_left[1];
195 Vecteur3 curv_fram_centre = compute_curv_fram_local_<_DIR_>(k_layer, input_left, input_centre, input_right);
196 double curv_centre = curv_fram_centre[0];
197 double fram_centre = curv_fram_centre[1];
199 double fram = std::max(fram_left, fram_centre);
200 double curv = velocity < 0. ? curv_centre : curv_left;
201 double T_amont = velocity < 0. ? input_centre : input_left ;
202 double flux = (input_left + input_centre) * 0.5 - delta_xyz_squared_over_8 * curv;
203 flux = ((1. - fram) * flux + fram * T_amont) * velocity * surface;
207template <DIRECTION _DIR_>
208double OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_(
double surface,
double velocity,
double input)
210 double flux = input * velocity * surface;
214template <DIRECTION _DIR_>
215bool OpConvQuickIJKScalar_cut_cell_double::flux_determined_by_wall_(
int k)
217 if (_DIR_==DIRECTION::Z)
220 const int global_k_layer = k +
channel_data_.offset_to_global_k_layer();
223 const int first_global_k_layer = 0;
224 const int last_global_k_layer =
channel_data_.nb_elem_k_tot();
230 if (!
perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
239template <DIRECTION _DIR_>
240Vecteur3 OpConvQuickIJKScalar_cut_cell_double::compute_curv_fram_local_(
int k_layer,
double input_left,
double input_centre,
double input_right)
242 if (_DIR_ == DIRECTION::Z)
245 const int global_k_layer = k_layer +
channel_data_.offset_to_global_k_layer();
248 const int first_global_k_layer = 0;
249 const int last_global_k_layer =
channel_data_.nb_elem_k_tot();
251 if (!
perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
255 return {curv, fram, 0.};
259 double factor01 = -1.0;
260 double factor12 = -1.0;
261 if (_DIR_==DIRECTION::X)
265 factor01 = inv_dx * inv_dx;
268 if (_DIR_==DIRECTION::Y)
272 factor01 = inv_dy * inv_dy;
275 if (_DIR_==DIRECTION::Z)
281 factor01 = 1. / (dz1 * (dz0 + dz1) * 0.5);
282 factor12 = 1. / (dz1 * (dz1 + dz2) * 0.5);
285 double curv = (input_right - input_centre) * factor12 - (input_centre - input_left) * factor01;
286 double smin = std::min(input_left, input_right);
287 double smax = std::max(input_left, input_right);
290 double dsabs = 0. < smax - smin ? smax - smin : smin - smax;
291 double ds = dsabs < DMINFLOAT ? 1. : smax - smin;
292 double sr = dsabs < DMINFLOAT ? 0. : ((input_centre - smin) / ds - 0.5) * 2.;
295 sr = std::min(sr, 1.);
297 return {curv, fram, 0.};
300template <DIRECTION _DIR_>
301void OpConvQuickIJKScalar_cut_cell_double::correct_flux_(IJK_Field_local_double *
const flux,
int k_layer)
303 const int dir =
static_cast<int>(_DIR_);
305 const Cut_field_double& velocity_dir =
static_cast<const Cut_field_double&
>(
get_input_velocity(_DIR_));
306 const Cut_field_double& input_cut_field =
static_cast<const Cut_field_double&
>(*input_field_);
309 const Cut_cell_FT_Disc& cut_cell_disc = (*cut_cell_flux_)[0].get_cut_cell_disc();
311 IJK_Field_int& treatment_count = *treatment_count_;
312 int& new_treatment = *new_treatment_;
315 int backward_receptive_stencil = 1;
316 int forward_receptive_stencil = 2;
317 assert(backward_receptive_stencil <= cut_cell_disc.
get_ghost_size());
318 assert(forward_receptive_stencil <= cut_cell_disc.
get_ghost_size());
320 if (_DIR_ == DIRECTION::Z)
329 if (n_dir == n_dir_tot)
339 int min_k = (_DIR_ == DIRECTION::Z) ? k_layer-forward_receptive_stencil : k_layer;
340 int max_k = (_DIR_ == DIRECTION::Z) ? k_layer+backward_receptive_stencil : k_layer;
341 for (
int k_c = min_k; k_c <= max_k; k_c++)
347 Int3 ijk_no_per = cut_cell_disc.
get_ijk(n);
348 assert(k_c == ijk_no_per[2]);
350 int min_decalage = (_DIR_ == DIRECTION::Z) ? (k_layer - k_c) : -backward_receptive_stencil;
351 int max_decalage = (_DIR_ == DIRECTION::Z) ? (k_layer - k_c) : forward_receptive_stencil;
352 for (
int decalage = min_decalage; decalage <= max_decalage; decalage++)
354 int i = ijk_no_per[0] + (_DIR_ == DIRECTION::X)*decalage;
355 int j = ijk_no_per[1] + (_DIR_ == DIRECTION::Y)*decalage;
356 int k = ijk_no_per[2] + (_DIR_ == DIRECTION::Z)*decalage;
357 assert(k_layer == k);
362 if (treatment_count(i,j,k) == new_treatment)
366 int index_ijk_per = 0;
367 while (index_ijk_per >= 0)
372 treatment_count(ijk[0],ijk[1],ijk[2]) = new_treatment;
378 int n_centre = cut_cell_disc.
get_n(i, j, k);
380 if (flux_determined_by_wall_<_DIR_>(k))
384 assert(n_centre < 0);
388 assert((n_centre >= 0) || ((indicatrice_centre == 0.) || (indicatrice_centre == 1.)));
391 int phase_min = (int)std::floor(.5*(indicatrice_centre + next_indicatrice_centre));
392 int phase_max = (int)std::ceil(.5*(indicatrice_centre + next_indicatrice_centre));
393 for (
int phase = phase_min ; phase <= phase_max ; phase++)
395 const DoubleTabFT_cut_cell& diph_input = (phase == 0) ? input_cut_field.
diph_v_ : input_cut_field.diph_l_;
396 const DoubleTabFT_cut_cell& diph_velocity = (phase == 0) ? velocity_dir.
diph_v_ : velocity_dir.diph_l_;
397 DoubleTabFT_cut_cell& diph_flux = (phase == 0) ? (*cut_cell_flux_)[dir].diph_v_ : (*cut_cell_flux_)[dir].diph_l_;
399 const int dir_i = (_DIR_ == DIRECTION::X);
400 const int dir_j = (_DIR_ == DIRECTION::Y);
401 const int dir_k = (_DIR_ == DIRECTION::Z);
403 int n_left_left = cut_cell_disc.
get_n(i-2*dir_i,j-2*dir_j,k-2*dir_k);
404 int n_left = cut_cell_disc.
get_n(i-dir_i,j-dir_j,k-dir_k);
405 int n_right = cut_cell_disc.
get_n(i+dir_i,j+dir_j,k+dir_k);
407 double indicatrice_left_left = cut_cell_disc.
get_interfaces().
I(i-2*dir_i,j-2*dir_j,k-2*dir_k);
408 double indicatrice_left = cut_cell_disc.
get_interfaces().
I(i-dir_i,j-dir_j,k-dir_k);
409 double indicatrice_right = cut_cell_disc.
get_interfaces().
I(i+dir_i,j+dir_j,k+dir_k);
411 double next_indicatrice_left_left = cut_cell_disc.
get_interfaces().
In(i-2*dir_i,j-2*dir_j,k-2*dir_k);
412 double next_indicatrice_left = cut_cell_disc.
get_interfaces().
In(i-dir_i,j-dir_j,k-dir_k);
413 double next_indicatrice_right = cut_cell_disc.
get_interfaces().
In(i+dir_i,j+dir_j,k+dir_k);
426 double indicatrice_surface = (n_centre < 0) ? ((phase == 0) ? 1 - indicatrice_centre : indicatrice_centre) : ((phase == 0) ? 1 - indicatrice_surfacique(n_centre,dir) : indicatrice_surfacique(n_centre,dir));
428 const double surface =
channel_data_.get_surface(k, 1, (
int)_DIR_) * indicatrice_surface;
430 double velocity = (n_centre < 0) ? velocity_dir.
pure_(i,j,k) : diph_velocity(n_centre);
435 assert((phase_left == phase) || (indicatrice_surface == 0.));
437 double input_left_left = (n_left_left < 0) ? input_cut_field.
pure_(i-2*dir_i,j-2*dir_j,k-2*dir_k) : diph_input(n_left_left);
438 double input_left = (n_left < 0) ? input_cut_field.
pure_(i-dir_i,j-dir_j,k-dir_k) : diph_input(n_left);
439 double input_centre = (n_centre < 0) ? input_cut_field.
pure_(i,j,k) : diph_input(n_centre);
440 double input_right = (n_right < 0) ? input_cut_field.
pure_(i+dir_i,j+dir_j,k+dir_k) : diph_input(n_right);
443 if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::CENTRE2)
444 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_CENTRE2_STENCIL)
445 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_CENTRE2_PERPENDICULAR_DISTANCE))
447 double input_milieu = (input_left + input_centre) * 0.5;
448 flux_2 = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(surface, velocity, input_milieu);
450 else if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::LINEAIRE2)
451 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_LINEAIRE2_STENCIL)
452 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_LINEAIRE2_PERPENDICULAR_DISTANCE))
455 assert((n_left >= 0) || (bar_dir_left == .5));
458 assert((n_centre >= 0) || (bar_dir_centre == .5));
461 double input_milieu = (input_left + input_centre) * 0.5;
462 double input_lineaire = (1 - bar_dir_left + bar_dir_centre) == 0. ? input_milieu : input_left + (1 - bar_dir_left)/(1 - bar_dir_left + bar_dir_centre)*(input_centre - input_left);
463 assert(std::abs(input_lineaire - input_left) <= std::abs(input_centre - input_left));
464 assert((input_lineaire - input_left)*(input_centre - input_left) >= 0);
465 flux_2 = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(surface, velocity, input_lineaire);
467 else if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::AMONT)
468 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_AMONT_STENCIL)
469 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_AMONT_PERPENDICULAR_DISTANCE))
471 double input_amont = velocity < 0. ? input_centre : input_left;
472 flux_2 = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(surface, velocity, input_amont);
476 Cerr <<
"OpConvQuickIJKScalar_cut_cell.tpp: cut_cell_conv_scheme_ inconnu pour flux_2." << finl;
481 double flux_1l = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(surface, velocity, input_left);
482 double flux_1c = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(surface, velocity, input_centre);
484 double flux_4 = OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_<_DIR_>(k, delta_xyz, surface, velocity, input_left_left, input_left, input_centre, input_right);
485 if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_CENTRE2_STENCIL)
486 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_LINEAIRE2_STENCIL)
487 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_AMONT_STENCIL)
488 || (left_left_monophasique && left_monophasique && centre_monophasique && right_monophasique))
492 else if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_CENTRE2_PERPENDICULAR_DISTANCE)
493 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_LINEAIRE2_PERPENDICULAR_DISTANCE)
494 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::QUICK_OU_AMONT_PERPENDICULAR_DISTANCE))
498 assert((n_left_left >= 0) || (bar_dir_perp1_left_left == .5));
499 assert((n_left_left >= 0) || (bar_dir_perp2_left_left == .5));
503 assert((n_left >= 0) || (bar_dir_perp1_left == .5));
504 assert((n_left >= 0) || (bar_dir_perp2_left == .5));
508 assert((n_centre >= 0) || (bar_dir_perp1_centre == .5));
509 assert((n_centre >= 0) || (bar_dir_perp2_centre == .5));
513 assert((n_right >= 0) || (bar_dir_perp1_right == .5));
514 assert((n_right >= 0) || (bar_dir_perp2_right == .5));
516 bool small_perpendicular_distance_left_left = ((std::abs(bar_dir_perp1_left_left - .5) < 0.1) && (std::abs(bar_dir_perp2_left_left - .5) < 0.1));
517 bool small_perpendicular_distance_left = ((std::abs(bar_dir_perp1_left - .5) < 0.1) && (std::abs(bar_dir_perp2_left - .5) < 0.1));
518 bool small_perpendicular_distance_centre = ((std::abs(bar_dir_perp1_centre - .5) < 0.1) && (std::abs(bar_dir_perp2_centre - .5) < 0.1));
519 bool small_perpendicular_distance_right = ((std::abs(bar_dir_perp1_right - .5) < 0.1) && (std::abs(bar_dir_perp2_right - .5) < 0.1));
521 if (small_perpendicular_distance_left_left && small_perpendicular_distance_left && small_perpendicular_distance_centre && small_perpendicular_distance_right)
530 else if ((cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::CENTRE2)
531 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::LINEAIRE2)
532 || (cut_cell_conv_scheme_.scheme == CUT_CELL_SCHEMA_CONVECTION::AMONT))
538 Cerr <<
"OpConvQuickIJKScalar_cut_cell.tpp: cut_cell_conv_scheme_ inconnu pour flux_4." << finl;
556 if (phase_naissante_centre)
558 assert(std::abs(input_centre) < 1e-16);
560 flux_value = flux_1l;
562 else if (phase_naissante_left)
564 assert(std::abs(input_left) < 1e-16);
566 flux_value = flux_1c;
568 else if (ignore_small_cells_ && (petit_centre || petit_left || phase_mourrante_centre || phase_mourrante_left))
572 else if (phase_mourrante_left_left || phase_mourrante_right || phase_naissante_left_left || phase_naissante_right)
574 assert(phase_invalide_left || (input_left != 0.));
575 assert(phase_invalide_centre || (input_centre != 0.));
578 else if ((phase_left_left == phase && (!phase_invalide_left_left)) && (phase_right == phase && (!phase_invalide_right)))
580 assert(input_left_left != 0);
581 assert(phase_invalide_left || (input_left != 0.));
582 assert(phase_invalide_centre || (input_centre != 0.));
583 assert(input_right != 0);
588 assert(phase_invalide_left || (input_left != 0.));
589 assert(phase_invalide_centre || (input_centre != 0.));
595 int index_ijk_per = 0;
596 while (index_ijk_per >= 0)
601 (*flux)(ijk[0],ijk[1],0) = flux_value;
606 diph_flux(n_centre) = flux_value;
607 if ((n_left < 0) && (phase == phase_left && (!phase_invalide_centre) && (!phase_invalide_left)))
609 int index_ijk_per = 0;
610 while (index_ijk_per >= 0)
615 (*flux)(ijk[0],ijk[1],0) = flux_value;
621 if (phase_invalide_centre || phase_invalide_left)
623 assert(flux_value == 0.);
const Domaine_IJK & get_domaine() const
const IJK_Interfaces & get_interfaces() const
int get_n_from_k_index(int index) const
int get_ghost_size() const
Int3 ijk_per_of_index(int i, int j, int k, int index) const
int next_index_ijk_per(int i, int j, int k, int index, int negative_ghost_size, int positive_ghost_size) const
Int3 get_ijk(int n) const
int get_k_value_index(int k) const
int get_n(int i, int j, int k) const
_TYPE_ & pure_(int i, int j, int k)
TRUSTTabFT_cut_cell< _TYPE_ > diph_v_
int get_nb_elem_local(int direction) const
Returns the number of elements owned by this processor in the given direction.
bool get_periodic_flag(int direction) const
Method returns true if periodic in this direction.
int get_nb_elem_tot(int direction) const
Returns the total (global) number of mesh cells in requested direction.
bool within_ghost_(int i, int j, int k, int negative_ghost_size, int positive_ghost_size) const
const DoubleTabFT_cut_cell_vector3 & get_indicatrice_surfacique_efficace_face() const
const IJK_Field_double & I() const
static int phase_naissante(int phase, double old_indicatrice, double next_indicatrice)
const IJK_Field_double & In() const
int next_below_small_threshold_for_phase(int phase, double old_indicatrice, double next_indicatrice) const
static int est_pure(double indicatrice)
double get_barycentre(bool next_time, int bary_compo, int phase, int i, int j, int k) const
static int phase_mourrante(int phase, double old_indicatrice, double next_indicatrice)
static int convert_indicatrice_to_phase(double indicatrice)
const Cut_cell_FT_Disc * get_cut_cell_disc()
const IJK_Field_double & get_input_velocity(DIRECTION _DIR_)
Operateur_IJK_data_channel channel_data_
const IJK_Field_double * input_field_
void compute_curv_fram(DIRECTION _DIR_, int k_layer)
void shift_curv_fram(IJK_Field_local_double &tmp_curv_fram)
IJK_Field_local_double tmp_curv_fram_
int stored_curv_fram_layer_z_
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.