16#ifndef Operateur_IJK_elem_diff_base_TPP_included
17#define Operateur_IJK_elem_diff_base_TPP_included
19#include <Operateur_IJK_elem_diff_base.h>
21#ifndef Operateur_IJK_elem_diff_base_included
22#error __FILE__ should only be included from corresponding header
25static void copy_boundary_condition(
const IJK_Field_local_double& boundary_flux, IJK_Field_local_double& resu)
27 assert(resu.
ni() >= boundary_flux.
ni());
28 assert(resu.
nj() >= boundary_flux.
nj());
32 const int ni = boundary_flux.
ni();
33 const int nj = boundary_flux.
nj();
34 for (
int j = 0; j < nj; j++)
35 for (
int i = 0; i < ni; i++)
36 resu(i,j,0) = boundary_flux(i,j,0);
39template <DIRECTION _DIR_>
45 ConstIJK_double_ptr input_field(*
input_field_, 0, 0, k_layer);
46 Simd_double uniform_lambda(1.);
47 Simd_double avg_lambda(1.);
67 const IJK_Field_local_double& dummy_field = *
input_field_;
71 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
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;
81 const int last_global_k_layer =
channel_data_.nb_elem_k_tot();
85 if (global_k_layer == first_global_k_layer)
94 else if (global_k_layer == last_global_k_layer)
105 double d0 = 0., d1 = 0.;
139 Simd_double lambda_m1(uniform_lambda);
140 Simd_double lambda_m2(uniform_lambda);
144 for (
int j = 0; ; j++)
146 for (
int i = 0; i < imax; i += vsize)
148 Simd_double flux = 0.;
151 Simd_double s_mo, s_mo_dummy;
153 flux = (-1.) * s_mo * surface;
157 Simd_double left_val, right_val;
159 Simd_double zeroVec = 0.;
160 Simd_double oneVec = 1.;
161 Simd_double minVec = DMINFLOAT;
171 Simd_double dsabs = SimdSelect(zeroVec, d0 * lambda_m2 + d1 * lambda_m1, d0 * lambda_m2 + d1 * lambda_m1, (-1) * (d0 * lambda_m2 + d1 * lambda_m1));
172 Simd_double ds = SimdSelect(dsabs, minVec, oneVec, d0 * lambda_m2 + d1 * lambda_m1);
175 avg_lambda = SimdSelect(dsabs, minVec, zeroVec, SimdDivideMed(d * lambda_m1 * lambda_m2, ds));
178 flux = (left_val - right_val) * avg_lambda * surface;
189 structural_model.
next_j();
194template <DIRECTION _DIR_>
197 const int dir_i = (_DIR_ == DIRECTION::X);
198 const int dir_j = (_DIR_ == DIRECTION::Y);
199 const int dir_k = (_DIR_ == DIRECTION::Z);
201 const IJK_Field_local_double& input_field = *
input_field_;
219 if (type_boundary_flux != BOUNDARY_FLUX::NOT_DETERMINED_BY_BOUNDARY)
227 double surface = surface_d0_d1[0];
228 double d0 = surface_d0_d1[1];
229 double d1 = surface_d0_d1[2];
231 double input_left = input_field(i-dir_i,j-dir_j,k-dir_k);
232 double input_centre = input_field(i,j,k);
233 double lambda_left = lambda(i-dir_i,j-dir_j,k-dir_k);
234 double lambda_centre = lambda(i,j,k);
235 double struct_model =
is_structural_ ? structural_model(i,j,k) : -1;
241template <DIRECTION _DIR_>
250 double s_mo = structural_model;
251 flux = (-1.) * s_mo * surface;
255 double lambda_m1 = lambda_left;
256 double lambda_m2 = lambda_centre;
259 double dsabs = (0. < d0 * lambda_m2 + d1 * lambda_m1) ? d0 * lambda_m2 + d1 * lambda_m1 : (-1) * (d0 * lambda_m2 + d1 * lambda_m1);
260 double ds = (dsabs < DMINFLOAT) ? 1. : d0 * lambda_m2 + d1 * lambda_m1;
262 double avg_lambda = (dsabs < DMINFLOAT) ? 0. : (lambda_m1 * lambda_m2)/ds;
265 flux = (input_left - input_centre) * avg_lambda * surface;
270template <DIRECTION _DIR_>
273 if (_DIR_ == DIRECTION::Z)
276 const int global_k_layer = k +
channel_data_.offset_to_global_k_layer();
279 const int first_global_k_layer = 0;
281 const int last_global_k_layer =
channel_data_.nb_elem_k_tot();
285 if (global_k_layer == first_global_k_layer)
287 return BOUNDARY_FLUX::KMIN_WALL;
289 else if (global_k_layer == last_global_k_layer)
291 return BOUNDARY_FLUX::KMAX_WALL;
295 return BOUNDARY_FLUX::NOT_DETERMINED_BY_BOUNDARY;
298template <DIRECTION _DIR_>
301 if (type_boundary_flux == BOUNDARY_FLUX::KMIN_WALL)
309 else if (type_boundary_flux == BOUNDARY_FLUX::KMAX_WALL)
318 Cerr <<
"Unexpected situation in compute_flux_local_boundary_condition_" << finl;
324template <DIRECTION _DIR_>
327 double d0 = 0., d1 = 0.;
360 return {surface, d0, d1};
363template <DIRECTION _DIR_>
364void OpDiffIJKScalar_cut_cell_double::correct_flux_(IJK_Field_local_double *
const flux,
int k_layer)
366 const int dir =
static_cast<int>(_DIR_);
368 const Cut_field_double& input_cut_field =
static_cast<const Cut_field_double&
>(*input_field_);
372 const Cut_cell_FT_Disc& cut_cell_disc = (*cut_cell_flux_)[0].get_cut_cell_disc();
374 IJK_Field_int& treatment_count = *treatment_count_;
375 int& new_treatment = *new_treatment_;
378 int backward_receptive_stencil = 0;
379 int forward_receptive_stencil = 1;
380 assert(backward_receptive_stencil <= cut_cell_disc.
get_ghost_size());
381 assert(forward_receptive_stencil <= cut_cell_disc.
get_ghost_size());
383 if (_DIR_ == DIRECTION::Z)
392 if (n_dir == n_dir_tot)
402 int min_k = (_DIR_ == DIRECTION::Z) ? k_layer-forward_receptive_stencil : k_layer;
403 int max_k = (_DIR_ == DIRECTION::Z) ? k_layer+backward_receptive_stencil : k_layer;
404 for (
int k_c = min_k; k_c <= max_k; k_c++)
410 Int3 ijk_no_per = cut_cell_disc.
get_ijk(n);
411 assert(k_c == ijk_no_per[2]);
413 int min_decalage = (_DIR_ == DIRECTION::Z) ? (k_layer - k_c) : -backward_receptive_stencil;
414 int max_decalage = (_DIR_ == DIRECTION::Z) ? (k_layer - k_c) : forward_receptive_stencil;
415 for (
int decalage = min_decalage; decalage <= max_decalage; decalage++)
417 int i = ijk_no_per[0] + (_DIR_ == DIRECTION::X)*decalage;
418 int j = ijk_no_per[1] + (_DIR_ == DIRECTION::Y)*decalage;
419 int k = ijk_no_per[2] + (_DIR_ == DIRECTION::Z)*decalage;
420 assert(k_layer == k);
425 if (treatment_count(i,j,k) == new_treatment)
429 int index_ijk_per = 0;
430 while (index_ijk_per >= 0)
435 treatment_count(ijk[0],ijk[1],ijk[2]) = new_treatment;
440 double old_indicatrice_centre = cut_cell_disc.
get_interfaces().
I(i,j,k);
441 int n_centre = cut_cell_disc.
get_n(i, j, k);
444 if (type_boundary_flux != BOUNDARY_FLUX::NOT_DETERMINED_BY_BOUNDARY)
448 assert(n_centre < 0);
452 assert((n_centre >= 0) || ((indicatrice_centre == 0.) || (indicatrice_centre == 1.)));
455 int phase_min = (int)std::floor(.5*(old_indicatrice_centre + indicatrice_centre));
456 int phase_max = (int)std::ceil(.5*(old_indicatrice_centre + indicatrice_centre));
457 for (
int phase = phase_min ; phase <= phase_max ; phase++)
459 const DoubleTabFT_cut_cell& diph_input = (phase == 0) ? input_cut_field.
diph_v_ : input_cut_field.diph_l_;
460 DoubleTabFT_cut_cell& diph_flux = (phase == 0) ? (*cut_cell_flux_)[dir].diph_v_ : (*cut_cell_flux_)[dir].diph_l_;
462 const int dir_i = (_DIR_ == DIRECTION::X);
463 const int dir_j = (_DIR_ == DIRECTION::Y);
464 const int dir_k = (_DIR_ == DIRECTION::Z);
466 int n_left = cut_cell_disc.
get_n(i-dir_i,j-dir_j,k-dir_k);
468 double indicatrice_left = cut_cell_disc.
get_interfaces().
In(i-dir_i,j-dir_j,k-dir_k);
470 double old_indicatrice_left = cut_cell_disc.
get_interfaces().
I(i-dir_i,j-dir_j,k-dir_k);
477 assert((n_left >= 0) || (bar_dir_left == .5));
480 assert((n_centre >= 0) || (bar_dir_centre == .5));
485 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));
487 const double surface = surface_d0_d1[0] * indicatrice_surface;
488 double d0 = surface_d0_d1[1] * 2*(1 - bar_dir_left);
489 double d1 = surface_d0_d1[2] * 2*(bar_dir_centre);
492 assert((phase_left == phase) || (indicatrice_surface == 0.));
494 double input_left = (n_left < 0) ? input_cut_field.
pure_(i-dir_i,j-dir_j,k-dir_k) : diph_input(n_left);
495 double input_centre = (n_centre < 0) ? input_cut_field.
pure_(i,j,k) : diph_input(n_centre);
499 double struct_model =
is_structural_ ? structural_model(i,j,k) : -1;
509 if (phase_mourrante_centre || phase_mourrante_left)
513 else if (ignore_small_cells_ && (petit_centre || petit_left || phase_naissante_centre || phase_naissante_left))
519 assert(phase_invalide_left || (input_left != 0.));
520 assert(phase_invalide_centre || (input_centre != 0.));
526 int index_ijk_per = 0;
527 while (index_ijk_per >= 0)
532 (*flux)(ijk[0],ijk[1],0) = flux_value;
537 diph_flux(n_centre) = flux_value;
538 if ((n_left < 0) && (phase == phase_left && (!phase_invalide_centre) && (!phase_invalide_left)))
540 int index_ijk_per = 0;
541 while (index_ijk_per >= 0)
546 (*flux)(ijk[0],ijk[1],0) = flux_value;
552 if (phase_invalide_centre || phase_invalide_left)
554 assert(flux_value == 0.);
void next_j()
increments the pointer by j_stride (eg, j = j+1)
void get_left_center(DIRECTION _DIR_, int i_offset, _TYPE_ &left, _TYPE_ ¢er) const
returns left=field(i+i_offset-1, j, k) and center=field(i+i_offset, j, k)
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)
void put_val(int i_offset, const _TYPE_ &val)
Performs the assignment: field(i+i_offset,j,k) = val.
const Cut_cell_FT_Disc * get_cut_cell_disc()
BOUNDARY_FLUX flux_determined_by_boundary_condition_(int k)
double compute_flux_local_(int i, int j, int k)
const double * uniform_lambda_liquid_
const double * uniform_lambda_vapour_
const IJK_Field_local_double * lambda_
const IJK_Field_local_double * boundary_flux_kmin_
double compute_flux_local_boundary_condition_(BOUNDARY_FLUX type_boundary_flux, int i, int j)
const double * uniform_lambda_
Vecteur3 compute_surface_d0_d1_(int k)
const IJK_Field_local_double & get_model(DIRECTION _DIR_)
const IJK_Field_double * input_field_
const IJK_Field_local_double * boundary_flux_kmax_
Operateur_IJK_data_channel channel_data_
void compute_flux_(IJK_Field_local_double &resu, const int k_layer)
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.