TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Grad_VEF_P1B_Face.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 <Op_Grad_VEF_P1B_Face.h>
17#include <Check_espace_virtuel.h>
18#include <Neumann_sortie_libre.h>
19#include <Dirichlet_homogene.h>
20#include <Schema_Temps_base.h>
21#include <Navier_Stokes_std.h>
22#include <communications.h>
23#include <Probleme_base.h>
24#include <EcrFicPartage.h>
25#include <Periodique.h>
26#include <Dirichlet.h>
27#include <TRUSTTrav.h>
28#include <Symetrie.h>
29#include <Domaine.h>
30#include <Device.h>
31#include <Debog.h>
32#include <Robin_VEF.h>
33
34Implemente_instanciable(Op_Grad_VEF_P1B_Face, "Op_Grad_VEFPreP1B_P1NC|Op_Grad_VEF_P1NC", Operateur_Grad_base);
35
36Sortie& Op_Grad_VEF_P1B_Face::printOn(Sortie& s) const { return s << que_suis_je(); }
37
39
41{
42 return ref_cast(Domaine_VEF, le_dom_vef.valeur());
43}
44
45void Op_Grad_VEF_P1B_Face::associer(const Domaine_dis_base& domaine_dis, const Domaine_Cl_dis_base& domaine_Cl_dis, const Champ_Inc_base&)
46{
47 le_dom_vef = ref_cast(Domaine_VEF, domaine_dis);
48 la_zcl_vef = ref_cast(Domaine_Cl_VEF, domaine_Cl_dis);
49}
50
51static int chercher_arete(int elem, int somi, int somj, const IntTab& elem_aretes, const IntTab& aretes_som)
52{
53 if (somi > somj)
54 {
55 int k = somi;
56 somi = somj;
57 somj = k;
58 }
59 for (int i_arete = 0; i_arete < 6; i_arete++)
60 {
61 int arete = elem_aretes(elem, i_arete);
62 int som1 = aretes_som(arete, 0);
63 if (somi == som1)
64 {
65 int som2 = aretes_som(arete, 1);
66 if (somj == som2)
67 return arete;
68 }
69 }
70 return -1;
71}
72static void verifier(const Op_Grad_VEF_P1B_Face& op, int& init, const Domaine_VEF& domaine_VEF, const DoubleTab& pre, DoubleTab& grad)
73
74{
75 // Method verifier only works for P0+P1 in 2D and P0+P1+Pa in 3D
76 if (Objet_U::dimension == 2 && domaine_VEF.get_alphaE() + domaine_VEF.get_alphaS() != 2)
77 {
78 Cerr << "Method verifier of Op_Grad_VEF_P1B_Face is not valid for this discretization." << finl;
80 }
81 if (Objet_U::dimension == 3 && domaine_VEF.get_alphaE() + domaine_VEF.get_alphaS() + domaine_VEF.get_alphaA() != 3)
82 {
83 Cerr << "Method verifier of Op_Grad_VEF_P1B_Face is not valid for this discretization." << finl;
85 }
86 const Domaine& domaine = domaine_VEF.domaine();
87 const Domaine& dom = domaine;
88 int nb_elem_tot = domaine.nb_elem_tot();
89 int nb_som_tot = dom.nb_som_tot();
90 int nb_elem = domaine.nb_elem();
91 init = 1;
92 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
93 const DoubleTab& xp = domaine_VEF.xp();
94 const DoubleTab& coord_sommets = dom.coord_sommets();
95
96 // Verification of the edge pressure
97 DoubleTab tab(pre);
98 exemple_champ_non_homogene(domaine_VEF, tab);
99
100 DoubleTab r(grad);
101 r = 0;
102 op.ajouter(tab, r);
103
104 // Pressure set to 1 on all nodes
105 DoubleTab p(pre);
106 p = 1;
107 r = 0;
108 op.ajouter(p, r);
109 if (nb_elem < 30)
110 {
111 Cerr << Process::me() << " grad(1) som = " << finl;
112 r.ecrit(Cerr);
113 }
114 // Pressure set to 1 on elements only
115 p = 0;
116 int i = 0;
117 for (; i < nb_elem_tot; i++)
118 p(i) = 0;
119 r = 0;
120 op.ajouter(p, r);
121 Cerr << "[" << Process::me() << "] p(1) elem = " << finl;
122 p.ecrit(Cerr);
123 Cerr << "[" << Process::me() << "] grad(1) elem = " << finl;
124 r.ecrit(Cerr);
125
126 // Pressure set to 1 on vertices only
127 p = 0;
128 for (; i < nb_elem_tot + nb_som_tot; i++)
129 p(i) = 1;
130 r = 0;
131 op.ajouter(p, r);
132 Cerr << Process::me() << " grad(1) som = " << finl;
133 r.ecrit(Cerr);
134
135 // Pressure set to 1 on edges only
136 p = 0;
137 int sz = p.size_totale();
138 for (; i < sz; i++)
139 p(i) = 1;
140 r = 0;
141 op.ajouter(p, r);
142 Cerr << Process::me() << " grad(1) aretes = " << finl;
143 r.ecrit(Cerr);
144 // Variable pressure on elements only
145 p = 0;
146 for (i = 0; i < nb_elem_tot; i++)
147 p(i) = xp(i, 0) - 1;
148 r = 0;
149 op.ajouter(p, r);
150 int nbf = volumes_entrelaces.size();
151 for (i = 0; i < nbf; i++)
152 for (int comp = 0; comp < Objet_U::dimension; comp++)
153 r(i, comp) /= volumes_entrelaces(i);
154 Cerr << Process::me() << " grad(x-1) elem = " << finl;
155 r.ecrit(Cerr);
156
157 // Variable pressure on vertices only
158 p = 0;
159 for (i = nb_elem_tot; i < nb_elem_tot + nb_som_tot; i++)
160 {
161 p(i) = coord_sommets(i - nb_elem_tot, 0) - 1;
162 }
163 r = 0;
164 op.ajouter(p, r);
165 for (i = 0; i < nbf; i++)
166 for (int comp = 0; comp < Objet_U::dimension; comp++)
167 r(i, comp) /= volumes_entrelaces(i);
168 Cerr << Process::me() << " grad(x-1) som = " << finl;
169 r.ecrit(Cerr);
170}
171
172DoubleTab& Op_Grad_VEF_P1B_Face::modifier_grad_pour_Cl(DoubleTab& tab_grad) const
173{
174 const Domaine_VEF& domaine_VEF = domaine_vef();
175 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
176 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
177 int nb_bords = les_cl.size();
178 int dim = Objet_U::dimension;
179 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
180 {
181 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
182 {
183 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
184 int num1 = le_bord.num_premiere_face();
185 int num2 = num1 + le_bord.nb_faces();
186 if (sub_type(Periodique, la_cl.valeur()))
187 {
188 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
189 CIntArrView face_associee = la_cl_perio.face_associee().view_ro();
190 DoubleTabView grad = tab_grad.view_rw();
191 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(num1, num1+le_bord.nb_faces()/2), KOKKOS_LAMBDA(const int face)
192 {
193 int face_ass = num1 + face_associee(face - num1);
194 for (int comp = 0; comp < dim; comp++)
195 {
196 grad(face, comp) += grad(face_ass, comp);
197 grad(face_ass, comp) = grad(face, comp);
198 }
199 });
200 end_gpu_timer(__KERNEL_NAME__);
201 }
202 else
203 {
204 if (sub_type(Symetrie, la_cl.valeur()))
205 {
206 CDoubleTabView face_normales = domaine_VEF.face_normales().view_ro();
207 DoubleTabView grad = tab_grad.view_rw();
208 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(num1, num2), KOKKOS_LAMBDA(const int face)
209 {
210 double psc = 0;
211 double norm = 0;
212 for (int comp = 0; comp < dim; comp++)
213 {
214 psc += grad(face, comp) * face_normales(face, comp);
215 norm += face_normales(face, comp) * face_normales(face, comp);
216 }
217 // psc/=norm; // Fixed bug: Arithmetic exception
218 if (std::fabs(norm) >= DMINFLOAT)
219 psc /= norm;
220 for (int comp = 0; comp < dim; comp++)
221 grad(face, comp) -= psc * face_normales(face, comp);
222 });
223 end_gpu_timer(__KERNEL_NAME__);
224 }
225 else if (sub_type(Dirichlet,la_cl.valeur()) || sub_type(Dirichlet_homogene, la_cl.valeur()))
226 {
227 DoubleTabView grad = tab_grad.view_wo();
228 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::MDRangePolicy<Kokkos::Rank<2>>({num1,0}, {num2,dim}), KOKKOS_LAMBDA(const int face, const int comp)
229 {
230 grad(face, comp) = 0;
231 });
232 end_gpu_timer(__KERNEL_NAME__);
233 }
234 }
235 }
236 }
237 return tab_grad;
238}
239
240DoubleTab& Op_Grad_VEF_P1B_Face::ajouter_elem(const DoubleTab& tab_pre, DoubleTab& tab_grad) const
241{
242 const Domaine_VEF& domaine_VEF = domaine_vef();
243 assert(domaine_VEF.get_alphaE());
244 const Domaine& domaine = domaine_VEF.domaine();
245 const IntTab& elem_faces = domaine_VEF.elem_faces();
246 int nfe = domaine.nb_faces_elem();
247 int nb_elem_tot = domaine.nb_elem_tot();
248 CDoubleArrView porosite_face = equation().milieu().porosite_face().view_ro();
249 CDoubleTabView face_normales = domaine_VEF.face_normales().view_ro();
250
251 // If no P1 support, impose Neumann on P0
252
253 if (domaine_VEF.get_alphaS() == 0)
254 {
255 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
256 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
257 int nb_bords = les_cl.size();
258 int dim = Objet_U::dimension;
259 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
260 {
261 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
262 if (sub_type(Neumann_sortie_libre, la_cl.valeur()))
263 {
264 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
265 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
266 int num1 = le_bord.num_premiere_face();
267 int num2 = num1 + le_bord.nb_faces();
268 CDoubleTabView flux_impose = la_sortie_libre.flux_impose().view_ro();
269 DoubleTabView grad = tab_grad.view_rw();
270 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(num1, num2), KOKKOS_LAMBDA(const int face)
271 {
272 double P_imp = flux_impose(face - num1, 0);
273 double diff = P_imp;
274 for (int comp = 0; comp < dim; comp++)
275 grad(face, comp) += diff * face_normales(face, comp) * porosite_face(face);
276 });
277 end_gpu_timer(__KERNEL_NAME__);
278 }
279
280 if (sub_type(Robin_VEF, la_cl.valeur()))
281 {
282#ifdef TRUST_USE_GPU
283 Cerr << "Warning not tested on GPU" << finl;
284#endif
285 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
286 int num1 = le_bord.num_premiere_face();
287 int num2 = num1 + le_bord.nb_faces();
288 DoubleTabView grad = tab_grad.view_rw();
289 CDoubleTabView pre = tab_pre.view_ro();
290 CIntTabView face_voisins = domaine_VEF.face_voisins().view_ro();
291 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(num1, num2), KOKKOS_LAMBDA(const int face)
292 {
293 int elem = face_voisins(face,0);
294 double Pstar_OSWR = pre(elem,0);//la_cl_robin.increment_pression_bord(face);// // TODO : [VKR] get the value of dPstar considering OSWR algorithm
295 double diff = Pstar_OSWR*0;
296 for (int comp = 0; comp < dim; comp++)
297 grad(face, comp) += diff * face_normales(face, comp) * porosite_face(face);
298 });
299 end_gpu_timer(__KERNEL_NAME__);
300 }
301 }
302 }
303
304 CIntTabView face_voisins = domaine_VEF.face_voisins().view_ro();
305 CIntTabView elem_faces_v = elem_faces.view_ro();
306 CDoubleTabView pre = tab_pre.view_ro();
307 DoubleTabView grad = tab_grad.view_rw();
308 int dim = Objet_U::dimension;
309
310 auto kern_elem = KOKKOS_LAMBDA(int
311 elem)
312 {
313 for (int indice = 0; indice < nfe; indice++)
314 {
315 double pe = pre(elem, 0);
316 int face = elem_faces_v(elem, indice);
317 double signe = 1;
318 if (elem != face_voisins(face, 0)) signe = -1;
319 for (int comp = 0; comp < dim; comp++)
320 {
321 double val = pe * signe * face_normales(face, comp) * porosite_face(face);
322 Kokkos::atomic_sub(&grad(face, comp), val);
323
324 }
325 }
326 };
327
328 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem_tot, kern_elem);
329 end_gpu_timer(__KERNEL_NAME__);
330
331 return tab_grad;
332}
333
334DoubleTab& Op_Grad_VEF_P1B_Face::ajouter_som(const DoubleTab& tab_pre, DoubleTab& tab_grad) const
335{
336 const Domaine_VEF& domaine_VEF = domaine_vef();
337 assert(domaine_VEF.get_alphaS());
338 const Domaine& domaine = domaine_VEF.domaine();
339 const Domaine& dom = domaine;
340 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
341
342 const DoubleTab& tab_face_normales = domaine_VEF.face_normales();
343 const DoubleVect& tab_porosite_face = equation().milieu().porosite_face();
344 const IntTab& tab_som_elem = domaine.les_elems();
345 const IntTab& tab_elem_faces = domaine_VEF.elem_faces();
346 const IntTab& tab_face_voisins = domaine_VEF.face_voisins();
347
348 int nfe = domaine.nb_faces_elem();
349 int nps = domaine_VEF.numero_premier_sommet();
350 int nb_elem_tot = domaine.nb_elem_tot();
351
352 if (som_.size_array() == 0)
353 {
354 // Tableaux constants
355 som_.resize(nb_elem_tot, nfe);
356 coeff_som_.resize(nb_elem_tot);
357 for (int el = 0; el < nb_elem_tot; el++)
358 {
359 coeff_som_(el) = calculer_coef_som(el, domaine_Cl_VEF, domaine_VEF);
360 for (int indice = 0; indice < nfe; indice++)
361 som_(el, indice) = nps + dom.get_renum_som_perio(tab_som_elem(el, indice));
362 }
363 }
364
365 CIntTabView elem_faces = tab_elem_faces.view_ro();
366 CIntTabView face_voisins = tab_face_voisins.view_ro();
367 CDoubleTabView face_normales = tab_face_normales.view_ro();
368 CDoubleArrView porosite_face = tab_porosite_face.view_ro();
369 CDoubleArrView coeff_som = coeff_som_.view_ro();
370 CIntTabView som_v = som_.view_ro();
371 CDoubleArrView pre = static_cast<const ArrOfDouble&>(tab_pre).view_ro();
372 DoubleTabView grad = tab_grad.view_rw();
373 int dim = Objet_U::dimension;
374
375 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
376 Kokkos::MDRangePolicy<Kokkos::Rank<2>>({0, 0}, {nb_elem_tot, nfe}),
377 KOKKOS_LAMBDA (int elem, int indice)
378 {
379 int face = elem_faces(elem,indice);
380
381 double signe = 1;
382 if (elem != face_voisins(face,0))
383 signe = -1;
384
385 double sigma[3];
386 for (int comp = 0; comp < dim; comp++)
387 sigma[comp] = face_normales(face,comp) * signe;
388
389 for (int indice2 = 0; indice2 < nfe; indice2++)
390 {
391 int face2 = elem_faces(elem,indice2);
392 for (int comp = 0; comp < dim; comp++)
393 {
394 Kokkos::atomic_add(&grad(face2,comp), -(coeff_som(elem) * pre(som_v(elem,indice)) * sigma[comp] * porosite_face(face2)));
395 }
396 }
397 });
398 end_gpu_timer(__KERNEL_NAME__);
399
400 bool has_sortie_libre = false;
401 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
402 int nb_bords = les_cl.size();
403 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
404 {
405 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
406 if (sub_type(Neumann_sortie_libre, la_cl.valeur())) has_sortie_libre = true;
407 }
408
409 if (has_sortie_libre)
410 {
411 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
412 {
413 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
414 if (sub_type(Neumann_sortie_libre, la_cl.valeur()))
415 {
416 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
417 const Neumann_sortie_libre& sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
418 int num1 = le_bord.num_premiere_face();
419 int num2 = num1 + le_bord.nb_faces();
420 CDoubleTabView flux_impose = sortie_libre.flux_impose().view_ro();
421 CIntTabView face_sommets = domaine_VEF.face_sommets().view_ro();
422 CIntArrView renum_som_perio = dom.get_renum_som_perio().view_ro();
423 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::RangePolicy<>(num1, num2), KOKKOS_LAMBDA(const int face)
424 {
425 const double P_imp = flux_impose(face - num1, 0);
426 for (int indice = 0; indice < (nfe - 1); indice++)
427 {
428 int som = nps + renum_som_perio(face_sommets(face, indice));
429 for (int comp = 0; comp < dim; comp++)
430 grad(face, comp) -= 1. / dim * face_normales(face, comp) * (pre(som) - P_imp) *
431 porosite_face(face);
432 }
433 });
434 end_gpu_timer(__KERNEL_NAME__);
435 }
436 }
437 }
438
439 return tab_grad;
440}
441
442DoubleTab& Op_Grad_VEF_P1B_Face::ajouter_aretes(const DoubleTab& pre, DoubleTab& grad) const
443{
444 const Domaine_VEF& domaine_VEF = domaine_vef();
445 assert(domaine_VEF.get_alphaA());
446 const Domaine& domaine = domaine_VEF.domaine();
447 //const Domaine& dom=domaine;
448 const DoubleTab& face_normales = domaine_VEF.face_normales();
449 const DoubleVect& porosite_face = equation().milieu().porosite_face();
450 const IntTab& som_elem = domaine.les_elems();
451 const IntTab& elem_faces = domaine_VEF.elem_faces();
452 const IntTab& face_voisins = domaine_VEF.face_voisins();
453 const IntTab& aretes_som = domaine_VEF.domaine().aretes_som();
454 const IntTab& elem_aretes = domaine_VEF.domaine().elem_aretes();
455 const ArrOfInt& renum_arete_perio = domaine_VEF.get_renum_arete_perio();
456 const ArrOfInt& ok_arete = domaine_VEF.get_ok_arete();
457 int nfe = domaine.nb_faces_elem();
458 int nb_elem_tot = domaine.nb_elem_tot();
459 // int nps=domaine_VEF.numero_premier_sommet();
460 int npa = domaine_VEF.numero_premiere_arete();
461 int indice;
462 ArrOfDouble sigma(dimension);
463 for (int elem = 0; elem < nb_elem_tot; elem++)
464 {
465 for (indice = 0; indice < nfe; indice++)
466 {
467 //som = nps+dom.get_renum_som_perio(som_elem(elem,indice));
468 int face = elem_faces(elem, indice);
469 double signe = 1;
470 if (elem != face_voisins(face, 0))
471 signe = -1;
472 for (int comp = 0; comp < dimension; comp++)
473 sigma[comp] = signe * face_normales(face, comp);
474 }
475 for (int isom = 0; isom < 3; isom++)
476 {
477 int somi = som_elem(elem, isom);
478 int facei = elem_faces(elem, isom);
479 double signei = 1.;
480 if (face_voisins(facei, 0) != elem)
481 signei = -1.;
482 for (int jsom = isom + 1; jsom < 4; jsom++)
483 {
484 int somj = som_elem(elem, jsom);
485 int facej = elem_faces(elem, jsom);
486 double signej = 1.;
487 if (face_voisins(facej, 0) != elem)
488 signej = -1.;
489 int arete = chercher_arete(elem, somi, somj, elem_aretes, aretes_som);
490 arete = renum_arete_perio[arete];
491 if (ok_arete[arete])
492 {
493 double pa = pre(npa + arete);
494 int niinij = 0;
495 for (int ksom = 0; ksom < 4; ksom++)
496 {
497 int face2 = elem_faces(elem, ksom);
498 if ((ksom == isom) || (ksom == jsom))
499 {
500 if (niinij == ksom)
501 niinij++;
502 for (int comp = 0; comp < 3; comp++)
503 grad(face2, comp) += porosite_face(face2) * 1. / 15. * (signei * face_normales(facei, comp) + signej * face_normales(facej, comp)) * pa;
504 }
505 else
506 {
507 if (niinij == ksom)
508 niinij++;
509 while ((niinij == jsom) || (niinij == isom))
510 niinij++;
511 assert(niinij < 4);
512 int facek = elem_faces(elem, niinij);
513 double signek = 1.;
514 if (face_voisins(facek, 0) != elem)
515 signek = -1.;
516 for (int comp = 0; comp < 3; comp++)
517 grad(face2, comp) += porosite_face(face2) * 2. / 15. * signek * face_normales(facek, comp) * pa;
518 niinij = ksom;
519 }
520 }
521 }
522 }
523 }
524 }
525 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
526 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
527 const IntTab& face_sommets = domaine_VEF.face_sommets();
528 int nb_bords = les_cl.size();
529 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
530 {
531 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
532 {
533 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
534 int num1 = le_bord.num_premiere_face();
535 int num2 = num1 + le_bord.nb_faces();
536 if (sub_type(Neumann_sortie_libre, la_cl.valeur()))
537 {
538 for (int face = num1; face < num2; face++)
539 {
540 int elem = face_voisins(face, 0);
541 for (int i = 0; i < 2; i++)
542 {
543 int somi = face_sommets(face, i);
544 for (int j = i + 1; j < 3; j++)
545 {
546 int somj = face_sommets(face, j);
547 int arete = chercher_arete(elem, somi, somj, elem_aretes, aretes_som);
548 arete = renum_arete_perio[arete];
549 for (int comp = 0; comp < dimension; comp++)
550 grad(face, comp) -= porosite_face(face) * 0 * face_normales(face, comp) * pre(npa + arete);
551 }
552 }
553 }
554 }
555 }
556 }
557 return grad;
558}
559
560double Op_Grad_VEF_P1B_Face::calculer_coef_som(int elem, const Domaine_Cl_VEF& zcl, const Domaine_VEF& domaine_VEF)
561{
562 double coef_std = 1. / (Objet_U::dimension * (Objet_U::dimension + 1));
563 if (domaine_VEF.get_modif_div_face_dirichlet() == 0)
564 return coef_std;
565 int type_elem = 0;
566 int rang_elem = domaine_VEF.rang_elem_non_std()(elem);
567 if (rang_elem != -1)
568 type_elem = zcl.type_elem_Cl(rang_elem);
569 double coef;
570 if (type_elem == 0)
571 return coef_std;
572 if (Objet_U::dimension == 2)
573 {
574 switch(type_elem)
575 {
576 case 0:
577 coef = 3;
578 break;
579 case 1:
580 case 2:
581 case 4:
582 coef = 2;
583 break;
584 case 3:
585 case 5:
586 case 6:
587 coef = 1;
588 break;
589 default:
590 coef = -1;
592 break;
593 }
594 }
595 else if (Objet_U::dimension == 3)
596 {
597 switch(type_elem)
598 {
599 case 0:
600 coef = 4;
601 break;
602 case 1:
603 case 2:
604 case 4:
605 case 8:
606 coef = 3;
607 break;
608 case 3:
609 case 5:
610 case 6:
611 case 9:
612 case 10:
613 case 12:
614 coef = 2;
615 break;
616 case 7:
617 case 11:
618 case 13:
619 case 14:
620 coef = 1;
621 break;
622 default:
623 coef = -1;
625 break;
626 }
627 }
628 else
629 {
630 coef = -1;
632 }
633 return 1. / (Objet_U::dimension * coef);
634}
635
636DoubleTab& Op_Grad_VEF_P1B_Face::ajouter(const DoubleTab& pre, DoubleTab& grad) const
637{
638 // pre must have its virtual space up to date
639 assert_espace_virtuel_vect(pre);
640 // we will do += on the virtual space, but without using the values
641 assert_invalide_items_non_calcules(grad);
642 //Debog::verifier("Op_Grad_VEF_P1B_Face::ajouter pre", pre);
643 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_vef.valeur());
644 static int init = 1;
645 if (!init)
646 verifier(*this, init, domaine_VEF, pre, grad);
647 if (domaine_VEF.get_alphaE())
648 ajouter_elem(pre, grad);
649 if (domaine_VEF.get_alphaS())
650 ajouter_som(pre, grad);
651 if (domaine_VEF.get_alphaA())
652 ajouter_aretes(pre, grad);
654 //calculer_flux_bords();
655 //Optimization: not necessary here:
656 //grad.echange_espace_virtuel();
657 //Debog::verifier("Op_Grad_VEF_P1B_Face::ajouter grad en sortie:", grad);
658 return grad;
659}
660
662{
663 const Domaine_VEF& domaine_VEF = domaine_vef();
664 if (flux_bords_.size_array() == 0)
665 flux_bords_.resize(domaine_VEF.nb_faces_bord(), dimension);
666 flux_bords_ = 0.;
667
668 //int nse=domaine_VEF.domaine().nb_som_elem();
669 int nb_faces_bord = domaine_VEF.premiere_face_int();
670 int nps = domaine_VEF.numero_premier_sommet();
671 const IntTab& sommets = domaine_VEF.face_sommets();
672 const IntTab& face_voisins = domaine_VEF.face_voisins();
673 //const IntTab& som_elem=le_dom_vef->domaine().les_elems();
674 const DoubleTab& face_normales = domaine_VEF.face_normales();
675 const Navier_Stokes_std& eqn_hydr = ref_cast(Navier_Stokes_std, equation());
676 const Champ_P1_isoP1Bulle& la_pression_P1B = ref_cast(Champ_P1_isoP1Bulle, eqn_hydr.pression_pa());
677 // If filtering:
678 if(domaine_VEF.domaine().que_suis_je() == "Domaine_ALE")
679 {
680 la_pression_P1B.filtrage(domaine_VEF, la_pression_P1B, eqn_hydr.getCouplingInfoForFiltering());
681 }
682 else
683 la_pression_P1B.filtrage(domaine_VEF, la_pression_P1B);
684
685
686
687 const DoubleVect& pression_P1B = la_pression_P1B.champ_filtre();
688
689 double coeff_P1 = 1. / dimension;
690 bool alphaE = domaine_VEF.get_alphaE();
691 bool alphaS = domaine_VEF.get_alphaS();
692 int nb_som_par_face = sommets.dimension(1);
693 CIntTabView face_voisins_v = face_voisins.view_ro();
694 CIntTabView sommets_v = sommets.view_ro();
695 CDoubleTabView face_normales_v = face_normales.view_ro();
696 CDoubleArrView pression_P1B_v = pression_P1B.view_ro();
697 DoubleTabView flux_bords_v = flux_bords_.view_wo();
698 int dim = Objet_U::dimension;
699
700 auto kern_flux_bords = KOKKOS_LAMBDA(int
701 face)
702 {
703 int elem = face_voisins_v(face, 0);
704 double pres_tot = 0.;
705 // Contribution of P0 pressure
706 if (alphaE) pres_tot = pression_P1B_v(elem);
707 // Contribution of P1 pressure
708 if (alphaS)
709 {
710 double pres_som = 0.;
711 for (int som = 0; som < nb_som_par_face; som++)
712 pres_som += pression_P1B_v(nps + sommets_v(face, som));
713 pres_tot += coeff_P1 * pres_som;
714 }
715 // Compute the resultant and pressure moment
716 for (int i = 0; i < dim; i++)
717 flux_bords_v(face, i) = pres_tot * face_normales_v(face, i);
718 };
719
720 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_faces_bord, kern_flux_bords);
721 end_gpu_timer(__KERNEL_NAME__);
722}
723
725{
726 const Domaine_VEF& domaine_VEF = domaine_vef();
727 const int impr_mom = domaine_VEF.domaine().moments_a_imprimer();
728 const int impr_sum = (domaine_VEF.domaine().bords_a_imprimer_sum().est_vide() ? 0 : 1);
729 const int impr_bord = (domaine_VEF.domaine().bords_a_imprimer().est_vide() ? 0 : 1);
731 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
732 DoubleTab xgr;
733 if (impr_mom)
734 xgr = domaine_VEF.calculer_xgr();
735
736 DoubleTrav tab_flux_bords(3, domaine_VEF.nb_front_Cl(), dimension);
737 tab_flux_bords = 0.;
738 /*
739 fluxx_s -> flux_bords2(0,num_cl,0)
740 fluxy_s -> flux_bords2(0,num_cl,1)
741 fluxz_s -> flux_bords2(0,num_cl,2)
742 fluxx_sum_s -> flux_bords2(1,num_cl,0)
743 fluxy_sum_s -> flux_bords2(1,num_cl,1)
744 fluxz_sum_s -> flux_bords2(1,num_cl,2)
745 moment(0) -> flux_bords2(2,num_cl,0)
746 moment(1) -> flux_bords2(2,num_cl,1)
747 moment(2) -> flux_bords2(2,num_cl,2)
748 */
749 int nb_bord = domaine_VEF.nb_front_Cl();
750 for (int n_bord = 0; n_bord < nb_bord; n_bord++)
751 {
752 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
753 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
754 int impr_boundary = (domaine_VEF.domaine().bords_a_imprimer_sum().contient(le_bord.le_nom()) ? 1 : 0);
755 int ndeb = le_bord.num_premiere_face();
756 int nfin = ndeb + le_bord.nb_faces();
757 for (int face = ndeb; face < nfin; face++)
758 {
759 // Compute the resultant and pressure moment
760 if (dimension == 2)
761 {
762 tab_flux_bords(0, n_bord, 0) += flux_bords_(face, 0);
763 tab_flux_bords(0, n_bord, 1) += flux_bords_(face, 1);
764
765 // Compute the moment exerted by the fluid on the boundary (OM/\F)
766 if (impr_mom)
767 tab_flux_bords(2, n_bord, 0) += flux_bords_(face, 1) * xgr(face, 0) - flux_bords_(face, 0) * xgr(face, 1);
768 if (impr_boundary)
769 {
770 tab_flux_bords(1, n_bord, 0) += flux_bords_(face, 0);
771 tab_flux_bords(1, n_bord, 1) += flux_bords_(face, 1);
772 }
773 }
774 else if (dimension == 3)
775 {
776 tab_flux_bords(0, n_bord, 0) += flux_bords_(face, 0);
777 tab_flux_bords(0, n_bord, 1) += flux_bords_(face, 1);
778 tab_flux_bords(0, n_bord, 2) += flux_bords_(face, 2);
779
780 if (impr_mom)
781 {
782 // Compute the moment exerted by the fluid on the boundary (OM/\F)
783 tab_flux_bords(2, n_bord, 0) += flux_bords_(face, 2) * xgr(face, 1) - flux_bords_(face, 1) * xgr(face, 2);
784 tab_flux_bords(2, n_bord, 1) += flux_bords_(face, 0) * xgr(face, 2) - flux_bords_(face, 2) * xgr(face, 0);
785 tab_flux_bords(2, n_bord, 2) += flux_bords_(face, 1) * xgr(face, 0) - flux_bords_(face, 0) * xgr(face, 1);
786 }
787 if (impr_boundary)
788 {
789 tab_flux_bords(1, n_bord, 0) += flux_bords_(face, 0);
790 tab_flux_bords(1, n_bord, 1) += flux_bords_(face, 1);
791 tab_flux_bords(1, n_bord, 2) += flux_bords_(face, 2);
792 }
793 }
794 }
795 } // end for n_bord
796
797 // Sum contributions from each processor
798 mp_sum_for_each_item(tab_flux_bords);
799
800 if (je_suis_maitre())
801 {
803 ouvrir_fichier(Flux_grad_moment, "moment", impr_mom);
804 ouvrir_fichier(Flux_grad_sum, "sum", impr_sum);
805
806 // Write time
807 Flux_grad.add_col(sch.temps_courant());
808 if (impr_sum)
809 Flux_grad_sum.add_col(sch.temps_courant());
810 if (impr_mom)
811 Flux_grad_moment.add_col(sch.temps_courant());
812
813 // Write flux on boundaries
814 for (int n_bord = 0; n_bord < nb_bord; n_bord++)
815 {
816 if (dimension == 2)
817 {
818 Flux_grad.add_col(tab_flux_bords(0, n_bord, 0));
819 Flux_grad.add_col(tab_flux_bords(0, n_bord, 1));
820 if (impr_sum)
821 {
822 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 0));
823 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 1));
824 }
825 if (impr_mom)
826 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 0));
827 }
828 else if (dimension == 3)
829 {
830 Flux_grad.add_col(tab_flux_bords(0, n_bord, 0));
831 Flux_grad.add_col(tab_flux_bords(0, n_bord, 1));
832 Flux_grad.add_col(tab_flux_bords(0, n_bord, 2));
833 if (impr_sum)
834 {
835 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 0));
836 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 1));
837 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 2));
838 }
839 if (impr_mom)
840 {
841 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 0));
842 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 1));
843 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 2));
844 }
845 }
846 }
847 Flux_grad << finl;
848 if (impr_sum)
849 Flux_grad_sum << finl;
850 if (impr_mom)
851 Flux_grad_moment << finl;
852 }
853
854 const LIST(Nom) &Liste_bords_a_imprimer = domaine_VEF.domaine().bords_a_imprimer();
855 if (!Liste_bords_a_imprimer.est_vide())
856 {
857 EcrFicPartage Flux_grad_face;
858 ouvrir_fichier_partage(Flux_grad_face, "", impr_bord);
859 for (int n_bord = 0; n_bord < nb_bord; n_bord++)
860 {
861 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
862 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
863 int ndeb = le_bord.num_premiere_face();
864 int nfin = ndeb + le_bord.nb_faces();
865 if (domaine_VEF.domaine().bords_a_imprimer().contient(le_bord.le_nom()))
866 {
867 if (je_suis_maitre())
868 {
869 Flux_grad_face << "# Force par face sur " << le_bord.le_nom() << " au temps ";
870 sch.imprimer_temps_courant(Flux_grad_face);
871 Flux_grad_face << " : " << finl;
872 }
873 for (int face = ndeb; face < nfin; face++)
874 {
875 Flux_grad_face << "# Face a x= " << domaine_VEF.xv(face, 0) << " y= " << domaine_VEF.xv(face, 1);
876 if (dimension == 3)
877 Flux_grad_face << " z= " << domaine_VEF.xv(face, 2);
878 Flux_grad_face << " : Fx= " << flux_bords_(face, 0) << " Fy= " << flux_bords_(face, 1);
879 if (dimension == 3)
880 Flux_grad_face << " Fz= " << flux_bords_(face, 2);
881 Flux_grad_face << finl;
882 }
883 Flux_grad_face.syncfile();
884 }
885 }
886 }
887 return 1;
888}
Class Champ_Inc_base.
DoubleTab & filtrage(const Domaine_VEF &, const Champ_base &, bool implicitCoupling=false) const
const DoubleTab & champ_filtre() const
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
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
int_t nb_elem_tot() const
Definition Domaine.h:132
const IntTab_t & aretes_som() const
returns the connectivity array edges/vertices.
Definition Domaine.h:156
int_t get_renum_som_perio(int_t i) const
Definition Domaine.h:281
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
int_t elem_aretes(int_t i, int j) const
returns the number of the j-th edge of the i-th element.
Definition Domaine.h:154
int_t nb_som_tot() const
Returns the total number of vertices of the domain i.e. the number of real and virtual vertices on th...
Definition Domaine.h:123
int type_elem_Cl(int i) const
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized 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 numero_premiere_arete() const
const IntVect & get_ok_arete() const
Definition Domaine_VEF.h:98
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:85
int numero_premier_sommet() const
int get_modif_div_face_dirichlet() const
Definition Domaine_VEF.h:95
int get_alphaA() const
Definition Domaine_VEF.h:93
const ArrOfInt & get_renum_arete_perio() const
Definition Domaine_VEF.h:97
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
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 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
DoubleTab calculer_xgr() const
Computes the xgr array for the computation of moments of forces at boundaries.
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
Definition Domaine_VF.h:512
int moments_a_imprimer() const
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_front_Cl() const
const Domaine & domaine() const
Sortie & syncfile() override
Triggers writing to disk of the data accumulated on the different processors since the last call to s...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
Probleme_base & probleme()
Returns the problem associated with the equation.
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
const Nom & le_nom() const override
Returns the name of the geometric boundary.
DoubleVect & porosite_face()
Definition Milieu_base.h:62
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.
Champ_Inc_base & pression_pa()
virtual bool getCouplingInfoForFiltering() const
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
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
static int dimension
Definition Objet_U.h:94
friend class Sortie
Definition Objet_U.h:70
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 Op_Grad_VEF_P1B_Face
DoubleTab & modifier_grad_pour_Cl(DoubleTab &) const
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
DoubleTab & ajouter_elem(const DoubleTab &, DoubleTab &) const
void calculer_flux_bords() const override
static double calculer_coef_som(int elem, const Domaine_Cl_VEF &zcl, const Domaine_VEF &domaine_VEF)
int impr(Sortie &) const override
DOES NOTHING - to override in derived classes.
const Domaine_VEF & domaine_vef() const
DoubleTab & ajouter_aretes(const DoubleTab &, DoubleTab &) const
DoubleTab & ajouter_som(const DoubleTab &, DoubleTab &) const
Classe Operateur_Grad_base This class is the base of the hierarchy of operators representing.
DoubleTab flux_bords_
void ouvrir_fichier_partage(EcrFicPartage &, const Nom &, const int flag=1) const
Opening/creation of a shared file for printing an operator. To override in derived classes.
void ouvrir_fichier(SFichier &os, const Nom &, const int flag=1) const
Opening/creation of a file for printing an operator. To override in derived classes.
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:194
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
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
Class Robin_VEF for Robin boundary conditions.
Definition Robin_VEF.h:44
class Schema_Temps_base
double temps_courant() const
Returns the current time.
void imprimer_temps_courant(SFichier &) const
Base class for output streams.
Definition Sortie.h:52
Symetrie On symmetry faces, the following properties hold:
Definition Symetrie.h:37
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_wo()
Definition TRUSTTab.h:276
void ecrit(Sortie &) const override
Definition TRUSTTab.tpp:688
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