16#ifndef Iterateur_VDF_Elem_TPP_included
17#define Iterateur_VDF_Elem_TPP_included
19#include <Convection_Diffusion_Temperature_base.h>
20#include <Operateur_Diff_base.h>
21#include <Champ_Uniforme.h>
22#include <communications.h>
23#include <TRUSTSingle.h>
29 ArrOfDouble aii(ncomp), ajj(ncomp);
32 if (_TYPE_::CALC_FLUX_FACES_ECH_GLOB_IMP)
35 for (
int f = ndeb; f < nfin; f++)
37 const int e1 = f2e[f].first, e2 = f2e[f].second;
39 for (
int i = 0; i < ncomp; i++)
40 matrice(e1 * ncomp + i, e2 * ncomp + i) = -(
elem(f, 0) > -1 ? aii[i] : ajj[i]);
53 assert(op_base->equation().inconnue().valeurs().nb_dim() < 3 && la_zcl && le_dom);
54 const int ncomp = op_base->equation().inconnue().valeurs().line_size();
55 DoubleTab& flux_bords = op_base->flux_bords();
56 flux_bords.
resize(le_dom->nb_faces_bord(), ncomp);
61 double *data = secmem.
addr() + secmem.
size();
62 for (; n; n--, data++) *data = 0.;
66 ajouter_blocs_bords < SingleDouble > (ncomp, mats, secmem, semi_impl);
67 ajouter_blocs_interne < SingleDouble > (ncomp, mats, secmem, semi_impl);
71 ajouter_blocs_bords < ArrOfDouble > (ncomp, mats, secmem, semi_impl);
72 ajouter_blocs_interne < ArrOfDouble > (ncomp, mats, secmem, semi_impl);
78template<
class _TYPE_>
template<
typename Type_Double>
79void Iterateur_VDF_Elem<_TYPE_>::ajouter_blocs_bords(
const int ncomp, matrices_t mats, DoubleTab& resu,
const tabs_t& semi_impl)
const
81 for (
int num_cl = 0; num_cl < le_dom->nb_front_Cl(); num_cl++)
83 const Cond_lim& la_cl = la_zcl->les_conditions_limites(num_cl);
87 if (bidim_axi && !sub_type(
Symetrie, la_cl.valeur()))
89 if (nfin > ndeb && est_egal(le_dom->face_surfaces()[ndeb], 0))
91 Cerr <<
"Error in the definition of the boundary conditions. The axis of revolution for this 2D calculation is along Y." << finl;
92 Cerr <<
"So you must specify symmetry boundary condition (symetrie keyword) for the boundary " << frontiere_dis.
le_nom() << finl;
97 switch(type_cl(la_cl))
100 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_SYMM, Type_Double>((
const Symetrie&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
103 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_SORTIE_LIB, Type_Double>((
const Neumann_sortie_libre&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
106 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_ENTREE_FL, Type_Double>((
const Dirichlet_entree_fluide&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
109 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_PAR_FIXE, Type_Double>((
const Dirichlet_paroi_fixe&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
111 case paroi_defilante:
112 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_PAR_DEFIL, Type_Double>((
const Dirichlet_paroi_defilante&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
114 case paroi_scalaire_impose:
115 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_SCAL_IMPOSEE, Type_Double>((
const Scalaire_impose_paroi&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
117 case paroi_dirichlet_loi_paroi:
118 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_SCAL_IMPOSEE , Type_Double>((
const Dirichlet_loi_paroi&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
121 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_PAR, Type_Double>((
const Neumann_paroi&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
123 case echange_global_impose:
124 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_ECH_GLOB_IMP, Type_Double>((
const Echange_global_impose&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
126 case paroi_adiabatique:
127 ajouter_blocs_bords_<_TYPE_::CALC_FLUX_FACES_PAR_ADIAB, Type_Double>((
const Neumann_paroi_adiabatique&) la_cl.valeur(), ndeb, nfin, ncomp, mats, resu, semi_impl);
129 case echange_externe_impose:
130 ajouter_blocs_bords_ < Type_Double > ((
const Echange_externe_impose&) la_cl.valeur(), ndeb, nfin, num_cl, ncomp, frontiere_dis, mats, resu, semi_impl);
133 ajouter_blocs_bords_ < Type_Double > ((
const Periodique&) la_cl.valeur(), ndeb, nfin, ncomp, frontiere_dis, mats, resu, semi_impl);
136 Cerr <<
"On ne reconnait pas la condition limite : " << la_cl.valeur() <<
" , dans Iterateur_VDF_Elem<_TYPE_>::ajouter_bords" << finl;
143template<
class _TYPE_>
template<
typename Type_Double>
144void Iterateur_VDF_Elem<_TYPE_>::ajouter_blocs_interne(
const int N, matrices_t mats, DoubleTab& resu,
const tabs_t& semi_impl)
const
146 const DoubleTab& donnee = semi_impl.count(nom_ch_inco_) ? semi_impl.at(nom_ch_inco_) : le_champ_convecte_ou_inc->valeurs();
147 Type_Double flux(N), aii(N * (multiscalar_diff_ ? N : 1)), ajj(N * (multiscalar_diff_ ? N : 1)), aef(N);
148 const int ndeb = le_dom->premiere_face_int(), nfin = le_dom->nb_faces(), Mv = le_ch_v ? le_ch_v->valeurs().line_size() : N;
149 for (
int face = ndeb; face < nfin; face++)
151 flux_evaluateur.flux_faces_interne(donnee, face, flux);
152 const int e0 = elem(face, 0), e1 = elem(face, 1);
154 for (
int k = 0; k < N; k++)
156 resu(e0, k) += flux[k];
157 resu(e1, k) -= flux[k];
161 Matrice_Morse *m_vit = (mats.count(
"vitesse") && is_convective_op()) ? mats.at(
"vitesse") :
nullptr, *mat = (!is_pb_multiphase() && mats.count(nom_ch_inco_)) ? mats.at(nom_ch_inco_) :
nullptr;
163 fill_derivee_cc(mats, semi_impl, d_cc);
167 for (
int face = ndeb; face < nfin; face++)
169 flux_evaluateur.coeffs_faces_interne_bloc_vitesse(donnee, face, aef);
170 for (
int i = 0; i < 2; i++)
171 for (
int n = 0, m = 0; n < N; n++, m += (Mv > 1))
172 (*m_vit)(N * elem(face, i) + n, Mv * face + m) += (i ? -1.0 : 1.0) * aef(n);
176 if (mat || d_cc.size() > 0)
177 for (
int face = ndeb; face < nfin; face++)
179 flux_evaluateur.coeffs_faces_interne(face, aii, ajj);
180 fill_coeffs_matrices(face, 1.0 , aii, ajj, mat, d_cc);
184template<
class _TYPE_>
template<
bool should_calc_flux,
typename Type_Double,
typename BC>
185void Iterateur_VDF_Elem<_TYPE_>::ajouter_blocs_bords_(
const BC& cl,
const int ndeb,
const int nfin,
const int N, matrices_t mats, DoubleTab& resu,
const tabs_t& semi_impl)
const
187 constexpr bool is_Neum_paroi_adiab = std::is_same<BC, Neumann_paroi_adiabatique>::value;
189 constexpr bool is_scal_imp = std::is_same<BC, Scalaire_impose_paroi>::value;
190 constexpr bool is_neum_paroi = std::is_same<BC, Neumann_paroi>::value;
191 constexpr bool is_paroi_contact = std::is_same<BC, Echange_global_impose>::value;
193 const bool is_Temp_impose_flux_parietal = is_scal_imp && corr_flux_parietal_ && !is_conv_op_;
194 const bool is_Neumann_flux_parietal = is_neum_paroi && corr_flux_parietal_ && !is_conv_op_;
195 const bool is_paroi_contact_flux_parietal = is_paroi_contact && corr_flux_parietal_ && !is_conv_op_;
197 if (should_calc_flux)
199 if (is_Neum_paroi_adiab)
202 const DoubleTab& donnee = semi_impl.count(nom_ch_inco_) ? semi_impl.at(nom_ch_inco_) : le_champ_convecte_ou_inc->valeurs(),
203 val_b = sub_type(
Champ_Face_base, le_champ_convecte_ou_inc.valeur()) ? DoubleTab() :
204 (use_base_val_b_ ? le_champ_convecte_ou_inc->
Champ_base::valeur_aux_bords() : le_champ_convecte_ou_inc->valeur_aux_bords());
206 Matrice_Morse *mat = (!is_pb_multiphase() && mats.count(nom_ch_inco_)) ? mats.at(nom_ch_inco_) :
nullptr;
211 if (is_Temp_impose_flux_parietal || is_Neumann_flux_parietal || is_paroi_contact_flux_parietal)
213 fill_derivee_cc(mats, semi_impl, d_cc);
214 const DoubleTab& donnee2 = is_pb_multiphase() ? le_champ_convecte_ou_inc->valeurs() : donnee ;
215 mat = mats.count(nom_ch_inco_) ? mats.at(nom_ch_inco_) :
nullptr;
216 ajouter_blocs_bords_flux_parietal_<Type_Double, BC>(cl, ndeb, nfin, N, donnee2, resu, mat, d_cc, semi_impl);
220 int e, Mv = le_ch_v ? le_ch_v->valeurs().line_size() : N;
221 Type_Double flux(N), aii(N * (multiscalar_diff_ ? N : 1)), ajj(N * (multiscalar_diff_ ? N : 1)), aef(N);
222 for (
int face = ndeb; face < nfin; face++)
224 flux_evaluateur.flux_face(donnee, val_b, face, cl, ndeb, flux);
225 fill_flux_tables_(face, N, 1.0 , flux, resu);
228 Matrice_Morse *m_vit = (mats.count(
"vitesse") && is_convective_op()) ? mats.at(
"vitesse") :
nullptr;
230 fill_derivee_cc(mats, semi_impl, d_cc);
235 const IntTab *fcl_v = le_ch_v ? &ref_cast(
Champ_Face_base, le_ch_v.valeur()).fcl() :
nullptr;
236 for (
int f = ndeb; f < nfin; f++)
237 if ((*fcl_v)(f, 0) < 2)
239 flux_evaluateur.coeffs_face_bloc_vitesse(donnee, val_b, f, cl, ndeb, aef);
240 for (
int i = 0; i < 2; i++)
241 if ((e = elem(f, i)) >= 0)
242 for (
int n = 0, m = 0; n < N; n++, m += (Mv > 1))
243 (*m_vit)(N * e + n, Mv * f + m) += (i ? -1.0 : 1.0) * aef(n);
248 if (mat || d_cc.size() > 0)
249 for (
int face = ndeb; face < nfin; face++)
251 flux_evaluateur.coeffs_face(face, ndeb, cl, aii, ajj);
252 fill_coeffs_matrices(face, aii, ajj, mat, d_cc);
258template<
class _TYPE_>
template<
typename Type_Double>
259void Iterateur_VDF_Elem<_TYPE_>::ajouter_blocs_bords_(
const Periodique& cl,
const int ndeb,
const int nfin,
const int N,
const Front_VF& frontiere_dis,
260 matrices_t mats, DoubleTab& resu,
const tabs_t& semi_impl)
const
262 DoubleTab& flux_bords = op_base->flux_bords();
263 if (_TYPE_::CALC_FLUX_FACES_PERIO)
265 const DoubleTab& donnee = semi_impl.count(nom_ch_inco_) ? semi_impl.at(nom_ch_inco_) : le_champ_convecte_ou_inc->valeurs();
268 Type_Double flux(N), aii(N * (multiscalar_diff_ ? N : 1)), ajj(N * (multiscalar_diff_ ? N : 1)), aef(N);
269 for (
int face = ndeb; face < nfin; face++)
271 const int e0 = elem(face, 0), e1 = elem(face, 1);
272 flux_evaluateur.flux_face(donnee, donnee, face, cl, ndeb, flux);
274 for (
int n = 0; n < N; n++)
278 resu(e0, n) += 0.5 * flux[n];
279 if (face < (ndeb + frontiere_dis.
nb_faces() / 2)) flux_bords(face, n) += flux[n];
283 resu(e1, n) -= 0.5 * flux[n];
284 if ((ndeb + frontiere_dis.
nb_faces() / 2) <= face) flux_bords(face, n) -= flux[n];
289 Matrice_Morse *m_vit = mats.count(
"vitesse") ? mats.at(
"vitesse") :
nullptr, *mat = (!is_pb_multiphase() && mats.count(nom_ch_inco_)) ? mats.at(nom_ch_inco_) :
nullptr;
291 fill_derivee_cc(mats, semi_impl, d_cc);
295 for (
int face = ndeb; face < nfin; face++)
297 const int e0 = elem(face, 0), e1 = elem(face, 1);
298 flux_evaluateur.coeffs_face_bloc_vitesse(donnee, DoubleTab(), face, cl, ndeb, aef);
300 for (
int i = 0; i < N; i++)
301 if (face < (ndeb + frontiere_dis.
nb_faces() / 2)) (*m_vit)(e0 * N + i, face * N + i) += aef[i];
303 for (
int i = 0; i < N; i++)
304 if ((ndeb + frontiere_dis.
nb_faces() / 2) <= face) (*m_vit)(e1 * N + i, face * N + i) -= aef[i];
308 if (mat || d_cc.size() > 0)
309 for (
int face = ndeb; face < nfin; face++)
311 flux_evaluateur.coeffs_face(face, ndeb, cl, aii, ajj);
312 fill_coeffs_matrices(face, 0.5 , aii, ajj, mat, d_cc);
317template<
class _TYPE_>
template<
typename Type_Double>
318void Iterateur_VDF_Elem<_TYPE_>::ajouter_blocs_bords_(
const Echange_externe_impose& cl,
const int ndeb,
const int nfin,
const int num_cl,
const int N,
const Front_VF& frontiere_dis,
319 matrices_t mats, DoubleTab& resu,
const tabs_t& semi_impl)
const
321 if (_TYPE_::CALC_FLUX_FACES_ECH_EXT_IMP)
324 const bool calculated_in_FT = ajouter_blocs_bords_echange_ext_FT_TCL<Type_Double>(cl, ndeb, nfin, num_cl, N, frontiere_dis, mats, resu, semi_impl);
325 if ( calculated_in_FT )
return;
328 const DoubleTab& donnee = semi_impl.count(nom_ch_inco_) ? semi_impl.at(nom_ch_inco_) : le_champ_convecte_ou_inc->valeurs();
330 Type_Double flux(N), aii(N * (multiscalar_diff_ ? N : 1)), ajj(N * (multiscalar_diff_ ? N : 1)), aef(N);
331 int boundary_index = -1;
332 if (le_dom->front_VF(num_cl).le_nom() == frontiere_dis.
le_nom())
333 boundary_index = num_cl;
335 int e, Mv = le_ch_v ? le_ch_v->valeurs().line_size() : N;
336 for (
int face = ndeb; face < nfin; face++)
338 const int local_face = le_dom->front_VF(boundary_index).num_local_face(face);
339 flux_evaluateur.flux_face(donnee, boundary_index, face, local_face, cl, ndeb, flux);
340 fill_flux_tables_(face, N, 1.0 , flux, resu);
343 Matrice_Morse *m_vit = (mats.count(
"vitesse") && is_convective_op()) ? mats.at(
"vitesse") :
nullptr, *mat = (!is_pb_multiphase() && mats.count(nom_ch_inco_)) ? mats.at(nom_ch_inco_) :
nullptr;
345 fill_derivee_cc(mats, semi_impl, d_cc);
350 DoubleTab val_b = use_base_val_b_ ? le_champ_convecte_ou_inc->Champ_base::valeur_aux_bords() : le_champ_convecte_ou_inc->valeur_aux_bords();
351 for (
int face = ndeb; face < nfin; face++)
353 const int local_face = le_dom->front_VF(boundary_index).num_local_face(face);
354 flux_evaluateur.coeffs_face_bloc_vitesse(donnee, val_b, boundary_index, face, local_face, cl, ndeb, aef);
356 for (
int i = 0; i < 2; i++)
357 if ((e = elem(face, i)) >= 0)
358 for (
int n = 0, m = 0; n < N; n++, m += (Mv > 1)) (*m_vit)(N * e + n, Mv * face + m) += (i ? -1.0 : 1.0) * aef(n);
363 if (mat || d_cc.size() > 0)
364 for (
int face = ndeb; face < nfin; face++)
366 const int local_face = le_dom->front_VF(boundary_index).num_local_face(face);
367 flux_evaluateur.coeffs_face(donnee, boundary_index, face, local_face, ndeb, cl, aii, ajj);
368 fill_coeffs_matrices(face, aii, ajj, mat, d_cc);
373template<
class _TYPE_>
374inline void Iterateur_VDF_Elem<_TYPE_>::fill_derivee_cc(matrices_t mats,
const tabs_t& semi_impl, VectorDeriv& d_cc)
const
377 if (is_pb_multiphase() && is_convective_op() && !semi_impl.count(le_champ_convecte_ou_inc->le_nom().getString()))
379 for (
auto &i_m : mats)
380 if (le_champ_convecte_ou_inc->derivees().count(i_m.first))
381 d_cc.push_back(std::make_tuple(&le_champ_convecte_ou_inc->derivees().at(i_m.first), i_m.second, op_base->equation().probleme().get_champ(i_m.first.c_str()).valeurs().line_size()));
383 else assert(d_cc.size() == 0);
386template<
class _TYPE_>
template<
typename Type_Double>
387inline void Iterateur_VDF_Elem<_TYPE_>::fill_coeffs_matrices(
const int f,
const double coeff, Type_Double& aii, Type_Double& ajj,
Matrice_Morse *mat, VectorDeriv& d_cc)
const
389 const int N = multiscalar_diff_ ? int(sqrt(aii.size_array())) : aii.size_array();
392 for (
int i = 0; i < 2; i++)
393 for (
int j = 0, e = elem(f, i); j < 2; j++)
394 for (
int n = 0, eb = elem(f, j); n < N; n++)
395 for (
int m = (multiscalar_diff_ ? 0 : n); m < (multiscalar_diff_ ? N : n + 1); m++)
396 (*mat)(N * e + n, N * eb + m) += (i == j ? 1.0 : -1.0) * coeff * (j ? ajj[multiscalar_diff_ ? N * n + m : n] : aii[multiscalar_diff_ ? N * n + m : n]);
399 for (
auto &&d_m_i : d_cc)
400 for (
int i = 0; i < 2; i++)
401 for (
int j = 0, e = elem(f, i); j < 2; j++)
403 const int M = std::get<2> (d_m_i);
404 const DoubleTab& d_var_cc = *std::get<0> (d_m_i);
407 for (
int n = 0, m = 0, eb = elem(f, j); n < N; n++, m += (M > 1))
408 d_var_operateur(N * e + n, M * eb + m) += (i == j ? 1.0 : -1.0) * coeff * (j ? ajj[n] : aii[n]) * d_var_cc(eb, m);
412template<
class _TYPE_>
template<
typename Type_Double>
413inline void Iterateur_VDF_Elem<_TYPE_>::fill_coeffs_matrices(
const int face, Type_Double& aii, Type_Double& ajj,
Matrice_Morse *mat, VectorDeriv& d_cc)
const
415 const int e0 = elem(face, 0), e1 = elem(face, 1);
416 const int N = multiscalar_diff_ ? int(sqrt(aii.size_array())) : aii.size_array();
421 for (
int n = 0; n < N; n++)
422 for (
int m = (multiscalar_diff_ ? 0 : n); m < (multiscalar_diff_ ? N : n + 1); m++)
423 (*mat)(e0 * N + n, e0 * N + m) += aii[multiscalar_diff_ ? N * n + m : n];
425 for (
int n = 0; n < N; n++)
426 for (
int m = (multiscalar_diff_ ? 0 : n); m < (multiscalar_diff_ ? N : n + 1); m++)
427 (*mat)(e1 * N + n, e1 * N + m) += ajj[multiscalar_diff_ ? N * n + m : n];
430 for (
auto &&d_m_i : d_cc)
432 const int M = std::get<2> (d_m_i);
433 const DoubleTab& d_var_cc = *std::get<0> (d_m_i);
437 for (
int n = 0, m = 0; n < N; n++, m += (M > 1))
439 const int i0 = N * e0 + n;
440 d_var_operateur(i0, i0) += aii[n] * d_var_cc(e0, m);
443 for (
int n = 0, m = 0; n < N; n++, m += (M > 1))
445 const int j0 = M * e1 + m;
446 d_var_operateur(j0, j0) += ajj[n] * d_var_cc(e1, m);
451#include <Iterateur_VDF_Elem_bis.tpp>
452#include <Iterateur_VDF_Elem_FT_TCL.tpp>
453#include <Iterateur_VDF_Elem_Multiphase_Parietal.tpp>
classe Champ_base Cette classe est la base de la hierarchie des champs.
classe Cond_lim Classe generique servant a representer n'importe quelle classe
classe Dirichlet_entree_fluide Cette classe represente une condition aux limite imposant une grandeur
Classe Dirichlet_loi_paroi Classe de base pour les valeurs impose pour une condition aux limites des ...
classe Dirichlet_paroi_defilante Impose la vitesse de paroi dnas une equation de type Navier_Stokes.
classe Dirichlet_paroi_fixe Represente une paroi immobile dans une equation de type Navier_Stokes.
Classe Echange_externe_impose: Cette classe represente le cas particulier de la classe.
Classe Echange_global_impose Cette classe represente le cas particulier de la classe.
int num_premiere_face() const
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
void ajouter_contribution_autre_pb(const DoubleTab &inco, Matrice_Morse &matrice, const Cond_lim &la_cl, std::map< int, std::pair< int, int > > &) const override
void ajouter_blocs(matrices_t mats, DoubleTab &secmem, const tabs_t &semi_impl) const override
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
Classe Neumann_paroi_adiabatique Cette condition limite correspond a une paroi adiabatique dans une.
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
classe Periodique Cette classe represente une condition aux limites periodique.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
classe Scalaire_impose_paroi Impose un scalaire a la paroi dans une equation de type Convection-Difus...
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
_SIZE_ size_array() const
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)