TrioCFD 1.9.9_beta
TrioCFD documentation
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 computes only once the conforming field u_bar (defined at vertices)
50// so it can be reused in the various operators or when calling
51// probes defined from "smooth" values (in the present case: 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 // Periodic boundary faces
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 // Non-periodic boundary faces
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 // Internal faces
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 // Divide by the element volume
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 // Case: gradient of a vector array or scalar array tab_gradient_elem(,,)
392 if (nb_comp != 1 || tab_gradient_elem.nb_dim() == 3)
393 calculer_gradientP1NC_3D(tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
394 // Case: gradient of a scalar array stored in gradient_elem(,)
395 else
396 calculer_gradientP1NC_2D(tab_variable, domaine_VEF, domaine_Cl_VEF, tab_gradient_elem);
397}
398
399void Champ_P1NC::gradient(DoubleTab& gradient_elem) const
400{
401 // Compute the gradient: e.g. velocity gradient for vorticity computation
402 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF, equation().domaine_Cl_dis());
403 calculer_gradientP1NC(valeurs(), domaine_vef(), domaine_Cl_VEF, gradient_elem);
404
405}
406
407int Champ_P1NC::imprime(Sortie& os, int ncomp) const
408{
409 imprime_P1NC(os, ncomp);
410 return 1;
411}
412
414{
415#ifdef CLEMENT
416 DoubleTab& tab = valeurs();
417 DoubleTab noeuds;
418 remplir_coord_noeuds(noeuds);
419 const Domaine_VEF& domaine_VEF = le_dom_VEF.valeur();
420 const int nb_faces = domaine_VEF.nb_faces();
421 const IntTab& face_sommets = domaine_VEF.face_sommets();
422 const DoubleTab& sommets=domaine().coord_sommets();
423 int nb_som=sommets.dimension(0);
424 Cerr << "Affecter Clement : ... " << finl;
425 DoubleTab valf(valeurs());
426 ch.valeur_aux(noeuds, valf);
427 DoubleTab vals(nb_som, nb_compo_);
428 if(nb_compo_==1)
429 {
430 vals.resize(nb_som);
431 }
432 ch.valeur_aux(sommets, vals);
433 for(int face=0; face<nb_faces; face++)
434 {
435 for(int comp=0; comp<nb_compo_; comp++)
436 {
437 double somme=0;
438 for (int isom=0; isom<dimension; isom++)
439 if(nb_compo_==1)
440 somme+=vals(face_sommets(face,isom));
441 else
442 somme+=vals(face_sommets(face,isom), comp);
443 if(nb_compo_==1)
444 {
445 if(dimension==2)
446 tab(face)=1./6.*somme+2./3.*valf(face);
447 else
448 tab(face)=17./60.*somme+3./20.*valf(face);
449 }
450 else if(dimension==2)
451 tab(face,comp)=1./6.*somme+2./3.*valf(face,comp);
452 else
453 tab(face,comp)=17./60.*somme+3./20.*valf(face,comp);
454 }
455 }
456 return *this;
457#else
458 return Champ_Inc_base::affecter_(ch);
459#endif
460}
461
462// Periodic BC case: ensures that values on facing periodic boundary faces are identical.
463// To do so, the half-sum of the two values is used.
465{
467 int nb_cl = zcl.nb_cond_lim();
468 DoubleTab& ch_tab = valeurs();
469 int nb_compo = nb_comp();
470 int ndeb, nfin, num_face;
471
472 for (int i = 0; i < nb_cl; i++)
473 {
474 const Cond_lim_base& la_cl = zcl.les_conditions_limites(i).valeur();
475 if (sub_type(Periodique, la_cl))
476 {
477 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
478 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
479 ndeb = le_bord.num_premiere_face();
480 nfin = ndeb + le_bord.nb_faces();
481 int voisine;
482 double moy;
483
484 for (num_face = ndeb; num_face < nfin; num_face++)
485 {
486 voisine = la_cl_perio.face_associee(num_face - ndeb) + ndeb;
487 for (int comp = 0; comp < nb_compo; comp++)
488 {
489 if (ch_tab(num_face, comp) != ch_tab(voisine, comp))
490 {
491 moy = 0.5 * (ch_tab(num_face, comp) + ch_tab(voisine, comp));
492 ch_tab(num_face, comp) = moy;
493 ch_tab(voisine, comp) = moy;
494 }
495 }
496 }
497 }
498 }
499 ch_tab.echange_espace_virtuel();
500}
501
502void Champ_P1NC::calcul_critere_Q(DoubleVect& tab_Critere_Q) const
503{
504 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF, equation().domaine_Cl_dis());
505 const int nb_elem = domaine_vef().nb_elem(), nb_elem_tot = domaine_vef().nb_elem_tot();
506 const int dim = Objet_U::dimension;
507
508 DoubleTrav tab_gradient_elem(nb_elem_tot, dim, dim);
509 const DoubleTab& vitesse = valeurs();
510 Champ_P1NC::calcul_gradient(vitesse, tab_gradient_elem, domaine_Cl_VEF);
511
512 CDoubleTabView3 gradient_elem = tab_gradient_elem.view_ro<3>();
513 DoubleArrView Critere_Q = tab_Critere_Q.view_rw();
514 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
515 range_1D(0, nb_elem), KOKKOS_LAMBDA(
516 const int num_elem)
517 {
518 double crit = 0.;
519 for (int i = 0; i < dim; i++)
520 for (int j = 0; j < dim; j++)
521 {
522 double deriv1 = gradient_elem(num_elem, i, j);
523 double deriv2 = gradient_elem(num_elem, j, i);
524 crit += -0.25 * deriv1 * deriv2;
525 }
526 Critere_Q[num_elem] = crit;
527 });
528 end_gpu_timer(__KERNEL_NAME__);
529}
530
531void Champ_P1NC::calcul_y_plus(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleVect& y_plus) const
532{
533 // Initialize the y_plus field with a negative value,
534 // so that when visualizing the field near the wall,
535 // one only needs to remove the negative values and only
536 // the values at the walls remain.
537
538 int ndeb, nfin, l_unif;
539 double visco0 = -1.;
540 y_plus = -1.;
541
542 const Equation_base& eqn_hydr = equation();
543 const Fluide_base& le_fluide = ref_cast(Fluide_base, eqn_hydr.milieu());
544 const Champ_Don_base& ch_visco_cin = le_fluide.viscosite_cinematique();
545 const DoubleTab& tab_visco = ch_visco_cin.valeurs();
546
547 if (sub_type(Champ_Uniforme, ch_visco_cin))
548 {
549 if (tab_visco(0, 0) > DMINFLOAT)
550 visco0 = tab_visco(0, 0);
551 else
552 visco0 = DMINFLOAT;
553 l_unif = 1;
554 }
555 else
556 l_unif = 0;
557
558 if ((!l_unif) && (tab_visco.local_min_vect() < DMINFLOAT))
559 // GF we must not modify tab_visco here!
560 {
561 Cerr << "In Champ_P1NC::calcul_y_plus : visco = " << tab_visco.local_min_vect() << " <= 0 ? " << finl;
562 exit();
563 }
564 // tab_visco+=DMINFLOAT;
565
566 DoubleTab yplus_faces(1, 1); // will contain yplus values if available
567 int yplus_already_computed = 0; // flag
568
569 const RefObjU& modele_turbulence = eqn_hydr.get_modele(TURBULENCE);
570 if (modele_turbulence && sub_type(Modele_turbulence_hyd_base, modele_turbulence.valeur()))
571 {
572 const Modele_turbulence_hyd_base& mod_turb = ref_cast(Modele_turbulence_hyd_base, modele_turbulence.valeur());
573 const Turbulence_paroi_base& loipar = mod_turb.loi_paroi();
574 // if( ! sub_type( Paroi_negligeable_VEF , loipar ) )
575 if (loipar.use_shear())
576 {
577 yplus_faces.resize(domaine_vef().nb_faces_tot());
578 yplus_faces.ref(loipar.tab_d_plus());
579 yplus_already_computed = 1;
580 }
581 }
582
583 for (int n_bord = 0; n_bord < domaine_vef().nb_front_Cl(); n_bord++)
584 {
585 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
586
587 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")
588 {
589 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
590 ndeb = le_bord.num_premiere_face();
591 nfin = ndeb + le_bord.nb_faces();
592 int dim = Objet_U::dimension;
593 int nfac = domaine_vef().domaine().nb_faces_elem();
594 DoubleTrav counter(y_plus.size());
595 CDoubleTabView xp = domaine_vef().xp().view_ro(); // DOUBT: Why defined inside the for loop?
596 CDoubleTabView xv = domaine_vef().xv().view_ro();
597 CDoubleTabView face_normale = domaine_vef().face_normales().view_ro();
598 CIntTabView elem_faces = domaine_vef().elem_faces().view_ro();
599 CIntTabView face_voisins = domaine_vef().face_voisins().view_ro();
600 CDoubleTabView vit = eqn_hydr.inconnue().valeurs().view_ro(); // DOUBT: Is this correct? Original assignment was `const Champ_P1NC& vit = *this;`
601 CDoubleArrView visco = static_cast<const DoubleVect&>(tab_visco).view_ro();
602 CDoubleArrView yp_faces = static_cast<const DoubleVect&>(yplus_faces).view_ro();
603 DoubleArrView y_plus_view = y_plus.view_rw();
604 DoubleArrView counter_view = static_cast<DoubleVect&>(counter).view_wo();
605 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int num_face)
606 {
607 int elem = face_voisins(num_face, 0);
608 y_plus_view(elem) = 0;
609 });
610 end_gpu_timer(__KERNEL_NAME__);
611 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int num_face)
612 {
613 int elem = face_voisins(num_face, 0);
614 if (yplus_already_computed)
615 {
616 // y+ is only defined on faces so we take the face value to put in the element
617 Kokkos::atomic_add(&y_plus_view(elem), yp_faces(num_face));
618 }
619 else
620 {
621 int num[3];
622 bool ok = false;
623 for (int i = 0; i < dim; i++)
624 {
625 num[i] = elem_faces(elem, i);
626 if (num[i] == num_face && !ok)
627 {
628 num[i] = elem_faces(elem, dim);
629 ok = true;
630 }
631 }
632
633 double dist = distance(dim, num_face, elem, xp, xv, face_normale);
634 dist *= (dim + 1.) / dim; // to convert to wall distance / midpoint of num[0]-num[1]
635 double val[3];
636 double norm_v = norm_vit1_lp(dim, vit, num_face, nfac, num, face_normale, val);
637 double d_visco = l_unif ? visco0:visco[elem];
638
639 // PQ : 01/10/03 : corrections relative to the first version
640 double norm_tau = d_visco * norm_v / dist;
641 double u_etoile = sqrt(norm_tau);
642 Kokkos::atomic_add(&y_plus_view(elem), dist * u_etoile / d_visco);
643 } // else yplus already computed
644 Kokkos::atomic_add(&counter_view(elem), +1);
645 }); // loop on faces
646 end_gpu_timer(__KERNEL_NAME__);
647 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(0, y_plus.size()), KOKKOS_LAMBDA (const int elem)
648 {
649 if (counter_view(elem)>0) y_plus_view(elem)/=counter_view(elem);
650 });
651 end_gpu_timer(__KERNEL_NAME__);
652
653 } // End of fixed wall
654
655 } // End loop over boundary conditions
656}
657
658void Champ_P1NC::calcul_grad_U(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& tab_grad_u) const
659{
660 const DoubleTab& u = valeurs();
661 const int nb_elem = domaine_vef().nb_elem(), nb_elem_tot = domaine_vef().nb_elem_tot();
662
663 DoubleTrav tab_gradient_elem(nb_elem_tot, dimension, dimension);
664 calculer_gradientP1NC(u, domaine_vef(), domaine_Cl_VEF, tab_gradient_elem);
665 int dim = dimension;
666 CDoubleTabView3 gradient_elem = tab_gradient_elem.view_ro<3>();
667 DoubleTabView grad_u = tab_grad_u.view_wo();
668 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(0, nb_elem), KOKKOS_LAMBDA(const int elem)
669 {
670 int comp = 0;
671 for (int i = 0; i < dim; i++)
672 {
673 for (int j = 0; j < dim; j++)
674 {
675 grad_u(elem, comp) = gradient_elem(elem, i, j);
676 comp++;
677 }
678 }
679 });
680 end_gpu_timer(__KERNEL_NAME__);
681}
682
683void Champ_P1NC::calcul_grad_T(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& grad_T) const
684{
685 const DoubleTab& temp = valeurs();
686 calculer_gradientP1NC(temp, domaine_vef(), domaine_Cl_VEF, grad_T);
687
688 // *******************************************************************
689 // PQ : 12/12/05 : to be able to visualize oscillations from
690 // sign changes in the gradient of T
691 // *******************************************************************
692 /*
693 const IntTab& face_voisins = domaine_VEF.face_voisins();
694 const IntTab& elem_faces=domaine_VEF.elem_faces();
695 int nb_faces = domaine_VEF.nb_faces();
696 const int nb_elem = domaine_VEF.nb_elem_tot();
697
698 int num_elem,num_face,elem0,elem1,i;
699 ArrOfInt sign_opp_x(nb_faces);
700 ArrOfInt sign_opp_y(nb_faces);
701 sign_opp_x=0;
702 sign_opp_y=0;
703
704 for (num_face=0;num_face<nb_faces;num_face++)
705 {
706 elem0 = face_voisins(num_face,0);
707 elem1 = face_voisins(num_face,1);
708 if (elem1!=-1)
709 {
710 if (grad_T(elem0,0)*grad_T(elem1,0)<0.) sign_opp_x(num_face)++;
711 if (grad_T(elem0,1)*grad_T(elem1,1)<0.) sign_opp_y(num_face)++;
712 }
713 }
714
715 grad_T=0.;
716
717 for (num_elem=0;num_elem<nb_elem;num_elem++)
718 {
719 for (i=0;i<dimension+1;i++)
720 {
721 grad_T(num_elem,0) +=sign_opp_x(elem_faces(num_elem,i));
722 grad_T(num_elem,1) +=sign_opp_y(elem_faces(num_elem,i));
723 }
724 }
725 */
726
727}
728
729// Compute the heat transfer coefficient
730void Champ_P1NC::calcul_h_conv(const Domaine_Cl_VEF& domaine_Cl_VEF, DoubleTab& h_conv, int temp_ref) const
731{
732 const DoubleTab& temp = valeurs();
733 const IntTab& face_voisins = domaine_vef().face_voisins();
734 const DoubleTab& face_normale = domaine_vef().face_normales();
735
736 // Retrieve the flux at boundaries
737 DoubleTab Flux;
738 Flux = equation().operateur(0).l_op_base().flux_bords();
739
740 // Initialize to -1
741 h_conv = -1.;
742
743 double T_ref = double(temp_ref);
744
745 for (int n_bord = 0; n_bord < domaine_vef().nb_front_Cl(); n_bord++)
746 {
747 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
748 const Frontiere_dis_base& la_fr = la_cl->frontiere_dis();
749 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
750 int ndeb = le_bord.num_premiere_face();
751 int nfin = ndeb + le_bord.nb_faces();
752 double h_moy = 0.;
753 // Depending on the boundary conditions
754 if (sub_type(Echange_externe_impose, la_cl.valeur()))
755 {
756 const Champ_base& rho = equation().milieu().masse_volumique();
758 int rho_uniforme = (sub_type(Champ_Uniforme,rho) ? 1 : 0);
759 int cp_uniforme = (sub_type(Champ_Uniforme,Cp) ? 1 : 0);
760 for (int num_face = ndeb; num_face < nfin; num_face++)
761 {
762 int elem = face_voisins(num_face, 0);
763 double rho_cp = (rho_uniforme ? rho.valeurs()(0, 0) : (rho.nb_comp() == 1 ? rho.valeurs()(num_face) : rho.valeurs()(num_face, 0)));
764 rho_cp *= (cp_uniforme ? Cp.valeurs()(0, 0) : (Cp.nb_comp() == 1 ? Cp.valeurs()(num_face) : Cp.valeurs()(num_face, 0)));
765 h_conv(elem) = ref_cast(Echange_externe_impose,la_cl.valeur()).h_imp(num_face) * rho_cp;
766 h_moy += h_conv(elem);
767 }
768 }
769 else if (sub_type(Scalaire_impose_paroi,la_cl.valeur()) || sub_type(Neumann_homogene, la_cl.valeur()) || sub_type(Neumann_paroi, la_cl.valeur()))
770 {
771 for (int num_face = ndeb; num_face < nfin; num_face++)
772 {
773 int elem = face_voisins(num_face, 0);
774
775 double norme_flux = 0.;
776 double surf = 0.;
777
778 for (int k = 0; k < Flux.dimension(1); k++)
779 norme_flux += Flux(num_face, k) * Flux(num_face, k);
780
781 for (int k = 0; k < Objet_U::dimension; k++)
782 surf += face_normale(num_face, k) * face_normale(num_face, k);
783
784 double DT = temp(num_face) - T_ref;
785
786 if (DT == 0.)
787 h_conv(elem) = 0.;
788 else
789 {
790 //This field is updated when its post-processing is requested,
791 //and consequently the fluxes have been updated and are already multiplied by rho*Cp
792 h_conv(elem) = sqrt(norme_flux / surf) / DT;
793 }
794 h_moy += h_conv(elem);
795 }
796 }
797 // Optimization: combine 2 mp_sum into 1 collective call
798 double nb_faces_d = static_cast<double>(le_bord.nb_faces());
799 mp_sum_for_each(h_moy, nb_faces_d);
800 int nb_faces = static_cast<int>(nb_faces_d); // a single 'bord' should not have so many faces
801 h_moy /= nb_faces;
802 if (je_suis_maitre())
803 {
804 Nom fich_hconv;
805 fich_hconv = "Heat_transfert_Coeff_";
806 fich_hconv += la_fr.le_nom();
807 fich_hconv += ".dat";
808
809 SFichier fic(fich_hconv, ios::app);
810 fic.setf(ios::scientific);
811
812 double le_temps = equation().schema_temps().temps_courant();
813 fic << le_temps << " " << h_moy << finl;
814 }
815 }
816}
817
818static double norme_L2(const DoubleTab& u, const Domaine_VEF& domaine_VEF)
819{
820 const int nb_faces = domaine_VEF.nb_faces();
821 double norme = 0;
822 int nb_compo_ = u.line_size();
823
824 CDoubleArrView volumes = domaine_VEF.volumes_entrelaces().view_ro(); // DOUBT: reference?
825 CDoubleTabView uview = u.view_ro(); // DOUBT: How to name this variable?
826
827 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_faces,
828 KOKKOS_LAMBDA (const int i, double& s)
829 {
830 for (int j = 0; j < nb_compo_; j++)
831 s += uview(i, j) * uview(i, j);
832 s *= volumes(i);
833 }, norme);
834 end_gpu_timer(__KERNEL_NAME__);
835
836 return sqrt(norme);
837}
838double Champ_P1NC::norme_L2(const Domaine& dom) const
839{
840 Cerr << "Champ_P1NC::norme_L2" << finl;
841 {
842 DoubleTab x(valeurs());
843 filtrer_L2(x);
844 Cerr << "Norme filtree : " << ::norme_L2(x, domaine_vef()) << finl;
845 }
846 const DoubleTab& u = valeurs();
847 return ::norme_L2(u, domaine_vef());
848}
849
850double Champ_P1NC::norme_H1(const Domaine& dom) const
851{
852 const Domaine& mon_dom = domaine_vef().domaine();
853
854 double dnorme_H1;
855 // DOUBT: dimension?
856 int dim = dimension;
857 const int nb_elem = mon_dom.nb_elem();
858 const int nb_faces_elem = mon_dom.nb_faces_elem();
859 CIntTabView elem_faces = domaine_vef().elem_faces().view_ro();
860 CDoubleTabView face_normales = domaine_vef().face_normales().view_ro();
861 CIntTabView face_voisins = domaine_vef().face_voisins().view_ro();
862 CDoubleTabView tab = valeurs().view_ro();
863 CDoubleArrView volumes = domaine_vef().volumes().view_ro();
864
865 // Compute the H1 norm of a P1NC unknown.
866 // The algorithm accounts for the following constraints:
867 // - the unknown may have several components (i.e. be a scalar or a vector)
868 // - the problem dimension is arbitrary (1, 2 or 3).
869 // WARNING: prisms are not supported.
870 dnorme_H1 = 0.;
871 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_comp(), //scalar or vector case
872 KOKKOS_LAMBDA (const int composante, double& norme_H1_comp)
873 {
874 for (int K = 0; K < nb_elem; K++) //loop over elements
875 {
876 double norme_grad_elem = 0.; //to avoid accumulation errors
877 for (int i = 0; i < dim; i++) //loop over problem dimension
878 {
879 double int_grad_elem = 0.; //to avoid accumulation errors
880 for (int face = 0; face < nb_faces_elem; face++) //loop over faces of element "K"
881 {
882 int face_globale = elem_faces(K, face);
883
884 int_grad_elem += tab(face_globale, composante) * face_normales(face_globale, i) * oriente_normale(face_globale, K, face_voisins);
885 } //end for on "face"
886
887 norme_grad_elem += int_grad_elem * int_grad_elem;
888 } //end for on "i"
889
890 norme_H1_comp += norme_grad_elem / volumes(K);
891 } //end for on "K"
892
893 }, dnorme_H1); // end for on "composante"
894 end_gpu_timer(__KERNEL_NAME__);
895
896 return sqrt(dnorme_H1);
897}
898
899double Champ_P1NC::norme_L2_H1(const Domaine& dom) const
900{
901 double pas_de_temps = equation().schema_temps().pas_de_temps();
902
903 return ((1. / pas_de_temps) * norme_L2(dom)) + norme_H1(dom);
904}
905
906/////////////////////////////////////////////////////////////////////////////////////////////////////
907// Method that returns gij at elements from the face field.
908// (gij represents the partial derivative dGi/dxj)
909// From gij, one can compute Sij = 0.5(gij(i,j)+gij(j,i))
910////////////////////////////////////////////////////////////////////////////////////////////////////
911
912DoubleTab& Champ_P1NC::calcul_gradient(const DoubleTab& champ, DoubleTab& gij, const Domaine_Cl_VEF& domaine_Cl_VEF)
913{
914 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
915 calculer_gradientP1NC(champ, domaine_VEF, domaine_Cl_VEF, gij);
916 return gij;
917
918}
919
920DoubleTab& 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)
921{
922 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
923
924 // Modify Sij for Dirichlet faces (Paroi_fixe) if Paroi_negligeable is not used!
925 // We will have: (grad u)_f = (grad u) - (grad u . n) x n + (grad u . n)_lp x n
926 //
927
928 // PQ : 25/01/08 : Method cleaned up to avoid being confused by sign issues
929 // and to know exactly what is being computed.
930 //
931 // PRINCIPLE:
932 // (described in 2D; the extension to 3D poses no particular difficulty)
933 //
934 // Consider 2 frames: the global frame (x,y) and the local frame (t,n) where n is the wall normal.
935 // The friction returned by the wall law corresponds to: || tau_tan || = u*^2 = nu.d(u_t)/dn
936 // Let P be the change-of-basis matrix from one frame to the other:
937 //
938 // P = ( tx nx )
939 // ( ty ny )
940 //
941 // The velocity gradient matrices in each frame:
942 //
943 // G_(x,y) = ( du/dx du/dy ) and F_(t,n) = ( du_t/dt du_t/dn )
944 // ( dv/dx dv/dy ) ( du_n/dt du_n/dn )
945 //
946 // -1
947 // are related by: G_(x,y) = P . F_(t,n) . P
948 //
949 //
950 // Thus the correction applied in F = ( du_t/dt du_t/dn + C ) where C = -du_t/dn + tau_tan/nu
951 // ( du_n/dt du_n/dn )
952 //
953 // maps into G as follows:
954 //
955 // -1
956 // G*_(x,y) = G_(x,y) + P . ( 0 C ). P = G_(x,y) + ( C.nx.tx C.ny.tx )
957 // ( 0 0 ) ( C.nx.ty C.ny.ty )
958 //
959 //
960 // it is this last term that must be determined here
961
962 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
963 int nb_cl = les_cl.size();
964
965 // tab_tau_tan could be uninitialized at this point. In such a case,
966 // we can skip the function because the value of gij won't change
967 if (tab_tau_tan.dimension_tot(0) == 0) return tab_gij;
968
969 for (int num_cl = 0; num_cl < nb_cl; num_cl++)
970 {
971 // Loop over the boundaries
972 const Cond_lim& la_cl = les_cl[num_cl];
973 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")
974 {
975 const Front_VF& la_front_dis = ref_cast(Front_VF, la_cl->frontiere_dis());
976 int ndeb = la_front_dis.num_premiere_face();
977 int nfin = ndeb + la_front_dis.nb_faces();
978 int dim = Objet_U::dimension;
979 // Loop over the faces
980 CDoubleTabView face_normale = domaine_VEF.face_normales().view_ro();
981 CIntTabView face_voisins = domaine_VEF.face_voisins().view_ro();
982 CDoubleArrView porosite_face = domaine_Cl_VEF.equation().milieu().porosite_face().view_ro();
983 CDoubleTabView tau_tan = tab_tau_tan.view_ro();
984 CDoubleArrView nu = static_cast<const ArrOfDouble&>(tab_nu).view_ro();
985 CDoubleArrView nu_turb = static_cast<const ArrOfDouble&>(tab_nu_turb).view_ro();
986 DoubleTabView3 gij = tab_gij.view_rw<3>();
987 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA (const int fac)
988 {
989 double P[3][3];
990 int num1 = face_voisins(fac, 0);
991 // definition of the unit vectors forming the local frame,
992 // stored in the change-of-basis matrix P
993 // tangential vector (aligned with the tangential velocity)
994 double sum = 0.;
995 for (int i = 0; i < dim; i++)
996 sum += tau_tan(fac, i) * tau_tan(fac, i);
997 double norme_tau_tan = sqrt(sum);
998 for (int i = 0; i < dim; i++)
999 P[i][0] = tau_tan(fac, i) / (norme_tau_tan + DMINFLOAT);
1000
1001 // vector normal to the wall
1002 sum = 0.;
1003 for (int i = 0; i < dim; i++)
1004 sum += face_normale(fac, i) * face_normale(fac, i);
1005 double norme = sqrt(sum);
1006
1007 int signe = -oriente_normale(fac, num1, face_voisins); // inward orientation
1008 for (int i = 0; i < dim; i++)
1009 P[i][1] = signe * face_normale(fac, i) / norme;
1010
1011 // (3D) complete the basis with the second tangential vector
1012 if (dim == 3)
1013 {
1014 P[0][2] = P[1][0] * P[2][1] - P[2][0] * P[1][1];
1015 P[1][2] = P[2][0] * P[0][1] - P[0][0] * P[2][1];
1016 P[2][2] = P[0][0] * P[1][1] - P[1][0] * P[0][1];
1017 }
1018 // determine the term d(u_t)/dn to be removed
1019 // -1
1020 // term identified using the product: F = P . G . P
1021 //
1022 double dutdn_old = 0.;
1023 for (int i = 0; i < dim; i++)
1024 for (int j = 0; j < dim; j++)
1025 {
1026 double gij_value = Kokkos::atomic_fetch_add(&gij(num1, i, j), 0.0);
1027 dutdn_old += gij_value * P[j][1] * P[i][0];
1028 }
1029
1030 // Final correction applied to matrix G
1031 double C = -dutdn_old + norme_tau_tan / (nu[num1] + nu_turb[num1]) * porosite_face(fac);
1032
1033 // the division by (nu[num1]+nu_turb[num1]) is required because the diffusion operator
1034 // involves the product: (nu[num1]+nu_turb[num1])*g(i,j)
1035 for (int i = 0; i < dim; i++)
1036 for (int j = 0; j < dim; j++)
1037 Kokkos::atomic_add(&gij(num1, i, j), C * P[j][1] * P[i][0]);
1038 });
1039 end_gpu_timer(__KERNEL_NAME__);
1040 }
1041 }
1042
1043 return tab_gij;
1044}
1045
1046////////////////////
1047// Compute 2SijSij
1048////////////////////
1049DoubleVect& Champ_P1NC::calcul_S_barre(const DoubleTab& la_vitesse, DoubleVect& SMA_barre, const Domaine_Cl_VEF& domaine_Cl_VEF)
1050{
1051 const Domaine_VEF& domaine_VEF = domaine_Cl_VEF.domaine_vef();
1052 const int nb_elem = domaine_VEF.nb_elem();
1053 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
1054
1055 DoubleTrav duidxj(nb_elem_tot, dimension, dimension);
1056
1057 Champ_P1NC::calcul_gradient(la_vitesse, duidxj, domaine_Cl_VEF);
1058
1059 int dim = Objet_U::dimension;
1060 CDoubleTabView3 duidxj_v = duidxj.view_ro<3>();
1061 DoubleArrView SMA_barre_v = SMA_barre.view_wo();
1062 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(
1063 const int elem)
1064 {
1065 double temp = 0.;
1066 for (int i = 0; i < dim; i++)
1067 for (int j = 0; j < dim; j++)
1068 {
1069 double Sij = 0.5 * (duidxj_v(elem, i, j) + duidxj_v(elem, j, i));
1070 temp += Sij * Sij;
1071 }
1072 SMA_barre_v(elem) = 2. * temp;
1073 });
1074 end_gpu_timer(__KERNEL_NAME__);
1075
1076 return SMA_barre;
1077}
1078
1079double Champ_P1NC::calculer_integrale_volumique(const Domaine_VEF& domaine, const DoubleVect& v, Ok_Perio ok)
1080{
1081 if (ok != FAUX_EN_PERIO)
1082 {
1083 // BM: sorry
1084 Cerr << "Champ_P1NC::calculer_integrale_volumique not yet correctly implemented in periodic case!" << finl;
1085 exit();
1086 }
1087
1088 assert(v.line_size() == 1);
1089 const DoubleVect& volume = domaine.volumes_entrelaces();
1090 const double resu = mp_prodscal(v, volume);
1091 return resu;
1092}
1093
1095{
1096 assert(nb_noeuds == domaine_vef().nb_faces());
1097 const MD_Vector& md = domaine_vef().md_vector_faces();
1099
1101
1102 return nb_noeuds;
1103}
class Champ_Don_base base class of Given Fields (not calculated)
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
Class 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 &)
Reads the field values from an input stream.
const Domaine_Cl_dis_base & domaine_Cl_dis() const
void mettre_a_jour(double temps) override
Performs a time update of the unknown field.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
Champ_base & affecter_(const Champ_base &) override
Assignment of a generic OWN_PTR(Champ_base) (Champ_base) to an unknown field.
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
Performs a time update of the unknown field.
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
Assignment of a generic OWN_PTR(Champ_base) (Champ_base) to an unknown field.
void calcul_grad_U(const Domaine_Cl_VEF &, DoubleTab &) const
DoubleTab & trace(const Frontiere_dis_base &, DoubleTab &, double, int distant) const override
See Champ_base. Special case (unfortunately) of 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
Champ_Uniforme Represents a field that is constant in space and time.
Champ_base()
Default constructor of a Champ_base.
virtual DoubleTab & valeur_aux(const DoubleTab &positions, DoubleTab &valeurs) const
Causes an error! Must be overridden by derived classes.
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
Dirichlet_paroi_defilante Imposes the wall velocity in an equation of type Navier_Stokes.
Dirichlet_paroi_fixe Represents a fixed wall in a Navier-Stokes type equation.
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Returns the number of faces of type i of the geometric elements that make up the domain.
Definition Domaine.h:484
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
Domaine_VEF & domaine_vef()
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
int nb_cond_lim() const
Returns the number of boundary conditions.
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VEF
Definition Domaine_VEF.h:53
int nb_faces() const
Returns the total number of 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
Returns the total number of 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
Returns the index of the i-th vertex of face num_face.
Definition Domaine_VF.h:582
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
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
Returns the neighbouring element of num_face in 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: This class represents the special case of the class.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Equation_base The role of an equation is the calculation of one or more fields....
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()
Returns the discretized boundary condition domain associated with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
virtual const Operateur & operateur(int) const =0
const Nom & le_nom() const override
Returns the name of the field.
virtual int nb_comp() const
Definition Field_base.h:56
int nb_compo_
Definition Field_base.h:95
Base class for an incompressible fluid and its properties:
Definition Fluide_base.h:36
const Champ_Don_base & viscosite_cinematique() const
Definition Fluide_base.h:56
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
class Frontiere_dis_base Class representing a discretized boundary.
const Nom & le_nom() const override
Returns the name of the geometric boundary.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
virtual const Champ_Don_base & capacite_calorifique() const
Returns the heat capacity of the medium (const version).
virtual const Champ_base & masse_volumique() const
Returns the mass density of the medium (const version).
DoubleVect & porosite_face()
Definition Milieu_base.h:62
Base class for the turbulence model hierarchy for Navier-Stokes equations.
const Turbulence_paroi_base & loi_paroi() const
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Classe Neumann_homogene This class is the base class of the hierarchy of homogeneous Neumann-type bou...
Classe Neumann_paroi This boundary condition corresponds to an imposed flux for the.
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
DoubleTab & flux_bords()
virtual Operateur_base & l_op_base()=0
class Periodique This class represents a periodic boundary condition.
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:208
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
SFichier is to the C++ ofstream class what Sortie is to the C++ ostream class.
Definition SFichier.h:29
Scalaire_impose_paroi Imposes a scalar at the wall in a Convection-Diffusion equation for a scalar.
double temps_courant() const
Returns the current time.
double pas_de_temps() const
Returns the current time step (delta_t).
void setf(IOS_FORMAT code) override
Base class for output streams.
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
Base class for the hierarchy of wall-law models computing turbulent quantities near walls....
const DoubleVect & tab_d_plus() const
virtual bool use_shear() const