TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Champ_P1NC.cpp
1/****************************************************************************
2* Copyright (c) 2026, 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 <Dirichlet_paroi_defilante.h>
17#include <Echange_externe_impose.h>
18#include <Scalaire_impose_paroi.h>
19#include <Dirichlet_paroi_fixe.h>
20#include <Modele_turbulence_hyd_base.h>
21#include <Schema_Temps_base.h>
22#include <Neumann_homogene.h>
23#include <Operateur_base.h>
24#include <Champ_Uniforme.h>
25#include <Neumann_paroi.h>
26#include <distances_VEF.h>
27#include <Probleme_base.h>
28#include <Fluide_base.h>
29#include <Periodique.h>
30#include <Champ_P1NC.h>
31#include <Operateur.h>
32#include <TRUSTTab.h>
33#include <TRUSTTrav.h>
34#include <SFichier.h>
35#include <Device.h>
36#include <kokkos++.h>
37#include <TRUSTArray_kokkos.tpp>
38
39Implemente_instanciable(Champ_P1NC,"Champ_P1NC",Champ_Inc_base);
40
41Sortie& Champ_P1NC::printOn(Sortie& s) const { return s << que_suis_je() << " " << le_nom(); }
42
44{
45 lire_donnees(s);
46 return s;
47}
48
49// PQ : 01/10/04 : mettre_a_jour permet de calculer qu'une seule fois le champ conforme u_bar (defini aux sommets)
50// pour pouvoir etre utilise dans les differents operateurs ou lors de l'appel
51// des sondes definies a partir des valeurs "smooth" (dans le cas present : u_bar)
52void Champ_P1NC::mettre_a_jour(double un_temps)
53{
56}
57/*! @brief
58 *
59 */
61{
62 ch_som_ = 0;
63}
64
66{
67 double vit_norm = 0;
68 for (int ncomp = 0; ncomp < nb_comp(); ncomp++)
69 vit_norm += valeurs()(num_face, ncomp) * domaine_vef().face_normales(num_face, ncomp);
70 return (vit_norm > 0);
71}
72
73DoubleTab& Champ_P1NC::trace(const Frontiere_dis_base& fr, DoubleTab& x, double tps, int distant) const
74{
75 return Champ_P1NC_implementation::trace(fr, valeurs(tps), x, distant);
76}
77
78void Champ_P1NC::cal_rot_ordre1(DoubleTab& tab_vorticite) const
79{
80 const int nb_elem = domaine_vef().nb_elem(), nb_elem_tot = domaine_vef().nb_elem_tot();
81 DoubleTrav tab_gradient_elem(nb_elem_tot, dimension, dimension);
82 gradient(tab_gradient_elem);
83 CDoubleTabView3 gradient_elem = tab_gradient_elem.view_ro<3>();
84 switch(dimension)
85 {
86 case 2:
87 {
88 DoubleArrView vorticite = static_cast<DoubleVect&>(tab_vorticite).view_wo();
89 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(const int num_elem)
90 {
91 vorticite(num_elem) = gradient_elem(num_elem, 1, 0) - gradient_elem(num_elem, 0, 1);
92 });
93 }
94 break;
95 case 3:
96 {
97 DoubleTabView vorticite = tab_vorticite.view_wo();
98 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(const int num_elem)
99 {
100 vorticite(num_elem, 0) = gradient_elem(num_elem, 2, 1) - gradient_elem(num_elem, 1, 2);
101 vorticite(num_elem, 1) = gradient_elem(num_elem, 0, 2) - gradient_elem(num_elem, 2, 0);
102 vorticite(num_elem, 2) = gradient_elem(num_elem, 1, 0) - gradient_elem(num_elem, 0, 1);
103 });
104 }
105 }
106 end_gpu_timer(__KERNEL_NAME__);
107 tab_vorticite.echange_espace_virtuel();
108 return;
109}
110
111void calculer_gradientP1NC_2D(const DoubleTab& tab_variable, const Domaine_VEF& domaine_VEF, const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& tab_gradient_elem)
112{
113 const DoubleTab& tab_face_normales = domaine_VEF.face_normales();
114 const IntTab& tab_face_voisins = domaine_VEF.face_voisins();
115 const DoubleVect& tab_inverse_volumes = domaine_VEF.inverse_volumes();
116 const ArrOfInt& tab_est_face_bord = domaine_VEF.est_face_bord();
117
118 CDoubleTabView face_normales = tab_face_normales.view_ro();
119 CIntTabView face_voisins = tab_face_voisins.view_ro();
120 CDoubleArrView inverse_volumes = tab_inverse_volumes.view_ro();
121 CDoubleArrView variable = static_cast<const ArrOfDouble&>(tab_variable).view_ro();
122 CIntArrView est_face_bord = tab_est_face_bord.view_ro();
123 DoubleTabView gradient_elem = tab_gradient_elem.view_rw();
124
125 int dimension = Objet_U::dimension;
126 const int nb_faces_tot = domaine_VEF.nb_faces_tot();
127 const int nb_elem = domaine_VEF.nb_elem_tot();
128
129 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
130 nb_faces_tot,
131 KOKKOS_LAMBDA (int fac)
132 {
133 int type_face = est_face_bord(fac);
134
135 // Faces de bord periodiques
136 if (type_face == 2)
137 {
138 int elem1 = face_voisins(fac, 0);
139 int elem2 = face_voisins(fac, 1);
140
141 for (int i = 0; i < dimension; i++)
142 {
143 double grad = 0.5 * face_normales(fac,i) * variable(fac);
144 Kokkos::atomic_add(&gradient_elem(elem1, i), +grad);
145 Kokkos::atomic_add(&gradient_elem(elem2, i), -grad);
146 }
147 }
148 // Faces de bord non periodiques
149 else if (type_face == 1)
150 {
151 int elem1 = face_voisins(fac,0);
152
153 for (int i = 0; i < dimension; i++)
154 {
155 double grad = face_normales(fac,i) * variable(fac);
156 Kokkos::atomic_add(&gradient_elem(elem1, i), grad);
157 }
158 }
159 // Faces internes
160 else if (type_face == 0)
161 {
162 int elem1 = face_voisins(fac, 0);
163 int elem2 = face_voisins(fac, 1);
164
165 for (int i = 0; i < dimension; i++)
166 {
167 double grad = face_normales(fac,i) * variable(fac);
168 if (elem1 >= 0) Kokkos::atomic_add(&gradient_elem(elem1, i), +grad);
169 if (elem2 >= 0) Kokkos::atomic_add(&gradient_elem(elem2, i), -grad);
170 }
171 }
172 });
173 end_gpu_timer(__KERNEL_NAME__);
174
175 // Division par le volume de l'element
176 auto vol_div = KOKKOS_LAMBDA (int elem, int i)
177 {
178 gradient_elem(elem, i) *= inverse_volumes(elem);
179 };
180 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0,0}, {nb_elem,dimension}), vol_div);
181 end_gpu_timer(__KERNEL_NAME__);
182}
183
184//Actually optimized kernel
185template<int nbcomp_compile_time, int dims, int nbface>
186void calculer_gradientP1NC_3D_template(const DoubleTab& tab_variable,
187 const Domaine_VEF& domaine_VEF,
188 const Domaine_Cl_VEF& domaine_Cl_VEF,
189 DoubleTab& tab_gradient_elem)
190{
191 const DoubleTab& tab_face_normales = domaine_VEF.face_normales();
192 const IntTab& tab_face_voisins = domaine_VEF.face_voisins();
193 const DoubleVect& tab_inverse_volumes = domaine_VEF.inverse_volumes();
194 const IntTab& tab_elem_faces = domaine_VEF.elem_faces();
195
196 int nb_elem_tot = domaine_VEF.nb_elem_tot();
197
198 CDoubleTabView face_normales = tab_face_normales.view_ro();
199 CIntTabView face_voisins = tab_face_voisins.view_ro();
200 CDoubleArrView inverse_volumes = tab_inverse_volumes.view_ro();
201 CDoubleTabView variable = tab_variable.view_ro();
202 CIntTabView elem_faces = tab_elem_faces.view_ro();
203 DoubleTabView3 gradient_elem = tab_gradient_elem.view_rw<3>();
204
205
206 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem_tot, KOKKOS_LAMBDA (int elem)
207 {
208
209 double contrib_grad_loc[nbcomp_compile_time*dims]= {};
210
211 for (int iface = 0; iface < nbface; iface++)
212 {
213 int fac = elem_faces(elem, iface);
214
215 double coef = (elem == face_voisins(fac, 0) ? 1 : -1);
216
217 double face_normales_loc[dims];
218 double variable_loc[nbcomp_compile_time];
219
220 for (int i = 0; i < dims; i++)
221 {
222 face_normales_loc[i] = face_normales(fac, i);
223 }
224
225 for (int icomp = 0; icomp < nbcomp_compile_time; icomp++)
226 {
227 variable_loc[icomp] = variable(fac, icomp);
228 }
229
230 for (int icomp = 0; icomp < nbcomp_compile_time; icomp++)
231 for (int i = 0; i < dims; i++)
232 {
233 double grad = coef * face_normales_loc[i] * variable_loc[icomp];
234 contrib_grad_loc[dims*icomp + i] += grad;
235 }
236 }
237
238 double inverse = inverse_volumes(elem);
239
240 for (int icomp = 0; icomp < nbcomp_compile_time; icomp++)
241 for (int i = 0; i < dims; i++)
242 {
243 gradient_elem(elem, icomp, i) = contrib_grad_loc[dims*icomp + i]*inverse;
244 }
245
246
247 });
248 end_gpu_timer(__KERNEL_NAME__);
249}
250
251// Helper for variadic template dispatch
252template <int ...> struct TemplateIntList {};
253
254// Base case: no more cases to try
255template<int dims, int nbface>
256void dispatch_nbcomp_impl(int, TemplateIntList<>, const DoubleTab&, const Domaine_VEF&,
257 const Domaine_Cl_VEF&, DoubleTab&)
258{
259 Cerr << "Error in calculer_gradientP1NC_3D: unsupported nb_comp, add more in 'dispatch_nbcomp'" << finl;
261}
262
263// Recursive case: try each nbcomp value
264template<int dims, int nbface, int nbcomp_compile_time, int ...Rest>
265void dispatch_nbcomp_impl(int nb_comp_runtime, TemplateIntList<nbcomp_compile_time, Rest...>,
266 const DoubleTab& tab_variable,
267 const Domaine_VEF& domaine_VEF,
268 const Domaine_Cl_VEF& domaine_Cl_VEF,
269 DoubleTab& tab_gradient_elem)
270{
271 if (nbcomp_compile_time == nb_comp_runtime)
272 {
273 calculer_gradientP1NC_3D_template<nbcomp_compile_time, dims, nbface>(tab_variable, domaine_VEF,
274 domaine_Cl_VEF, tab_gradient_elem);
275 }
276 else
277 {
278 dispatch_nbcomp_impl<dims, nbface>(nb_comp_runtime, TemplateIntList<Rest...>(),
279 tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
280 }
281}
282
283// Wrapper for nbcomp dispatch
284template<int dims, int nbface>
285void dispatch_nbcomp(int nb_comp_runtime, const DoubleTab& tab_variable,
286 const Domaine_VEF& domaine_VEF,
287 const Domaine_Cl_VEF& domaine_Cl_VEF,
288 DoubleTab& tab_gradient_elem)
289{
290 // List all supported nbcomp values here - easy to extend!
291 dispatch_nbcomp_impl<dims, nbface>(nb_comp_runtime, TemplateIntList<1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20>(),
292 tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
293}
294
295void calculer_gradientP1NC_3D(const DoubleTab& tab_variable,
296 const Domaine_VEF& domaine_VEF,
297 const Domaine_Cl_VEF& domaine_Cl_VEF,
298 DoubleTab& tab_gradient_elem)
299{
300 const int nb_comp = tab_variable.line_size();
301 const int dimensions = Objet_U::dimension;
302 int nb_faces_elem = domaine_VEF.elem_faces().dimension(1);
303
304
305 //Switch to allow compile time optimizations https://rbourgeois33.github.io./posts/post1/ namely:
306 //no atomics, no redundant memory requests
307 //Weird but this kernel is also called for some 2D cases..., exemple Bilans_VEF_QC_Turb_Null
308 //Also weird, P1NC should always be called on tetra so we could deduce nb_faces_elem from dim (3 in 2D, 4 in 3D)
309 //But in triocfd, it is called with quadrangles/hexahedron... tests Smago_hexa Smago_quadra Obstacle_Turb_quadra
310
311 switch (nb_faces_elem)
312 {
313 case 3:
314 switch (dimensions)
315 {
316 case 2:
317 dispatch_nbcomp<2,3>(nb_comp, tab_variable,
318 domaine_VEF, domaine_Cl_VEF,
319 tab_gradient_elem);
320 break;
321
322 case 3:
323 dispatch_nbcomp<3,3>(nb_comp, tab_variable,
324 domaine_VEF, domaine_Cl_VEF,
325 tab_gradient_elem);
326 break;
327
328 default:
329 Cerr << "Error in calculer_gradientP1NC_3D: dimensions must be 2 or 3, got "
330 << dimensions << finl;
332 }
333 break;
334
335 case 4:
336 switch (dimensions)
337 {
338 case 2:
339 dispatch_nbcomp<2,4>(nb_comp, tab_variable,
340 domaine_VEF, domaine_Cl_VEF,
341 tab_gradient_elem);
342 break;
343
344 case 3:
345 dispatch_nbcomp<3,4>(nb_comp, tab_variable,
346 domaine_VEF, domaine_Cl_VEF,
347 tab_gradient_elem);
348 break;
349
350 default:
351 Cerr << "Error in calculer_gradientP1NC_3D: dimensions must be 2 or 3, got "
352 << dimensions << finl;
354 }
355 break;
356
357 case 6:
358 switch (dimensions)
359 {
360 case 2:
361 dispatch_nbcomp<2,6>(nb_comp, tab_variable,
362 domaine_VEF, domaine_Cl_VEF,
363 tab_gradient_elem);
364 break;
365
366 case 3:
367 dispatch_nbcomp<3,6>(nb_comp, tab_variable,
368 domaine_VEF, domaine_Cl_VEF,
369 tab_gradient_elem);
370 break;
371
372 default:
373 Cerr << "Error in calculer_gradientP1NC_3D: dimensions must be 2 or 3, got "
374 << dimensions << finl;
376 }
377 break;
378
379 default:
380 Cerr << "Error in calculer_gradientP1NC_3D: nb_faces_elem must be 3, 4, or 6 got "
381 << nb_faces_elem << finl;
383 }
384}
385
386void calculer_gradientP1NC(const DoubleTab& tab_variable, const Domaine_VEF& domaine_VEF, const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& tab_gradient_elem)
387{
388 const int nb_comp = tab_variable.line_size();
389 tab_gradient_elem = 0.;
390
391 // Cas du calcul du gradient d'un tableau de vecteurs ou
392 // tableau de scalaires tab_gradient_elem(,,)
393 if (nb_comp != 1 || tab_gradient_elem.nb_dim() == 3)
394 calculer_gradientP1NC_3D(tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
395 // Cas du calcul du gradient d'un tableau de scalaire dans un
396 // tableau gradient_elem(,)
397 else
398 calculer_gradientP1NC_2D(tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
399}
400
401void Champ_P1NC::gradient(DoubleTab& gradient_elem) const
402{
403 // Calcul du gradient: par exemple gradient de la vitesse pour le calcul de la vorticite
404 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF, equation().domaine_Cl_dis());
405 calculer_gradientP1NC(valeurs(), domaine_vef(), domaine_Cl_VEF, gradient_elem);
406
407}
408
409int Champ_P1NC::imprime(Sortie& os, int ncomp) const
410{
411 imprime_P1NC(os, ncomp);
412 return 1;
413}
414
416{
417#ifdef CLEMENT
418 DoubleTab& tab = valeurs();
419 DoubleTab noeuds;
420 remplir_coord_noeuds(noeuds);
421 const Domaine_VEF& domaine_VEF = le_dom_VEF.valeur();
422 const int nb_faces = domaine_VEF.nb_faces();
423 const IntTab& face_sommets = domaine_VEF.face_sommets();
424 const DoubleTab& sommets=domaine().coord_sommets();
425 int nb_som=sommets.dimension(0);
426 Cerr << "Affecter Clement : ... " << finl;
427 DoubleTab valf(valeurs());
428 ch.valeur_aux(noeuds, valf);
429 DoubleTab vals(nb_som, nb_compo_);
430 if(nb_compo_==1)
431 {
432 vals.resize(nb_som);
433 }
434 ch.valeur_aux(sommets, vals);
435 for(int face=0; face<nb_faces; face++)
436 {
437 for(int comp=0; comp<nb_compo_; comp++)
438 {
439 double somme=0;
440 for (int isom=0; isom<dimension; isom++)
441 if(nb_compo_==1)
442 somme+=vals(face_sommets(face,isom));
443 else
444 somme+=vals(face_sommets(face,isom), comp);
445 if(nb_compo_==1)
446 {
447 if(dimension==2)
448 tab(face)=1./6.*somme+2./3.*valf(face);
449 else
450 tab(face)=17./60.*somme+3./20.*valf(face);
451 }
452 else if(dimension==2)
453 tab(face,comp)=1./6.*somme+2./3.*valf(face,comp);
454 else
455 tab(face,comp)=17./60.*somme+3./20.*valf(face,comp);
456 }
457 }
458 return *this;
459#else
460 return Champ_Inc_base::affecter_(ch);
461#endif
462}
463
464//-Cas CL periodique : assure que les valeurs sur des faces periodiques
465// en vis a vis sont identiques. Pour cela on prend la demi somme des deux valeurs.
467{
469 int nb_cl = zcl.nb_cond_lim();
470 DoubleTab& ch_tab = valeurs();
471 int nb_compo = nb_comp();
472 int ndeb, nfin, num_face;
473
474 for (int i = 0; i < nb_cl; i++)
475 {
476 const Cond_lim_base& la_cl = zcl.les_conditions_limites(i).valeur();
477 if (sub_type(Periodique, la_cl))
478 {
479 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
480 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
481 ndeb = le_bord.num_premiere_face();
482 nfin = ndeb + le_bord.nb_faces();
483 int voisine;
484 double moy;
485
486 for (num_face = ndeb; num_face < nfin; num_face++)
487 {
488 voisine = la_cl_perio.face_associee(num_face - ndeb) + ndeb;
489 for (int comp = 0; comp < nb_compo; comp++)
490 {
491 if (ch_tab(num_face, comp) != ch_tab(voisine, comp))
492 {
493 moy = 0.5 * (ch_tab(num_face, comp) + ch_tab(voisine, comp));
494 ch_tab(num_face, comp) = moy;
495 ch_tab(voisine, comp) = moy;
496 }
497 }
498 }
499 }
500 }
501 ch_tab.echange_espace_virtuel();
502}
503
504void Champ_P1NC::calcul_critere_Q(DoubleVect& tab_Critere_Q) const
505{
506 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF, equation().domaine_Cl_dis());
507 const int nb_elem = domaine_vef().nb_elem(), nb_elem_tot = domaine_vef().nb_elem_tot();
508 const int dim = Objet_U::dimension;
509
510 DoubleTrav tab_gradient_elem(nb_elem_tot, dim, dim);
511 const DoubleTab& vitesse = valeurs();
512 Champ_P1NC::calcul_gradient(vitesse, tab_gradient_elem, domaine_Cl_VEF);
513
514 CDoubleTabView3 gradient_elem = tab_gradient_elem.view_ro<3>();
515 DoubleArrView Critere_Q = tab_Critere_Q.view_rw();
516 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
517 range_1D(0, nb_elem), KOKKOS_LAMBDA(
518 const int num_elem)
519 {
520 double crit = 0.;
521 for (int i = 0; i < dim; i++)
522 for (int j = 0; j < dim; j++)
523 {
524 double deriv1 = gradient_elem(num_elem, i, j);
525 double deriv2 = gradient_elem(num_elem, j, i);
526 crit += -0.25 * deriv1 * deriv2;
527 }
528 Critere_Q[num_elem] = crit;
529 });
530 end_gpu_timer(__KERNEL_NAME__);
531}
532
533void Champ_P1NC::calcul_y_plus(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleVect& y_plus) const
534{
535 // On initialise le champ y_plus avec une valeur negative,
536 // comme ca lorsqu'on veut visualiser le champ pres de la paroi,
537 // on n'a qu'a supprimer les valeurs negatives et n'apparaissent
538 // que les valeurs aux parois.
539
540 int ndeb, nfin, l_unif;
541 double visco0 = -1.;
542 y_plus = -1.;
543
544 const Equation_base& eqn_hydr = equation();
545 const Fluide_base& le_fluide = ref_cast(Fluide_base, eqn_hydr.milieu());
546 const Champ_Don_base& ch_visco_cin = le_fluide.viscosite_cinematique();
547 const DoubleTab& tab_visco = ch_visco_cin.valeurs();
548
549 if (sub_type(Champ_Uniforme, ch_visco_cin))
550 {
551 if (tab_visco(0, 0) > DMINFLOAT)
552 visco0 = tab_visco(0, 0);
553 else
554 visco0 = DMINFLOAT;
555 l_unif = 1;
556 }
557 else
558 l_unif = 0;
559
560 if ((!l_unif) && (tab_visco.local_min_vect() < DMINFLOAT))
561 // GF on ne doit pas changer tab_visco ici !
562 {
563 Cerr << "In Champ_P1NC::calcul_y_plus : visco = " << tab_visco.local_min_vect() << " <= 0 ? " << finl;
564 exit();
565 }
566 // tab_visco+=DMINFLOAT;
567
568 DoubleTab yplus_faces(1, 1); // will contain yplus values if available
569 int yplus_already_computed = 0; // flag
570
571 const RefObjU& modele_turbulence = eqn_hydr.get_modele(TURBULENCE);
572 if (modele_turbulence && sub_type(Modele_turbulence_hyd_base, modele_turbulence.valeur()))
573 {
574 const Modele_turbulence_hyd_base& mod_turb = ref_cast(Modele_turbulence_hyd_base, modele_turbulence.valeur());
575 const Turbulence_paroi_base& loipar = mod_turb.loi_paroi();
576 // if( ! sub_type( Paroi_negligeable_VEF , loipar ) )
577 if (loipar.use_shear())
578 {
579 yplus_faces.resize(domaine_vef().nb_faces_tot());
580 yplus_faces.ref(loipar.tab_d_plus());
581 yplus_already_computed = 1;
582 }
583 }
584
585 for (int n_bord = 0; n_bord < domaine_vef().nb_front_Cl(); n_bord++)
586 {
587 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
588
589 if( sub_type(Dirichlet_paroi_fixe,la_cl.valeur()) || sub_type(Dirichlet_paroi_defilante, la_cl.valeur()) || la_cl->que_suis_je() == "Frontiere_ouverte_vitesse_imposee_ALE")
590 {
591 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
592 ndeb = le_bord.num_premiere_face();
593 nfin = ndeb + le_bord.nb_faces();
594 int dim = Objet_U::dimension;
595 int nfac = domaine_vef().domaine().nb_faces_elem();
596 DoubleTrav counter(y_plus.size());
597 CDoubleTabView xp = domaine_vef().xp().view_ro(); // DOUBT: Why defined inside the for loop?
598 CDoubleTabView xv = domaine_vef().xv().view_ro();
599 CDoubleTabView face_normale = domaine_vef().face_normales().view_ro();
600 CIntTabView elem_faces = domaine_vef().elem_faces().view_ro();
601 CIntTabView face_voisins = domaine_vef().face_voisins().view_ro();
602 CDoubleTabView vit = eqn_hydr.inconnue().valeurs().view_ro(); // DOUBT: Is this correct? Original assignment was `const Champ_P1NC& vit = *this;`
603 CDoubleArrView visco = static_cast<const DoubleVect&>(tab_visco).view_ro();
604 CDoubleArrView yp_faces = static_cast<const DoubleVect&>(yplus_faces).view_ro();
605 DoubleArrView y_plus_view = y_plus.view_rw();
606 DoubleArrView counter_view = static_cast<DoubleVect&>(counter).view_wo();
607 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int num_face)
608 {
609 int elem = face_voisins(num_face, 0);
610 y_plus_view(elem) = 0;
611 });
612 end_gpu_timer(__KERNEL_NAME__);
613 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int num_face)
614 {
615 int elem = face_voisins(num_face, 0);
616 if (yplus_already_computed)
617 {
618 // y+ is only defined on faces so we take the face value to put in the element
619 Kokkos::atomic_add(&y_plus_view(elem), yp_faces(num_face));
620 }
621 else
622 {
623 int num[3];
624 bool ok = false;
625 for (int i = 0; i < dim; i++)
626 {
627 num[i] = elem_faces(elem, i);
628 if (num[i] == num_face && !ok)
629 {
630 num[i] = elem_faces(elem, dim);
631 ok = true;
632 }
633 }
634
635 double dist = distance(dim, num_face, elem, xp, xv, face_normale);
636 dist *= (dim + 1.) / dim; // pour se ramener a distance paroi / milieu de num[0]-num[1]
637 double val[3];
638 double norm_v = norm_vit1_lp(dim, vit, num_face, nfac, num, face_normale, val);
639 double d_visco = l_unif ? visco0:visco[elem];
640
641 // PQ : 01/10/03 : corrections par rapport a la version premiere
642 double norm_tau = d_visco * norm_v / dist;
643 double u_etoile = sqrt(norm_tau);
644 Kokkos::atomic_add(&y_plus_view(elem), dist * u_etoile / d_visco);
645 } // else yplus already computed
646 Kokkos::atomic_add(&counter_view(elem), +1);
647 }); // loop on faces
648 end_gpu_timer(__KERNEL_NAME__);
649 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(0, y_plus.size()), KOKKOS_LAMBDA (const int elem)
650 {
651 if (counter_view(elem)>0) y_plus_view(elem)/=counter_view(elem);
652 });
653 end_gpu_timer(__KERNEL_NAME__);
654
655 } // Fin de paroi fixe
656
657 } // Fin boucle sur les bords
658}
659
660void Champ_P1NC::calcul_grad_U(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& tab_grad_u) const
661{
662 const DoubleTab& u = valeurs();
663 const int nb_elem = domaine_vef().nb_elem(), nb_elem_tot = domaine_vef().nb_elem_tot();
664
665 DoubleTrav tab_gradient_elem(nb_elem_tot, dimension, dimension);
666 calculer_gradientP1NC(u, domaine_vef(), domaine_Cl_VEF, tab_gradient_elem);
667 int dim = dimension;
668 CDoubleTabView3 gradient_elem = tab_gradient_elem.view_ro<3>();
669 DoubleTabView grad_u = tab_grad_u.view_wo();
670 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(0, nb_elem), KOKKOS_LAMBDA(const int elem)
671 {
672 int comp = 0;
673 for (int i = 0; i < dim; i++)
674 {
675 for (int j = 0; j < dim; j++)
676 {
677 grad_u(elem, comp) = gradient_elem(elem, i, j);
678 comp++;
679 }
680 }
681 });
682 end_gpu_timer(__KERNEL_NAME__);
683}
684
685void Champ_P1NC::calcul_grad_T(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& grad_T) const
686{
687 const DoubleTab& temp = valeurs();
688 calculer_gradientP1NC(temp, domaine_vef(), domaine_Cl_VEF, grad_T);
689
690 // *******************************************************************
691 // PQ : 12/12/05 : pour pouvoir visualiser les oscillations a partir
692 // des changements de signes du gradient de T
693 // *******************************************************************
694 /*
695 const IntTab& face_voisins = domaine_VEF.face_voisins();
696 const IntTab& elem_faces=domaine_VEF.elem_faces();
697 int nb_faces = domaine_VEF.nb_faces();
698 const int nb_elem = domaine_VEF.nb_elem_tot();
699
700 int num_elem,num_face,elem0,elem1,i;
701 ArrOfInt sign_opp_x(nb_faces);
702 ArrOfInt sign_opp_y(nb_faces);
703 sign_opp_x=0;
704 sign_opp_y=0;
705
706 for (num_face=0;num_face<nb_faces;num_face++)
707 {
708 elem0 = face_voisins(num_face,0);
709 elem1 = face_voisins(num_face,1);
710 if (elem1!=-1)
711 {
712 if (grad_T(elem0,0)*grad_T(elem1,0)<0.) sign_opp_x(num_face)++;
713 if (grad_T(elem0,1)*grad_T(elem1,1)<0.) sign_opp_y(num_face)++;
714 }
715 }
716
717 grad_T=0.;
718
719 for (num_elem=0;num_elem<nb_elem;num_elem++)
720 {
721 for (i=0;i<dimension+1;i++)
722 {
723 grad_T(num_elem,0) +=sign_opp_x(elem_faces(num_elem,i));
724 grad_T(num_elem,1) +=sign_opp_y(elem_faces(num_elem,i));
725 }
726 }
727 */
728
729}
730
731// Calcul du coefficient d'echange
732void Champ_P1NC::calcul_h_conv(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& h_conv, int temp_ref) const
733{
734 const DoubleTab& temp = valeurs();
735 const IntTab& face_voisins = domaine_vef().face_voisins();
736 const DoubleTab& face_normale = domaine_vef().face_normales();
737
738 // On recupere le flux aux frontieres
739 DoubleTab Flux;
740 Flux = equation().operateur(0).l_op_base().flux_bords();
741
742 // On initialise a -1
743 h_conv = -1.;
744
745 double T_ref = double(temp_ref);
746
747 for (int n_bord = 0; n_bord < domaine_vef().nb_front_Cl(); n_bord++)
748 {
749 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
750 const Frontiere_dis_base& la_fr = la_cl->frontiere_dis();
751 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
752 int ndeb = le_bord.num_premiere_face();
753 int nfin = ndeb + le_bord.nb_faces();
754 double h_moy = 0.;
755 // Selon les conditions limites
756 if (sub_type(Echange_externe_impose, la_cl.valeur()))
757 {
758 const Champ_base& rho = equation().milieu().masse_volumique();
760 int rho_uniforme = (sub_type(Champ_Uniforme,rho) ? 1 : 0);
761 int cp_uniforme = (sub_type(Champ_Uniforme,Cp) ? 1 : 0);
762 for (int num_face = ndeb; num_face < nfin; num_face++)
763 {
764 int elem = face_voisins(num_face, 0);
765 double rho_cp = (rho_uniforme ? rho.valeurs()(0, 0) : (rho.nb_comp() == 1 ? rho.valeurs()(num_face) : rho.valeurs()(num_face, 0)));
766 rho_cp *= (cp_uniforme ? Cp.valeurs()(0, 0) : (Cp.nb_comp() == 1 ? Cp.valeurs()(num_face) : Cp.valeurs()(num_face, 0)));
767 h_conv(elem) = ref_cast(Echange_externe_impose,la_cl.valeur()).h_imp(num_face) * rho_cp;
768 h_moy += h_conv(elem);
769 }
770 }
771 else if (sub_type(Scalaire_impose_paroi,la_cl.valeur()) || sub_type(Neumann_homogene, la_cl.valeur()) || sub_type(Neumann_paroi, la_cl.valeur()))
772 {
773 for (int num_face = ndeb; num_face < nfin; num_face++)
774 {
775 int elem = face_voisins(num_face, 0);
776
777 double norme_flux = 0.;
778 double surf = 0.;
779
780 for (int k = 0; k < Flux.dimension(1); k++)
781 norme_flux += Flux(num_face, k) * Flux(num_face, k);
782
783 for (int k = 0; k < Objet_U::dimension; k++)
784 surf += face_normale(num_face, k) * face_normale(num_face, k);
785
786 double DT = temp(num_face) - T_ref;
787
788 if (DT == 0.)
789 h_conv(elem) = 0.;
790 else
791 {
792 //La mise a jour de ce champ est faite quand on demande son postraitement
793 //et par consequent les flux ont ete mis a jour et sont deja multiplies par rho*Cp
794 h_conv(elem) = sqrt(norme_flux / surf) / DT;
795 }
796 h_moy += h_conv(elem);
797 }
798 }
799 // Optimization: combine 2 mp_sum into 1 collective call
800 double nb_faces_d = static_cast<double>(le_bord.nb_faces());
801 mp_sum_for_each(h_moy, nb_faces_d);
802 int nb_faces = static_cast<int>(nb_faces_d); // a single 'bord' should not have so many faces
803 h_moy /= nb_faces;
804 if (je_suis_maitre())
805 {
806 Nom fich_hconv;
807 fich_hconv = "Heat_transfert_Coeff_";
808 fich_hconv += la_fr.le_nom();
809 fich_hconv += ".dat";
810
811 SFichier fic(fich_hconv, ios::app);
812 fic.setf(ios::scientific);
813
814 double le_temps = equation().schema_temps().temps_courant();
815 fic << le_temps << " " << h_moy << finl;
816 }
817 }
818}
819
820static double norme_L2(const DoubleTab& u, const Domaine_VEF& domaine_VEF)
821{
822 const int nb_faces = domaine_VEF.nb_faces();
823 double norme = 0;
824 int nb_compo_ = u.line_size();
825
826 CDoubleArrView volumes = domaine_VEF.volumes_entrelaces().view_ro(); // DOUBT: reference?
827 CDoubleTabView uview = u.view_ro(); // DOUBT: How to name this variable?
828
829 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_faces,
830 KOKKOS_LAMBDA (const int i, double& s)
831 {
832 for (int j = 0; j < nb_compo_; j++)
833 s += uview(i, j) * uview(i, j);
834 s *= volumes(i);
835 }, norme);
836 end_gpu_timer(__KERNEL_NAME__);
837
838 return sqrt(norme);
839}
840double Champ_P1NC::norme_L2(const Domaine& dom) const
841{
842 Cerr << "Champ_P1NC::norme_L2" << finl;
843 {
844 DoubleTab x(valeurs());
845 filtrer_L2(x);
846 Cerr << "Norme filtree : " << ::norme_L2(x, domaine_vef()) << finl;
847 }
848 const DoubleTab& u = valeurs();
849 return ::norme_L2(u, domaine_vef());
850}
851
852double Champ_P1NC::norme_H1(const Domaine& dom) const
853{
854 const Domaine& mon_dom = domaine_vef().domaine();
855
856 double dnorme_H1;
857 // DOUBT: dimension?
858 int dim = dimension;
859 const int nb_elem = mon_dom.nb_elem();
860 const int nb_faces_elem = mon_dom.nb_faces_elem();
861 CIntTabView elem_faces = domaine_vef().elem_faces().view_ro();
862 CDoubleTabView face_normales = domaine_vef().face_normales().view_ro();
863 CIntTabView face_voisins = domaine_vef().face_voisins().view_ro();
864 CDoubleTabView tab = valeurs().view_ro();
865 CDoubleArrView volumes = domaine_vef().volumes().view_ro();
866
867 //On va calculer la norme H1 d'une inconnue P1NC.
868 //L'algorithme tient compte des contraintes suivantes:
869 //- l'inconnue peut avoir plusieurs composantes
870 // (i.e etre un scalaire ou etre un vecteur)
871 //- la dimension du probleme est arbitraire (1, 2 ou 3).
872 //ATTENTION: les prismes ne sont pas supportes.
873 dnorme_H1 = 0.;
874 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_comp(), //cas scalaire ou vectoriel
875 KOKKOS_LAMBDA (const int composante, double& norme_H1_comp)
876 {
877 for (int K = 0; K < nb_elem; K++) //boucle sur les elements
878 {
879 double norme_grad_elem = 0.; //pour eviter les accumulations
880 for (int i = 0; i < dim; i++) //boucle sur la dimension du pb
881 {
882 double int_grad_elem = 0.; //pour eviter les accumulations
883 for (int face = 0; face < nb_faces_elem; face++) //boucle sur les faces d'un "K"
884 {
885 int face_globale = elem_faces(K, face);
886
887 int_grad_elem += tab(face_globale, composante) * face_normales(face_globale, i) * oriente_normale(face_globale, K, face_voisins);
888 } //fin du for sur "face"
889
890 norme_grad_elem += int_grad_elem * int_grad_elem;
891 } //fin du for sur "i"
892
893 norme_H1_comp += norme_grad_elem / volumes(K);
894 } //fin du for sur "K"
895
896 }, dnorme_H1); // fin du for sur "composante"
897 end_gpu_timer(__KERNEL_NAME__);
898
899 return sqrt(dnorme_H1);
900}
901
902double Champ_P1NC::norme_L2_H1(const Domaine& dom) const
903{
904 double pas_de_temps = equation().schema_temps().pas_de_temps();
905
906 return ((1. / pas_de_temps) * norme_L2(dom)) + norme_H1(dom);
907}
908
909/////////////////////////////////////////////////////////////////////////////////////////////////////
910//Methode qui renvoie gij aux elements a partir du champ aux faces
911//(gij represente la derivee partielle dGi/dxj)
912//A partir de gij, on peut calculer Sij = 0.5(gij(i,j)+gij(j,i))
913////////////////////////////////////////////////////////////////////////////////////////////////////
914
915DoubleTab& Champ_P1NC::calcul_gradient(const DoubleTab& champ, DoubleTab& gij, const Domaine_Cl_VEF& domaine_Cl_VEF)
916{
917 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
918 calculer_gradientP1NC(champ, domaine_VEF, domaine_Cl_VEF, gij);
919 return gij;
920
921}
922
923DoubleTab& Champ_P1NC::calcul_duidxj_paroi(DoubleTab& tab_gij, const DoubleTab& tab_nu, const DoubleTab& tab_nu_turb, const DoubleTab& tab_tau_tan, const Domaine_Cl_VEF& domaine_Cl_VEF)
924{
925 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
926
927 // On va modifier Sij pour les faces de Dirichlet (Paroi_fixe) si nous n utilisons pas Paroi_negligeable!!!!
928 // On aura : (grad u)_f = (grad u) - (grad u . n) x n + (grad u . n)_lp x n
929 //
930
931 // PQ : 25/01/08 : Mise au propre de la methode pour ne plus etre embete par les histoires de signes notamment
932 // et savoir reellement ce qu'on fait !!
933 //
934 // PRINCIPE :
935 // (expose en 2D, l'extension au 3D ne pose pas de probleme particulier)
936 //
937 // On considere 2 reperes : le repere global (x,y) et le repere local (t,n) ou n designe la normale a la paroi
938 // Le frottement retourne par la loi de paroi correspond a : || tau_tan || = u*^2 = nu.d(u_t)/dn
939 // Soit P la matrice de passage permettant de passer d'un repere a l'autre
940 //
941 // P = ( tx nx )
942 // ( ty ny )
943 //
944 // Les matrices des gradients de vitesse dans chacun des reperes :
945 //
946 // G_(x,y) = ( du/dx du/dy ) et F_(t,n) = ( du_t/dt du_t/dn )
947 // ( dv/dx dv/dy ) ( du_n/dt du_n/dn )
948 //
949 // -1
950 // sont reliees l'une a l'autre par : G_(x,y) = P . F_(t,n) . P
951 //
952 //
953 // Ainsi la correction apportee dans F = ( du_t/dt du_t/dn + C ) ou C = -du_t/dn + tau_tan/nu
954 // ( du_n/dt du_n/dn )
955 //
956 // se reporte dans G de la maniere suivante :
957 //
958 // -1
959 // G*_(x,y) = G_(x,y) + P . ( 0 C ). P = G_(x,y) + ( C.nx.tx C.ny.tx )
960 // ( 0 0 ) ( C.nx.ty C.ny.ty )
961 //
962 //
963 // c'est ce dernier terme qu'il s'agit donc de determiner ici
964
965 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
966 int nb_cl = les_cl.size();
967
968 // tab_tau_tan could be uninitialized at this point. In such a case,
969 // we can skip the function because the value of gij won't change
970 if (tab_tau_tan.dimension_tot(0) == 0) return tab_gij;
971
972 for (int num_cl = 0; num_cl < nb_cl; num_cl++)
973 {
974 //Boucle sur les bords
975 const Cond_lim& la_cl = les_cl[num_cl];
976 if (sub_type(Dirichlet_paroi_fixe,la_cl.valeur()) || sub_type(Dirichlet_paroi_defilante, la_cl.valeur()) || la_cl->que_suis_je() == "Frontiere_ouverte_vitesse_imposee_ALE")
977 {
978 const Front_VF& la_front_dis = ref_cast(Front_VF, la_cl->frontiere_dis());
979 int ndeb = la_front_dis.num_premiere_face();
980 int nfin = ndeb + la_front_dis.nb_faces();
981 int dim = Objet_U::dimension;
982 // Boucle sur les faces
983 CDoubleTabView face_normale = domaine_VEF.face_normales().view_ro();
984 CIntTabView face_voisins = domaine_VEF.face_voisins().view_ro();
985 CDoubleArrView porosite_face = domaine_Cl_VEF.equation().milieu().porosite_face().view_ro();
986 CDoubleTabView tau_tan = tab_tau_tan.view_ro();
987 CDoubleArrView nu = static_cast<const ArrOfDouble&>(tab_nu).view_ro();
988 CDoubleArrView nu_turb = static_cast<const ArrOfDouble&>(tab_nu_turb).view_ro();
989 DoubleTabView3 gij = tab_gij.view_rw<3>();
990 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int fac)
991 {
992 double P[3][3];
993 int num1 = face_voisins(fac, 0);
994 // definition des vecteurs unitaires constituant le repere local
995 // stockes dans la matrice de passage P
996 // vecteur tangentiel (porte par la vitesse tangentielle)
997 double sum = 0.;
998 for (int i = 0; i < dim; i++)
999 sum += tau_tan(fac, i) * tau_tan(fac, i);
1000 double norme_tau_tan = sqrt(sum);
1001 for (int i = 0; i < dim; i++)
1002 P[i][0] = tau_tan(fac, i) / (norme_tau_tan + DMINFLOAT);
1003
1004 // vecteur normal a la paroi
1005 sum = 0.;
1006 for (int i = 0; i < dim; i++)
1007 sum += face_normale(fac, i) * face_normale(fac, i);
1008 double norme = sqrt(sum);
1009
1010 int signe = -oriente_normale(fac, num1, face_voisins); // orientation vers l'interieur
1011 for (int i = 0; i < dim; i++)
1012 P[i][1] = signe * face_normale(fac, i) / norme;
1013
1014 // (3D) on complete la base par le deuxieme vecteur tangentiel
1015 if (dim == 3)
1016 {
1017 P[0][2] = P[1][0] * P[2][1] - P[2][0] * P[1][1];
1018 P[1][2] = P[2][0] * P[0][1] - P[0][0] * P[2][1];
1019 P[2][2] = P[0][0] * P[1][1] - P[1][0] * P[0][1];
1020 }
1021 // determination du terme d(u_t)/dn a enlever
1022 // -1
1023 // terme identifie a l'aide du produit : F = P . G . P
1024 //
1025 double dutdn_old = 0.;
1026 for (int i = 0; i < dim; i++)
1027 for (int j = 0; j < dim; j++)
1028 {
1029 double gij_value = Kokkos::atomic_fetch_add(&gij(num1, i, j), 0.0);
1030 dutdn_old += gij_value * P[j][1] * P[i][0];
1031 }
1032
1033 // Correction finale apportee a la matrice G
1034 double C = -dutdn_old + norme_tau_tan / (nu[num1] + nu_turb[num1]) * porosite_face(fac);
1035
1036 // la division par (nu[num1]+nu_turb[num1]) s'impose du fait que l'operateur de diffusion
1037 // fait intervenir le produit : (nu[num1]+nu_turb[num1])*g(i,j)
1038 for (int i = 0; i < dim; i++)
1039 for (int j = 0; j < dim; j++)
1040 Kokkos::atomic_add(&gij(num1, i, j), C * P[j][1] * P[i][0]);
1041 });
1042 end_gpu_timer(__KERNEL_NAME__);
1043 }
1044 }
1045
1046 return tab_gij;
1047}
1048
1049////////////////////
1050// Calcul de 2SijSij
1051////////////////////
1052DoubleVect& Champ_P1NC::calcul_S_barre(const DoubleTab& la_vitesse, DoubleVect& SMA_barre, const Domaine_Cl_VEF& domaine_Cl_VEF)
1053{
1054 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
1055 const int nb_elem = domaine_VEF.nb_elem();
1056 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
1057
1058 DoubleTrav duidxj(nb_elem_tot, dimension, dimension);
1059
1060 Champ_P1NC::calcul_gradient(la_vitesse, duidxj, domaine_Cl_VEF);
1061
1062 int dim = Objet_U::dimension;
1063 CDoubleTabView3 duidxj_v = duidxj.view_ro<3>();
1064 DoubleArrView SMA_barre_v = SMA_barre.view_wo();
1065 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(
1066 const int elem)
1067 {
1068 double temp = 0.;
1069 for (int i = 0; i < dim; i++)
1070 for (int j = 0; j < dim; j++)
1071 {
1072 double Sij = 0.5 * (duidxj_v(elem, i, j) + duidxj_v(elem, j, i));
1073 temp += Sij * Sij;
1074 }
1075 SMA_barre_v(elem) = 2. * temp;
1076 });
1077 end_gpu_timer(__KERNEL_NAME__);
1078
1079 return SMA_barre;
1080}
1081
1082double Champ_P1NC::calculer_integrale_volumique(const Domaine_VEF& domaine, const DoubleVect& v, Ok_Perio ok)
1083{
1084 if (ok != FAUX_EN_PERIO)
1085 {
1086 // BM: desole
1087 Cerr << "Champ_P1NC::calculer_integrale_volumique pas encore code juste en perio !" << finl;
1088 exit();
1089 }
1090
1091 assert(v.line_size() == 1);
1092 const DoubleVect& volume = domaine.volumes_entrelaces();
1093 const double resu = mp_prodscal(v, volume);
1094 return resu;
1095}
1096
1098{
1099 assert(nb_noeuds == domaine_vef().nb_faces());
1100 const MD_Vector& md = domaine_vef().md_vector_faces();
1102
1104
1105 return nb_noeuds;
1106}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
Classe Champ_Inc_base.
const Domaine & domaine() const
virtual void creer_tableau_distribue(const MD_Vector &, RESIZE_OPTIONS=RESIZE_OPTIONS::COPY_INIT)
int lire_donnees(Entree &)
Lit les valeurs du champs a partir d'un flot d'entree.
const Domaine_Cl_dis_base & domaine_Cl_dis() const
void mettre_a_jour(double temps) override
Effectue une mise a jour en temps du champ inconnue.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
Champ_base & affecter_(const Champ_base &) override
Affectation d'un OWN_PTR(Champ_base) generique (Champ_base) dans un champ inconnue.
DoubleTab & trace(const Frontiere_dis_base &fr, const DoubleTab &y, DoubleTab &x, int distant) const
void calcul_h_conv(const Domaine_Cl_VEF &, DoubleTab &, int temp_ref) const
void abortTimeStep() override
void cal_rot_ordre1(DoubleTab &) const
virtual double norme_H1(const Domaine &) const
void mettre_a_jour(double temps) override
Effectue une mise a jour en temps du champ inconnue.
virtual double norme_L2_H1(const Domaine &dom) const
void calcul_grad_T(const Domaine_Cl_VEF &, DoubleTab &) const
static DoubleVect & calcul_S_barre(const DoubleTab &, DoubleVect &, const Domaine_Cl_VEF &)
void calcul_y_plus(const Domaine_Cl_VEF &, DoubleVect &) const
DoubleTab & remplir_coord_noeuds(DoubleTab &positions) const override
Definition Champ_P1NC.h:117
void verifie_valeurs_cl() override
void gradient(DoubleTab &) const
int compo_normale_sortante(int) const
static DoubleTab & calcul_gradient(const DoubleTab &, DoubleTab &, const Domaine_Cl_VEF &)
void calcul_critere_Q(DoubleVect &) const
void filtrer_L2(DoubleTab &x) const
Definition Champ_P1NC.h:127
Champ_base & affecter_(const Champ_base &) override
Affectation d'un OWN_PTR(Champ_base) generique (Champ_base) dans un champ inconnue.
void calcul_grad_U(const Domaine_Cl_VEF &, DoubleTab &) const
DoubleTab & trace(const Frontiere_dis_base &, DoubleTab &, double, int distant) const override
voir Champ_base Cas particulier (malheureusement) du Champ_P0_VDF :
static DoubleTab & calcul_duidxj_paroi(DoubleTab &, const DoubleTab &, const DoubleTab &, const DoubleTab &, const Domaine_Cl_VEF &)
int fixer_nb_valeurs_nodales(int nb_noeuds) override
int imprime(Sortie &, int) const override
const Domaine_VEF & domaine_vef() const override
Definition Champ_P1NC.h:66
virtual double norme_L2(const Domaine &) const
static double calculer_integrale_volumique(const Domaine_VEF &, const DoubleVect &, Ok_Perio ok)
virtual DoubleTab & valeurs()=0
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
Champ_base()
Constructeur par defaut d'un Champ_base.
virtual DoubleTab & valeur_aux(const DoubleTab &positions, DoubleTab &valeurs) const
Provoque une erreur ! Doit etre surchargee par les classes derivees.
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
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.
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
Domaine_VEF & domaine_vef()
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
const MD_Vector & md_vector_faces() const
Definition Domaine_VF.h:158
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
double volumes(int i) const
Definition Domaine_VF.h:113
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
ArrOfInt & est_face_bord()
Definition Domaine_VF.h:85
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
double inverse_volumes(int i) const
Definition Domaine_VF.h:114
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
Classe Echange_externe_impose: Cette classe represente le cas particulier de la classe.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual const Milieu_base & milieu() const =0
virtual const RefObjU & get_modele(Type_modele type) const
virtual const Champ_Inc_base & inconnue() const =0
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
virtual const Operateur & operateur(int) const =0
const Nom & le_nom() const override
Renvoie le nom du champ.
virtual int nb_comp() const
Definition Field_base.h:56
int nb_compo_
Definition Field_base.h:95
classe Fluide_base Cette classe represente un d'un fluide incompressible ainsi que
Definition Fluide_base.h:38
const Champ_Don_base & viscosite_cinematique() const
Definition Fluide_base.h:58
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
classe Frontiere_dis_base Classe representant une frontiere discretisee.
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
virtual const Champ_Don_base & capacite_calorifique() const
Renvoie la capacite calorifique du milieu.
virtual const Champ_base & masse_volumique() const
Renvoie la masse volumique du milieu.
DoubleVect & porosite_face()
Definition Milieu_base.h:62
Classe Modele_turbulence_hyd_base Cette classe sert de base a la hierarchie des classes.
const Turbulence_paroi_base & loi_paroi() const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
Classe Neumann_homogene Cette classe est la classe de base de la hierarchie des conditions aux limite...
Classe Neumann_paroi Cette condition limite correspond a un flux impose pour l'equation de.
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
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
DoubleTab & flux_bords()
virtual Operateur_base & l_op_base()=0
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:207
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
classe Scalaire_impose_paroi Impose un scalaire a la paroi dans une equation de type Convection-Difus...
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_wo()
Definition TRUSTTab.h:276
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_rw()
Definition TRUSTTab.h:291
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
_TYPE_ local_min_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:155
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
const Objet_U & valeur() const
Definition TRUST_Ref.h:134
Classe Turbulence_paroi_base Classe de base pour la hierarchie des classes representant les modeles.
const DoubleVect & tab_d_plus() const
virtual bool use_shear() const