TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Domaine_Cl_VEF.cpp
1/****************************************************************************
2* Copyright (c) 2025, 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_entree_fluide_leaves.h>
17#include <Dirichlet_paroi_defilante.h>
18#include <Scalaire_impose_paroi.h>
19#include <Check_espace_virtuel.h>
20#include <Dirichlet_paroi_fixe.h>
21#include <Neumann_sortie_libre.h>
22#include <Domaine_VEF.h>
23#include <Dirichlet_homogene.h>
24#include <Navier_Stokes_std.h>
25#include <MD_Vector_tools.h>
26#include <Domaine_Cl_VEF.h>
27#include <Champ_P0_VEF.h>
28#include <Hexaedre_VEF.h>
29#include <Domaine_VEF.h>
30#include <Quadri_VEF.h>
31#include <Champ_P1NC.h>
32#include <Periodique.h>
33#include <Conduction.h>
34#include <Dirichlet.h>
35#include <Tetra_VEF.h>
36#include <Hexa_VEF.h>
37#include <Symetrie.h>
38#include <Domaine.h>
39#include <Tri_VEF.h>
40#include <Debog.h>
41
42Implemente_instanciable(Domaine_Cl_VEF, "Domaine_Cl_VEF", Domaine_Cl_dis_base);
43
44int Deux_Puissance(int n)
45{
46 switch(n)
47 {
48 case 0:
49 return 1;
50 case 1:
51 return 2;
52 case 2:
53 return 4;
54 case 3:
55 return 8;
56 default:
57 return 8 * Deux_Puissance((int) (n - 3));
58 }
59}
60
62{
65 os << type_elem_Cl_;
66 return os;
67}
68
70
72{
73 const Domaine_VEF& le_dom_VEF = ref_cast(Domaine_VEF, dom_dis);
74 int nb_faces_non_std = le_dom_VEF.nb_faces_non_std();
75 const Elem_VEF_base& type_elem = le_dom_VEF.type_elem();
76 int nb_fa7_elem = type_elem.nb_facette();
77
78 {
79 IntVect renum;
80 le_dom_VEF.creer_tableau_faces(renum, RESIZE_OPTIONS::NOCOPY_NOINIT);
81 renum = -1;
82 // Marquer les faces non standard reelles (premieres faces dans le domaine)
83 for (int i = 0; i < nb_faces_non_std; i++)
84 renum[i] = 0;
85 // Echange espace virtuel => marquer les faces virtuelles non standard
87 MD_Vector md_vect;
89 MD_Vector_tools::creer_tableau_distribue(md_vect, volumes_entrelaces_Cl_, RESIZE_OPTIONS::NOCOPY_NOINIT);
90 }
91 {
92 // Construction du descripteur pour le tableau des elements "Cl":
93 MD_Vector md_vect;
95
96 // Creation de tableaux aux elements "Cl":
97 normales_facettes_Cl_.resize(0, nb_fa7_elem, dimension);
98 MD_Vector_tools::creer_tableau_distribue(md_vect, normales_facettes_Cl_, RESIZE_OPTIONS::NOCOPY_NOINIT);
99
100 vecteur_face_facette_Cl_.resize(0, nb_fa7_elem, dimension, 2);
101 MD_Vector_tools::creer_tableau_distribue(md_vect, vecteur_face_facette_Cl_, RESIZE_OPTIONS::NOCOPY_NOINIT);
102
103 MD_Vector_tools::creer_tableau_distribue(md_vect, type_elem_Cl_, RESIZE_OPTIONS::NOCOPY_NOINIT);
104 }
105}
106
107/*! @brief remplissage des tableaux
108 *
109 */
111{
112 if (sub_type(Domaine_VEF, un_domaine_dis))
113 {
114 const Domaine_VEF& le_dom_VEF = ref_cast(Domaine_VEF, un_domaine_dis);
115 remplir_type_elem_Cl(le_dom_VEF);
118 }
119 else
120 {
121 Cerr << "Domaine_Cl_VEF::completer() prend comme argument un Domaine_VEF " << finl;
122 exit();
123 }
124}
125
126/*! @brief appele par completer() : remplissage de type_elem_Cl_ et volumes_entrelaces_Cl_
127 *
128 */
130{
131 Cerr << "On passe dans Domaine_Cl_VEF::remplir_volumes_entrelaces" << finl;
132 const Domaine_VEF& z = ref_cast(Domaine_VEF, le_dom_VEF);
133
134 // On etendre les volumes de controles sur les faces non standard. Uniquement en conduction pour l'instant ou en P0 seul
135 if ((z.get_modif_div_face_dirichlet()) || sub_type(Conduction, equation()) || (z.get_alphaE() && !z.get_alphaS() && !z.get_alphaA()))
136 {
137 const DoubleVect& volumes_entrelaces = le_dom_VEF.volumes_entrelaces();
138 const IntVect& rang_elem = le_dom_VEF.rang_elem_non_std();
139
140 // Initialisation du tableau volumes_entrelaces_Cl
141 // a priori les faces non standard ne sont pas touchees par les C.L
142
143 for (int i = 0; i < le_dom_VEF.nb_faces_non_std(); i++)
144 volumes_entrelaces_Cl_[i] = volumes_entrelaces(i);
145
146 // Calcul des valeurs des volumes entrelaces modifiees par les C.L:
147
148 int nb_poly_tot = le_dom_VEF.domaine().nb_elem_tot();
149 ArrOfInt poly_fait(nb_poly_tot);
150 poly_fait = 0;
151 for (int i = 0; i < les_conditions_limites_.size(); i++)
152 {
153 const Cond_lim_base& la_cl = les_conditions_limites_[i].valeur();
154 if ((sub_type(Dirichlet, la_cl)) || (sub_type(Dirichlet_homogene, la_cl)))
155 {
156 const Front_VF& le_bord = le_dom_VEF.front_VF(i);
157 const Frontiere& front = le_bord.frontiere();
158 int premiere = le_bord.num_premiere_face();
159 int derniere = premiere + le_bord.nb_faces();
160 for (int j = premiere; j < derniere; j++)
161 {
163 int elem = le_dom_VEF.face_voisins(j, 0);
164 int n_poly = rang_elem(elem);
165 if (!poly_fait[n_poly])
166 {
167 poly_fait[n_poly] = 1;
168 const Elem_VEF_base& type_elem = le_dom_VEF.type_elem();
169 type_elem.modif_volumes_entrelaces(j, elem, le_dom_VEF, volumes_entrelaces_Cl(), type_elem_Cl(n_poly));
170 }
171 }
172 // faces virtuelles de bord :
173 const ArrOfInt& faces_virt = front.get_faces_virt();
174 int nb_faces_virt = faces_virt.size_array();
175 for (int ind_face = 0; ind_face < nb_faces_virt; ind_face++)
176 {
177 int num_face = faces_virt[ind_face];
178 int elem = le_dom_VEF.face_voisins(num_face, 0);
179 int n_poly = rang_elem(elem);
180 if (n_poly != -1)
181 {
182 if (!poly_fait[n_poly])
183 {
184 poly_fait[n_poly] = 1;
185 const Elem_VEF_base& type_elem = le_dom_VEF.type_elem();
186 type_elem.modif_volumes_entrelaces_faces_joints(num_face, elem, le_dom_VEF, volumes_entrelaces_Cl(), type_elem_Cl(n_poly));
187 }
188 }
189 }
190 }
191 }
192 }
193 else
194 {
195 const DoubleVect& volumes_entrelaces = le_dom_VEF.volumes_entrelaces();
196 // Initialisation du tableau volumes_entrelaces_Cl a priori les faces non standard ne sont pas touchees par les C.L
197 for (int i = 0; i < le_dom_VEF.nb_faces_non_std(); i++)
198 volumes_entrelaces_Cl(i) = volumes_entrelaces(i);
199 Cerr << "Fin creation esp. virtuel volumes_entrelaces_Cl_" << finl;
200 }
201}
202
203/*! @brief appele par completer() : remplissage de normales_facettes_Cl_ et vecteur_face_caette_Cl_
204 *
205 * CHANGER LE NOM
206 *
207 */
209{
210 const Domaine& z = le_dom_VEF.domaine();
211 const Domaine& dom = z;
212 const DoubleTab& les_coords = dom.coord_sommets();
213 const IntTab& les_Polys = z.les_elems();
214 const Elem_VEF_base& elemvef = le_dom_VEF.type_elem();
215 const IntVect& rang_elem = le_dom_VEF.rang_elem_non_std();
216 const IntTab& elem_faces = le_dom_VEF.elem_faces();
217 const DoubleTab& xv = le_dom_VEF.xv();
218 const IntTab& KEL = elemvef.KEL();
219
220 int num_elem, fa7;
221 int isom, ncomp;
222 int idirichlet = -1, n1 = -1, n2 = -1, n3 = -1;
223 int nb_elem = z.nb_elem();
224 int nsom = z.nb_som_elem();
225 int nfa7 = elemvef.nb_facette();
226 //int nb_som_facette = domaine().type_elem().nb_som_face();
227 //if ( sub_type(Hexaedre_VEF,domaine().type_elem().valeur())) { nb_som_facette--; }
228 int nb_som_facette = dimension;
229
230 IntVect num_som(nsom);
231 DoubleTab x(nsom, dimension);
232 DoubleVect xg(dimension);
233 //DoubleVect xj0(dimension);
234 //DoubleVect u(dimension);
235 //DoubleVect v(dimension);
236
237 // Calcul des valeurs des normales aux facettes modifiees par les C.L:
238
239 for (int elem = 0; elem < nb_elem; elem++)
240 {
241
242 if (rang_elem(elem) != -1)
243 {
244 num_elem = rang_elem(elem);
245
246 // numero des sommets du polyedre:
247 for (isom = 0; isom < nsom; isom++)
248 num_som[isom] = les_Polys(elem, isom);
249
250 // Calcul des coordonnees des sommets du polyedre:
251 for (isom = 0; isom < nsom; isom++)
252 for (ncomp = 0; ncomp < dimension; ncomp++)
253 x(isom, ncomp) = les_coords(num_som[isom], ncomp);
254
255 // Calcul des coordonnees du point G en fonction du type du polyedre
256 // idirichlet= nb de faces de dirichlet de l'elem
257 // pour triangle si idirichlet=2, n1=sommet confondu avec G
258 // pour quadrangle se reporter a Quadri_VEF.cpp
259
260 elemvef.calcul_xg(xg, x, type_elem_Cl_[num_elem], idirichlet, n1, n2, n3);
261 // Calcul des valeurs du tableau normales_facettes_Cl:
262
263 for (fa7 = 0; fa7 < nfa7; fa7++)
264 {
265 elemvef.creer_normales_facettes_Cl(normales_facettes_Cl(), fa7, num_elem, x, xg, z);
266 // Correction des valeurs du tableau normales_facettes_Cl:
267 elemvef.modif_normales_facettes_Cl(normales_facettes_Cl(), fa7, num_elem, idirichlet, n1, n2, n3);
268 int num1 = elem_faces(elem, KEL(0, fa7));
269 int num2 = elem_faces(elem, KEL(1, fa7));
270 for (int dir = 0; dir < dimension; dir++)
271 {
272 double coord_centre_fa7 = xg(dir);
273
274 for (int num_som_fa7 = 0; num_som_fa7 < nb_som_facette - 1; num_som_fa7++)
275 {
276 int isom_loc = KEL(num_som_fa7 + 2, fa7);
277 int isom_glob = les_Polys(elem, isom_loc);
278 coord_centre_fa7 += les_coords(isom_glob, dir);
279 }
280 coord_centre_fa7 /= nb_som_facette;
281
282 vecteur_face_facette_Cl_(num_elem, fa7, dir, 0) = coord_centre_fa7 - xv(num1, dir);
283 vecteur_face_facette_Cl_(num_elem, fa7, dir, 1) = coord_centre_fa7 - xv(num2, dir);
284 }
285
286 }
287 }
288 }
289 normales_facettes_Cl_.echange_espace_virtuel();
290 vecteur_face_facette_Cl_.echange_espace_virtuel();
291}
292
293int trois_puissance(int n)
294{
295 switch(n)
296 {
297 case 0:
298 return 1;
299 case 1:
300 return 3;
301 case 2:
302 return 9;
303 case 3:
304 return 27;
305 default:
306 return 27 * trois_puissance(n - 3);
307 }
308}
309
310/*! @brief appele par remplir_volumes_entrelaces_Cl() : remplissage de type_elem_Cl_
311 *
312 */
314{
315 const Domaine& z = le_dom_VEF.domaine();
316 int nfac = z.type_elem()->nb_faces(); // dans Elem_geom
317 const IntTab& elem_faces = le_dom_VEF.elem_faces();
318 const IntTab& face_voisins = le_dom_VEF.face_voisins();
319 const IntVect& rang_elem = le_dom_VEF.rang_elem_non_std();
320 type_elem_Cl_ = 0;
321 int elem, num_elem;
322
323 for (int i = 0; i < les_conditions_limites_.size(); i++)
324 {
325 Cond_lim_base& la_cl = les_conditions_limites_[i].valeur();
326 if ((sub_type(Dirichlet, la_cl)) || (sub_type(Dirichlet_homogene, la_cl)))
327 {
328 const Front_VF& le_bord = le_dom_VEF.front_VF(i);
329 int premiere = le_bord.num_premiere_face();
330 int derniere = premiere + le_bord.nb_faces();
331 for (int j = premiere; j < derniere; j++)
332 {
333 elem = face_voisins(j, 0);
334 int numero1, numero2 = -1;
335 for (numero1 = 0; numero1 < nfac; numero1++)
336 if (elem_faces(elem, numero1) == j)
337 numero2 = numero1;
338 if (numero2 == -1)
339 Cerr << "Domaine_Cl_VEF::creer_type_elem_Cl() PAS POSSIBLE!! " << finl;
340 num_elem = rang_elem(elem);
341 assert(num_elem != -1);
342 if (sub_type(Tri_VEF,le_dom_VEF.type_elem()) || sub_type(Tetra_VEF, le_dom_VEF.type_elem()))
343 type_elem_Cl_[num_elem] += Deux_Puissance((int) (nfac - 1 - numero2));
344 else if (sub_type(Quadri_VEF,le_dom_VEF.type_elem()) || sub_type(Hexa_VEF, le_dom_VEF.type_elem()))
345 type_elem_Cl_[num_elem] += trois_puissance((int) (nfac - 1 - numero2));
346 else
347 {
348 Cerr << "erreur dans Domaine_Cl_VEF::remplir_type_elem_Cl mauvais typage d'element " << finl;
349 exit();
350 }
351
352 }
353 }
354 }
355
356 type_elem_Cl_.echange_espace_virtuel();
357}
358
359/*! @brief Impose les conditions aux limites a la valeur temporelle "temps" du Champ_Inc
360 *
361 */
363{
364 DoubleTab& ch_tab = ch.valeurs(temps);
365 int nb_comp = ch.nb_comp();
366 if (sub_type(Champ_P0_VEF, ch)) { /* Do nothing */ }
367 else if (sub_type(Champ_P1NC,ch) || sub_type(Champ_Q1NC, ch))
368 {
369 for (int i = 0; i < nb_cond_lim(); i++)
370 {
371 const Cond_lim_base& la_cl = les_conditions_limites(i).valeur();
372 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
373 int ndeb = le_bord.num_premiere_face();
374 int nfin = ndeb + le_bord.nb_faces();
375 if (sub_type(Periodique, la_cl))
376 {
377 // On fait en sorte que le champ ait la meme valeur
378 // sur deux faces de periodicite qui sont en face l'une de l'autre
379 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
380 CIntArrView face_associee = la_cl_perio.face_associee().view_ro();
381 if (nb_comp==1)
382 {
383 DoubleArrView tab = static_cast<ArrOfDouble&>(ch_tab).view_wo();
384 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
385 {
386 int voisine = face_associee(num_face - ndeb) + ndeb;
387 if (tab(num_face) != tab(voisine))
388 {
389 double moy = 0.5 * (tab(num_face) + tab(voisine));
390 tab(num_face) = moy;
391 tab(voisine) = moy;
392 }
393 });
394 }
395 else
396 {
397 DoubleTabView tab = ch_tab.view_wo();
398 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
399 {
400 int voisine = face_associee(num_face - ndeb) + ndeb;
401 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
402 if (tab(num_face, ncomp) != tab(voisine, ncomp))
403 {
404 double moy = 0.5 * (tab(num_face, ncomp) + tab(voisine, ncomp));
405 tab(num_face, ncomp) = moy;
406 tab(voisine, ncomp) = moy;
407 }
408 });
409 }
410 end_gpu_timer(__KERNEL_NAME__);
411 }
412 else if ((sub_type(Symetrie, la_cl)) && (ch.nature_du_champ() == vectoriel))
413 {
414 if (nb_comp == dimension)
415 {
416 CDoubleTabView face_normales = domaine_vef().face_normales().view_ro();
417 DoubleTabView tab = ch_tab.view_rw();
418 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
419 {
420 double surf = 0, flux = 0;
421 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
422 {
423 double face_n = face_normales(num_face, ncomp);
424 flux += tab(num_face, ncomp) * face_n;
425 surf += face_n * face_n;
426 }
427 // flux /= surf; // Fixed bug: Arithmetic exception
428 if (std::fabs(surf) >= DMINFLOAT)
429 flux /= surf;
430 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
431 tab(num_face, ncomp) -= flux * face_normales(num_face, ncomp);
432 });
433 end_gpu_timer(__KERNEL_NAME__);
434 }
435 }
436 else if (sub_type(Dirichlet_entree_fluide, la_cl))
437 {
438 const Dirichlet_entree_fluide& la_cl_diri = ref_cast(Dirichlet_entree_fluide, la_cl);
439 CDoubleTabView val_imp = la_cl_diri.tab_val_imp(temps).view_ro();
440 if (nb_comp == 1)
441 {
442 DoubleArrView tab = static_cast<ArrOfDouble&>(ch_tab).view_wo();
443 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin),
444 KOKKOS_LAMBDA(const int num_face)
445 {
446 tab(num_face) = val_imp(num_face - ndeb, 0);
447 });
448 }
449 else
450 {
451 DoubleTabView tab = ch_tab.view_wo();
452 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
453 {
454 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
455 tab(num_face, ncomp) = val_imp(num_face - ndeb, ncomp);
456 });
457 }
458 end_gpu_timer(__KERNEL_NAME__);
459 }
460 else if (sub_type(Scalaire_impose_paroi, la_cl))
461 {
462 const Scalaire_impose_paroi& la_cl_diri = ref_cast(Scalaire_impose_paroi, la_cl);
463 CDoubleTabView val_imp = la_cl_diri.tab_val_imp(temps).view_ro();
464 if (nb_comp == 1)
465 {
466 DoubleArrView tab = static_cast<ArrOfDouble&>(ch_tab).view_wo();
467 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin),
468 KOKKOS_LAMBDA(const int num_face)
469 {
470 tab(num_face) = val_imp(num_face - ndeb, 0);
471 });
472 }
473 else
474 {
475 DoubleTabView tab = ch_tab.view_wo();
476 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
477 {
478 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
479 tab(num_face, ncomp) = val_imp(num_face - ndeb, ncomp);
480 });
481 }
482 end_gpu_timer(__KERNEL_NAME__);
483 }
484 else if ((sub_type(Dirichlet_paroi_fixe, la_cl)) && (ch.nature_du_champ() == multi_scalaire))
485 {
486 if (nb_comp == 1)
487 {
488 DoubleArrView tab = static_cast<ArrOfDouble&>(ch_tab).view_wo();
489 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin),
490 KOKKOS_LAMBDA(const int num_face)
491 {
492 tab(num_face) = 0;
493 });
494 }
495 else
496 {
497 DoubleTabView tab = ch_tab.view_wo();
498 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
499 {
500 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
501 {
502 tab(num_face, 0) = 0;
503 tab(num_face, 1) = 0;
504 }
505 });
506 }
507 end_gpu_timer(__KERNEL_NAME__);
508 }
509 else if (sub_type(Dirichlet_paroi_fixe, la_cl))
510 {
511 if (nb_comp == 1)
512 {
513 DoubleArrView tab = static_cast<ArrOfDouble&>(ch_tab).view_wo();
514 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin),
515 KOKKOS_LAMBDA(const int num_face)
516 {
517 tab(num_face) = 0;
518 });
519 }
520 else
521 {
522 DoubleTabView tab = ch_tab.view_wo();
523 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
524 {
525 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
526 tab(num_face, ncomp) = 0;
527 });
528 }
529 end_gpu_timer(__KERNEL_NAME__);
530 }
531 else if (sub_type(Dirichlet_paroi_defilante, la_cl))
532 {
533 const Dirichlet_paroi_defilante& la_cl_diri = ref_cast(Dirichlet_paroi_defilante, la_cl);
534 CDoubleTabView face_normales = domaine_vef().face_normales().view_ro();
535 if (nb_comp != dimension)
536 {
537 Cerr << "Cas non prevu dans Domaine_Cl_VEF::imposer_cond_lim." << finl;
538 exit();
539 }
540 else
541 {
542 CDoubleTabView val_imp = la_cl_diri.tab_val_imp(temps).view_ro();
543 DoubleTabView tab = ch_tab.view_wo();
544 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
545 {
546 double surf = 0, flux = 0;
547 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
548 {
549 double face_n = face_normales(num_face, ncomp);
550 flux += val_imp(num_face - ndeb, ncomp) * face_n;
551 surf += face_n * face_n;
552 }
553 // flux /= surf; // Fixed bug: Arithmetic exception
554 if (std::fabs(surf) >= DMINFLOAT)
555 flux /= surf;
556 for (int ncomp = 0; ncomp < nb_comp; ncomp++)
557 tab(num_face, ncomp) = val_imp(num_face - ndeb, ncomp) -
558 flux * face_normales(num_face, ncomp);
559 });
560 end_gpu_timer(__KERNEL_NAME__);
561 }
562 }
563 }
564 }
565 else
566 {
567 Cerr << "Le type de OWN_PTR(Champ_Inc_base) " << ch.que_suis_je() << " n'est pas prevu en VEF\n" << finl;
568 exit();
569 }
570 ch_tab.echange_espace_virtuel();
571
572 // PARTIE PRESSION
573 // dans le cas Navier stokes et si la condition est forte en pression aux sommets on impose la valeur aux sommets
574 if (sub_type(Navier_Stokes_std, ch.equation()))
575 {
577 if ((domaine_vef.get_cl_pression_sommet_faible() == 0) && (domaine_vef.get_alphaS()))
578 {
579 int nps = domaine_vef.numero_premier_sommet();
580 int nbsom_tot = domaine_vef.nb_som_tot();
581 DoubleTrav tab_surf_loc(nbsom_tot);
582 tab_surf_loc = 0;
583 DoubleTab& tab_pression = ref_cast(Navier_Stokes_std,ch.equation()).pression().valeurs();
584 int nb_cond_lims = nb_cond_lim();
585 // On boucle une premiere fois pour mettre a zero la pression aux sommets
586 for (int i = 0; i < nb_cond_lims; i++)
587 {
588 const Cond_lim_base& la_cl = les_conditions_limites(i).valeur();
589 if (sub_type(Neumann_sortie_libre, la_cl))
590 {
591 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
592 int nbsf = domaine_vef.face_sommets().dimension(1);
593 int num2 = le_bord.nb_faces_tot();
594 CIntTabView faces = domaine_vef.face_sommets().view_ro();
595 CIntArrView num_face = le_bord.num_face().view_ro();
596 DoubleArrView pression = static_cast<DoubleVect&>(tab_pression).view_rw();
597 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
598 Kokkos::RangePolicy<>(0, num2), KOKKOS_LAMBDA(
599 const int ind_face)
600 {
601 int face = num_face(ind_face);
602 for (int som = 0; som < nbsf; som++)
603 {
604 int som_glob = faces(face, som);
605 Kokkos::atomic_store(&pression(nps + som_glob), 0);
606 }
607 });
608 end_gpu_timer(__KERNEL_NAME__);
609 }
610 }
611
612 // On boucle une deuxieme fois pour ajouter la contribution de chaque face
613 for (int i = 0; i < nb_cond_lims; i++)
614 {
615 const Cond_lim_base& la_cl = les_conditions_limites(i).valeur();
616 if (sub_type(Neumann_sortie_libre, la_cl))
617 {
618 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl);
619 const Front_VF& le_bord = ref_cast(Front_VF, la_cl.frontiere_dis());
620 int nbsf = domaine_vef.face_sommets().dimension(1);
621 int num2 = le_bord.nb_faces_tot();
622 CIntArrView num_face = le_bord.num_face().view_ro();
623 CIntTabView faces = domaine_vef.face_sommets().view_ro();
624 CDoubleArrView flux_impose = static_cast<const DoubleVect&>(la_sortie_libre.flux_impose(true)).view_ro();
625 CDoubleArrView face_surfaces = domaine_vef.face_surfaces().view_ro();
626 DoubleArrView surf_loc = static_cast<DoubleVect&>(tab_surf_loc).view_rw();
627 DoubleArrView pression = static_cast<DoubleVect&>(tab_pression).view_rw();
628 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
629 Kokkos::RangePolicy<>(0, num2), KOKKOS_LAMBDA(
630 const int ind_face)
631 {
632 int face = num_face(ind_face);
633 double P_imp = flux_impose(ind_face);
634 double face_surf = face_surfaces(face);
635 for (int som = 0; som < nbsf; som++)
636 {
637 int som_glob = faces(face, som);
638 Kokkos::atomic_add(&pression(nps + som_glob), P_imp * face_surf);
639 Kokkos::atomic_add(&surf_loc[som_glob], face_surf);
640 }
641 });
642 end_gpu_timer(__KERNEL_NAME__);
643 }
644 }
645 // On boucle une troisieme fois pour diviser par la surface
646 for (int i = 0; i < nb_cond_lims; i++)
647 {
648 const Cond_lim_base& la_cl = les_conditions_limites(i).valeur();
649 if (sub_type(Neumann_sortie_libre, la_cl))
650 {
651 DoubleArrView surf_loc = static_cast<DoubleVect&>(tab_surf_loc).view_rw();
652 DoubleArrView pression = static_cast<DoubleVect&>(tab_pression).view_rw();
653 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
654 Kokkos::RangePolicy<>(0, nbsom_tot), KOKKOS_LAMBDA(
655 const int som_glob)
656 {
657 if (surf_loc[som_glob] > 0)
658 {
659 pression(nps + som_glob) /= surf_loc[som_glob];
660 surf_loc[som_glob] = 0;
661 }
662 });
663 end_gpu_timer(__KERNEL_NAME__);
664 }
665 }
666 tab_pression.echange_espace_virtuel();
667 Debog::verifier("pression dans Domaine_Cl_VEF::imposer_cond_lim", tab_pression);
668 }
669 }
670}
671
673{
674 int compteur = 0;
675 for (const auto &itr : les_conditions_limites_)
676 {
677 if (sub_type(Neumann_sortie_libre, itr.valeur()))
678 {
679 const Front_VF& le_bord = ref_cast(Front_VF, itr->frontiere_dis());
680 compteur += le_bord.nb_faces();
681 }
682 }
683 return compteur;
684}
685
687{
688 int compteur = 0;
689 for (const auto &itr : les_conditions_limites_)
690 {
691 if (sub_type(Periodique, itr.valeur()))
692 compteur++;
693 }
694 return compteur;
695}
696
698{
700
701 if (nb_bord_periodicite() > 0)
702 {
703 if (modif_perio_fait_ == 0)
704 {
705 Cerr << "modification du Domaine_Cl_VEF pour periodicite" << finl;
706 const Domaine_VEF& le_dom_VEF = ref_cast(Domaine_VEF, domaine_dis());
707 const DoubleVect& volumes_entrelaces = le_dom_VEF.volumes_entrelaces();
709 for (int i = 0; i < les_conditions_limites_.size(); i++)
710 {
711 const Cond_lim_base& la_cl = les_conditions_limites_[i].valeur();
712
713 if (sub_type(Periodique, la_cl))
714 {
715
716 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl);
717 const Front_VF& le_bord = le_dom_VEF.front_VF(i);
718 int premiere = le_bord.num_premiere_face();
719 int derniere = premiere + le_bord.nb_faces();
720 IntVect fait(le_bord.nb_faces());
721 fait = 0;
722 int ind_fac_loc;
723
724 for (int j = premiere; j < derniere; j++)
725 {
726 ind_fac_loc = j - premiere;
727
728 if (fait[ind_fac_loc] == 0)
729 {
730 int fac_associee = la_cl_perio.face_associee(j - premiere) + premiere;
731 if (volumes_entrelaces_Cl_[j] != volumes_entrelaces[j])
733 else
735
736 fait[ind_fac_loc] = 1;
737 fait[fac_associee - premiere] = 1;
738 }
739 }
740 }
741 }
742
744 }
745 }
746 return 1;
747}
748
753
755{
756 return ref_cast(Domaine_VEF, domaine_dis());
757}
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Champ_P0_VEF Classe qui represente un champ discret P0 par element associe a un domaine discre...
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 Conduction Cette classe represente l'equation d'evolution.
Definition Conduction.h:41
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
classe Dirichlet_entree_fluide Cette classe represente une condition aux limite imposant une grandeur
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet_paroi_defilante Impose la vitesse de paroi dnas une equation de type Navier_Stokes.
classe Dirichlet_paroi_fixe Represente une paroi immobile dans une equation de type Navier_Stokes.
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
virtual const DoubleTab & tab_val_imp(double temps=DMAXFLOAT) const
Definition Dirichlet.cpp:75
int nb_som_elem() const
Renvoie le nombre de sommets des elements geometriques constituants le domaine.
Definition Domaine.h:474
int_t nb_elem_tot() const
Definition Domaine.h:132
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
DoubleVect & volumes_entrelaces_Cl()
Domaine_VEF & domaine_vef()
int initialiser(double temps) override
Initialise les CLs Contrairement aux methodes mettre_a_jour, les methodes.
void imposer_cond_lim(Champ_Inc_base &, double) override
Impose les conditions aux limites a la valeur temporelle "temps" du Champ_Inc.
DoubleTab normales_facettes_Cl_
void associer(const Domaine_dis_base &) override
int nb_bord_periodicite() const
void remplir_type_elem_Cl(const Domaine_VEF &)
appele par remplir_volumes_entrelaces_Cl() : remplissage de type_elem_Cl_
virtual void remplir_volumes_entrelaces_Cl(const Domaine_VEF &)
appele par completer() : remplissage de type_elem_Cl_ et volumes_entrelaces_Cl_
void remplir_normales_facettes_Cl(const Domaine_VEF &)
appele par completer() : remplissage de normales_facettes_Cl_ et vecteur_face_caette_Cl_
IntVect type_elem_Cl_
DoubleVect volumes_entrelaces_Cl_
int nb_faces_sortie_libre() const
DoubleTab & normales_facettes_Cl()
DoubleTab vecteur_face_facette_Cl_
const IntVect & type_elem_Cl() const
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
virtual int initialiser(double temps)
Initialise les CLs Contrairement aux methodes mettre_a_jour, les methodes.
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
void completer()
Appel Cond_lim_base::completer() sur chaque condition aux limites.
Conds_lim & les_conditions_limites()
Renvoie le tableaux des conditions aux limites.
Domaine_dis_base & domaine_dis()
Renvoie une reference sur le domaine discretise associe aux conditions aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:86
int nb_faces_non_std() const
Definition Domaine_VEF.h:81
int get_modif_div_face_dirichlet() const
Definition Domaine_VEF.h:96
const Elem_VEF_base & type_elem() const
Definition Domaine_VEF.h:75
int get_alphaA() const
Definition Domaine_VEF.h:94
int get_alphaS() const
Definition Domaine_VEF.h:93
int get_alphaE() const
Definition Domaine_VEF.h:92
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
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
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
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
const Front_VF & front_VF(int i) const
Definition Domaine_VF.h:112
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Domaine & domaine() const
virtual void calcul_xg(DoubleVect &, const DoubleTab &, const int, int &, int &, int &, int &) const =0
virtual void modif_volumes_entrelaces(int, int, const Domaine_VEF &, DoubleVect &, int) const =0
const IntTab & KEL() const
virtual int nb_facette() const =0
virtual void modif_volumes_entrelaces_faces_joints(int, int, const Domaine_VEF &, DoubleVect &, int) const =0
virtual void modif_normales_facettes_Cl(DoubleTab &, int, int, int, int, int, int) const =0
virtual void creer_normales_facettes_Cl(DoubleTab &, int, int, const DoubleTab &, const DoubleVect &, const Domaine &) const =0
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int nb_comp() const
Definition Field_base.h:56
virtual Nature_du_champ nature_du_champ() const
Definition Field_base.h:77
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
int nb_faces_tot() const
Definition Front_VF.h:58
int num_face(const int) const
Definition Front_VF.h:68
const ArrOfInt_t & get_faces_virt() const
Definition Frontiere.h:69
const Frontiere & frontiere() const
Renvoie la frontiere geometrique associee.
static void creer_md_vect_renum_auto(IntVect &flags_renum, MD_Vector &md_vect)
Idem que creer_md_vect_renum() mais cree une numerotation par defaut.
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
transforme v en un tableau parallele ayant la structure md.
static void creer_md_vect_renum(const IntVect &renum, MD_Vector &md_vect)
cree un descripteur pour un sous-ensemble d'un vecteur.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
virtual double flux_impose(int i) const
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
Definition Neumann.cpp:35
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
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 exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
classe Scalaire_impose_paroi Impose un scalaire a la paroi dans une equation de type Convection-Difus...
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37
_SIZE_ size_array() const
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_wo()
Definition TRUSTTab.h:276
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
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")