TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
OpConvDiscQuickIJKScalar.h
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 OpConvDiscQuickIJKScalar_included
17#define OpConvDiscQuickIJKScalar_included
18
19#include <Operateur_IJK_elem_conv_base.h>
20#include <IJK_ptr.h>
21
23{
24 Declare_instanciable_sans_constructeur(OpConvDiscQuickIJKScalar_double);
25public:
27 void calculer(const IJK_Field_double& field,
28 const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz,
29 IJK_Field_double& result) override;
30 void ajouter(const IJK_Field_double& field,
31 const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz,
32 IJK_Field_double& result) override;
33protected:
34
35 inline void compute_flux_x(IJK_Field_local_double& resu, const int k_layer) override
36 {
37 compute_flux_<DIRECTION::X>(resu,k_layer);
38 }
39 inline void compute_flux_y(IJK_Field_local_double& resu, const int k_layer) override
40 {
41 compute_flux_<DIRECTION::Y>(resu,k_layer);
42 }
43 inline void compute_flux_z(IJK_Field_local_double& resu, const int k_layer) override
44 {
45 compute_flux_<DIRECTION::Z>(resu,k_layer);
46 }
47
48 const IJK_Field_local_double *input_indicatrice_=0;
49
50private:
51
52 template <DIRECTION _DIR_>
53 void compute_flux_(IJK_Field_local_double& resu, const int k_layer);
54
55};
56
57
58template <DIRECTION _DIR_>
59void OpConvDiscQuickIJKScalar_double::compute_flux_(IJK_Field_local_double& resu, const int k_layer)
60{
61 if(_DIR_==DIRECTION::Z)
62 {
63 // The previous layer of curv and fram values might have been computed already
64 if (stored_curv_fram_layer_z_ != k_layer-1)
65 {
66 compute_curv_fram(_DIR_, k_layer-1);
68 }
69 }
70 compute_curv_fram(_DIR_, k_layer);
71
72 ConstIJK_double_ptr velocity_dir(get_input_velocity(_DIR_), 0, 0, k_layer);
73 ConstIJK_double_ptr input_field(*input_field_, 0, 0, k_layer);
74 ConstIJK_double_ptr input_indicatrice(*input_indicatrice_, 0, 0, k_layer);
75 ConstIJK_double_ptr curv_values(tmp_curv_fram_, 0, 0, 1); /* if z direction, "left" will be in layer 0 */
76 ConstIJK_double_ptr fram_values(tmp_curv_fram_, 0, 0, 3); /* if z direction, "left" is in layer 2 */
77 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
78 const int nx = _DIR_==DIRECTION::X ? input_field_->ni() + 1 : input_field_->ni();
79 const int ny = _DIR_==DIRECTION::Y ? input_field_->nj() + 1 : input_field_->nj();
80
81 double dx = 0.0;
82 double surface = 0.0;
83 if(_DIR_==DIRECTION::X)
84 {
85 dx = channel_data_.get_delta_x();
86 surface = channel_data_.get_delta_y() * channel_data_.get_delta_z()[k_layer];
87 }
88 if(_DIR_==DIRECTION::Y)
89 {
90 dx = channel_data_.get_delta_y();
91 surface = channel_data_.get_delta_x() * channel_data_.get_delta_z()[k_layer];
92
93 }
94 if(_DIR_==DIRECTION::Z)
95 {
96 dx = (channel_data_.get_delta_z()[k_layer-1] + channel_data_.get_delta_z()[k_layer]) * 0.5;
97 surface = channel_data_.get_delta_x() * channel_data_.get_delta_y();
98 }
99
100 const double dx_squared_over_8 = dx * dx * 0.125;
101
102 if(_DIR_==DIRECTION::Z)
103 {
104 // Are we on the wall ?
105 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
106 // global index of the layer of flux of the wall
107 // (assume one walls at zmin and zmax)
108 const int first_global_k_layer = 0;
109 const int last_global_k_layer = channel_data_.nb_elem_k_tot();
110
111 // GB 21/12/2020 : Similarly to velocity, we make the same adjustments.
112 // if (global_k_layer == first_global_k_layer || global_k_layer == last_global_k_layer) {
113 // ie (i) replace the former "==" by "<=" and ">=" to be identic to the condition in OpCentre4IJK
114 // and (ii) add the condition on perio_k
115 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
116 {
117 // We are on (or worse inside) the wall, zero flux
118 putzero(resu);
119 return;
120 }
121 }
122
123 const int imax = nx;
124 const int jmax = ny;
125 const int vsize = Simd_double::size();
126 for (int j = 0; ; j++)
127 {
128 for (int i = 0; i < imax; i += vsize)
129 {
130 Simd_double velocity;
131 velocity_dir.get_center(i, velocity);
132 double indm1, ind0, ind1, ind2;
133 input_indicatrice.get_leftleft_left_center_right(_DIR_,i, indm1, ind0, ind1, ind2);
134 const double diphm1 = indm1*(1-indm1)<DMINFLOAT?0:1;
135 const double diph0 = ind0*(1-ind0)<DMINFLOAT?0:1;
136 const double diph1 = ind1*(1-ind1)<DMINFLOAT?0:1;
137 const double diph2 = ind2*(1-ind2)<DMINFLOAT?0:1;
138 //TODO: completer les conditions
139 if ((!diphm1) && (!diph0) && (!diph1) && (!diph2)) //normal
140 {
141 Simd_double T0, T1; // scalar value at left and at right of the computed flux
142 Simd_double fram0, fram1;
143 Simd_double curv0, curv1;
144 input_field.get_left_center(_DIR_, i, T0, T1);
145 fram_values.get_left_center(_DIR_, i, fram0, fram1);
146 curv_values.get_left_center(_DIR_, i, curv0, curv1);
147 Simd_double fram = SimdMax(fram0, fram1);
148 Simd_double curv = SimdSelect<double>(velocity, 0., curv1, curv0);
149 Simd_double T_amont = SimdSelect<double>(velocity, 0., T1 /* if velocity < 0 */, T0 /* if velocity > 0 */);
150 Simd_double flux = (T0 + T1) * 0.5 - dx_squared_over_8 * curv;
151 flux = ((1. - fram) * flux + fram * T_amont) * velocity * surface;
152 resu_ptr.put_val(i, flux);
153 }
154 else if (((diph0) && (diph1)) || ((!diph0) && (!diph1) && (diph2 || diphm1))) // cas centre
155 {
156 Simd_double T0, T1; // scalar value at left and at right of the computed flux
157 input_field.get_left_center(_DIR_, i, T0, T1);
158 Simd_double flux = (T0 + T1) * 0.5 ;
159 flux = flux * velocity * surface;
160 resu_ptr.put_val(i, flux);
161 }
162 else if ((diph1) && (!diph0) && (!diphm1))//schema decentre a gauche
163 {
164 Simd_double Tm1, T0, T1, T2; // scalar value at left and at right of the computed flux
165 input_field.get_leftleft_left_center_right(_DIR_, i, Tm1, T0, T1, T2);
166 Simd_double flux = T0 + (T0 - Tm1)*0.5 ;
167 flux = flux * velocity * surface;
168 resu_ptr.put_val(i, flux);
169 }
170 else if ((diph0) && (!diph1) && (!diph2))//schema decentre a droite
171 {
172 Simd_double T0, T1, T2; // scalar value at left and at right of the computed flux
173 input_field.get_left_center_right(_DIR_, i, T0, T1, T2);
174 Simd_double flux = T1 - (T2 - T1)*0.5 ;
175 flux = flux * velocity * surface;
176 resu_ptr.put_val(i, flux);
177 }
178 else if ((diph1) && (!diph0) && (diphm1))//cas particulier diphasique - mono - diph, on extrapole la valeur mono gauche
179 {
180 Simd_double T0, T1; // scalar value at left and at right of the computed flux
181 input_field.get_left_center(_DIR_, i, T0, T1);
182 Simd_double flux = T0;
183 flux = flux * velocity * surface;
184 resu_ptr.put_val(i, flux);
185 }
186 else if ((diph0) && (!diph1) && (diph2))//cas particulier diphasique - mono - diph, on extrapole la valeur mono droite
187 {
188 Simd_double T0, T1; // scalar value at left and at right of the computed flux
189 input_field.get_left_center(_DIR_, i, T0, T1);
190 Simd_double flux = T1;
191 flux = flux * velocity * surface;
192 resu_ptr.put_val(i, flux);
193 }
194 }
195 // do not execute end_iloop at last iteration (because of assert on valid j+1)
196 if (j+1==jmax)
197 break;
198 input_field.next_j();
199 velocity_dir.next_j();
200 fram_values.next_j();
201 curv_values.next_j();
202 resu_ptr.next_j();
203 }
204
205}
206
207#endif /* OpConvDiscQuickIJKScalar_included */
void compute_flux_x(IJK_Field_local_double &resu, const int k_layer) override
void compute_flux_z(IJK_Field_local_double &resu, const int k_layer) override
void ajouter(const IJK_Field_double &field, const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, IJK_Field_double &result) override
const IJK_Field_local_double * input_indicatrice_
void calculer(const IJK_Field_double &field, const IJK_Field_double &vx, const IJK_Field_double &vy, const IJK_Field_double &vz, IJK_Field_double &result) override
void compute_flux_y(IJK_Field_local_double &resu, const int k_layer) override
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)