TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Operateur_IJK_elem_conv_base.cpp
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#include <Operateur_IJK_elem_conv_base.h>
17
18Implemente_base_sans_constructeur(Operateur_IJK_elem_conv_base_double,"Operateur_IJK_elem_conv_base_double",Operateur_IJK_elem_base_double);
19
20Operateur_IJK_elem_conv_base_double::Operateur_IJK_elem_conv_base_double()
21{
22
24 input_field_ = nullptr;
25 input_velocity_x_ = nullptr;
26 input_velocity_y_ = nullptr;
27 input_velocity_z_ = nullptr;
28 perio_k_ = false;
29 stored_curv_fram_layer_z_ = 0; // which (local) layer is currently stored in layer 0 of the tmp array ?
30
31 corrige_flux_ = nullptr;
32 indicatrice_ = nullptr;
33
34 is_corrected_ = false;
35 is_grad_ = false;
36 is_flux_ = false;
37}
38
40{
41 return os;
42}
43
45{
46 return is;
47}
48
50{
51 perio_k_= splitting.get_periodic_flag(DIRECTION_K);
52 channel_data_.initialize(splitting);
53 input_field_ = nullptr;
54 input_velocity_x_ = nullptr;
55 input_velocity_y_ = nullptr;
56 input_velocity_z_ = nullptr;
57}
58
59void Operateur_IJK_elem_conv_base_double::calculer(const IJK_Field_double& field,
60 const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz,
61 IJK_Field_double& result)
62{
63 // Si ce test plante, c'est qu'on a oublie d'appeler la methode initialize() !!!
64 assert(channel_data_.get_delta_z().size() == field.nk());
65
69 input_field_ = &field;
70 stored_curv_fram_layer_z_ = -1000; // put a non-existant layer index: curv_fram will be computed at first call
71 // Storage for curvature and fram limiter. We need 1 ghost layer:
72 // flux at left of the leftmost field data requires curv and fram on the element at left
73 // flux at the right of the rightmost field data requires on the element at right
74 // We need 4 layers of temporary storage: curv and fram, and, for each, two consecutive layers in z
75 const int ni = field.ni();
76 const int nj = field.nj();
77 tmp_curv_fram_.allocate(ni, nj, 4, 1);
78 compute_set(result);
79 input_field_ = nullptr;
80 input_velocity_x_ = nullptr;
81 input_velocity_y_ = nullptr;
82 input_velocity_z_ = nullptr;
84}
85
86void Operateur_IJK_elem_conv_base_double::ajouter(const IJK_Field_double& field,
87 const IJK_Field_double& vx, const IJK_Field_double& vy, const IJK_Field_double& vz,
88 IJK_Field_double& result)
89{
90 // Si ce test plante, c'est qu'on a oublie d'appeler la methode initialize() !!!
91 assert(channel_data_.get_delta_z().size() == field.nk());
92
96 input_field_ = &field;
97 stored_curv_fram_layer_z_ = -1000; // put a non-existant layer index: curv_fram will be computed at first call
98 // Storage for curvature and fram limiter. We need 1 ghost layer:
99 // flux at left of the leftmost field data requires curv and fram on the element at left
100 // flux at the right of the rightmost field data requires on the element at right
101 // We need 4 layers of temporary storage: curv and fram, and, for each, two consecutive layers in z
102 const int ni = field.ni();
103 const int nj = field.nj();
104 tmp_curv_fram_.allocate(ni, nj, 4, 1);
105 compute_add(result);
106 input_field_ = nullptr;
107 input_velocity_x_ = nullptr;
108 input_velocity_y_ = nullptr;
109 input_velocity_z_ = nullptr;
110 velocity_frame_of_reference_ = {0.,0.,0.};
111}
112
113// Copy curv_fram values from layers 1 and 3 to layers 0 and 2
114// (called at end of the computation of fluxes in z direction to keep the values
115// for the next layer).
116void Operateur_IJK_elem_conv_base_double::shift_curv_fram(IJK_Field_local_double& tmp_curv_fram)
117{
118 const int ni = tmp_curv_fram.ni();
119 const int nj = tmp_curv_fram.nj();
120 int i, j;
121
122 for (j = 0; j < nj; j++)
123 for (i = 0; i < ni; i++)
124 tmp_curv_fram(i,j,0) = tmp_curv_fram(i,j,1);
125
126 for (j = 0; j < nj; j++)
127 for (i = 0; i < ni; i++)
128 tmp_curv_fram(i,j,2) = tmp_curv_fram(i,j,3);
129
130}
131
132
133// compute the "curv" value and part of the fram limiter (in the Fram routine from Eval_Quick_VDF_Elem.h) for 3 adjacent T values
134// store result in tmp_curv_fram_, z layer=1 (curv) and z layer=3 (fram)
136{
137 int index = _DIR_ == DIRECTION::Y ? -1 : 0;
138 ConstIJK_double_ptr input_field(*input_field_, 0, index, k_layer);
139 // Where to store result:
140 IJK_double_ptr curv_values(tmp_curv_fram_, 0, index, 1);
141 IJK_double_ptr fram_values(tmp_curv_fram_, 0, index, 3);
142 const int ni = tmp_curv_fram_.ni();
143 const int nj = tmp_curv_fram_.nj();
144
145 if(_DIR_ == DIRECTION::Z)
146 {
147 // Are we on the wall ?
148 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
149 // global index of the layer of flux of the wall
150 // (assume one walls at zmin and zmax)
151 const int first_global_k_layer = 0;
152 const int last_global_k_layer = channel_data_.nb_elem_k_tot();
153
154 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
155 {
156 for (int j = 0; j < nj; j++)
157 for (int i = 0; i < ni; i++)
158 tmp_curv_fram_(i, j, 1) = 0.;
159 for (int j = 0; j < nj; j++)
160 for (int i = 0; i < ni; i++)
161 tmp_curv_fram_(i, j, 3) = 1.; // fram = 1 => upwind scheme on first layer of cells in z direction.
162
163 return;
164 }
165 }
166
167 double factor01 = -1.0;
168 double factor12 = -1.0;
169 if(_DIR_==DIRECTION::X)
170 {
171 // Compute invd1 and invd2 factors:
172 const double inv_dx = 1./channel_data_.get_delta_x();
173 factor01 = inv_dx * inv_dx;
174 factor12 = factor01;
175 }
176 if(_DIR_==DIRECTION::Y)
177 {
178 // Compute invd1 and invd2 factors:
179 const double inv_dy = 1. / channel_data_.get_delta_y();
180 factor01 = inv_dy * inv_dy;
181 factor12 = factor01;
182 }
183 if(_DIR_==DIRECTION::Z)
184 {
185 // Compute invd1 and invd2 factors:
186 const double dz0 = channel_data_.get_delta_z()[k_layer-1];
187 const double dz1 = channel_data_.get_delta_z()[k_layer];
188 const double dz2 = channel_data_.get_delta_z()[k_layer+1];
189 factor01 = 1. / (dz1 * (dz0 + dz1) * 0.5);
190 factor12 = 1. / (dz1 * (dz1 + dz2) * 0.5);
191 }
192
193 const int vsize = Simd_double::size();
194 const int imax = _DIR_==DIRECTION::X ? ni + 1 : ni;
195 const int imax1 = imax - (vsize-1); // test to check for end of vectorizable part
196 const int jmax = _DIR_==DIRECTION::Y ? nj + 1 : nj;
197 const int imin = _DIR_ == DIRECTION::X ? -1:0;
198 const int jmin = _DIR_ == DIRECTION::Y ? -1:0;
199 /*
200 * DEV Dorian DUPUY and Yanis ZATOUT: Bug in curv farm computation
201 * due to not taking into account the extra cell in the I and J direction
202 * for the offset in each parallel domain.
203 */
204 for (int j = jmin; ; j++)
205 {
206 int i;
207 for (i = imin; i < 0; i++)
208 compute_curv_fram_loop_(_DIR_, i, factor12, factor01, input_field, curv_values, fram_values );
209
210 for (i = 0; i < imax1; i += vsize)
211 {
212 Simd_double t0 = 0., t1 = 0., t2 = 0.;
213 input_field.get_left_center_right(_DIR_, i, t0, t1, t2);
214 Simd_double curv = (t2 - t1) * factor12 - (t1 - t0) * factor01;
215 curv_values.put_val(i, curv);
216 Simd_double smin = SimdMin(t0, t2);
217 Simd_double smax = SimdMax(t0, t2);
218 // Compared to original code (Eval_Quick_VDF_Elem.h), we first compute the 4th power,
219 // then take the max (dabs is then useless)
220 Simd_double zeroVec = 0.;
221 Simd_double oneVec = 1.;
222 Simd_double minVec = DMINFLOAT;
223 Simd_double dsabs = SimdSelect(zeroVec, smax - smin, smax - smin, smin - smax);
224 Simd_double ds = SimdSelect(dsabs, minVec, oneVec, smax - smin);
225 Simd_double sr = SimdSelect(dsabs, minVec, zeroVec, ((t1 - smin) / ds - 0.5) * 2.);
226 sr *= sr;
227 sr *= sr;
228 sr = SimdMin(sr, oneVec);
229
230 fram_values.put_val(i, sr);
231 }
232 for (; i < imax; i++) compute_curv_fram_loop_(_DIR_, i, factor12, factor01, input_field, curv_values, fram_values );
233
234 // do not execute end_iloop at last iteration (because of assert on valid j+1)
235 if (j+1==jmax)
236 break;
237 input_field.next_j();
238 curv_values.next_j();
239 fram_values.next_j();
240
241 }
242}
243
244void Operateur_IJK_elem_conv_base_double::compute_curv_fram_loop_(DIRECTION _DIR_, int iter, double factor12, double factor01, const ConstIJK_double_ptr& input_field, IJK_double_ptr& curv_values, IJK_double_ptr& fram_values )
245{
246 double t0 = 0., t1 = 0., t2 = 0.;
247 input_field.get_left_center_right(_DIR_, iter, t0, t1, t2);
248 double curv = (t2 - t1) * factor12 - (t1 - t0) * factor01;
249 curv_values.put_val(iter, curv);
250 double smin = std::min(t0, t2);
251 double smax = std::max(t0, t2);
252 // Compared to original code (Eval_Quick_VDF_Elem.h), we first compute the 4th power,
253 // then take the max (dabs is then useless)
254 double sr = std::fabs(smax - smin)<DMINFLOAT ? 0. : ((t1 - smin) / (smax - smin) - 0.5) * 2.;
255 sr *= sr;
256 sr *= sr;
257 sr = std::min(sr, 1.);
258
259 fram_values.put_val(iter, sr);
260}
261
void get_left_center_right(DIRECTION _DIR_, int i_offset, _TYPE_ &left, _TYPE_ &center, _TYPE_ &right) const
void next_j()
increments the pointer by j_stride (eg, j = j+1)
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
bool get_periodic_flag(int direction) const
Method returns true if periodic in this direction.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
void put_val(int i_offset, const _TYPE_ &val)
Performs the assignment: field(i+i_offset,j,k) = val.
Definition IJK_ptr.h:32
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
virtual void compute_add(IJK_Field_double &dx)
virtual void compute_set(IJK_Field_double &dx)
virtual 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)
void initialize(const Domaine_IJK &splitting) override
void compute_curv_fram(DIRECTION _DIR_, int k_layer)
void shift_curv_fram(IJK_Field_local_double &tmp_curv_fram)
virtual 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)
Classe de base des flux de sortie.
Definition Sortie.h:52