TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Simple.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 <Simple.h>
17#include <Navier_Stokes_std.h>
18#include <EChaine.h>
19#include <Matrice_Bloc.h>
20#include <Matrice_Morse_Sym.h>
21#include <Assembleur_base.h>
22#include <Schema_Temps_base.h>
23#include <Schema_Euler_Implicite.h>
24#include <Fluide_Dilatable_base.h>
25#include <Probleme_base.h>
26#include <MD_Vector_composite.h>
27#include <MD_Vector_tools.h>
28#include <TRUSTTab_parts.h>
29#include <SETS.h>
30#include <TRUSTTrav.h>
31#include <Discretisation_base.h>
32
33Implemente_instanciable_sans_constructeur(Simple,"Simple",Simpler_Base);
34// XD simple piso simple INHERITS_BRACE SIMPLE type algorithm
35// XD attr relax_pression floattant relax_pression OPT Value between 0 and 1 (by default 1), this keyword is used only
36// XD_CONT by the SIMPLE algorithm for relaxing the increment of pressure.
37
39{
40 alpha_ = 1.;
41 beta_ = 1.;
43 Ustar_old.resize(0);
44}
45
46Sortie& Simple::printOn(Sortie& os ) const
47{
48 return Simpler_Base::printOn(os);
49}
50
52{
53 return Simpler_Base::readOn(is);
54}
55
56Entree& Simple::lire(const Motcle& motlu,Entree& is)
57{
58 Motcles les_mots(1);
59 {
60 les_mots[0] = "relax_pression";
61 }
62
63 int rang=les_mots.search(motlu);
64 switch(rang)
65 {
66 case 0:
67 {
68 is >> beta_;
69 break;
70 }
71
72 default :
73 {
74 return Simpler_Base::lire(motlu, is);
75 }
76 }
77
78 return is;
79}
80
81void diviser_par_rho_np1_face(Equation_base& eqn,DoubleTab& tab_array)
82{
83 Fluide_Dilatable_base& fluide_dil = ref_cast(Fluide_Dilatable_base,eqn.milieu());
84 int nbdim = tab_array.nb_dim();
85 int taille_0_tot = tab_array.dimension_tot(0);
86 int dim = tab_array.dimension(1);
87 CDoubleArrView rho = static_cast<const ArrOfDouble&>(fluide_dil.rho_face_np1()).view_ro();
88 if (nbdim==1)
89 {
90 DoubleArrView array = static_cast<ArrOfDouble&>(tab_array).view_rw();
91 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, taille_0_tot), KOKKOS_LAMBDA(const int i)
92 {
93 for (int j = 0; j < dim; j++)
94 array(i) /= rho(i);
95 });
96 }
97 else
98 {
99 DoubleTabView array = tab_array.view_rw();
100 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, taille_0_tot), KOKKOS_LAMBDA(const int i)
101 {
102 for (int j=0; j<dim; j++)
103 array(i,j) /= rho(i);
104 });
105 }
106 end_gpu_timer(__KERNEL_NAME__);
107}
108
109void iterer_eqn_expl(Equation_base& eqn,int nb_iter,double dt,DoubleTab& current,DoubleTab& dudt,
110 int& converge,const int no_qdm_)
111{
112 if (nb_iter>1)
113 {
114 converge = 1;
115 return;
116 }
117 if ((no_qdm_))
118 {
119 Cout<<eqn.que_suis_je()<<" equation is not solved."<<finl;
120 eqn.valider_iteration();
121 converge = 1;
122 return;
123
124 }
125 double dt_stab = eqn.calculer_pas_de_temps();
126
127 // See Schema_Temps_base::limpr for information on modf
128 double n_sous_ite;
129 modf((dt/dt_stab), &n_sous_ite);
130 if (dt>dt_stab*n_sous_ite) n_sous_ite=n_sous_ite+1.;
131 double dt_calc = dt/n_sous_ite;
132 assert(dt_calc<=dt_stab);
133 for (double i=0; i<n_sous_ite; i=i+1.)
134 {
135 eqn.derivee_en_temps_inco(dudt);
136 dudt *= dt_calc;
137 current += dudt;
138 eqn.valider_iteration();
139 }
140 Cout <<"It is solved with " << n_sous_ite << " explicit sub-iterations."<<finl;
141 converge=1;
142}
143
144void iterer_eqn_expl_diffusion_implicite(Equation_base& eqn,int nb_iter,double dt,DoubleTab& current,DoubleTab& dudt,
145 int& converge,const int no_qdm_,const double seuil)
146{
147 if (nb_iter>1)
148 {
149 converge = 1;
150 return;
151 }
152 if ((no_qdm_))
153 {
154 Cout<<eqn.que_suis_je()<<" equation is not solved."<<finl;
155 eqn.valider_iteration();
156 converge = 1;
157 return;
158 }
159
160 //dudt = current;
162 double seuil_sa = sch.seuil_diffusion_implicite();
163 int flag_sa = sch.diffusion_implicite();
164 sch.set_seuil_diffusion_implicite() = seuil;
165 sch.set_diffusion_implicite() = 1;
166 eqn.derivee_en_temps_inco(dudt);
167 dudt *= dt;
168 current += dudt;
169 eqn.valider_iteration();
170
171 //Restore the implicit diffusion parameters to their previous values
172 sch.set_seuil_diffusion_implicite() = seuil_sa;
173 sch.set_diffusion_implicite() = flag_sa;
174 converge = 1;
175}
176
177bool Simple::iterer_eqn(Equation_base& eqn,const DoubleTab& inut,DoubleTab& current,
178 double dt,int nb_iter, int& ok)
179{
180 DoubleTab dudt(current);
182
183
184 int converge=0;
185 int nb_pas_dt = eqn.schema_temps().nb_pas_dt();
186
187 double temps = eqn.schema_temps().temps_courant();
188 int freq = param.equation_frequence_resolue(temps);
189
190 if (freq!=0 && (nb_pas_dt%freq)!=0)
191 {
192 Cout<<"Time step : "<<nb_pas_dt<<" - "<<eqn.que_suis_je()<<" equation is not solved."<<finl;
193 eqn.valider_iteration();
194 return true;
195 }
196 if (eqn.equation_non_resolue())
197 {
198 Cout<<eqn.que_suis_je()<<" equation is not solved."<<finl;
199 // compute the derivative once to obtain the boundary fluxes
200 if (eqn.schema_temps().nb_pas_dt()==0)
201 {
202 DoubleTab toto(eqn.inconnue().valeurs());
203 eqn.derivee_en_temps_inco(toto);
204 }
205 eqn.valider_iteration();
206 converge = 1;
207 return true;
208 }
209 if (param.calcul_explicite())
210 {
211 if (param.seuil_diffusion_implicite()<0)
212 iterer_eqn_expl(eqn,nb_iter,dt,current,dudt,converge,no_qdm_);
213 else
214 iterer_eqn_expl_diffusion_implicite(eqn,nb_iter,dt,current,dudt,converge,no_qdm_,param.seuil_diffusion_implicite());
215
216 return (converge==1);
217 }
218
219 double& seuil_convergence_implicite = param.seuil_convergence_implicite();
220 double seuil_verification_solveur = param.seuil_verification_solveur();
221 double seuil_test_preliminaire_solveur = param.seuil_test_preliminaire_solveur();
222 assert(seuil_verification_solveur>0);
223 SolveurSys& solveur = param.solveur();
224 double seuil_convg = seuil_convergence_implicite;
226 {
227 double residu = ref_cast(Schema_Euler_Implicite,eqn.schema_temps()).residu_old();
228
229 if ((residu*dt*10<seuil_convg)&&(nb_iter==1))
230 {
231 seuil_convergence_implicite /= 1.1;
232 seuil_convg = seuil_convergence_implicite;
233 }
234 Cout<<"seuil_convg "<<seuil_convg<<finl;
235 }
236
237 converge = 0;
238 if ((no_qdm_) && (sub_type(Navier_Stokes_std,eqn)))
239 {
240 Matrice& matrice_en_pression_2 = ref_cast(Navier_Stokes_std, eqn).matrice_pression();
241 if (!matrice_en_pression_2) matrice_en_pression_2.detach();
242
243 converge = 1;
244 return true;
245 }
246
247 //////////////////////////////////////////////////////////////////////////////////////////
248 // Implicit resolution - via iterer_NS for Navier_Stokes
249 // - ...solveur.resoudre_systeme()... for other equations
250 /////////////////////////////////////////////////////////////////////////////////////////
251
252 dudt = current; // to be able to test convergence.
253 Matrice_Morse matrice;
254 if (!(sub_type(Navier_Stokes_std,eqn) && sub_type(SETS, *this))) //SETS and ICE manage their own matrices
255 {
256 eqn.dimensionner_matrice(matrice);
257 matrice.get_set_coeff() = 0;
258 }
259
260 DoubleTrav resu(current);
261
262 if( sub_type(Navier_Stokes_std,eqn))
263 {
264 Navier_Stokes_std& eqnNS = ref_cast(Navier_Stokes_std,eqn);
265 DoubleTab& pression = eqnNS.pression().valeurs();
266 DoubleTrav secmem(pression);
267 pression.echange_espace_virtuel();
268 iterer_NS(eqnNS,current,pression,dt,matrice,seuil_verification_solveur,secmem,nb_iter,converge, ok);
269 }
270 else
271 {
272 solveur->reinit();
273 DoubleTrav resu_temp(current); /* residu en increments */
274 if (eqn.has_interface_blocs()) /* if assembler_blocs is available */
275 {
276 if (eqn.discretisation().is_poly_family() || eqn.que_suis_je().debute_par("Equation_flux"))
277 {
278 eqn.assembler_blocs_avec_inertie({{ eqn.inconnue().le_nom().getString(), &matrice }}, resu_temp, { });
279 resu = resu_temp;
280 matrice.ajouter_multvect(current, resu);
281 }
282 else
283 {
284 eqn.assembler_blocs_avec_inertie({{ eqn.inconnue().le_nom().getString(), &matrice }}, resu, { });
285 resu_temp = 0;
286 matrice.ajouter_multvect(current,resu_temp);
287 resu_temp -= resu;
288 }
289
290 }
291 else
292 {
293 eqn.assembler_avec_inertie(matrice,current,resu);
294 resu_temp = 0;
295 matrice.ajouter_multvect(current,resu_temp);
296 resu_temp -= resu;
297 }
298
299 if (seuil_test_preliminaire_solveur>0)
300 {
301 double norme_b=mp_norme_vect(resu_temp);
302 if (norme_b<seuil_test_preliminaire_solveur)
303 {
304 // GF the following test might be sensible?
305 // if ( nb_iter>1)
306 {
307 converge = 1;
308 Cout<<"Resolution of system is not necessary: "<< norme_b <<" < "<< seuil_test_preliminaire_solveur <<finl;
309 }
310 }
311 }
312 if (converge==0)
313 {
314 int con = 0;
315 while (con==0)
316 {
317 con = 1;
318 solveur.resoudre_systeme(matrice,resu,current);
319 if (eqn.positive_unkown())
320 for (int i = 0; i < current.dimension_tot(0); i++)
321 for (int j = 0; j < current.line_size(); j++)
322 current(i, j) = std::max(current(i, j), 0.);
323 ok = eqn.milieu().check_unknown_range(); //verify that the unknown is within the medium's bounds
324
325 if (ok)
326 {
327 resu_temp = 0;
328 matrice.ajouter_multvect(current,resu_temp);
329 resu_temp -= resu;
330 double norme_resu = mp_norme_vect(resu_temp) ;
331
332 if (norme_resu>seuil_verification_solveur) con = 0;
333 if (con==0)
334 {
335 Cout<<"Residu of iterative solving : "<<norme_resu<<" instead of "<<seuil_verification_solveur<<finl;
336 Cout<<"Iterating on the linear system again:"<< finl;
337 seuil_verification_solveur *= 2;
338 con = 0;
339 }
340 }
341 else current = eqn.inconnue().passe(); //if ok == 0, restore the previous value of the unknown
342 }
343 converge = 0;
344 }
345 }
346
347 ///////////////////////////////////////////////////////////////////////
348 // Convergence test of the solution between two successive iterations
349 // Not applied for the N_S unknown with the PISO and Implicit algorithm
350 ///////////////////////////////////////////////////////////////////////
351
352 if(!converge && ok)
353 {
354 // allows checking what happens
355 // in particular the positivity of K and eps
356 eqn.valider_iteration();
357 dudt -= current;
358 double dudt_norme = mp_norme_vect(dudt);
359 converge = (dudt_norme < seuil_convg);
360 if (!converge)
361 {
362 Cout<<eqn.que_suis_je()<<" is not converged at the implicit iteration "<<nb_iter<<" ( ||uk-uk-1|| = "<<dudt_norme<<" > implicit threshold "<<seuil_convg<<" )"<<finl;
363 if (nb_iter>=10) Cout << "Consider lowering facsec_max value. Look at the reference manual for advice to set facsec_max value according to the problem type." << finl;
364 }
365 else
366 Cout<<eqn.que_suis_je()<<" is converged at the implicit iteration "<<nb_iter<<" ( ||uk-uk-1|| = "<<dudt_norme<<" < implicit threshold "<<seuil_convg<<" )"<<finl;
367 }
368
369 if(ok && (eqn.discretisation().is_poly_family() || eqn.probleme().que_suis_je().debute_par("Pb_Multiphase"))) eqn.probleme().mettre_a_jour(eqn.schema_temps().temps_courant());
370 solveur->reinit();
371 return (ok && converge==1);
372}
373
374bool Simple::iterer_eqs(LIST(OBS_PTR(Equation_base)) eqs, int nb_iter, int& ok)
375{
376 // retrieve the linear system solver
378 SolveurSys& solveur = param.solveur();
379 double seuil_convg = param.seuil_convergence_implicite();
380 int i, j, bs = 0; //bs : common line size of arrays if > 0, 0 otherwise
381
382 /* key for memoization */
383 list_of_eq_ptr_t key(eqs.size());
384 for (i = 0; i < eqs.size(); i++) key[i] = (intptr_t) &eqs[i].valeur();
385
386 int init = !mbloc.count(key); //first pass
387 Matrice_Bloc& Mglob = mbloc[key];
388
389 if (init)
390 for (Mglob.dimensionner(eqs.size(), eqs.size()), i = 0; i < eqs.size(); i++)
391 for (j = 0; j < eqs.size(); j++) Mglob.get_bloc(i, j).typer("Matrice_Morse");
392
393 /* for interface_blocs: if all equations have this interface, we use it */
394 int interface_blocs_ok = 1;
395 for (i = 0; i < eqs.size(); i++) interface_blocs_ok &= eqs[i]->has_interface_blocs();
396 std::vector<matrices_t> mats(eqs.size()); //matrix row for equation i
397 for (i = 0; i < eqs.size(); i++)
398 for (j = 0; j < eqs.size(); j++)
399 {
400 Nom nom_i = eqs[j]->inconnue().le_nom();
401 // field from another problem: add a suffix
402 if (eqs[i]->probleme().le_nom().getString() != eqs[j]->probleme().le_nom().getString()) nom_i += Nom("/") + eqs[j]->probleme().le_nom();
403 mats[i][nom_i.getString()] = &ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur());
404 }
405
406 //Do the unknowns/residuals have the same shape?
407 for (bs = eqs[0]->inconnue().valeurs().line_size(), i = 1; i < eqs.size(); i++)
408 if (eqs[i]->inconnue().valeurs().line_size() != bs) bs = 0;
409
410 //MD_Vector global
411 MD_Vector_composite mdc; //version composite
412 for (i = 0; i < eqs.size(); i++)
413 mdc.add_part(eqs[i]->inconnue().valeurs().get_md_vector(), bs ? 0 : eqs[i]->inconnue().valeurs().line_size());
414 MD_Vector mdv;
415 mdv.copy(mdc);
416
417 if (init) //first pass -> sizing of MD_Vector and matrices
418 {
419 /* dimensionnement de la matrice globale */
420 if (interface_blocs_ok)
421 for (i = 0; i < eqs.size(); i++)
422 for (eqs[i]->dimensionner_blocs(mats[i], {}), j = 0; j < eqs.size(); j++)
423 {
424 Matrice_Morse& mat = ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur());
425 if (!mat.nb_colonnes())
426 mat.dimensionner(eqs[i]->inconnue().valeurs().size_totale(), eqs[j]->inconnue().valeurs().size_totale(), 0);
427 }
428 else for (i = 0; i < eqs.size(); i++)
429 for (j = 0; j < eqs.size(); j++)
430 {
431 Matrice_Morse& mat = ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur()), mat2;
432 int nl = eqs[i]->inconnue().valeurs().size_totale(), nc = eqs[j]->inconnue().valeurs().size_totale();
433 if (i == j) eqs[i]->dimensionner_matrice(mat);
434 eqs[i]->dimensionner_termes_croises(i == j ? mat2 : mat, eqs[j]->probleme(), nl, nc);
435 if (i == j) mat += mat2;
436 }
437 }
438 else for (i = 0; i < eqs.size(); i++)
439 for (j = 0; j < eqs.size(); j++) //subsequent passes -> just reallocate the coeff() arrays
440 {
441 Matrice_Morse& mat = ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur());
442 mat.get_set_coeff().resize(mat.get_set_tab2().size_array());
443 }
444
445 //work arrays
446 DoubleTrav inconnues, residus, dudt;
447 if (bs) inconnues.resize(0, bs), residus.resize(0, bs), dudt.resize(0, bs); //so that aggregated arrays have the correct line_size() if it exists
451 DoubleTab_parts residu_parts(residus), inconnues_parts(inconnues), dudt_parts(dudt);
452
453 //fill unknowns
454 for(i = 0; i < eqs.size(); i++) inconnues_parts[i] = eqs[i]->inconnue().valeurs();
455 dudt = inconnues;
456
457 //fill matrices
458 if (interface_blocs_ok)
459 {
460 for (i = 0; i < eqs.size(); i++)
461 {
462 eqs[i]->assembler_blocs_avec_inertie(mats[i], residu_parts[i], {});
463 if (!eqs[i]->discretisation().is_poly_family())
464 {
465 for (j = 0; j < eqs.size(); j++)
466 {
467 Nom nom_j = eqs[j]->inconnue().le_nom();
468 if (eqs[i]->probleme().le_nom().getString() != eqs[j]->probleme().le_nom().getString())
469 {
470 nom_j += Nom("/") + eqs[j]->probleme().le_nom();
471 mats[i][nom_j.getString()]->ajouter_multvect(inconnues_parts[j], residu_parts[i]);
472 }
473 }
474 }
475 }
476 if (eqs[0]->discretisation().is_poly_family()) Mglob.ajouter_multvect(inconnues, residus); //to avoid solving in increments
477 }
478 else for(i = 0; i < eqs.size(); i++)
479 for (j = 0; j < eqs.size(); j++)
480 {
481 Matrice_Morse& mat = ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur());
482 eqs[i]->ajouter_termes_croises(inconnues_parts[i], eqs[j]->probleme(), inconnues_parts[j], residu_parts[i]);
483 eqs[i]->contribuer_termes_croises(inconnues_parts[i], eqs[j]->probleme(), inconnues_parts[j], mat);
484 /* if i == j, then assembler_avec_inertie() handles the matrix/vector product: otherwise it must be done manually */
485 if (i == j) eqs[i]->assembler_avec_inertie(mat, inconnues_parts[i], residu_parts[i]);
486 else mat.ajouter_multvect(inconnues_parts[j], residu_parts[i]);
487 }
488
489 // resolution
490 solveur->reinit();
491 solveur.resoudre_systeme(Mglob, residus, inconnues);
492 inconnues.echange_espace_virtuel();
493
494 // update
495 // Optimization: combine N mp_norme_vect into 1 collective call
496 // First pass: compute local squared norms
497 ArrOfDouble dudt_carres((int)eqs.size());
498 for(i = 0; i < eqs.size(); i++)
499 {
500 dudt_parts[i] -= inconnues_parts[i];
501 dudt_carres[(int)i] = local_carre_norme_vect(dudt_parts[i]);
502 }
503 // Single MPI reduction for all norms
505 // Second pass: use the norms and do updates
506 bool converge = true;
507 for(i = 0; i < eqs.size(); i++)
508 {
509 double dudt_norme = sqrt(dudt_carres[(int)i]);
510 eqs[i]->inconnue().valeurs() = inconnues_parts[i];
511
512 converge &= (dudt_norme < seuil_convg);
513 if (!converge)
514 {
515 Cout<<eqs[i]->que_suis_je()<<" is not converged at the implicit iteration "<<nb_iter<<" ( ||uk-uk-1|| = "<<dudt_norme<<" > implicit threshold "<<seuil_convg<<" )"<<finl;
516 if (nb_iter>=10) Cout << "Consider lowering facsec_max value. Look at the reference manual for advice to set facsec_max value according to the problem type." << finl;
517 }
518 else
519 Cout<<eqs[i]->que_suis_je()<<" is converged at the implicit iteration "<<nb_iter<<" ( ||uk-uk-1|| = "<<dudt_norme<<" < implicit threshold "<<seuil_convg<<" )"<<finl;
520 eqs[i]->inconnue().futur() = eqs[i]->inconnue().valeurs();
521 const double t = eqs[i]->schema_temps().temps_courant() + eqs[i]->schema_temps().pas_de_temps();
522 eqs[i]->domaine_Cl_dis().imposer_cond_lim(eqs[i]->inconnue(), t);
523 eqs[i]->inconnue().valeurs() = eqs[i]->inconnue().futur();
524 eqs[i]->inconnue().Champ_base::changer_temps(t);
525 }
526 for(i = 0; i < eqs.size(); i++) eqs[i]->probleme().mettre_a_jour(eqs[i]->schema_temps().temps_courant());
527
528 //deallocate the coefficient arrays
529 for (i = 0; i < eqs.size(); i++)
530 for (j = 0; j < eqs.size(); j++) ref_cast(Matrice_Morse, Mglob.get_bloc(i, j).valeur()).get_set_coeff().reset();
531
532 return converge;
533}
534
535void Simple::calculer_correction_en_vitesse(const DoubleTrav& correction_en_pression,DoubleTrav& gradP,DoubleTrav& correction_en_vitesse,const Matrice_Morse& matrice,const Operateur_Grad& gradient)
536{
537 int deux_entrees = 0;
538 if (correction_en_vitesse.nb_dim()==2) deux_entrees = 1;
539 gradient->multvect(correction_en_pression,gradP);
540 int nb_comp = 1;
541 if(deux_entrees)
542 nb_comp = correction_en_vitesse.dimension(1);
543
544 ConstDoubleTab_parts part(correction_en_vitesse);
545 int nb_ligne_reel = part[0].dimension(0);
546 if (deux_entrees==0)
547 {
548 // D(Uk-1)^-1 resu
549 int i,j;
550 for(i=0; i<nb_ligne_reel; i++)
551
552 for (j=0; j<nb_comp; j++)
553 {
554 //k=tab1(i*nb_comp+j)-1;
555 correction_en_vitesse(i) = -gradP(i)/matrice(i*nb_comp+j,i*nb_comp+j);
556 }
557 }
558 else
559 {
560 int i,j;
561 for(i=0; i<nb_ligne_reel; i++)
562 for (j=0; j<nb_comp; j++)
563 {
564 //k = tab1(i*nb_comp+j)-1;
565 correction_en_vitesse(i,j) = -gradP(i,j)/matrice(i*nb_comp+j,i*nb_comp+j);
566 }
567 }
568 correction_en_vitesse.echange_espace_virtuel();
569}
570
571
572//Input: Uk-1 ; Pk-1
573//Output: Uk ; Pk
574//k denotes an iteration
575
576void Simple::iterer_NS(Equation_base& eqn,DoubleTab& current,DoubleTab& pression,
577 double dt,Matrice_Morse& matrice,double seuil_resol,DoubleTrav& secmem,int nb_ite,int& converge, int& ok)
578{
580 SolveurSys& solveur = param.solveur();
581
582 Navier_Stokes_std& eqnNS = ref_cast(Navier_Stokes_std,eqn);
584 DoubleTrav gradP(current);
585 DoubleTrav correction_en_pression(pression);
586 DoubleTrav correction_en_vitesse(current);
587 DoubleTrav resu(current);
588 int is_dilat = eqn.probleme().is_dilatable();
589
590 //int deux_entrees = 0;
591 //if (current.nb_dim()==2) deux_entrees = 1;
592 Operateur_Grad& gradient = eqnNS.operateur_gradient();
593 Operateur_Div& divergence = eqnNS.operateur_divergence();
594
595 /* int nb_comp = 1;
596 int nb_dim = current.nb_dim();
597 if (nb_dim==2)
598 nb_comp = current.dimension(1);
599 */
600
601 gradient.calculer(pression,gradP);
602 //Build matrix and residual
603 //matrice = A[Uk-1] = M/dt + CONV + DIFF
604 //resu = A[Uk-1]Uk-1 -(A[Uk-1]Uk-1-Ss) + Sv + (M/dt)Uk-1 -BtPk-1
605 if (eqnNS.has_interface_blocs()) //if the interface_blocs is available, use it
606 eqnNS.assembler_blocs_avec_inertie({{ "vitesse", &matrice }}, resu);
607 else //otherwise, go through ajouter/contribuer
608 {
609 resu -= gradP;
610 eqnNS.assembler_avec_inertie(matrice,current,resu);
611 }
612
613 solveur->reinit();
614
615 //Solve the system A[Uk-1]U* = -BtP* + Sv + Ss + (M/dt)Uk-1
616 //current = U*
617 solveur.resoudre_systeme(matrice,resu,current);
618
619 //Velocity field relaxation U*
620 //U* = alpha U*_new + (1-alpha)*U*_old
621 if (nb_ite==1)
622 Ustar_old = current;
623 current *= alpha_ ;
624 current.ajoute(1.-alpha_,Ustar_old);
625 current.echange_espace_virtuel();
626 Ustar_old = current;
627
628 //Build matrice_en_pression_2 = BD-1Bt[Uk-1]
629 Matrice& matrice_en_pression_2 = eqnNS.matrice_pression();
630 assembler_matrice_pression_implicite(eqnNS,matrice,matrice_en_pression_2);
631 SolveurSys& solveur_pression_ = eqnNS.solveur_pression();
632 solveur_pression_->reinit();
633
634 //Compute secmem = BU* (incompressible) BU* -drho/dt (quasi-compressible)
635 if (is_dilat)
636 {
637 if (with_d_rho_dt_)
638 {
639 Fluide_Dilatable_base& fluide_dil = ref_cast(Fluide_Dilatable_base,eqn.milieu());
640 fluide_dil.secmembre_divU_Z(secmem);
641 secmem *= -1;
642 }
643 else secmem = 0;
644 divergence.ajouter(current,secmem);
645 }
646 else
647 divergence.calculer(current,secmem);
648 secmem *= -1;
649 secmem.echange_espace_virtuel();
650
651
652 //Solve the system (BD-1Bt)P' = BU* (incompressible)
653 // (BD-1Bt)P' = BU* -drho/dt (quasi-compressible)
654 //correction_en_pression = P'
655 solveur_pression_.resoudre_systeme(matrice_en_pression_2.valeur(),
656 secmem,correction_en_pression);
657
658 //Solve DU' = BP'
659 //correction_en_vitesse = U'
660 calculer_correction_en_vitesse(correction_en_pression,gradP,correction_en_vitesse,matrice,gradient);
661
662 //Pressure correction P = P* + beta_*P'
663 //Velocity correction U = U* + beta_u*U' (beta_u=1)
664
665 pression.ajoute(beta_,correction_en_pression);
666 eqnNS.assembleur_pression()->modifier_solution(pression);
667
668 current += correction_en_vitesse;
669
670 if (is_dilat)
671 diviser_par_rho_np1_face(eqn,current);
672}
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 bool is_poly_family() const
virtual void imposer_cond_lim(Champ_Inc_base &, double)=0
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Equation_base The role of an equation is the calculation of one or more fields....
virtual int equation_non_resolue() const
virtual void dimensionner_termes_croises(Matrice_Morse &matrice, const Probleme_base &autre_pb, int nl, int nc)
virtual void ajouter_termes_croises(const DoubleTab &inco, const Probleme_base &autre_pb, const DoubleTab &autre_inco, DoubleTab &resu) const
virtual const Milieu_base & milieu() const =0
virtual void assembler_blocs_avec_inertie(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={})
const Discretisation_base & discretisation() const
Returns the discretization associated with the equation.
virtual void valider_iteration()
virtual method to correct the unknown during implicit iterations for example K-eps must remain positi...
virtual const Champ_Inc_base & inconnue() const =0
virtual void contribuer_termes_croises(const DoubleTab &inco, const Probleme_base &autre_pb, const DoubleTab &autre_inco, Matrice_Morse &matrice) const
virtual void mettre_a_jour(double temps)
The value of the unknown at the time step has been calculated.
virtual void assembler_avec_inertie(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem)
virtual bool positive_unkown()
virtual DoubleTab & derivee_en_temps_inco(DoubleTab &)
Returns the time derivative of the unknown I of the equation: dI/dt = M-1*(sum(operators(I) + sources...
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.
virtual void dimensionner_matrice(Matrice_Morse &mat_morse)
virtual int has_interface_blocs() const
virtual double calculer_pas_de_temps() const
Calculation of the next time step.
const Nom & le_nom() const override
Returns the name of the field.
Base class for a dilatable fluid, inheriting from Fluide_base.
virtual void secmembre_divU_Z(DoubleTab &) const =0
const DoubleTab & rho_face_np1() const
Metadata for a distributed composite vector.
void add_part(const MD_Vector &part, int shape=0, Nom name="")
Append the "part" descriptor to the composite vector.
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Transforms v into a parallel array having the structure md.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
void copy(const MD_Vector_base &)
Constructs an MD_Vector object by copying an existing object.
Definition MD_Vector.cpp:26
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Matrix-vector multiply-accumulate operation (saxpy).
virtual void dimensionner(int N, int M)
virtual const Matrice & get_bloc(int i, int j) const
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
auto & get_set_tab2()
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
auto & get_set_coeff()
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
Matrice class - Generic class in the matrix hierarchy.
Definition Matrice.h:34
virtual int check_unknown_range() const
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:319
Navier_Stokes_std This class carries the terms of the momentum equation.
Operateur_Div & operateur_divergence()
Returns the divergence operator associated with the equation.
Operateur_Grad & operateur_gradient()
Returns the gradient operator associated with the equation.
int has_interface_blocs() const override
void reassembler_pression_si_necessaire()
Matrice & matrice_pression()
SolveurSys & solveur_pression()
Returns the pressure solver (const version).
Champ_Inc_base & pression()
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
virtual int debute_par(const char *const n) const
Definition Nom.cpp:314
const std::string & getString() const
Definition Nom.h:92
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Objet_U.cpp:317
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Operateur_Div Generic class of the hierarchy of operators computing the divergence.
Classe Operateur_Grad Generic class of the hierarchy of operators computing the gradient.
class Parametre_implicite A Parametre_implicite object groups together the various
double & seuil_verification_solveur()
double & seuil_diffusion_implicite()
int equation_frequence_resolue(double t)
double & seuil_convergence_implicite()
double & seuil_test_preliminaire_solveur()
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
bool is_dilatable() const
virtual void mettre_a_jour(double temps)
Performs a time update of the problem.
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:194
SETS scheme (semi-implicit + stabilisation steps, TRACE-style).
Definition SETS.h:35
class Schema_Temps_base
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).
double seuil_diffusion_implicite() const
int nb_pas_dt() const
Returns the number of time steps performed.
double & set_seuil_diffusion_implicite()
std::map< list_of_eq_ptr_t, Matrice_Bloc > mbloc
Definition Simple.h:75
double beta_
Definition Simple.h:80
int with_d_rho_dt_
Definition Simple.h:81
void iterer_NS(Equation_base &, DoubleTab &current, DoubleTab &pression, double, Matrice_Morse &, double, DoubleTrav &, int nb_iter, int &converge, int &ok) override
Definition Simple.cpp:576
double alpha_
Definition Simple.h:80
Entree & lire(const Motcle &, Entree &) override
Definition Simple.cpp:56
DoubleTab Ustar_old
Definition Simple.h:79
bool iterer_eqs(LIST(OBS_PTR(Equation_base)) eqs, int compteur, int &ok) override
Definition Simple.cpp:374
void calculer_correction_en_vitesse(const DoubleTrav &correction_en_pression, DoubleTrav &gradP, DoubleTrav &correction_en_vitesse, const Matrice_Morse &matrice, const Operateur_Grad &gradient)
Definition Simple.cpp:535
Simple()
Definition Simple.cpp:38
std::vector< intptr_t > list_of_eq_ptr_t
Definition Simple.h:74
bool iterer_eqn(Equation_base &equation, const DoubleTab &inconnue, DoubleTab &result, double dt, int numero_iteration, int &ok) override
Definition Simple.cpp:177
Entree & lire(const Motcle &, Entree &) override
void assembler_matrice_pression_implicite(Equation_base &eqn_NS, const Matrice_Morse &matrice, Matrice &matrice_en_pression_2)
class SolveurSys A SolveurSys represents any class
Definition SolveurSys.h:32
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
Parametre_implicite & get_and_set_parametre_implicite(Equation_base &eqn)
Base class for output streams.
Definition Sortie.h:52
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
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_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
void ajoute(_SCALAR_TYPE_ alpha, const TRUSTVect &y, Mp_vect_options opt=VECT_ALL_ITEMS)
Definition TRUSTVect.tpp:52
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")