TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
OpConvCentre4IJK.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#ifndef OpConvCentre4IJK_TPP_included
16#define OpConvCentre4IJK_TPP_included
17
18#include <OpConvCentre4IJK.h>
19
20#ifndef OpConvCentre4IJK_included
21#error __FILE__ should only be included from corresponding header
22#endif
23
24#include <ConstIJK_ptr.h>
25#include <Domaine_IJK.h>
26#include <IJK_Field.h>
27#include <IJK_Field_local_template.h>
28#include <IJK_Field_template.h>
29#include <IJK_ptr.h>
30#include <Operateur_IJK_base.h>
31#include <Simd_template.h>
32
33// Methode appelee a chaque couche de vitesses calculees, apres le calcul de la divergence du flux
34// div(u x rho_u) pour la composante _DIR_ de vitesse, par Operateur_IJK_faces_base_double::compute_
35// On ajoute ici u * div(rho_u) si c'est necessaire
36template <DIRECTION _DIR_>
37void OpConvCentre4IJK_double::exec_after_divergence_flux_(IJK_Field_double& resu, const int k_layer)
38{
39 if (div_rho_u_ == 0)
40 return;
41
42 if (_DIR_==DIRECTION::Z)
43 {
44 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
45 // global index of the layer of flux of the wall
46 // (assume one walls at zmin and zmax)
47 const int first_global_k_layer = 0;
48 const int last_global_k_layer = resu.get_domaine().get_nb_items_global(Domaine_IJK::FACES_K, DIRECTION_K) - 1;
49
50 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
51 {
52 return; // pas de calcul pour les faces en paroi (de toutes facons, v=0)
53 }
54 }
55 // Calcul de div(rho_u) sur la couche, si besoin
57 {
58 // Il faut calculer une couche de div_rhou:
59 calculer_div_rhou(*inputx_, *inputy_, *inputz_, *div_rho_u_, k_layer, channel_data_);
61 }
62 ConstIJK_double_ptr vitesse(get_v(_DIR_), 0, 0, k_layer);
63 ConstIJK_double_ptr div_rhou(*div_rho_u_, 0, 0, k_layer);
64 IJK_double_ptr resu_ptr(resu, 0, 0, k_layer);
65
66 const int nx = resu.ni();
67 const int ny = resu.nj();
68
69 const int imax = nx;
70 const int jmax = ny;
71 const int vsize = Simd_double::size();
72 for (int j = 0; ; j++)
73 {
74 for (int i = 0; i < imax; i += vsize)
75 {
76 Simd_double v, x_left, x_right;
77 vitesse.get_center(i, v);
78 // on prend div(rho_u) dans les elements a gauche et a droite de la face
79 // rappel: l'element a gauche de la face i est a l'indice i-1
80 div_rhou.get_left_center(_DIR_, i, x_left, x_right);
81 // calcul du produit vitesse * div(rho_u)
82 // en prenant div(rho_u) sur le volume de controle de la face (c'est l'integrale de div(rho_u)
83 // qui est stocke, donc ici moyenne au sens volume fini)
84 Simd_double a;
85 resu_ptr.get_center(i, a);
86 a += (x_left + x_right) * 0.5 * v;
87 resu_ptr.put_val(i, a);
88 }
89 // do not execute end_iloop at last iteration (because of assert on valid j+1)
90 if (j+1==jmax)
91 break;
92 // instructions to perform to jump to next row
93 vitesse.next_j();
94 div_rhou.next_j();
95 resu_ptr.next_j();
96 }
97
98
99}
100
101/*! @brief compute fluxes in direction DIR for velocity component COMPO for the layer of fluxes k_layer
102 *
103 * 4-th order centered convection scheme
104 *
105 */
106template <DIRECTION _DIR_, DIRECTION _VCOMPO_>
107void OpConvCentre4IJK_double::compute_flux_(IJK_Field_local_double& resu, const int k_layer)
108{
109 // convected field
110 const IJK_Field_local_double& src = get_input(_VCOMPO_);
111 // Convected vector field:
112 ConstIJK_double_ptr src_ptr(src, 0, 0, k_layer);
113 // Velocity in direction _DIR_ (convecting velocity)
114 ConstIJK_double_ptr vconv_ptr(get_v(_DIR_), 0, 0, k_layer);
115
116 const int idir = (int)_DIR_;
117 const int nx = _DIR_ == DIRECTION::X ? src.ni() + 1 : src.ni();
118 const int ny = _DIR_ == DIRECTION::Y ? src.nj() + 1 : src.nj();
119 const int icompo = (int)_VCOMPO_;
120
121 // Result (fluxes in direction x for component x of the convected field)
122 IJK_double_ptr resu_ptr(resu, 0, 0, 0);
123
124 const int global_k_layer = k_layer + channel_data_.offset_to_global_k_layer();
125 // global index of the layer of flux of the wall
126 // (assume one walls at zmin and zmax)
127 const int first_global_k_layer = channel_data_.first_global_k_layer_flux(icompo, idir);
128 const int last_global_k_layer = channel_data_.last_global_k_layer_flux(icompo, idir);
129
130
131
132
133 if (!perio_k_ && (global_k_layer <= first_global_k_layer || global_k_layer >= last_global_k_layer))
134 {
135 // We are in the wall
136 putzero(resu);
137 return;
138 }
139
140 // constant or variable coefficients depending on mesh.
141 // second order degeneration is handeled here by setting appropriate coefficients:
142 double g1, g2, g3, g4;
143 double constant_factor0, constant_factor1;
144 // surface of left face will be multiplied by velocity of right face, and reversed...
145 channel_data_.get_surface_leftright(k_layer, icompo, idir, constant_factor1, constant_factor0);
146 constant_factor0 *= 0.5;
147 constant_factor1 *= 0.5;
148
149 if (_DIR_ != DIRECTION::Z || channel_data_.is_k_uniform_and_periodic())
150 {
151 // Specific coding for an uniform _and_ periodic grid along a given direction.
152 // An uniform but non-periodic grid may have different g coefficients near walls, thus is not included.
153 g1 = g4 = -0.0625;
154 g2 = g3 = 0.5625;
155 }
156 else
157 {
158 // Specific coding for non-uniform or non-periodic grid.
159 // This only concerns the Z direction, as X and Y directions are always assumed to be uniform and periodic.
160 g1 = get_g(k_layer,icompo,idir,0);
161 g2 = get_g(k_layer,icompo,idir,1);
162 g3 = get_g(k_layer,icompo,idir,2);
163 g4 = get_g(k_layer,icompo,idir,3);
164 }
165
166 {
167 const int imax = nx;
168 const int jmax = ny;
169 const int vsize = Simd_double::size();
170 for (int j = 0; ; j++)
171 {
172 for (int i = 0; i < imax; i += vsize) // specific coding for uniform mesh in x and y: surfaces are constant on an xy plane
173 {
174 Simd_double vit_0_0,vit_0,vit_1,vit_1_1; // 4 adjacent velocity values
175 src_ptr.get_leftleft_left_center_right(_DIR_,i,vit_0_0,vit_0,vit_1,vit_1_1);
176
177 Simd_double order4_velocity = g1 * vit_0_0 + g2 * vit_0 + g3 * vit_1 + g4 * vit_1_1;
178
179
180
181 // get convecting velocity
182 Simd_double vconv0, vconv1;
183 vconv_ptr.get_left_center(_VCOMPO_,i, vconv0, vconv1);
184
185 Simd_double psc = vconv0 * constant_factor0 + vconv1 * constant_factor1;
186 // with porosity we would code this: vconv = (vconv0 * porosity0 + vconv1 * porosity1) * constant_factor;
187 Simd_double flux_conv = order4_velocity * psc;
188
189 resu_ptr.put_val(i, flux_conv);
190 }
191 // do not execute end_iloop at last iteration (because of assert on valid j+1)
192 if (j+1==jmax)
193 break;
194 // instructions to perform to jump to next row
195 src_ptr.next_j();
196 resu_ptr.next_j();
197 vconv_ptr.next_j();
198 }
199 }
200}
201
202
203#endif
int get_nb_items_global(Localisation loc, int direction) const
Returns the number of local items (on this processor) for the given localisation in the requested dir...
const Domaine_IJK & get_domaine() const
double get_g(int k_layer, int compo, int dir, int g_index) const
IJK_Field_double * div_rho_u_
const IJK_Field_double & get_input(DIRECTION _DIR_)
const IJK_Field_double & get_v(DIRECTION _DIR_)