TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
OpConvQuickIJKScalar_cut_cell.tpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#ifndef OpConvQuickIJKScalar_cut_cell_TPP_included
17#define OpConvQuickIJKScalar_cut_cell_TPP_included
18
19#include <OpConvQuickIJKScalar_cut_cell.h>
20
21#ifndef OpConvQuickIJKScalar_cut_cell_included
22#error __FILE__ should only be included from corresponding header
23#endif
24
25#include <ConstIJK_ptr.h>
26#include <Cut_cell_FT_Disc.h>
27#include <Cut_field.h>
28#include <Domaine_IJK.h>
29#include <Double.h>
30#include <EntreeSortie.h>
31#include <IJK_Field_local_template.h>
32#include <IJK_Interfaces.h>
33#include <IJK_ptr.h>
34#include <Operateur_IJK_base.h>
35#include <Process.h>
36#include <Simd_template.h>
37#include <TRUSTTabFT_cut_cell.h>
38#include <Vecteur3.h>
39#include <algorithm>
40#include <cassert>
41#include <cmath>
42#include <cstdlib>
43
44#include <IJK_Field_vector.h>
45#include <IJK_Field.h>
46#include <Cut_cell_convection_auxiliaire.h>
47#include <simd_tools.h>
48
49template <DIRECTION _DIR_>
50void OpConvQuickIJKScalar_cut_cell_double::compute_flux_(IJK_Field_local_double& resu, const int k_layer)
51{
52 if (_DIR_==DIRECTION::Z)
53 {
54 // The previous layer of curv and fram values might have been computed already
55 if (stored_curv_fram_layer_z_ != k_layer-1)
56 {
57 compute_curv_fram(_DIR_, k_layer-1);
59 }
60 }
61 compute_curv_fram(_DIR_, k_layer);
62
63 ConstIJK_double_ptr velocity_dir(get_input_velocity(_DIR_), 0, 0, k_layer);
64 ConstIJK_double_ptr input_field(*input_field_, 0, 0, k_layer);
65 ConstIJK_double_ptr curv_values(tmp_curv_fram_, 0, 0, 1); /* if z direction, "left" will be in layer 0 */
66 ConstIJK_double_ptr fram_values(tmp_curv_fram_, 0, 0, 3); /* if z direction, "left" is in layer 2 */
67 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
68 const int nx = _DIR_==DIRECTION::X ? input_field_->ni() + 1 : input_field_->ni();
69 const int ny = _DIR_==DIRECTION::Y ? input_field_->nj() + 1 : input_field_->nj();
70
71 const double delta_xyz = _DIR_==DIRECTION::Z ? (channel_data_.get_delta_z()[k_layer-1] + channel_data_.get_delta_z()[k_layer]) * 0.5 : channel_data_.get_delta((int)_DIR_);
72 const double surface = channel_data_.get_surface(k_layer, 1, (int)_DIR_);
73 if (_DIR_==DIRECTION::Z)
74 {
75 // Are we on the wall ?
76 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
77 // global index of the layer of flux of the wall
78 // (assume one walls at zmin and zmax)
79 const int first_global_k_layer = 0;
80 const int last_global_k_layer = channel_data_.nb_elem_k_tot();
81
82 // GB 21/12/2020 : Similarly to velocity, we make the same adjustments.
83 // if (global_k_layer == first_global_k_layer || global_k_layer == last_global_k_layer) {
84 // ie (i) replace the former "==" by "<=" and ">=" to be identic to the condition in OpCentre4IJK
85 // and (ii) add the condition on perio_k
86 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
87 {
88 // We are on (or worse inside) the wall, zero flux
89 putzero(resu);
90 return;
91 }
92 }
93
94 const double delta_xyz_squared_over_8 = delta_xyz * delta_xyz * 0.125;
95 const int imax = nx;
96 const int jmax = ny;
97 const int vsize = Simd_double::size();
98 const Simd_double zero = 0.;
99 for (int j = 0; ; j++)
100 {
101 for (int i = 0; i < imax; i += vsize)
102 {
103 Simd_double velocity;
104 velocity_dir.get_center(i, velocity);
105 Simd_double T0, T1; // scalar value at left and at right of the computed flux
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 /* if velocity < 0 */, T0 /* if velocity > 0 */);
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);
117 }
118 // do not execute end_iloop at last iteration (because of assert on valid j+1)
119 if (j+1==jmax)
120 break;
121 input_field.next_j();
122 velocity_dir.next_j();
123 fram_values.next_j();
124 curv_values.next_j();
125 resu_ptr.next_j();
126 }
127
128 if (_DIR_==DIRECTION::Z)
129 {
130 // store curv and fram for next layer of fluxes in z direction
133 }
134}
135
136//template <DIRECTION _DIR_>
137//void OpConvQuickIJKScalar_cut_cell_double::compute_flux_(IJK_Field_local_double& resu, const int k_layer)
138//{
139// const int nx = _DIR_==DIRECTION::X ? input_field_->ni() + 1 : input_field_->ni();
140// const int ny = _DIR_==DIRECTION::Y ? input_field_->nj() + 1 : input_field_->nj();
141//
142// const int imax = nx;
143// const int jmax = ny;
144// for (int j = 0; j < jmax; j++)
145// {
146// for (int i = 0; i < imax; i++)
147// {
148// double flux = compute_flux_local_<_DIR_>(i,j,k_layer);
149// resu(i,j,0) = flux;
150// }
151// }
152//}
153
154template <DIRECTION _DIR_>
155double OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_(int i, int j, int k)
156{
157 const int dir_i = (_DIR_ == DIRECTION::X);
158 const int dir_j = (_DIR_ == DIRECTION::Y);
159 const int dir_k = (_DIR_ == DIRECTION::Z);
160
161 const IJK_Field_local_double& velocity_dir = get_input_velocity(_DIR_);
162 const IJK_Field_local_double& input_field = *input_field_;
163
164 const double delta_xyz = _DIR_==DIRECTION::Z ? (channel_data_.get_delta_z()[k-1] + channel_data_.get_delta_z()[k]) * 0.5 : channel_data_.get_delta((int)_DIR_);
165 const double surface = channel_data_.get_surface(k, 1, (int)_DIR_);
166
167 if (flux_determined_by_wall_<_DIR_>(k))
168 {
169 return 0;
170 }
171 else
172 {
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);
178
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);
180 return flux;
181 }
182}
183
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)
186{
187 const int dir_k = (_DIR_ == DIRECTION::Z);
188
189 const double delta_xyz_squared_over_8 = delta_xyz * delta_xyz * 0.125;
190
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];
194
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];
198
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 /* if velocity < 0 */ : input_left /* if velocity > 0 */;
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;
204 return flux;
205}
206
207template <DIRECTION _DIR_>
208double OpConvQuickIJKScalar_cut_cell_double::compute_flux_local_(double surface, double velocity, double input)
209{
210 double flux = input * velocity * surface;
211 return flux;
212}
213
214template <DIRECTION _DIR_>
215bool OpConvQuickIJKScalar_cut_cell_double::flux_determined_by_wall_(int k)
216{
217 if (_DIR_==DIRECTION::Z)
218 {
219 // Are we on the wall ?
220 const int global_k_layer = k + channel_data_.offset_to_global_k_layer();
221 // global index of the layer of flux of the wall
222 // (assume one walls at zmin and zmax)
223 const int first_global_k_layer = 0;
224 const int last_global_k_layer = channel_data_.nb_elem_k_tot();
225
226 // GB 21/12/2020 : Similarly to velocity, we make the same adjustments.
227 // if (global_k_layer == first_global_k_layer || global_k_layer == last_global_k_layer) {
228 // ie (i) replace the former "==" by "<=" and ">=" to be identic to the condition in OpCentre4IJK
229 // and (ii) add the condition on perio_k
230 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
231 {
232 // We are on (or worse inside) the wall, zero flux
233 return 1;
234 }
235 }
236 return 0;
237}
238
239template <DIRECTION _DIR_>
240Vecteur3 OpConvQuickIJKScalar_cut_cell_double::compute_curv_fram_local_(int k_layer, double input_left, double input_centre, double input_right)
241{
242 if (_DIR_ == DIRECTION::Z)
243 {
244 // Are we on the wall ?
245 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
246 // global index of the layer of flux of the wall
247 // (assume one walls at zmin and zmax)
248 const int first_global_k_layer = 0;
249 const int last_global_k_layer = channel_data_.nb_elem_k_tot();
250
251 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
252 {
253 double curv = 0.;
254 double fram = 1.;
255 return {curv, fram, 0.};
256 }
257 }
258
259 double factor01 = -1.0;
260 double factor12 = -1.0;
261 if (_DIR_==DIRECTION::X)
262 {
263 // Compute invd1 and invd2 factors:
264 const double inv_dx = 1./channel_data_.get_delta_x();
265 factor01 = inv_dx * inv_dx;
266 factor12 = factor01;
267 }
268 if (_DIR_==DIRECTION::Y)
269 {
270 // Compute invd1 and invd2 factors:
271 const double inv_dy = 1. / channel_data_.get_delta_y();
272 factor01 = inv_dy * inv_dy;
273 factor12 = factor01;
274 }
275 if (_DIR_==DIRECTION::Z)
276 {
277 // Compute invd1 and invd2 factors:
278 const double dz0 = channel_data_.get_delta_z()[k_layer-1];
279 const double dz1 = channel_data_.get_delta_z()[k_layer];
280 const double dz2 = channel_data_.get_delta_z()[k_layer+1];
281 factor01 = 1. / (dz1 * (dz0 + dz1) * 0.5);
282 factor12 = 1. / (dz1 * (dz1 + dz2) * 0.5);
283 }
284
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);
288 // Compared to original code (Eval_Quick_VDF_Elem.h), we first compute the 4th power,
289 // then take the max (dabs is then useless)
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.;
293 sr *= sr;
294 sr *= sr;
295 sr = std::min(sr, 1.);
296 double fram = sr;
297 return {curv, fram, 0.};
298}
299
300template <DIRECTION _DIR_>
301void OpConvQuickIJKScalar_cut_cell_double::correct_flux_(IJK_Field_local_double *const flux, int k_layer)
302{
303 const int dir = static_cast<int>(_DIR_);
304
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_);
307 assert(&(*cut_cell_flux_)[0].get_cut_cell_disc() == &(*cut_cell_flux_)[1].get_cut_cell_disc());
308 assert(&(*cut_cell_flux_)[0].get_cut_cell_disc() == &(*cut_cell_flux_)[2].get_cut_cell_disc());
309 const Cut_cell_FT_Disc& cut_cell_disc = (*cut_cell_flux_)[0].get_cut_cell_disc();
310
311 IJK_Field_int& treatment_count = *treatment_count_;
312 int& new_treatment = *new_treatment_;
313 new_treatment += 1;
314
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());
319
320 if (_DIR_ == DIRECTION::Z)
321 {
322 if (cut_cell_disc.get_domaine().get_periodic_flag(dir))
323 {
324 const int kmax = cut_cell_disc.get_interfaces().I().nk();
325 int n_dir = cut_cell_disc.get_domaine().get_nb_elem_local(dir);
326 int n_dir_tot = cut_cell_disc.get_domaine().get_nb_elem_tot(dir);
327
328 // Le processeur contient deux fois les valeurs sur les bords
329 if (n_dir == n_dir_tot)
330 {
331 if (k_layer == kmax)
332 {
333 k_layer = 0;
334 }
335 }
336 }
337 }
338
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++)
342 {
343 for (int index = cut_cell_disc.get_k_value_index(k_c); index < cut_cell_disc.get_k_value_index(k_c+1); index++)
344 {
345 int n = cut_cell_disc.get_n_from_k_index(index);
346
347 Int3 ijk_no_per = cut_cell_disc.get_ijk(n);
348 assert(k_c == ijk_no_per[2]);
349
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++)
353 {
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);
358
359 if (!cut_cell_disc.get_domaine().within_ghost_<dir>(i, j, k, 0, 1))
360 continue;
361
362 if (treatment_count(i,j,k) == new_treatment)
363 continue;
364
365 {
366 int index_ijk_per = 0;
367 while (index_ijk_per >= 0)
368 {
369 Int3 ijk = cut_cell_disc.ijk_per_of_index(i, j, k, index_ijk_per);
370 index_ijk_per = cut_cell_disc.next_index_ijk_per(i, j, k, index_ijk_per, 0, 1);
371
372 treatment_count(ijk[0],ijk[1],ijk[2]) = new_treatment;
373 }
374 }
375
376 double indicatrice_centre = cut_cell_disc.get_interfaces().I(i,j,k);
377 double next_indicatrice_centre = cut_cell_disc.get_interfaces().In(i,j,k);
378 int n_centre = cut_cell_disc.get_n(i, j, k);
379
380 if (flux_determined_by_wall_<_DIR_>(k))
381 {
382 // Le flux est dans ce cas determine par la paroi
383 // Aucune correction n'est donc necessaire
384 assert(n_centre < 0); // Le cas d'une cellule diphasique avec flux de paroi n'est pas traite
385 }
386 else
387 {
388 assert((n_centre >= 0) || ((indicatrice_centre == 0.) || (indicatrice_centre == 1.)));
389 bool centre_monophasique = IJK_Interfaces::est_pure(.5*(indicatrice_centre + next_indicatrice_centre));
390
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++)
394 {
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_;
398
399 const int dir_i = (_DIR_ == DIRECTION::X);
400 const int dir_j = (_DIR_ == DIRECTION::Y);
401 const int dir_k = (_DIR_ == DIRECTION::Z);
402
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);
406
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);
410
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);
414
415 bool left_left_monophasique = IJK_Interfaces::est_pure(.5*(indicatrice_left_left + next_indicatrice_left_left));
416 bool left_monophasique = IJK_Interfaces::est_pure(.5*(indicatrice_left + next_indicatrice_left));
417 bool right_monophasique = IJK_Interfaces::est_pure(.5*(indicatrice_right + next_indicatrice_right));
418 bool phase_invalide_left_left = (left_left_monophasique && (phase != IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_left_left)));
419 bool phase_invalide_left = (left_monophasique && (phase != IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_left)));
420 bool phase_invalide_centre = (centre_monophasique && (phase != IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_centre)));
421 bool phase_invalide_right = (right_monophasique && (phase != IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_right)));
422
423 const double delta_xyz = _DIR_==DIRECTION::Z ? (channel_data_.get_delta_z()[k-1] + channel_data_.get_delta_z()[k]) * 0.5 : channel_data_.get_delta((int)_DIR_);
424
425 const DoubleTabFT_cut_cell_vector3& indicatrice_surfacique = cut_cell_disc.get_interfaces().get_indicatrice_surfacique_efficace_face();
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));
427
428 const double surface = channel_data_.get_surface(k, 1, (int)_DIR_) * indicatrice_surface;
429
430 double velocity = (n_centre < 0) ? velocity_dir.pure_(i,j,k) : diph_velocity(n_centre);
431
432 int phase_left_left = (n_left_left < 0) ? IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_left_left) : phase;
433 int phase_left = (n_left < 0) ? IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_left) : phase;
434 int phase_right = (n_right < 0) ? IJK_Interfaces::convert_indicatrice_to_phase(indicatrice_right) : phase;
435 assert((phase_left == phase) || (indicatrice_surface == 0.));
436
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);
441
442 double flux_2 = 0.;
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))
446 {
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);
449 }
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))
453 {
454 double bar_dir_left = cut_cell_disc.get_interfaces().get_barycentre(true, dir, phase, i-dir_i,j-dir_j,k-dir_k);
455 assert((n_left >= 0) || (bar_dir_left == .5));
456
457 double bar_dir_centre = cut_cell_disc.get_interfaces().get_barycentre(true, dir, phase, i,j,k);
458 assert((n_centre >= 0) || (bar_dir_centre == .5));
459
460 // Note : suppose un maillage uniforme, splitting_.is_uniform(_DIR_)
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);
466 }
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))
470 {
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);
473 }
474 else
475 {
476 Cerr << "OpConvQuickIJKScalar_cut_cell.tpp: cut_cell_conv_scheme_ inconnu pour flux_2." << finl;
478 }
479
480
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);
483
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))
489 {
490 // Ne fait rien : on garde le flux_4 quick
491 }
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))
495 {
496 double bar_dir_perp1_left_left = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+1)%3, phase, i-2*dir_i,j-2*dir_j,k-2*dir_k);
497 double bar_dir_perp2_left_left = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+2)%3, phase, i-2*dir_i,j-2*dir_j,k-2*dir_k);
498 assert((n_left_left >= 0) || (bar_dir_perp1_left_left == .5));
499 assert((n_left_left >= 0) || (bar_dir_perp2_left_left == .5));
500
501 double bar_dir_perp1_left = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+1)%3, phase, i-dir_i,j-dir_j,k-dir_k);
502 double bar_dir_perp2_left = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+2)%3, phase, i-dir_i,j-dir_j,k-dir_k);
503 assert((n_left >= 0) || (bar_dir_perp1_left == .5));
504 assert((n_left >= 0) || (bar_dir_perp2_left == .5));
505
506 double bar_dir_perp1_centre = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+1)%3, phase, i,j,k);
507 double bar_dir_perp2_centre = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+2)%3, phase, i,j,k);
508 assert((n_centre >= 0) || (bar_dir_perp1_centre == .5));
509 assert((n_centre >= 0) || (bar_dir_perp2_centre == .5));
510
511 double bar_dir_perp1_right = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+1)%3, phase, i+dir_i,j+dir_j,k+dir_k);
512 double bar_dir_perp2_right = cut_cell_disc.get_interfaces().get_barycentre(true, (dir+2)%3, phase, i+dir_i,j+dir_j,k+dir_k);
513 assert((n_right >= 0) || (bar_dir_perp1_right == .5));
514 assert((n_right >= 0) || (bar_dir_perp2_right == .5));
515
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));
520
521 if (small_perpendicular_distance_left_left && small_perpendicular_distance_left && small_perpendicular_distance_centre && small_perpendicular_distance_right)
522 {
523 // Ne fait rien : on garde le flux_4 quick
524 }
525 else
526 {
527 flux_4 = flux_2;
528 }
529 }
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))
533 {
534 flux_4 = flux_2;
535 }
536 else
537 {
538 Cerr << "OpConvQuickIJKScalar_cut_cell.tpp: cut_cell_conv_scheme_ inconnu pour flux_4." << finl;
540 }
541
542 int phase_mourrante_left_left = cut_cell_disc.get_interfaces().phase_mourrante(phase, indicatrice_left_left, next_indicatrice_left_left);
543 int phase_mourrante_left = cut_cell_disc.get_interfaces().phase_mourrante(phase, indicatrice_left, next_indicatrice_left);
544 int phase_mourrante_centre = cut_cell_disc.get_interfaces().phase_mourrante(phase, indicatrice_centre, next_indicatrice_centre);
545 int phase_mourrante_right = cut_cell_disc.get_interfaces().phase_mourrante(phase, indicatrice_right, next_indicatrice_right);
546 int phase_naissante_left_left = cut_cell_disc.get_interfaces().phase_naissante(phase, indicatrice_left_left, next_indicatrice_left_left);
547 int phase_naissante_left = cut_cell_disc.get_interfaces().phase_naissante(phase, indicatrice_left, next_indicatrice_left);
548 int phase_naissante_centre = cut_cell_disc.get_interfaces().phase_naissante(phase, indicatrice_centre, next_indicatrice_centre);
549 int phase_naissante_right = cut_cell_disc.get_interfaces().phase_naissante(phase, indicatrice_right, next_indicatrice_right);
550 //int petit_left_left = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, indicatrice_left_left, next_indicatrice_left_left);
551 int petit_left = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, indicatrice_left, next_indicatrice_left);
552 int petit_centre = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, indicatrice_centre, next_indicatrice_centre);
553 //int petit_right = cut_cell_disc.get_interfaces().next_below_small_threshold_for_phase(phase, indicatrice_right, next_indicatrice_right);
554
555 double flux_value;
556 if (phase_naissante_centre)
557 {
558 assert(std::abs(input_centre) < 1e-16);
559 //assert(input_centre == 0);
560 flux_value = flux_1l;
561 }
562 else if (phase_naissante_left)
563 {
564 assert(std::abs(input_left) < 1e-16);
565 //assert(input_left == 0);
566 flux_value = flux_1c;
567 }
568 else if (ignore_small_cells_ && (petit_centre || petit_left || phase_mourrante_centre || phase_mourrante_left))
569 {
570 flux_value = 0.;
571 }
572 else if (phase_mourrante_left_left || phase_mourrante_right || phase_naissante_left_left || phase_naissante_right) //|| petit_left_left || petit_right)
573 {
574 assert(phase_invalide_left || (input_left != 0.));
575 assert(phase_invalide_centre || (input_centre != 0.));
576 flux_value = flux_2;
577 }
578 else if ((phase_left_left == phase && (!phase_invalide_left_left)) && (phase_right == phase && (!phase_invalide_right)))
579 {
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);
584 flux_value = flux_4;
585 }
586 else
587 {
588 assert(phase_invalide_left || (input_left != 0.));
589 assert(phase_invalide_centre || (input_centre != 0.));
590 flux_value = flux_2;
591 }
592
593 if (n_centre < 0) // Si la cellule est pure
594 {
595 int index_ijk_per = 0;
596 while (index_ijk_per >= 0)
597 {
598 Int3 ijk = cut_cell_disc.ijk_per_of_index(i, j, k, index_ijk_per);
599 index_ijk_per = cut_cell_disc.next_index_ijk_per(i, j, k, index_ijk_per, 0, 1);
600
601 (*flux)(ijk[0],ijk[1],0) = flux_value;
602 }
603 }
604 else
605 {
606 diph_flux(n_centre) = flux_value;
607 if ((n_left < 0) && (phase == phase_left && (!phase_invalide_centre) && (!phase_invalide_left)))
608 {
609 int index_ijk_per = 0;
610 while (index_ijk_per >= 0)
611 {
612 Int3 ijk = cut_cell_disc.ijk_per_of_index(i, j, k, index_ijk_per);
613 index_ijk_per = cut_cell_disc.next_index_ijk_per(i, j, k, index_ijk_per, 0, 1);
614
615 (*flux)(ijk[0],ijk[1],0) = flux_value;
616 }
617 }
618 }
619
620 // Si on est monophasique de la phase non-existante, le flux devrait etre nul
621 if (phase_invalide_centre || phase_invalide_left)
622 {
623 assert(flux_value == 0.);
624 }
625 }
626 }
627 }
628 }
629 }
630}
631
632#endif
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)
Definition Cut_field.h:116
TRUSTTabFT_cut_cell< _TYPE_ > diph_v_
Definition Cut_field.h:50
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 IJK_Field_double & get_input_velocity(DIRECTION _DIR_)
void compute_curv_fram(DIRECTION _DIR_, int k_layer)
void shift_curv_fram(IJK_Field_local_double &tmp_curv_fram)
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455