TrioCFD 1.9.9_beta
TrioCFD documentation
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 // Note (B.M.): some implementations of this method do not perform virtual space exchange:
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 // Divide array by vol(i)
83
84 // Divide by a mean rho
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 @brief Computes the time derivative of the velocity unknown, i.e. the acceleration dU/dt, and returns it.
107 *
108 * Calls Equation_base::derivee_en_temps_inco(DoubleTab&) and also computes the pressure.
109 *
110 * @param vpoint Array of acceleration values dU/dt.
111 * @return Array of acceleration values (velocity derivative).
112 */
114{
115 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
116 DoubleTab& press = eqn.pression().valeurs(), &vit = eqn.vitesse().valeurs();
117 DoubleTrav secmem(press);
118 DoubleTrav inc_pre(press);
119 DoubleTrav rhoU(vit);
120
121 if (!tab_W.get_md_vector())
122 {
123 tab_W.copy(secmem, RESIZE_OPTIONS::NOCOPY_NOINIT); // copy structure
124 // initialisation to avoid assert failure when filling in EDO_Pression_th_VEF::secmembre_divU_Z_VEFP1B
125 tab_W = 0.;
126 }
127
128 // Get champ gradP
129 OBS_PTR(Champ_base) gradient_pression;
130 eqn.has_champ("gradient_pression", gradient_pression);
131
132 if (!gradient_pression)
133 {
134 Cerr<<"the equation does not include gradient_pression "<<finl;
136 }
137
138 DoubleTab& gradP = gradient_pression->valeurs();
139 DoubleTrav Mmoins1grad(gradP);
140
141 // We use the incremental pressure-projection algorithm (Chorin)
142
143 // Step 1 : prepare operators and solve for a provisional velocity u*
144 prepare_and_solve_u_star(eqn,fluide_dil,rhoU, vpoint);
145
146 // Step 2 : solve the poisson equation for the pressure increment (Pi = P^n+1 - P^n)
147 // Attention the matrix has a constant coefficient as the variable of NS is rhoU and not U !!!
148 solve_pressure_increment(eqn,fluide_dil,rhoU,secmem,inc_pre,vpoint);
149
150 // Step 3 : compute P^n+1 & compute the correct velocity u^n+1
151 correct_and_compute_u_np1(eqn,fluide_dil,rhoU,Mmoins1grad,inc_pre,gradP,vpoint);
152
153 return vpoint;
154}
155
157 const DoubleTab& present, DoubleTab& tab_secmem)
158{
159 // ****** before inertia ******
160 // diffusion in div(mu grad u), but we want to implicitize in rho * u => divide contributions by the associated rho_face
161 // GF: add after contributing so as to have the correct boundary fluxes
162 DoubleTrav rhovitesse(present);
163
164 // Op diff
165 eqn.operateur(0).l_op_base().contribuer_a_avec(present,mat_morse);
166 eqn.operateur(0).ajouter(tab_secmem);
167
168 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
169 const DoubleTab& tab_rho_face_np1 = fluide_dil.rho_face_np1(), &tab_rho_face_n=fluide_dil.rho_face_n();
170 const int nb_compo = present.line_size();
171
172 auto tab1 = mat_morse.get_tab1().view_ro();
173 CIntArrView tab2 = mat_morse.get_tab2().view_ro();
174 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
175 DoubleArrView coeff = mat_morse.get_set_coeff().view_rw();
176 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), mat_morse.nb_lignes(), KOKKOS_LAMBDA(const int i)
177 {
178 for (auto k=tab1(i)-1; k<tab1(i+1)-1; k++)
179 {
180 int j = tab2(k)-1;
181 double rapport = rho_face_np1(j/nb_compo);
182 coeff(k) /= rapport;
183 }
184 });
185 end_gpu_timer(__KERNEL_NAME__);
186
187 rho_vitesse_impl(tab_rho_face_np1,present,rhovitesse); // rho*U
188
189 // Op conv
190 eqn.operateur(1).l_op_base().contribuer_a_avec(rhovitesse,mat_morse);
191 eqn.operateur(1).ajouter(rhovitesse,tab_secmem);
192
193 // sources
194 eqn.sources().ajouter(tab_secmem);
195 eqn.sources().contribuer_a_avec(present,mat_morse);
196
197 // solve in rho*u, so store rho*u in present
198 rho_vitesse_impl(tab_rho_face_np1,present,ref_cast_non_const(DoubleTab,present));
199 mat_morse.ajouter_multvect(present, tab_secmem);
200
201 /*
202 * contribution to the inertia matrix:
203 * divide the diagonal by rho^{n+1}_face
204 * add inertia in the standard way
205 * multiply the diagonal back by rho^{n+1}
206 */
207
208 // add inertia
209 const double dt=eqn.schema_temps().pas_de_temps();
210 eqn.solv_masse().ajouter_masse(dt,mat_morse,0);
211
212 rho_vitesse_impl(tab_rho_face_n,eqn.inconnue().passe(),rhovitesse);
213 eqn.solv_masse().ajouter_masse(dt,tab_secmem,rhovitesse,0);
214
215 // boundary condition locking wrong if Dirichlet u!=0 !!!!!! missing multiplication by rho
216 for (int op=0; op< eqn.nombre_d_operateurs(); op++) eqn.operateur(op).l_op_base().modifier_pour_Cl(mat_morse,tab_secmem);
217
218 /*
219 * final correction for Dirichlet conditions:
220 * we must not impose u^{n+1} but rho*u^{n+1} => multiply the result by rho_face_np1
221 */
223
224 for (auto& itr : lescl)
225 {
226 const Cond_lim_base& la_cl_base = itr.valeur();
227 if (sub_type(Dirichlet,la_cl_base))
228 {
229 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
230 int ndeb = la_front_dis.num_premiere_face();
231 int nfin = ndeb + la_front_dis.nb_faces();
232 int dim = present.line_size()==1 ? 1 : Objet_U::dimension;
233 DoubleTabView secmem = tab_secmem.view_rw();
234 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
235 {
236 for (int dir=0; dir<dim; dir++)
237 secmem(num_face,dir)*=rho_face_np1(num_face);
238 });
239 end_gpu_timer(__KERNEL_NAME__);
240 }
241 }
242}
243
244
245void 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)
246{
247 statistics().begin_count(STD_COUNTERS::ajouter_blocs,statistics().get_last_opened_counter_level()+1);
248 const std::string& nom_inco = eqn.inconnue().le_nom().getString();
249 Matrice_Morse *mat = matrices.count(nom_inco)?matrices.at(nom_inco):nullptr;
250 const DoubleTab& present = eqn.inconnue().valeurs();
251
252 // ****** before inertia ******
253 // diffusion in div(mu grad u), but we want to implicitize in rho * u => divide contributions by the associated rho_face
254 // GF: add after contributing so as to have the correct boundary fluxes
255 DoubleTrav rhovitesse(present);
256
257 // Op diff
258 eqn.operateur(0).l_op_base().ajouter_blocs(matrices, tab_secmem, semi_impl);
259
260 const Fluide_Dilatable_base& fluide_dil=ref_cast(Fluide_Dilatable_base,eqn.milieu());
261 const DoubleTab& tab_rho_face_np1 = fluide_dil.rho_face_np1(), &tab_rho_face_n=fluide_dil.rho_face_n();
262 const int nb_compo = present.line_size();
263
264 auto tab1 = mat->get_tab1().view_ro();
265 CIntArrView tab2 = mat->get_tab2().view_ro();
266 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
267 DoubleArrView coeff = mat->get_set_coeff().view_rw();
268 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), mat->nb_lignes(), KOKKOS_LAMBDA(const int i)
269 {
270 for (auto k=tab1(i)-1; k<tab1(i+1)-1; k++)
271 {
272 int j = tab2(k)-1;
273 double rapport = rho_face_np1(j/nb_compo);
274 coeff(k) /= rapport;
275 }
276 });
277 end_gpu_timer(__KERNEL_NAME__);
278
279 rho_vitesse_impl(tab_rho_face_np1,present,rhovitesse); // rho*U
280
281 // Op conv
282 eqn.operateur(1).l_op_base().ajouter_blocs(matrices, tab_secmem, {{nom_inco,rhovitesse}});
283 statistics().end_count(STD_COUNTERS::ajouter_blocs);
284
285 // sources
286 statistics().begin_count(STD_COUNTERS::source_terms,statistics().get_last_opened_counter_level()+1);
287 for (int i = 0; i < eqn.sources().size(); i++)
288 eqn.sources()(i)->ajouter_blocs(matrices, tab_secmem, semi_impl);
289 statistics().end_count(STD_COUNTERS::source_terms);
290
291 statistics().begin_count(STD_COUNTERS::ajouter_blocs,statistics().get_last_opened_counter_level()+1);
292 // solve in rho*u, so store rho*u in present
293 rho_vitesse_impl(tab_rho_face_np1,present,ref_cast_non_const(DoubleTab,present));
294 mat->ajouter_multvect(present,tab_secmem);
295 eqn.operateur_gradient()->ajouter_blocs(matrices, tab_secmem, semi_impl);
296
297 /*
298 * contribution to the inertia matrix:
299 * divide the diagonal by rho^{n+1}_face
300 * add inertia in the standard way
301 * multiply the diagonal back by rho^{n+1}
302 */
303
304 // add inertia
305 const double dt=eqn.schema_temps().pas_de_temps();
306 eqn.solv_masse().ajouter_masse(dt,*mat,0);
307 rho_vitesse_impl(tab_rho_face_n,eqn.inconnue().passe(),rhovitesse);
308 eqn.solv_masse().ajouter_masse(dt,tab_secmem,rhovitesse,0);
309
310 // boundary condition locking wrong if Dirichlet u!=0 !!!!!! missing multiplication by rho
311 for (int op=0; op< eqn.nombre_d_operateurs(); op++) eqn.operateur(op).l_op_base().modifier_pour_Cl(*mat,tab_secmem);
312
313 /*
314 * final correction for Dirichlet conditions:
315 * we must not impose u^{n+1} but rho*u^{n+1} => multiply the result by rho_face_np1
316 */
318
319 for (auto& itr : lescl)
320 {
321 const Cond_lim_base& la_cl_base = itr.valeur();
322 if (sub_type(Dirichlet,la_cl_base))
323 {
324
325 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
326 int ndeb = la_front_dis.num_premiere_face();
327 int nfin = ndeb + la_front_dis.nb_faces();
328 int dim = present.line_size()==1 ? 1 : Objet_U::dimension;
329 DoubleTabView secmem = tab_secmem.view_rw();
330 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(ndeb, nfin), KOKKOS_LAMBDA(const int num_face)
331 {
332 for (int dir=0; dir<dim; dir++)
333 secmem(num_face,dir)*=rho_face_np1(num_face);
334 });
335 end_gpu_timer(__KERNEL_NAME__);
336 }
337 }
338 tab_secmem.echange_espace_virtuel();
339 statistics().end_count(STD_COUNTERS::ajouter_blocs);
340
341}
342
343
344void Navier_Stokes_Fluide_Dilatable_Proto::assembler_impl( Matrice_Morse& mat_morse, const DoubleTab& present, DoubleTab& secmem)
345{
346 Cerr << "Navier_Stokes_Fluide_Dilatable_Proto::assembler is not coded ! You should use assembler_avec_inertie !" << finl;
348}
349
350/*
351 * ***************
352 * Private methods
353 * ***************
354 */
355void Navier_Stokes_Fluide_Dilatable_Proto::prepare_and_solve_u_star(Navier_Stokes_std& eqn,
356 const Fluide_Dilatable_base& fluide_dil,
357 DoubleTab& rhoU, DoubleTab& vpoint)
358{
359 const DoubleTab& tab_rho_face_n =fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
360 const DoubleTab& tab_rho = fluide_dil.rho_discvit(); // rho with the same discretization as velocity
361 const DoubleTab& vit = eqn.vitesse().valeurs();
362
363 fluide_dil.secmembre_divU_Z(tab_W); // Compute W=-dZ/dt, right-hand side of the equation div(rhoU) = W
364 vpoint=0;
365
366 // add diffusion (with the dynamic viscosity)
367 if (!eqn.schema_temps().diffusion_implicite()) eqn.operateur(0).ajouter(vpoint);
368
369 DoubleTab& rhovitesse = ref_cast_non_const(DoubleTab,eqn.rho_la_vitesse().valeurs());
370 rho_vitesse_impl(tab_rho,vit,rhovitesse);
371
372 // add convection using rhovitesse
373 if (!eqn.schema_temps().diffusion_implicite()) eqn.operateur(1).ajouter(rhovitesse,vpoint);
374 else
375 {
376 DoubleTrav trav(vpoint);
377 eqn.derivee_en_temps_conv(trav,rhovitesse);
378 vpoint = trav;
379 }
380
381 // add source term
382 eqn.sources().ajouter(vpoint);
383
384 // add gradP
385 eqn.corriger_derivee_expl(vpoint);
386
387 const Champ_base& rho_vit=eqn.get_champ("rho_comme_v");
388 ref_cast_non_const(DoubleTab,rho_vit.valeurs())=tab_rho_face_np1;
389
391 {
392 DoubleTrav secmemV(vpoint);
393 secmemV = vpoint;
394 double dt = eqn.schema_temps().pas_de_temps();
395 /*
396 * secmemV contains M(rho^{n+1} u^{n+1} - rho^n u^n)/dt
397 * M^{-1} secmemV*dt + rho^n u^n - rho^{n+1} u^n = rho^{n+1} (u^{n+1} - u^n)
398 * dt/rho^{n+1} = (u^{n+1} - u^n)/dt
399 * M^{-1} secmemV/rho^{n+1} + (rho^n - rho^{n+1})/rho^{n+1}/dt * u^n
400 *
401 * modify the mass solver to divide by rho^{n+1}
402 * (also useful for implicit diffusion)
403 */
404
405 eqn.solv_masse().set_name_of_coefficient_temporel("rho_comme_v");
406 eqn.solv_masse().appliquer(secmemV);
407 DoubleTrav dr(tab_rho_face_n);
408
409 CDoubleTabView tab_rho_face_n_v = tab_rho_face_n.view_ro();
410 CDoubleTabView tab_rho_face_np1_v = tab_rho_face_np1.view_ro();
411 DoubleTabView dr_v = dr.view_rw();
412 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), dr.size_totale(),
413 KOKKOS_LAMBDA(
414 const int i)
415 {
416 dr_v(i, 0) = (tab_rho_face_n_v(i, 0) / tab_rho_face_np1_v(i, 0) - 1.) / dt;
417 });
418 end_gpu_timer(__KERNEL_NAME__);
419
420 // use vpoint as a temporary array
421 rho_vitesse_impl(dr,vit,vpoint);
422 secmemV += vpoint;
423
424 DoubleTrav delta_u(eqn.inconnue().futur());
425 delta_u = eqn.inconnue().futur();
426 eqn.Gradient_conjugue_diff_impl(secmemV, delta_u ) ;
427
428 /*
429 * delta_u=unp1 -un => delta_u + un=unp1
430 * (delat_u + un)*rhonp1 = rhonp1 * unp1
431 * (delat_u + un)*rhonp1 - rhon * un= rhonp1 * unp1 - rhon * un
432 */
433
434 delta_u *= dt;
435 delta_u += vit;
436 rho_vitesse_impl(tab_rho_face_np1,delta_u,vpoint);
437 vpoint -= rhovitesse;
438 vpoint /= dt;
440 }
441 else eqn.solv_masse().appliquer(vpoint);
442
443 update_vpoint_on_boundaries(eqn,fluide_dil,vpoint);
444
445} /* END prepare_and_solve_u_star */
446
447void Navier_Stokes_Fluide_Dilatable_Proto::update_vpoint_on_boundaries(const Navier_Stokes_std& eqn,
448 const Fluide_Dilatable_base& fluide_dil,
449 DoubleTab& tab_vpoint)
450{
451 // add d(rho)/dt at Dirichlet boundaries because the mass solver has set it to zero
452 // NOTE: for incompressible flows the term is added by modifier_secmem
453 const double dt_ = eqn.schema_temps().pas_de_temps();
454 const DoubleTab& tab_rho_face_n = fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
455 const DoubleTab& tab_vit = eqn.vitesse().valeurs();
456 const Conds_lim& lescl = eqn.domaine_Cl_dis().les_conditions_limites();
457 const IntTab& face_voisins = eqn.domaine_dis().face_voisins();
458 const int taille = tab_vpoint.line_size();
459
460 if (taille==1)
461 if (orientation_VDF_.size() == 0)
462 orientation_VDF_.ref(ref_cast(Domaine_VF,eqn.domaine_dis()).orientation());
463 for (auto& itr : lescl)
464 {
465 const Cond_lim_base& la_cl_base = itr.valeur();
466 if (sub_type(Dirichlet,la_cl_base))
467 {
468 const Front_VF& la_front_dis = ref_cast(Front_VF,la_cl_base.frontiere_dis());
469 const Dirichlet& diri=ref_cast(Dirichlet,la_cl_base);
470 const int ndeb = la_front_dis.num_premiere_face(), nfin = ndeb + la_front_dis.nb_faces();
471
472 if (taille==1) // VDF //
473 {
474 ToDo_Kokkos("critical");
475 for (int num_face=ndeb; num_face<nfin; num_face++)
476 {
477 int n0 = face_voisins(num_face, 0);
478 if (n0 == -1) n0 = face_voisins(num_face, 1);
479
480 // GF: in case of implicit diffusion, vpoint!=0 so we ignore the old value
481 tab_vpoint(num_face)=(diri.val_imp(num_face-ndeb,orientation_VDF_(num_face))*tab_rho_face_np1(num_face)-
482 tab_vit(num_face)*tab_rho_face_n(num_face))/dt_;
483 }
484 }
485 else // VEF //
486 {
487 int dim = Objet_U::dimension;
488 CDoubleTabView val_imp = diri.tab_val_imp().view_ro();
489 CDoubleArrView rho_face_np1 = static_cast<const ArrOfDouble&>(tab_rho_face_np1).view_ro();
490 CDoubleArrView rho_face_n = static_cast<const ArrOfDouble&>(tab_rho_face_n).view_ro();
491 CDoubleTabView vit = tab_vit.view_ro();
492 DoubleTabView vpoint = tab_vpoint.view_wo();
493 Kokkos::MDRangePolicy<Kokkos::Rank<2>> policy({ndeb, 0}, {nfin, dim});
494 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int num_face, const int jj)
495 {
496 // GF: in case of implicit diffusion, vpoint!=0 so we ignore the old value
497 vpoint(num_face,jj)=(rho_face_np1(num_face)*val_imp(num_face-ndeb,jj)
498 -rho_face_n(num_face)*vit(num_face,jj))/dt_;
499 });
500 end_gpu_timer(__KERNEL_NAME__);
501 }
502 }
503 }
504
505} /* END update_vpoint_on_boundaries */
506
507void Navier_Stokes_Fluide_Dilatable_Proto::solve_pressure_increment(Navier_Stokes_std& eqn,
508 const Fluide_Dilatable_base& fluide_dil,
509 DoubleTab& rhoU, DoubleTab& secmem,
510 DoubleTab& inc_pre, DoubleTab& vpoint)
511{
512 const DoubleTab& tab_rho_face_n =fluide_dil.rho_face_n(), &tab_rho_face_np1=fluide_dil.rho_face_np1();
513 const DoubleTab& vit = eqn.vitesse().valeurs();
514 const double dt_ = eqn.schema_temps().pas_de_temps(), t = eqn.schema_temps().temps_courant();
515
516 // Pressure resolution
517 vpoint.echange_espace_virtuel();
518
519 // Compute rhoU(n) :
520 rho_vitesse_impl(tab_rho_face_n,vit,rhoU);
521
522 // Add source term to vpoint if interfaces
523 Probleme_base& prob=eqn.probleme();
524 DoubleTrav vpoint0(vpoint);
525 vpoint0 = vpoint;
526 for (int i=0; i<prob.nombre_d_equations(); i++)
527 if (sub_type(Transport_Interfaces_base,prob.equation(i)))
528 {
529 Transport_Interfaces_base& eq_transport = ref_cast(Transport_Interfaces_base,prob.equation(i));
530 const int nb = vpoint.dimension(0), m = vpoint.line_size();
531 DoubleTab source_ibc(nb,m);
532
533 // Add a source term to vpoint to impose the interface velocity on the fluid.
534 // source_ibc is local and not post-processable (unlike the FT case where the source term is defined and can be post-processed).
535 eq_transport.modifier_vpoint_pour_imposer_vit(rhoU,vpoint0,vpoint,tab_rho_face_np1,source_ibc,t,dt_);
536 }
537
538 secmem = tab_W;
539 operator_negate(secmem);
540 eqn.operateur_divergence().ajouter(rhoU,secmem);
541 secmem /= dt_; // (-tabW + Div(rhoU))/dt
542
543 eqn.operateur_divergence().ajouter(vpoint, secmem);
544 secmem *= -1;
545 secmem.echange_espace_virtuel();
546 Debog::verifier("Navier_Stokes_Fluide_Dilatable_base::derivee_en_temps_inco, secmem : ", secmem);
547
548 // assembler is called only once during preparer_calcul (instead of assembler_QC)
549 // Correction of the right-hand side according to boundary conditions:
550 eqn.assembleur_pression()->modifier_secmem(secmem);
551 eqn.solveur_pression().resoudre_systeme(eqn.matrice_pression().valeur(),secmem,inc_pre);
552
553} /* END solve_pressure_increment */
554
555void Navier_Stokes_Fluide_Dilatable_Proto::correct_and_compute_u_np1(Navier_Stokes_std& eqn,
556 const Fluide_Dilatable_base& fluide_dil,
557 DoubleTab& rhoU,DoubleTab& Mmoins1grad,
558 DoubleTab& inc_pre,DoubleTab& gradP,
559 DoubleTab& vpoint)
560{
561 const DoubleTab& tab_rho_face_np1=fluide_dil.rho_face_np1();
562 const DoubleTab& vit = eqn.vitesse().valeurs();
563 DoubleTab& press = eqn.pression().valeurs();
564 const double dt_ = eqn.schema_temps().pas_de_temps();
565
566 // The virtual space of the pressure is needed to compute the gradient below,
567 // and modifier_solution does not always perform the virtual space exchange.
568 // We assume that pression and inc_pre have their virtual space up to date.
569 // Compute pression += inc_pre:
570 operator_add(press, inc_pre, VECT_ALL_ITEMS);
571 eqn.assembleur_pression()->modifier_solution(press);
572
573 // Pressure correction of velocity: M^{-1} B^T P
574 eqn.solv_masse().appliquer(gradP);
575 vpoint += gradP; // M-1 F
576
578 eqn.operateur_gradient().calculer(press, gradP);
579
580 // Save B^T P for the next step.
581 Mmoins1grad = gradP;
582 eqn.solv_masse().appliquer(Mmoins1grad);
583
584 // Pressure correction
585 vpoint -= Mmoins1grad;
586
587 // vpoint = (rhoU(n+1)-rhoU(n))/dt
588 vpoint *= dt_;
589 vpoint += rhoU; // rhoU(n+1)
590
591 // Compute U(n+1):
592 tab_divide_any_shape(vpoint, tab_rho_face_np1);
593
594 // Compute (U(n+1)-U(n))/dt :
595 vpoint -= vit;
596 vpoint /= dt_;
597
598 vpoint.echange_espace_virtuel();
599 Debog::verifier("Navier_Stokes_Fluide_Dilatable_base::derivee_en_temps_inco, vpoint : ", vpoint);
600
601} /* END correct_and_compute_u_np1 */
602
DoubleTab & futur(int i=1) override
Returns field values at instant t+i.
DoubleTab & passe(int i=1) override
Returns field values at instant t-i.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
virtual double val_imp(int i) const
Returns the imposed value on the i-th component of the field at the boundary at the default time of c...
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:876
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
virtual IntTab & face_voisins()
DoubleTab & derivee_en_temps_conv(DoubleTab &, const DoubleTab &)
Add convection term In: solution is the unknown I.
Sources & sources()
Returns the source terms associated with the equation.
Solveur_Masse_base & solv_masse()
Returns the mass solver associated with the equation.
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Returns the discretized boundary condition domain associated with the equation.
Probleme_base & probleme()
Returns the problem associated with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
void Gradient_conjugue_diff_impl(DoubleTrav &secmem, DoubleTab &solution)
Domaine_dis_base & domaine_dis()
Returns the discretized domain associated with the equation.
const Nom & le_nom() const override
Returns the name of the field.
Base class for a dilatable fluid, inheriting from Fluide_base.
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
Matrix-vector multiply-accumulate operation (saxpy).
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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)
Computes the time derivative of the velocity unknown, i.e. the acceleration dU/dt,...
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)
Navier_Stokes_std This class carries the terms of the momentum equation.
virtual const Champ_Inc_base & rho_la_vitesse() const
const Milieu_base & milieu() const override
Returns the physical medium of the equation (Fluide_base upcast to Milieu_base).
const Champ_Inc_base & inconnue() const override
Returns the velocity (unknown field of the equation) (const version).
const Fluide_base & fluide() const
Returns the incompressible fluid (physical medium of the equation) associated with the equation.
virtual const Champ_Inc_base & vitesse() const
Operateur_Div & operateur_divergence()
Returns the divergence operator associated with the equation.
const Champ_base & get_champ(const Motcle &nom) const override
Champ_Inc_base & div()
Operateur_Grad & operateur_gradient()
Returns the gradient operator associated with the equation.
DoubleTab & corriger_derivee_expl(DoubleTab &) override
Add a specific term for Navier Stokes (-gradP(n)) if necessary.
const Operateur & operateur(int) const override
Returns the i-th operator of the equation: - terme_diffusif if i = 0.
Matrice & matrice_pression()
SolveurSys & solveur_pression()
Returns the pressure solver (const version).
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
int nombre_d_operateurs() const override
Returns the number of operators in the equation: 2 for the standard Navier-Stokes equations.
Champ_Inc_base & pression()
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:94
void volumique(DoubleTab &) const
Initializes the array passed as parameter with the contribution of the operator.
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
Adds the contribution of the operator to the array passed as parameter.
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
Initializes the array passed as parameter with the contribution of the operator.
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
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Probleme_U.h:109
const Domaine & domaine() const
Returns the domain associated with the problem.
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
int diffusion_implicite() const
Returns 1 if the time scheme has been read with diffusion_implicite.
double temps_courant() const
Returns the current time.
double pas_de_temps() const
Returns the current time step (delta_t).
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
Returns appliquer_impl(x/temporal_coefficient) if a temporal coefficient is set, otherwise returns ap...
void set_name_of_coefficient_temporel(const Nom &)
Allows choosing the name of the temporal coefficient to use for apply.
Base class for output streams.
Definition Sortie.h:52
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const
Contribution to the implicit matrix of source terms. By default, no contribution.
Definition Sources.cpp:201
DoubleTab & ajouter(DoubleTab &) const
Adds the contribution of all sources in the list to the array passed as parameter,...
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