TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Operateur_IJK_faces_diff_base.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 Operateur_IJK_faces_diff_base_TPP_included
17#define Operateur_IJK_faces_diff_base_TPP_included
18
19#include <Operateur_IJK_faces_diff_base.h>
20
21#ifndef Operateur_IJK_faces_diff_base_included
22#error __FILE__ should only be included from corresponding header
23#endif
24
25
26/*
27 * Options for CASE
28 *
29 * Yes_Turb: the flux is turbulent_mu * (grad u + grad^T u) - 2/3 * k + molecular_mu * grad u)'
30 * Yes_M_Grad: the flux is 'molecular_mu * grad u'
31 * Yes_M_Trans: the flux is 'molecular_mu * (grad u + grad^T u)'
32 * Yes_M_Div: the flux is 'molecular_mu * (grad u + grad^T u - 2/3 * div u * Id)'
33 * Yes_M_GradAnisotropic: the flux is 'molecular_mu^a * grad^a u' where (grad^a)_i = Delta_i (grad)_i
34 * Yes_M_TransAnisotropic: the flux is 'molecular_mu^a * (grad^a u + grad^a^T u)' where (grad^a)_i = Delta_i (grad)_i
35 * Yes_M_DivAnisotropic: the flux is 'molecular_mu^a * (grad^a u + grad^a^T u - 2/3 * div^a u * Id)' where (grad^a)_i = Delta_i (grad)_i
36 * Yes_M_GradTensorial: the flux is 'molecular_mu_tensor * grad u'
37 * Yes_M_TransTensorial: the flux is 'molecular_mu_tensor * (grad u + grad^T u)'
38 * Yes_M_DivTensorial: the flux is 'molecular_mu_tensor * (grad u + grad^T u - 2/3 * div u * Id)'
39 * Yes_M_GradTensorialAnisotropic: the flux is 'molecular_mu_tensor^a * grad^a u' where (grad^a)_i = Delta_i (grad)_i
40 * Yes_M_TransTensorialAnisotropic: the flux is 'molecular_mu_tensor^a * (grad^a u + grad^a^T u)' where (grad^a)_i = Delta_i (grad)_i
41 * Yes_M_DivTensorialAnisotropic: the flux is 'molecular_mu_tensor^a * (grad^a u + grad^a^T u - 2/3 * div^a u * Id)' where (grad^a)_i = Delta_i (grad)_i
42 * Yes_M_Struct: the flux is 'structural_model'
43 */
44
45/*! @brief compute fluxes in direction DIR for velocity component COMPO for the layer of fluxes k_layer
46 *
47 * Diffusion
48 *
49 */
50template<DIRECTION _DIR_, DIRECTION _VCOMPO_>
51void Operateur_IJK_faces_diff_base_double::compute_flux_(IJK_Field_local_double& resu, const int k_layer)
52{
53 const int idir = (int)_DIR_;
54 const int icompo = (int)_VCOMPO_;
55
56 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
57 // global index of the layer of flux of the wall
58 // (assume one walls at zmin and zmax)
59 const int first_global_k_layer = channel_data_.first_global_k_layer_flux(icompo, idir);
60 const int last_global_k_layer = channel_data_.last_global_k_layer_flux(icompo, idir);
61
62 Boundary_Conditions::BCType bc_type = ref_bc_->get_bctype_k_min();
63
64 // for mixte_shear boundary condition >> need to localize to and bottom boundary even if perio_k
66 {
67 // For this direction and this component, we possibly have a wall boundary condition to treat:
68 if(_DIR_ == DIRECTION::Z && _VCOMPO_ != DIRECTION::Z)
69 {
70 int top_wall = 0, bottom_wall = 0;
71 // We are at bottom wall: z=0
72 if (global_k_layer == first_global_k_layer-1)
73 {
74 bc_type = ref_bc_->get_bctype_k_min();
75 bottom_wall = 1;
76 }
77 if (global_k_layer == last_global_k_layer + 1)
78 {
79 bc_type = ref_bc_->get_bctype_k_max();
80 top_wall = 1;
81 }
82
83 if(bottom_wall || top_wall)
84 {
85 switch(bc_type)
86 {
88 {
89 flux_loop_<_DIR_, _VCOMPO_>(resu, k_layer, top_wall, bottom_wall);
90 break;
91 }
93 {
94 flux_loop_<_DIR_, _VCOMPO_>(resu, k_layer, top_wall, bottom_wall);
95 break;
96 }
98 {
99 // Symetry boundary condition: momentum flux is zero
100 putzero(resu);
101 break;
102 }
103 default:
104 Cerr << "Operateur_IJK_faces_diff_base_double::compute_flux_ wrong boundary condition." << finl;
106 }
107 return;
108 }
109 }
110
111 if (global_k_layer < first_global_k_layer || global_k_layer > last_global_k_layer)
112 {
113 // We are inside the wall
114 putzero(resu);
115 return;
116 }
117 }
118
119 flux_loop_<_DIR_, _VCOMPO_>(resu, k_layer);
120}
121
122
123template<DIRECTION _DIR_, DIRECTION _VCOMPO_>
124void Operateur_IJK_faces_diff_base_double::flux_loop_(IJK_Field_local_double& resu, int k_layer, int top_wall, int bottom_wall )
125{
126 const IJK_Field_local_double& vCOMPO = get_v(_VCOMPO_);
127 const IJK_Field_local_double& vDIR = get_v(_DIR_);
128
129 const int idir = (int)_DIR_;
130 const int nx = _DIR_ == DIRECTION::X ? vCOMPO.ni() + 1 : vCOMPO.ni() ;
131 const int ny = _DIR_ == DIRECTION::Y ? vCOMPO.nj() + 1 : vCOMPO.nj();
132 const int icompo = (int)_VCOMPO_;
133
134 const double surface = - channel_data_.get_surface(k_layer, icompo, idir);
135 const double inv_distance_COMPO = channel_data_.inv_distance_for_gradient(k_layer, idir, icompo);
136 const double inv_distance_DIR = channel_data_.inv_distance_for_gradient(k_layer, icompo, idir);
137
138 // Velocity field
139 ConstIJK_double_ptr vCOMPO_ptr(vCOMPO, 0, 0, k_layer);
140 ConstIJK_double_ptr vDIR_ptr(vDIR, 0, 0, k_layer);
141
142 const IJK_Field_local_double& dummy_field = vCOMPO;
143
144 ConstIJK_double_ptr molecular_nu(!is_structural_ ? (is_tensorial_? get_coeff_tensor(_VCOMPO_, _DIR_) : get_nu()) : dummy_field , 0, 0, k_layer);
145
146 ConstIJK_double_ptr div_ptr(with_divergence_ ? get_divergence() : dummy_field, 0, 0, k_layer);
147
148 // Turbulent kinetic energy from turbulence model
149 // ConstIJK_double_ptr turbulent_nu(is_turb_ ? get_turbulent_nu() : dummy_field, 0, 0, k_layer);
150 // ConstIJK_double_ptr turbulent_k_energy(is_turb_ ? get_turbulent_k_energy() : dummy_field, 0, 0, k_layer );
151 // ConstIJK_double_ptr structural_model(is_structural_ ? get_structural_model(_DIR_, _VCOMPO_) : dummy_field, 0, 0, k_layer);
152 // ConstIJK_double_ptr structural_model(is_structural_ ? get_coeff_tensor(_DIR_, _VCOMPO_) : dummy_field, 0, 0, k_layer);
153
154 /*
155 * Y.Z.: If the model is functional (i.e. not structural) then lambda takes the right value, and the "structural_model" variable points to dummy_field.
156 * Otherwise the model is structural then lambda points towards the dummy_field.
157 */
158 ConstIJK_double_ptr turbulent_nu (is_turb_ ? get_nu() : dummy_field, 0, 0, k_layer);
159 ConstIJK_double_ptr turbulent_k_energy(is_turb_ ? get_nu() : dummy_field, 0, 0, k_layer );
160 ConstIJK_double_ptr structural_model(is_structural_ ? get_coeff_tensor(_DIR_, _VCOMPO_) : dummy_field, 0, 0, k_layer);
161
162 // Result (fluxes in direction DIR for component COMPO of the convected field)
163 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
164
165 const int imax = nx;
166 const int jmax = ny;
167 const int vsize = Simd_double::size();
168 for (int j = 0; ; j++)
169 {
170 for (int i = 0; i < imax; i += vsize)
171 {
172 Simd_double flux = 0.;
173 if(_DIR_ == _VCOMPO_)
174 {
175 flux_loop_same_dir_compo_<_DIR_, _VCOMPO_>(i, surface, inv_distance_DIR, inv_distance_COMPO,
176 vCOMPO_ptr, vDIR_ptr,
177 molecular_nu, div_ptr,
178 turbulent_nu, turbulent_k_energy,
179 structural_model, flux);
180 }
181 else
182 {
183 flux_loop_different_dir_compo_<_DIR_, _VCOMPO_>(i, surface, inv_distance_DIR, inv_distance_COMPO,
184 top_wall, bottom_wall,
185 vCOMPO_ptr, vDIR_ptr,
186 molecular_nu, div_ptr,
187 turbulent_nu, turbulent_k_energy,
188 structural_model, flux);
189
190 }
191 resu_ptr.put_val(i, flux);
192
193 }
194 // do not execute end_iloop at last iteration (because of assert on valid j+1)
195 if (j+1==jmax)
196 break;
197 // instructions to perform to jump to next row
198 vCOMPO_ptr.next_j();
199 if(_DIR_ != _VCOMPO_)
200 vDIR_ptr.next_j();
201 if(!is_structural_)
202 molecular_nu.next_j();
203 if(is_turb_)
204 {
205 turbulent_nu.next_j();
206 turbulent_k_energy.next_j();
207 }
209 div_ptr.next_j();
211 structural_model.next_j();
212
213 resu_ptr.next_j();
214
215 }
216}
217
218template<DIRECTION _DIR_, DIRECTION _VCOMPO_>
219void Operateur_IJK_faces_diff_base_double::flux_loop_same_dir_compo_(int i, double surface, double inv_distance_DIR, double inv_distance_COMPO,
220 const ConstIJK_double_ptr& vCOMPO_ptr, const ConstIJK_double_ptr& vDIR_ptr,
221 const ConstIJK_double_ptr& molecular_nu, const ConstIJK_double_ptr& div_ptr,
222 const ConstIJK_double_ptr& turbulent_nu, const ConstIJK_double_ptr& turbulent_k_energy,
223 const ConstIJK_double_ptr& structural_model, Simd_double& flux )
224{
226 {
227 Simd_double s_mo, s_mo_dummy;
228 structural_model.get_left_center(_DIR_, i, s_mo, s_mo_dummy);
229 flux = s_mo * surface;
230 }
231 else
232 {
233 // recoding of Eval_Dift_VDF_var_Face::flux_fa7_elem
234 Simd_double m_nu, m_nu_dummy;
235 // flux is between left face and center face, hence, it is centered on the "left" cell
236 molecular_nu.get_left_center(_DIR_, i, m_nu, m_nu_dummy);
237 Simd_double v1, v2;
238 vCOMPO_ptr.get_left_center(_VCOMPO_, i, v1, v2);
239 Simd_double tau = (v2 - v1);
240 if(!is_anisotropic_) tau *= inv_distance_COMPO;
241
242 Simd_double minus_reyn = 0.;
243 if(is_turb_)
244 {
245 Simd_double t_nu, t_nu_dummy;
246 turbulent_nu.get_left_center(_DIR_, i, t_nu, t_nu_dummy);
247 minus_reyn = t_nu * tau * (2.);
248 // Shall we include "k" or not ? If we do, it is equivalent to adding
249 // grad(k) to the rhs of Navier Stokes, il we be "eaten" by the pressure
250 // solver.
251 Simd_double k, k_dummy;
252 // flux is between left face and center face, hence, it is centered on the "left" cell
253 turbulent_k_energy.get_left_center(_DIR_, i, k, k_dummy);
254 minus_reyn += (-0.66666666666666666) * k;
255 // Check that diagonal terms of the Reynolds tensor are positive
256 // (exactly copied from Eval_Dift_VDF_var_Face::flux_fa7_elem)
257 Simd_double zeroVec = 0.;
258 minus_reyn = SimdMin(minus_reyn, zeroVec);
259 }
260
261 flux = (minus_reyn + m_nu * tau) * surface;
262
264 flux *= 2.; // The factor 2. is because tau_tr = tau
265
267 {
268 Simd_double v5, v6_dummy;
269 div_ptr.get_left_center(_DIR_,i, v5, v6_dummy);
270 flux -= m_nu * surface * 0.66666666666666666 * v5; // The factor 2. is because tau_tr = tau
271 }
272
273 }
274
275}
276
277template<DIRECTION _DIR_, DIRECTION _VCOMPO_>
278void Operateur_IJK_faces_diff_base_double::flux_loop_different_dir_compo_(int i, double surface, double inv_distance_DIR, double inv_distance_COMPO, int top_wall, int bottom_wall,
279 const ConstIJK_double_ptr& vCOMPO_ptr, const ConstIJK_double_ptr& vDIR_ptr,
280 const ConstIJK_double_ptr& molecular_nu, const ConstIJK_double_ptr& div_ptr,
281 const ConstIJK_double_ptr& turbulent_nu, const ConstIJK_double_ptr& turbulent_k_energy,
282 const ConstIJK_double_ptr& structural_model, Simd_double& flux )
283{
284
286 {
287 Simd_double s_mo, s_mo_dummy;
288 structural_model.get_left_center(_DIR_, i, s_mo_dummy, s_mo);
289 // recoding of Eval_Dift_VDF_var_Face::flux_arete_interne
290 // gradient in direction x of component y
291 Simd_double v3, v4;
292 vCOMPO_ptr.get_left_center(_DIR_, i, v3, v4);
293 flux = s_mo * surface;
294
295 }
296 else
297 {
298
299 Boundary_Conditions::BCType bc_type = ref_bc_->get_bctype_k_min();
300 // Interpolate diffusion coefficient from values at elements:
301 Simd_double m_nu1, m_nu2, m_nu3, m_nu4;
302 molecular_nu.get_left_center_c1c2(_DIR_, _VCOMPO_, i, m_nu1, m_nu2, m_nu3, m_nu4);
303 double mult_coeff = 0.25;
304
305//antoine_mu_harmonic
306 // for wall boundary conditions
307 if(bottom_wall && bc_type!=Boundary_Conditions::Mixte_shear)
308 {
309 // bottom wall (z=0)
310 // nu1 and nu2 are "left" in direction z, hence in the wall:
311 if (harmonic_nu_)
312 {
313 m_nu1 = 1., m_nu2 = -1.;
314 }
315 else
316 {
317 m_nu1 = 0., m_nu2 = 0.;
318 }
319 mult_coeff = 0.5;
320 }
321 // for wall boundary conditions
322 if(top_wall && bc_type!=Boundary_Conditions::Mixte_shear)
323 {
324 // top wall (z=zmax)
325 // nu3 and nu4 are "center" in direction z, hence in the wall:
326 if (harmonic_nu_)
327 {
328 m_nu3 = 1., m_nu4 = -1.;
329 }
330 else
331 {
332 m_nu3 = 0., m_nu4 = 0.;
333 }
334 mult_coeff = 0.5;
335 }
336 // recoding of Eval_Dift_VDF_var_Face::flux_arete_interne
337 Simd_double m_nu;
338
339 if (harmonic_nu_)
340 {
341 // 1/mult_coeff = 4 or 2 at the wall
342 m_nu = (1/mult_coeff)/(1./m_nu1 + 1./m_nu2 + 1./m_nu3 + 1./m_nu4) ;
343 }
344 else
345 {
346 m_nu = (m_nu1 + m_nu2 + m_nu3 + m_nu4) * mult_coeff;
347 }
348 // gradient in direction DIR of component COMPO
349 Simd_double v3, v4;
350 vCOMPO_ptr.get_left_center(_DIR_, i, v3, v4);
351
352 // for wall(or mooving wall) boundary conditions
353 if(top_wall && bc_type!=Boundary_Conditions::Mixte_shear)
354 {
355 if(_VCOMPO_ == DIRECTION::X)
356 {
357 v4 = ref_bc_->get_vx_kmax();
358 }
359 else
360 {
361 v4 = 0.;
362 }
363 }
364 if(bottom_wall && bc_type!=Boundary_Conditions::Mixte_shear)
365 {
366 if(_VCOMPO_ == DIRECTION::X)
367 {
368 v3 = ref_bc_->get_vx_kmin();
369 }
370 else
371 {
372 v3 = 0.;
373 }
374 }
375
376
377 Simd_double tau = (v4 - v3);
378 if(!is_anisotropic_)
379 tau *= inv_distance_DIR;
380
381 Simd_double tau_tr = 0.;
383 {
384 // gradient in direction COMPO of component DIR
385 if(!bottom_wall && !top_wall)
386 {
387 Simd_double v1, v2;
388 vDIR_ptr.get_left_center(_VCOMPO_, i, v1, v2);
389 tau_tr = (v2 - v1);
390 if(!is_anisotropic_)
391 tau_tr *= inv_distance_COMPO;
392 }
393 }
394
395 Simd_double reyn = 0.;
396 if(is_turb_)
397 {
398 Simd_double t_nu1, t_nu2, t_nu3, t_nu4;
399 turbulent_nu.get_left_center_c1c2(_DIR_, _VCOMPO_, i, t_nu1, t_nu2, t_nu3, t_nu4);
400
401 mult_coeff = 0.25;
402 if(bottom_wall)
403 {
404 t_nu1 = 0., t_nu2 = 0.;
405 mult_coeff = 0.5;
406 }
407 if(top_wall)
408 {
409 t_nu3 = 0., t_nu4 = 0.;
410 mult_coeff = 0.5;
411 }
412 Simd_double t_nu = (t_nu1 + t_nu2 + t_nu3 + t_nu4) * mult_coeff;
413 // gradient in direction COMPO of component DIR
414 if(!bottom_wall && !top_wall)
415 {
416 Simd_double v1, v2;
417 vDIR_ptr.get_left_center(_VCOMPO_, i, v1, v2);
418 tau_tr = (v2 - v1) * inv_distance_COMPO;
419 }
420 reyn = (tau + tau_tr) * t_nu;
421 }
422
423 flux = (m_nu * (tau+tau_tr) + reyn) * surface;
424 }
425}
426
427#endif
void get_left_center_c1c2(DIRECTION _COMPO1_, DIRECTION _COMPO2_, int i_offset, Simd_template< _TYPE_ > &leftc1_leftc2, Simd_template< _TYPE_ > &leftc1_centerc2, Simd_template< _TYPE_ > &centerc1_leftc2, Simd_template< _TYPE_ > &centerc1_centerc2) const
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_ &center) const
returns left=field(i+i_offset-1, j, k) and center=field(i+i_offset, j, k)
void put_val(int i_offset, const _TYPE_ &val)
Performs the assignment: field(i+i_offset,j,k) = val.
Definition IJK_ptr.h:32
const IJK_Field_local_double & get_v(DIRECTION _DIR_)
void flux_loop_(IJK_Field_local_double &resu, int k_layer, int top_wall=0, int bottom_wall=0)
void flux_loop_different_dir_compo_(int i, double surface, double inv_distance_DIR, double inv_distance_COMPO, int top_wall, int bottom_wall, const ConstIJK_double_ptr &vCOMPO_ptr, const ConstIJK_double_ptr &vDIR_ptr, const ConstIJK_double_ptr &molecular_nu, const ConstIJK_double_ptr &div_ptr, const ConstIJK_double_ptr &turbulent_nu, const ConstIJK_double_ptr &turbulent_k_energy, const ConstIJK_double_ptr &structural_model, Simd_double &flux)
void flux_loop_same_dir_compo_(int i, double surface, double inv_distance_DIR, double inv_distance_COMPO, const ConstIJK_double_ptr &vCOMPO_ptr, const ConstIJK_double_ptr &vDIR_ptr, const ConstIJK_double_ptr &molecular_nu, const ConstIJK_double_ptr &div_ptr, const ConstIJK_double_ptr &turbulent_nu, const ConstIJK_double_ptr &turbulent_k_energy, const ConstIJK_double_ptr &structural_model, Simd_double &flux)
const IJK_Field_local_double & get_coeff_tensor(DIRECTION _COMPO1_, DIRECTION _COMPO2_)
void compute_flux_(IJK_Field_local_double &resu, const int k_layer)
compute fluxes in direction DIR for velocity component COMPO for the layer of fluxes k_layer
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455