TrioCFD 1.9.9_beta
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 // Mark real non-standard faces (first faces in the domain)
83 for (int i = 0; i < nb_faces_non_std; i++)
84 renum[i] = 0;
85 // Exchange virtual space => mark virtual non-standard faces
87 MD_Vector md_vect;
89 MD_Vector_tools::creer_tableau_distribue(md_vect, volumes_entrelaces_Cl_, RESIZE_OPTIONS::NOCOPY_NOINIT);
90 }
91 {
92 // Build the descriptor for the "Cl" element array:
93 MD_Vector md_vect;
95
96 // Create arrays for "Cl" elements:
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 Fill arrays.
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() expects a Domaine_VEF argument " << finl;
122 exit();
123 }
124}
125
126/*! @brief Called by completer(): fills type_elem_Cl_ and volumes_entrelaces_Cl_.
127 *
128 */
130{
131 Cerr << "Entering Domaine_Cl_VEF::remplir_volumes_entrelaces" << finl;
132 const Domaine_VEF& z = ref_cast(Domaine_VEF, le_dom_VEF);
133
134 // Extend control volumes on non-standard faces. Only in conduction for now or in P0-only mode
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 // Initialise the volumes_entrelaces_Cl array
141 // non-standard faces are not a priori touched by boundary conditions
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 // Compute the interlaced volumes modified by boundary conditions:
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 // virtual boundary faces:
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 // Initialization of the volumes_entrelaces_Cl array: non-standard faces are a priori not affected by boundary conditions
197 for (int i = 0; i < le_dom_VEF.nb_faces_non_std(); i++)
198 volumes_entrelaces_Cl(i) = volumes_entrelaces(i);
199 Cerr << "End of virtual space creation for volumes_entrelaces_Cl_" << finl;
200 }
201}
202
203/*! @brief Called by completer(): fills normales_facettes_Cl_ and vecteur_face_facette_Cl_.
204 *
205 * RENAME THIS METHOD
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 // Compute the facet normals modified by boundary conditions:
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 // index of the vertices of the polyhedron:
247 for (isom = 0; isom < nsom; isom++)
248 num_som[isom] = les_Polys(elem, isom);
249
250 // Compute the coordinates of the polyhedron vertices:
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 // Compute the coordinates of point G based on the polyhedron type
256 // idirichlet = number of Dirichlet faces of the element
257 // for triangle if idirichlet=2, n1=vertex coinciding with G
258 // for quadrilateral refer to Quadri_VEF.cpp
259
260 elemvef.calcul_xg(xg, x, type_elem_Cl_[num_elem], idirichlet, n1, n2, n3);
261 // Compute values of the normales_facettes_Cl array:
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 of the normales_facettes_Cl array values:
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 Called by remplir_volumes_entrelaces_Cl(): fills type_elem_Cl_.
311 *
312 */
314{
315 const Domaine& z = le_dom_VEF.domaine();
316 int nfac = z.type_elem()->nb_faces(); // in 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() NOT 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 << "error in Domaine_Cl_VEF::remplir_type_elem_Cl wrong element type " << finl;
349 exit();
350 }
351
352 }
353 }
354 }
355
356 type_elem_Cl_.echange_espace_virtuel();
357}
358
359/*! @brief Imposes boundary conditions at the time "temps" of the 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 // Ensure the field has the same value
378 // on two periodic faces that are opposite each other
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 << "Case not handled in 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 << "The type of OWN_PTR(Champ_Inc_base) " << ch.que_suis_je() << " is not handled in VEF\n" << finl;
568 exit();
569 }
570 ch_tab.echange_espace_virtuel();
571
572 // PRESSURE PART
573 // In the Navier-Stokes case and if the pressure BC is imposed strongly at vertices, impose the pressure values at vertices
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 // First loop: zero out the pressure at vertices
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 // Second loop: add the contribution of each 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 // Third loop: divide by the surface area
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 << "Updating Domaine_Cl_VEF for periodicity" << 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}
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
class Champ_P0_VEF
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 Conduction: represents the temperature evolution equation.
Definition Conduction.h:41
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Dirichlet_entree_fluide This class represents a boundary condition imposing a quantity.
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
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.
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
virtual const DoubleTab & tab_val_imp(double temps=DMAXFLOAT) const
Definition Dirichlet.cpp:75
int nb_som_elem() const
Returns the number of vertices of the geometric elements that make up the domain.
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
Initializes the BCs. Unlike the update methods, the.
void imposer_cond_lim(Champ_Inc_base &, double) override
Imposes boundary conditions at the time "temps" of the 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 &)
Called by remplir_volumes_entrelaces_Cl(): fills type_elem_Cl_.
virtual void remplir_volumes_entrelaces_Cl(const Domaine_VEF &)
Called by completer(): fills type_elem_Cl_ and volumes_entrelaces_Cl_.
void remplir_normales_facettes_Cl(const Domaine_VEF &)
Called by completer(): fills normales_facettes_Cl_ and vecteur_face_facette_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
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
virtual int initialiser(double temps)
Initializes the BCs. Unlike the update methods, the.
int nb_cond_lim() const
Returns the number of boundary conditions.
void completer()
Calls Cond_lim_base::completer() on each boundary condition.
Conds_lim & les_conditions_limites()
Returns the array of boundary conditions.
Domaine_dis_base & domaine_dis()
Returns a reference to the discretized domain associated with the boundary conditions.
class Domaine_VEF
Definition Domaine_VEF.h:53
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:85
int nb_faces_non_std() const
Definition Domaine_VEF.h:80
int get_modif_div_face_dirichlet() const
Definition Domaine_VEF.h:95
const Elem_VEF_base & type_elem() const
Definition Domaine_VEF.h:74
int get_alphaA() const
Definition Domaine_VEF.h:93
int get_alphaS() const
Definition Domaine_VEF.h:92
int get_alphaE() const
Definition Domaine_VEF.h:91
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
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
const Front_VF & front_VF(int i) const
Definition Domaine_VF.h:112
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
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
Returns the associated geometric boundary.
static void creer_md_vect_renum_auto(IntVect &flags_renum, MD_Vector &md_vect)
Same as creer_md_vect_renum() but creates a default numbering.
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Transforms v into a parallel array having the structure md.
static void creer_md_vect_renum(const IntVect &renum, MD_Vector &md_vect)
Creates a descriptor for a subset of a vector.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Navier_Stokes_std This class carries the terms of the momentum equation.
Neumann_sortie_libre This class represents an open boundary without imposed velocity.
virtual double flux_impose(int i) const
Returns the value of the imposed flux on the i-th component of the field representing the flux at the...
Definition Neumann.cpp:35
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
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 exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Scalaire_impose_paroi Imposes a scalar at the wall in a Convection-Diffusion equation for a scalar.
Base class for output streams.
Definition Sortie.h:52
Symetrie On symmetry faces, the following properties hold:
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")