TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Navier_Stokes_Fluide_Dilatable_Proto.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Navier_Stokes_Fluide_Dilatable_Proto.h>
17#include <Transport_Interfaces_base.h>
18#include <Fluide_Dilatable_base.h>
19#include <Navier_Stokes_std.h>
20#include <Schema_Temps_base.h>
21#include <Probleme_base.h>
22#include <Dirichlet.h>
23#include <TRUSTTrav.h>
24#include <Domaine_VF.h>
25#include <Domaine.h>
26#include <Debog.h>
27#include <kokkos++.h>
28#include <Perf_counters.h>
29
31
32// Multiply density by velocity and return density*velocity (mass flux)
33DoubleTab& Navier_Stokes_Fluide_Dilatable_Proto::rho_vitesse_impl(const DoubleTab& tab_rho, const DoubleTab& vit,
34 DoubleTab& rhovitesse) const
35{
36 const int n = vit.dimension(0), ncomp = vit.line_size();
37 CDoubleTabView tab_rho_v = tab_rho.view_ro();
38 CDoubleTabView vit_v = vit.view_ro();
39 DoubleTabView rhovitesse_v = rhovitesse.view_wo();
40 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), n, KOKKOS_LAMBDA(
41 const int i)
42 {
43 for (int j=0 ; j<ncomp ; j++)
44 rhovitesse_v(i, j) = tab_rho_v(i, 0) * vit_v(i, j);
45 });
46 end_gpu_timer(__KERNEL_NAME__);
47
48 rhovitesse.echange_espace_virtuel();
49 Debog::verifier("Navier_Stokes_Fluide_Dilatable_Proto::rho_vitesse : ", rhovitesse);
50 return rhovitesse;
51}
52
54{
55 const Fluide_Dilatable_base& fluide_dil = ref_cast(Fluide_Dilatable_base,eqn.fluide());
56 const DoubleTab& vit = eqn.vitesse().valeurs(), &rho = fluide_dil.rho_face_np1();
57 DoubleTrav mass_flux(vit);
58 rho_vitesse_impl(rho,vit,mass_flux);
59
60 DoubleTrav array(eqn.div().valeurs());
61 if (tab_W.get_md_vector())
62 {
63 operator_egal(array, tab_W ); //, VECT_REAL_ITEMS); // initialise
64 array*=-1;
65 }
66 else
67 {
68 // remarque B.M.: certaines implementations de cette methode ne font pas echange espace virtuel:
69 fluide_dil.secmembre_divU_Z(array);
70 array*=-1;
71 }
72
74 eqn.operateur_divergence().ajouter(mass_flux, array);
75 double LocalMassFlowRateError = mp_max_abs_vect(array); // max|sum(rho*u*ndS)|
76
77 os << "-------------------------------------------------------------------"<< finl;
78 os << "Cell balance mass flow rate control for the problem " << eqn.probleme().le_nom() << " : " << finl;
79 os << "Absolute value : " << LocalMassFlowRateError << " kg/s" << finl; ;
80
81 // On divise array par vol(i)
83
84 // On divise par un rho moyen
85 double rho_moyen = mp_moyenne_vect(rho), dt = eqn.probleme().schema_temps().pas_de_temps();
86 double bilan_massique_relatif = mp_max_abs_vect(array) * dt / rho_moyen;
87 os << "Relative value : " << bilan_massique_relatif << finl; // =max|LocalMassFlowRateError/(rho_moyen*Vol(i)/dt)|
88
89 // Calculation as OpenFOAM: http://foam.sourceforge.net/docs/cpp/a04190_source.html
90 // It is relative errors (normalized by the volume/dt)
91 double TotalMass = rho_moyen * eqn.probleme().domaine().volume_total();
92 double local = LocalMassFlowRateError / ( TotalMass / dt ), global = mp_somme_vect(array) / ( TotalMass / dt );
93 cumulative_ += global;
94
95 os << "time step continuity errors : sum local = " << local << ", global = " << global << ", cumulative = " << cumulative_ << finl;
96
97 if (local > 0.01)
98 {
99 Cerr << "The mass balance is too bad (relative value > 1%)." << finl;
100 Cerr << "Please check and lower the convergence value of the pressure solver." << finl;
102 }
103 return 1;
104}
105
106/*! @brief Calcule la derivee en temps de l'inconnue vitesse, i.
107 *
108 * e. l'acceleration dU/dt et la renvoie.
109 * Appelle Equation_base::derivee_en_temps_inco(DoubleTab& )
110 * Calcule egalement la pression.
111 *
112 * @param (DoubleTab& vpoint) le tableau des valeurs de l'acceleration dU/dt
113 * @return (DoubleTab&) le tableau des valeurs de l'acceleration (derivee de la vitesse)
114 */
116{
117 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
118 DoubleTab& press = eqn.pression().valeurs(), &vit = eqn.vitesse().valeurs();
119 DoubleTrav secmem(press);
120 DoubleTrav inc_pre(press);
121 DoubleTrav rhoU(vit);
122
123 if (!tab_W.get_md_vector())
124 {
125 tab_W.copy(secmem, RESIZE_OPTIONS::NOCOPY_NOINIT); // copie la structure
126 // initialisation sinon plantage assert lors du remplissage dans EDO_Pression_th_VEF::secmembre_divU_Z_VEFP1B
127 tab_W = 0.;
128 }
129
130 // Get champ gradP
131 OBS_PTR(Champ_base) gradient_pression;
132 eqn.has_champ("gradient_pression", gradient_pression);
133
134 if (!gradient_pression)
135 {
136 Cerr<<"l'equation ne comprend pas gradient_pression "<<finl;
138 }
139
140 DoubleTab& gradP = gradient_pression->valeurs();
141 DoubleTrav Mmoins1grad(gradP);
142
143 // We use the incremental pressure-projection algorithm (Chorin)
144
145 // Step 1 : prepare operators and solve for a provisional velocity u*
146 prepare_and_solve_u_star(eqn,fluide_dil,rhoU, vpoint);
147
148 // Step 2 : solve the poisson equation for the pressure increment (Pi = P^n+1 - P^n)
149 // Attention the matrix has a constant coefficient as the variable of NS is rhoU and not U !!!
150 solve_pressure_increment(eqn,fluide_dil,rhoU,secmem,inc_pre,vpoint);
151
152 // Step 3 : compute P^n+1 & compute the correct velocity u^n+1
153 correct_and_compute_u_np1(eqn,fluide_dil,rhoU,Mmoins1grad,inc_pre,gradP,vpoint);
154
155 return vpoint;
156}
157
159 const DoubleTab& present, DoubleTab& tab_secmem)
160{
161 // ****** avant inertie ******
162 // diffusion en div(mu grad u ) or on veut impliciter en rho * u => on divise les contributions par le rho_face associe
163 // GF on ajoute apres avoir contribuer pour avoir les bons flux bords
164 DoubleTrav rhovitesse(present);
165
166 // Op diff
167 eqn.operateur(0).l_op_base().contribuer_a_avec(present,mat_morse);
168 eqn.operateur(0).ajouter(tab_secmem);
169
170 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
171 const DoubleTab& tab_rho_face_np1 = fluide_dil.rho_face_np1(), &tab_rho_face_n=fluide_dil.rho_face_n();
172 const int nb_compo = present.line_size();
173
174 auto tab1 = mat_morse.get_tab1().view_ro();
175 CIntArrView tab2 = mat_morse.get_tab2().view_ro();
176 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
177 DoubleArrView coeff = mat_morse.get_set_coeff().view_rw();
178 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), mat_morse.nb_lignes(), KOKKOS_LAMBDA(const int i)
179 {
180 for (auto k=tab1(i)-1; k<tab1(i+1)-1; k++)
181 {
182 int j = tab2(k)-1;
183 double rapport = rho_face_np1(j/nb_compo);
184 coeff(k) /= rapport;
185 }
186 });
187 end_gpu_timer(__KERNEL_NAME__);
188
189 rho_vitesse_impl(tab_rho_face_np1,present,rhovitesse); // rho*U
190
191 // Op conv
192 eqn.operateur(1).l_op_base().contribuer_a_avec(rhovitesse,mat_morse);
193 eqn.operateur(1).ajouter(rhovitesse,tab_secmem);
194
195 // sources
196 eqn.sources().ajouter(tab_secmem);
197 eqn.sources().contribuer_a_avec(present,mat_morse);
198
199 // on resout en rho u on stocke donc rho u dans present
200 rho_vitesse_impl(tab_rho_face_np1,present,ref_cast_non_const(DoubleTab,present));
201 mat_morse.ajouter_multvect(present, tab_secmem);
202
203 /*
204 * contribution a la matrice de l'inertie :
205 * on divisie la diagonale par rhon+1 face
206 * on ajoute l'inertie de facon standard
207 * on remultiplie la diagonale par rhon+1
208 */
209
210 // ajout de l'inertie
211 const double dt=eqn.schema_temps().pas_de_temps();
212 eqn.solv_masse().ajouter_masse(dt,mat_morse,0);
213
214 rho_vitesse_impl(tab_rho_face_n,eqn.inconnue().passe(),rhovitesse);
215 eqn.solv_masse().ajouter_masse(dt,tab_secmem,rhovitesse,0);
216
217 // blocage_cl faux si dirichlet u!=0 !!!!!! manque multiplication par rho
218 for (int op=0; op< eqn.nombre_d_operateurs(); op++) eqn.operateur(op).l_op_base().modifier_pour_Cl(mat_morse,tab_secmem);
219
220 /*
221 * correction finale pour les dirichlets
222 * on ne doit pas imposer un+1 mais rho_un+1 => on multiplie dons le resu par rho_face_np1
223 */
225
226 for (auto& itr : lescl)
227 {
228 const Cond_lim_base& la_cl_base = itr.valeur();
229 if (sub_type(Dirichlet,la_cl_base))
230 {
231 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
232 int ndeb = la_front_dis.num_premiere_face();
233 int nfin = ndeb + la_front_dis.nb_faces();
234 int dim = present.line_size()==1 ? 1 : Objet_U::dimension;
235 DoubleTabView secmem = tab_secmem.view_rw();
236 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
237 {
238 for (int dir=0; dir<dim; dir++)
239 secmem(num_face,dir)*=rho_face_np1(num_face);
240 });
241 end_gpu_timer(__KERNEL_NAME__);
242 }
243 }
244}
245
246
247void Navier_Stokes_Fluide_Dilatable_Proto::assembler_blocs_avec_inertie(const Navier_Stokes_std& eqn, matrices_t matrices, DoubleTab& tab_secmem, const tabs_t& semi_impl)
248{
249 statistics().begin_count(STD_COUNTERS::ajouter_blocs,statistics().get_last_opened_counter_level()+1);
250 const std::string& nom_inco = eqn.inconnue().le_nom().getString();
251 Matrice_Morse *mat = matrices.count(nom_inco)?matrices.at(nom_inco):nullptr;
252 const DoubleTab& present = eqn.inconnue().valeurs();
253
254 // ****** avant inertie ******
255 // diffusion en div(mu grad u ) or on veut impliciter en rho * u => on divise les contributions par le rho_face associe
256 // GF on ajoute apres avoir contribuer pour avoir les bons flux bords
257 DoubleTrav rhovitesse(present);
258
259 // Op diff
260 eqn.operateur(0).l_op_base().ajouter_blocs(matrices, tab_secmem, semi_impl);
261
262 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
263 const DoubleTab& tab_rho_face_np1 = fluide_dil.rho_face_np1(), &tab_rho_face_n=fluide_dil.rho_face_n();
264 const int nb_compo = present.line_size();
265
266 auto tab1 = mat->get_tab1().view_ro();
267 CIntArrView tab2 = mat->get_tab2().view_ro();
268 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
269 DoubleArrView coeff = mat->get_set_coeff().view_rw();
270 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), mat->nb_lignes(), KOKKOS_LAMBDA(const int i)
271 {
272 for (auto k=tab1(i)-1; k<tab1(i+1)-1; k++)
273 {
274 int j = tab2(k)-1;
275 double rapport = rho_face_np1(j/nb_compo);
276 coeff(k) /= rapport;
277 }
278 });
279 end_gpu_timer(__KERNEL_NAME__);
280
281 rho_vitesse_impl(tab_rho_face_np1,present,rhovitesse); // rho*U
282
283 // Op conv
284 eqn.operateur(1).l_op_base().ajouter_blocs(matrices, tab_secmem, {{nom_inco,rhovitesse}});
285 statistics().end_count(STD_COUNTERS::ajouter_blocs);
286
287 // sources
288 statistics().begin_count(STD_COUNTERS::source_terms,statistics().get_last_opened_counter_level()+1);
289 for (int i = 0; i < eqn.sources().size(); i++)
290 eqn.sources()(i)->ajouter_blocs(matrices, tab_secmem, semi_impl);
291 statistics().end_count(STD_COUNTERS::source_terms);
292
293 statistics().begin_count(STD_COUNTERS::ajouter_blocs,statistics().get_last_opened_counter_level()+1);
294 // on resout en rho u on stocke donc rho u dans present
295 rho_vitesse_impl(tab_rho_face_np1,present,ref_cast_non_const(DoubleTab,present));
296 mat->ajouter_multvect(present,tab_secmem);
297 eqn.operateur_gradient()->ajouter_blocs(matrices, tab_secmem, semi_impl);
298
299 /*
300 * contribution a la matrice de l'inertie :
301 * on divisie la diagonale par rhon+1 face
302 * on ajoute l'inertie de facon standard
303 * on remultiplie la diagonale par rhon+1
304 */
305
306 // ajout de l'inertie
307 const double dt=eqn.schema_temps().pas_de_temps();
308 eqn.solv_masse().ajouter_masse(dt,*mat,0);
309 rho_vitesse_impl(tab_rho_face_n,eqn.inconnue().passe(),rhovitesse);
310 eqn.solv_masse().ajouter_masse(dt,tab_secmem,rhovitesse,0);
311
312 // blocage_cl faux si dirichlet u!=0 !!!!!! manque multiplication par rho
313 for (int op=0; op< eqn.nombre_d_operateurs(); op++) eqn.operateur(op).l_op_base().modifier_pour_Cl(*mat,tab_secmem);
314
315 /*
316 * correction finale pour les dirichlets
317 * on ne doit pas imposer un+1 mais rho_un+1 => on multiplie dons le resu par rho_face_np1
318 */
320
321 for (auto& itr : lescl)
322 {
323 const Cond_lim_base& la_cl_base = itr.valeur();
324 if (sub_type(Dirichlet,la_cl_base))
325 {
326
327 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
328 int ndeb = la_front_dis.num_premiere_face();
329 int nfin = ndeb + la_front_dis.nb_faces();
330 int dim = present.line_size()==1 ? 1 : Objet_U::dimension;
331 DoubleTabView secmem = tab_secmem.view_rw();
332 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
333 {
334 for (int dir=0; dir<dim; dir++)
335 secmem(num_face,dir)*=rho_face_np1(num_face);
336 });
337 end_gpu_timer(__KERNEL_NAME__);
338 }
339 }
340 tab_secmem.echange_espace_virtuel();
341 statistics().end_count(STD_COUNTERS::ajouter_blocs);
342
343}
344
345
346void Navier_Stokes_Fluide_Dilatable_Proto::assembler_impl( Matrice_Morse& mat_morse, const DoubleTab& present, DoubleTab& secmem)
347{
348 Cerr << "Navier_Stokes_Fluide_Dilatable_Proto::assembler is not coded ! You should use assembler_avec_inertie !" << finl;
350}
351
352/*
353 * ***************
354 * Private methods
355 * ***************
356 */
357void Navier_Stokes_Fluide_Dilatable_Proto::prepare_and_solve_u_star(Navier_Stokes_std& eqn,
358 const Fluide_Dilatable_base& fluide_dil,
359 DoubleTab& rhoU, DoubleTab& vpoint)
360{
361 const DoubleTab& tab_rho_face_n =fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
362 const DoubleTab& tab_rho = fluide_dil.rho_discvit(); // rho avec la meme discretisation que la vitesse
363 const DoubleTab& vit = eqn.vitesse().valeurs();
364
365 fluide_dil.secmembre_divU_Z(tab_W); //Calcule W=-dZ/dt, 2nd membre de l'equation div(rhoU) = W
366 vpoint=0;
367
368 // ajout diffusion (avec la viscosite dynamique)
369 if (!eqn.schema_temps().diffusion_implicite()) eqn.operateur(0).ajouter(vpoint);
370
371 DoubleTab& rhovitesse = ref_cast_non_const(DoubleTab,eqn.rho_la_vitesse().valeurs());
372 rho_vitesse_impl(tab_rho,vit,rhovitesse);
373
374 // ajout convection utilise rhovitesse
375 if (!eqn.schema_temps().diffusion_implicite()) eqn.operateur(1).ajouter(rhovitesse,vpoint);
376 else
377 {
378 DoubleTrav trav(vpoint);
379 eqn.derivee_en_temps_conv(trav,rhovitesse);
380 vpoint = trav;
381 }
382
383 // ajout source
384 eqn.sources().ajouter(vpoint);
385
386 // ajout de gradP
387 eqn.corriger_derivee_expl(vpoint);
388
389 const Champ_base& rho_vit=eqn.get_champ("rho_comme_v");
390 ref_cast_non_const(DoubleTab,rho_vit.valeurs())=tab_rho_face_np1;
391
393 {
394 DoubleTrav secmemV(vpoint);
395 secmemV = vpoint;
396 double dt = eqn.schema_temps().pas_de_temps();
397 /*
398 * secmemV contient M(rhonp1 unp1 -rhon un)/dt
399 * M-1 secmemv*dt+rhon un -rhonp1un= rhonp1 (unp1 -unp )
400 * dt/rhnhonp1 =(unp1-un)/dt
401 * M-1 secmemV/rhonp1 + (rhon -rhonp1)/rhonp1/dt un
402 *
403 * on modifie le solveur masse pour diviser par rhonp1
404 * (pratique aussi pour la diffusion implicite)
405 */
406
407 eqn.solv_masse().set_name_of_coefficient_temporel("rho_comme_v");
408 eqn.solv_masse().appliquer(secmemV);
409 DoubleTrav dr(tab_rho_face_n);
410
411 CDoubleTabView tab_rho_face_n_v = tab_rho_face_n.view_ro();
412 CDoubleTabView tab_rho_face_np1_v = tab_rho_face_np1.view_ro();
413 DoubleTabView dr_v = dr.view_rw();
414 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), dr.size_totale(),
415 KOKKOS_LAMBDA(
416 const int i)
417 {
418 dr_v(i, 0) = (tab_rho_face_n_v(i, 0) / tab_rho_face_np1_v(i, 0) - 1.) / dt;
419 });
420 end_gpu_timer(__KERNEL_NAME__);
421
422 // on sert de vpoint pour calculer
423 rho_vitesse_impl(dr,vit,vpoint);
424 secmemV += vpoint;
425
426 DoubleTrav delta_u(eqn.inconnue().futur());
427 delta_u = eqn.inconnue().futur();
428 eqn.Gradient_conjugue_diff_impl(secmemV, delta_u ) ;
429
430 /*
431 * delta_u=unp1 -un => delta_u + un=unp1
432 * (delat_u + un)*rhonp1 = rhonp1 * unp1
433 * (delat_u + un)*rhonp1 - rhon * un= rhonp1 * unp1 - rhon * un
434 */
435
436 delta_u *= dt;
437 delta_u += vit;
438 rho_vitesse_impl(tab_rho_face_np1,delta_u,vpoint);
439 vpoint -= rhovitesse;
440 vpoint /= dt;
442 }
443 else eqn.solv_masse().appliquer(vpoint);
444
445 update_vpoint_on_boundaries(eqn,fluide_dil,vpoint);
446
447} /* END prepare_and_solve_u_star */
448
449void Navier_Stokes_Fluide_Dilatable_Proto::update_vpoint_on_boundaries(const Navier_Stokes_std& eqn,
450 const Fluide_Dilatable_base& fluide_dil,
451 DoubleTab& tab_vpoint)
452{
453 // on ajoute durho/dt au bord Dirichlet car les solveur masse a mis a zero
454 // NOTE : en incompressible le terme est rajoute par modifier_secmem
455 const double dt_ = eqn.schema_temps().pas_de_temps();
456 const DoubleTab& tab_rho_face_n = fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
457 const DoubleTab& tab_vit = eqn.vitesse().valeurs();
458 const Conds_lim& lescl = eqn.domaine_Cl_dis().les_conditions_limites();
459 const IntTab& face_voisins = eqn.domaine_dis().face_voisins();
460 const int taille = tab_vpoint.line_size();
461
462 if (taille==1)
463 if (orientation_VDF_.size() == 0)
464 orientation_VDF_.ref(ref_cast(Domaine_VF,eqn.domaine_dis()).orientation());
465 for (auto& itr : lescl)
466 {
467 const Cond_lim_base& la_cl_base = itr.valeur();
468 if (sub_type(Dirichlet,la_cl_base))
469 {
470 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
471 const Dirichlet& diri=ref_cast(Dirichlet,la_cl_base);
472 const int ndeb = la_front_dis.num_premiere_face(), nfin = ndeb + la_front_dis.nb_faces();
473
474 if (taille==1) // VDF //
475 {
476 ToDo_Kokkos("critical");
477 for (int num_face=ndeb; num_face<nfin; num_face++)
478 {
479 int n0 = face_voisins(num_face, 0);
480 if (n0 == -1) n0 = face_voisins(num_face, 1);
481
482 // GF en cas de diffsion implicite vpoint!=0 on ignrore l'ancienne valeur
483 tab_vpoint(num_face)=(diri.val_imp(num_face-ndeb,orientation_VDF_(num_face))*tab_rho_face_np1(num_face)-
484 tab_vit(num_face)*tab_rho_face_n(num_face))/dt_;
485 }
486 }
487 else // VEF //
488 {
489 int dim = Objet_U::dimension;
490 CDoubleTabView val_imp = diri.tab_val_imp().view_ro();
491 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
492 CDoubleArrView rho_face_n = static_cast<const ArrOfDouble&>(tab_rho_face_n).view_ro();
493 CDoubleTabView vit = tab_vit.view_ro();
494 DoubleTabView vpoint = tab_vpoint.view_wo();
495 Kokkos::MDRangePolicy<Kokkos::Rank<2>> policy({ndeb, 0}, {nfin, dim});
496 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int num_face, const int jj)
497 {
498 // GF en cas de diffusion implicite vpoint!=0 on ignrore l'ancienne valeur
499 vpoint(num_face,jj)=(rho_face_np1(num_face)*val_imp(num_face-ndeb,jj)
500 -rho_face_n(num_face)*vit(num_face,jj))/dt_;
501 });
502 end_gpu_timer(__KERNEL_NAME__);
503 }
504 }
505 }
506
507} /* END update_vpoint_on_boundaries */
508
509void Navier_Stokes_Fluide_Dilatable_Proto::solve_pressure_increment(Navier_Stokes_std& eqn,
510 const Fluide_Dilatable_base& fluide_dil,
511 DoubleTab& rhoU, DoubleTab& secmem,
512 DoubleTab& inc_pre, DoubleTab& vpoint)
513{
514 const DoubleTab& tab_rho_face_n =fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
515 const DoubleTab& vit = eqn.vitesse().valeurs();
516 const double dt_ = eqn.schema_temps().pas_de_temps(), t = eqn.schema_temps().temps_courant();
517
518 // Resolution pression
519 vpoint.echange_espace_virtuel();
520
521 // Compute rhoU(n) :
522 rho_vitesse_impl(tab_rho_face_n,vit,rhoU);
523
524 // Add source term to vpoint if interfaces
525 Probleme_base& prob=eqn.probleme();
526 DoubleTrav vpoint0(vpoint);
527 vpoint0 = vpoint;
528 for (int i=0; i<prob.nombre_d_equations(); i++)
529 if (sub_type(Transport_Interfaces_base,prob.equation(i)))
530 {
531 Transport_Interfaces_base& eq_transport = ref_cast(Transport_Interfaces_base,prob.equation(i));
532 const int nb = vpoint.dimension(0), m = vpoint.line_size();
533 DoubleTab source_ibc(nb,m);
534
535 //On ajoute un terme source a vpoint pour imposer au fluide la vitesse de l interface
536 //source_ibc est local pas postraitable (different cas FT ou le terme source est defini et peut etre postraite)
537 eq_transport.modifier_vpoint_pour_imposer_vit(rhoU,vpoint0,vpoint,tab_rho_face_np1,source_ibc,t,dt_);
538 }
539
540 secmem = tab_W;
541 operator_negate(secmem);
542 eqn.operateur_divergence().ajouter(rhoU,secmem);
543 secmem /= dt_; // (-tabW + Div(rhoU))/dt
544
545 eqn.operateur_divergence().ajouter(vpoint, secmem);
546 secmem *= -1;
547 secmem.echange_espace_virtuel();
548 Debog::verifier("Navier_Stokes_Fluide_Dilatable_base::derivee_en_temps_inco, secmem : ", secmem);
549
550 // On ne fait appel qu une seule fois a assembler dans preparer calcul (au lieu de assembler_QC)
551 // Correction du second membre d'apres les conditions aux limites :
552 eqn.assembleur_pression()->modifier_secmem(secmem);
553 eqn.solveur_pression().resoudre_systeme(eqn.matrice_pression().valeur(),secmem,inc_pre);
554
555} /* END solve_pressure_increment */
556
557void Navier_Stokes_Fluide_Dilatable_Proto::correct_and_compute_u_np1(Navier_Stokes_std& eqn,
558 const Fluide_Dilatable_base& fluide_dil,
559 DoubleTab& rhoU,DoubleTab& Mmoins1grad,
560 DoubleTab& inc_pre,DoubleTab& gradP,
561 DoubleTab& vpoint)
562{
563 const DoubleTab& tab_rho_face_np1=fluide_dil.rho_face_np1();
564 const DoubleTab& vit = eqn.vitesse().valeurs();
565 DoubleTab& press = eqn.pression().valeurs();
566 const double dt_ = eqn.schema_temps().pas_de_temps();
567
568 // On a besoin de l'espace virtuel de la pression pour calculer le gradient plus bas
569 // et modifier_solution ne fait pas toujours l'echange_espace_virtuel.
570 // On suppose que pression et inc_pre ont leur espace virtuel a jour
571 // On fait pression += inc_pre:
572 operator_add(press, inc_pre, VECT_ALL_ITEMS);
573 eqn.assembleur_pression()->modifier_solution(press);
574
575 // Correction de la vitesse en pression : M-1 Bt P
576 eqn.solv_masse().appliquer(gradP);
577 vpoint += gradP; // M-1 F
578
580 eqn.operateur_gradient().calculer(press, gradP);
581
582 // On conserve Bt P pour la prochaine fois.
583 Mmoins1grad = gradP;
584 eqn.solv_masse().appliquer(Mmoins1grad);
585
586 // Correction en pression
587 vpoint -= Mmoins1grad;
588
589 // vpoint = (rhoU(n+1)-rhoU(n))/dt
590 vpoint *= dt_;
591 vpoint += rhoU; // rhoU(n+1)
592
593 // Compute U(n+1):
594 tab_divide_any_shape(vpoint, tab_rho_face_np1);
595
596 // Compute (U(n+1)-U(n))/dt :
597 vpoint -= vit;
598 vpoint /= dt_;
599
600 vpoint.echange_espace_virtuel();
601 Debog::verifier("Navier_Stokes_Fluide_Dilatable_base::derivee_en_temps_inco, vpoint : ", vpoint);
602
603} /* END correct_and_compute_u_np1 */
604
DoubleTab & futur(int i=1) override
Renvoie les valeurs du champs a l'instant t+i.
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
virtual double val_imp(int i) const
Renvoie la valeur imposee sur la i-eme composante du champ a la frontiere au temps par defaut du cham...
Definition Dirichlet.cpp:35
virtual const DoubleTab & tab_val_imp(double temps=DMAXFLOAT) const
Definition Dirichlet.cpp:75
double volume_total() const
Definition Domaine.cpp:877
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
virtual IntTab & face_voisins()
DoubleTab & derivee_en_temps_conv(DoubleTab &, const DoubleTab &)
Add convection term In: solution is the unknown I.
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Renvoie le domaine des conditions aux limite discretisee associee a l'equation.
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
classe Fluide_Dilatable_base Cette classe represente un d'un fluide dilatable,
const DoubleTab & rho_face_n() const
const DoubleTab & rho_discvit() const
virtual void secmembre_divU_Z(DoubleTab &) const =0
const DoubleTab & rho_face_np1() const
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
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Operation de multiplication-accumulation (saxpy) matrice vecteur.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
const auto & get_tab2() const
const auto & get_tab1() const
auto & get_set_coeff()
int nb_lignes() const override
Return local number of lines (=size on the current proc).
void assembler_avec_inertie_impl(const Navier_Stokes_std &eqn, Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem)
DoubleTab & rho_vitesse_impl(const DoubleTab &tab_rho, const DoubleTab &vit, DoubleTab &rhovitesse) const
int impr_impl(const Navier_Stokes_std &eqn, Sortie &os) const
DoubleTab & derivee_en_temps_inco_impl(Navier_Stokes_std &, DoubleTab &res)
Calcule la derivee en temps de l'inconnue vitesse, i.
void assembler_blocs_avec_inertie(const Navier_Stokes_std &eqn, matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl)
void assembler_impl(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem)
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
virtual const Champ_Inc_base & rho_la_vitesse() const
const Milieu_base & milieu() const override
Renvoie le milieu physique de l'equation (le Fluide_base upcaste en Milieu_base).
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
const Fluide_base & fluide() const
Renvoie le fluide incompressible (milieu physique de l'equation) associe a l'equation.
virtual const Champ_Inc_base & vitesse() const
Operateur_Div & operateur_divergence()
Renvoie l'operateur de calcul de la divergence associe a l'equation.
const Champ_base & get_champ(const Motcle &nom) const override
Champ_Inc_base & div()
Operateur_Grad & operateur_gradient()
Renvoie l'operateur de calcul du gradient associe a l'equation.
DoubleTab & corriger_derivee_expl(DoubleTab &) override
Add a specific term for Navier Stokes (-gradP(n)) if necessary.
const Operateur & operateur(int) const override
Renvoie le i-eme operateur de l'equation: - le terme_diffusif si i = 0.
Matrice & matrice_pression()
SolveurSys & solveur_pression()
Renvoie le solveur en pression (version const).
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
int nombre_d_operateurs() const override
Renvoie le nombre d'operateurs de l'equation: Pour Navier Stokes Standard c'est 2.
Champ_Inc_base & pression()
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:99
void volumique(DoubleTab &) const
Initialise le tableau passe en parametre avec la contribution de l'operateur.
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
Ajoute la contribution de l'operateur au tableau passe en parametre.
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initialise le tableau passe en parametre avec la contribution de l'operateur.
virtual void modifier_pour_Cl(Matrice_Morse &, DoubleTab &) const
DOES NOTHING - to override in derived classes.
virtual void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
DOES NOTHING - to override in derived classes.
virtual void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const
virtual Operateur_base & l_op_base()=0
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const =0
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
const Domaine & domaine() const
Renvoie le domaine associe au probleme.
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
int diffusion_implicite() const
Renvoie 1 si le schema en temps a ete lu diffusion_implicite.
double temps_courant() const
Renvoie le temps courant.
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
virtual Matrice_Base & ajouter_masse(double dt, Matrice_Base &matrice, int penalisation=1) const
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
void set_name_of_coefficient_temporel(const Nom &)
permet de choisir le nom du coefficient temporelle que l'on veut utiliser pour appliquer
Classe de base des flux de sortie.
Definition Sortie.h:52
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
contribution a la matrice implicite des termes sources par defaut pas de contribution
Definition Sources.cpp:201
DoubleTab & ajouter(DoubleTab &) const
Ajoute la contribution de toutes les sources de la liste au tableau passe en parametre,...
Definition Sources.cpp:85
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
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
virtual void modifier_vpoint_pour_imposer_vit(const DoubleTab &inco_val, DoubleTab &vpoint0, DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &source_val, const double temps, const double dt, const int is_explicite=1, const double eta=1.)=0