TRUST 1.9.8
HPC thermohydraulic platform
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 // Methode verifier ne marche que pour P0+P1 en 2D et P0+P1+Pa en 3D
76 if (Objet_U::dimension == 2 && domaine_VEF.get_alphaE() + domaine_VEF.get_alphaS() != 2)
77 {
78 Cerr << "Methode verifier de Op_Grad_VEF_P1B_Face non valable pour cette discretisation." << finl;
80 }
81 if (Objet_U::dimension == 3 && domaine_VEF.get_alphaE() + domaine_VEF.get_alphaS() + domaine_VEF.get_alphaA() != 3)
82 {
83 Cerr << "Methode verifier de Op_Grad_VEF_P1B_Face non valable pour cette discretisation." << 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 de la pression arete
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 // Pression mise a 1 sur tous les noeuds
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 // Pression mise a 1 sur les elements seulement
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 // Pression mise a 1 sur les sommets seulement
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 // Pression mise a 1 sur les aretes seulement
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 // Pression variable sur les elements seulement
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 // Pression variable sur les sommets seulement
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 // Si pas de support P1, on impose Neumann sur 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 doit avoir son espace virtuel a jour
639 assert_espace_virtuel_vect(pre);
640 // on va faire += sur l'espace virtuel, mais sans utiliser les valeurs
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 //Optimisation car pas necessaire:
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 // Si on filtre:
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 de la pression P0
706 if (alphaE) pres_tot = pression_P1B_v(elem);
707 // Contribution de la pression P1
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 // Calcul de la resultante et du couple de pression
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 // Calcul de la resultante et du couple de pression
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 // Calcul du moment exerce par le fluide sur le bord (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 // Calcul du moment exerce par le fluide sur le bord (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 } // fin for n_bord
796
797 // On somme les contributions de chaque processeur
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}
Classe Champ_Inc_base.
DoubleTab & filtrage(const Domaine_VEF &, const Champ_base &, bool implicitCoupling=false) const
const DoubleTab & champ_filtre() const
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
int_t nb_elem_tot() const
Definition Domaine.h:132
const IntTab_t & aretes_som() const
renvoie le tableau de connectivite aretes/sommets.
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
renvoie le numero de la jeme arete du ieme element.
Definition Domaine.h:154
int_t nb_som_tot() const
Renvoie le nombre total de sommets du domaine i.e. le nombre de sommets reels et virtuels sur le proc...
Definition Domaine.h:123
int type_elem_Cl(int i) const
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
int numero_premiere_arete() const
const IntVect & get_ok_arete() const
Definition Domaine_VEF.h:99
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:86
int numero_premier_sommet() const
int get_modif_div_face_dirichlet() const
Definition Domaine_VEF.h:96
int get_alphaA() const
Definition Domaine_VEF.h:94
const ArrOfInt & get_renum_arete_perio() const
Definition Domaine_VEF.h:98
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
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
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
DoubleTab calculer_xgr() const
calcul le tableau xgr pour le calcul des moments des forces aux bords :
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
int moments_a_imprimer() const
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_front_Cl() const
const Domaine & domaine() const
Sortie & syncfile() override
Provoque l'ecriture sur disque des donnees accumulees sur les differents processeurs depuis le dernie...
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()
Renvoie le probleme associe a l'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
Renvoie le nom de la frontiere geometrique.
DoubleVect & porosite_face()
Definition Milieu_base.h:62
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
Champ_Inc_base & pression_pa()
virtual bool getCouplingInfoForFiltering() const
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
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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
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 Cette classe est la base de la hierarchie des operateurs representant.
DoubleTab flux_bords_
void ouvrir_fichier_partage(EcrFicPartage &, const Nom &, const int flag=1) const
Ouverture/creation d'un fichier d'impression d'un operateur A surcharger dans les classes derivees.
void ouvrir_fichier(SFichier &os, const Nom &, const int flag=1) const
Ouverture/creation d'un fichier d'impression d'un operateur A surcharger dans les classes derivees.
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Class Robin_VEF for Robin boundary conditions.
Definition Robin_VEF.h:44
class Schema_Temps_base
double temps_courant() const
Renvoie le temps courant.
void imprimer_temps_courant(SFichier &) const
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
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