TrioCFD 1.9.8
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 // Voir Schema_Temps_base::limpr pour information sur 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 //On remet les parametres de diffusion implicite a leur ancienne valeur
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 // on calcule une fois la derivee pour avoir les flux bord
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 // Resolution implicite -par iterer_NS pour Navier_Stokes
249 // -...solveur.resoudre_systeme()... pour les autres equations
250 /////////////////////////////////////////////////////////////////////////////////////////
251
252 dudt = current; // pour pouvoir tester la convergence.
253 Matrice_Morse matrice;
254 if (!(sub_type(Navier_Stokes_std,eqn) && sub_type(SETS, *this))) //SETS et ICE gerent eux-memes leurs 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()) /* si assembler_blocs est disponible */
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 le test suivant est peut etre intelligent ?
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(); //verification que l'inconnue est dans les bornes du milieu
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(); //si ok == 0, on restaure la valeur passee de inco
342 }
343 converge = 0;
344 }
345 }
346
347 ///////////////////////////////////////////////////////////////////////
348 // Test de convergence de la solution entre deux iterations successives
349 // Pas applique pour l inconnue de N_S avec alorithme PISO et Implicite
350 ///////////////////////////////////////////////////////////////////////
351
352 if(!converge && ok)
353 {
354 // permet de controler ce qui se passe
355 // en particulier la positivite de K et de 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 // on recupere le solveur de systeme lineaire
378 SolveurSys& solveur = param.solveur();
379 double seuil_convg = param.seuil_convergence_implicite();
380 int i, j, bs = 0; //bs : linesize commune des tableaux si > 0, 0 sinon
381
382 /* cle pour la 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); //premier passage
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 /* pour interface_blocs : si toutes les equations ont cette interface, on l'utilise */
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()); //ligne de matrices de l'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 // champ d'un autre probleme : on ajoute un suffixe
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 //Les inconues/residus ont-ils la meme forme?
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) //1er passage -> dimensionnement des MD_Vector et des 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++) //passages suivantes -> il suffit de reallouer les tableaux coeff()
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 //tableaux de travail
446 DoubleTrav inconnues, residus, dudt;
447 if (bs) inconnues.resize(0, bs), residus.resize(0, bs), dudt.resize(0, bs); //pour que les tableaux aggreges aient la bonne line_size() si elle existe
451 DoubleTab_parts residu_parts(residus), inconnues_parts(inconnues), dudt_parts(dudt);
452
453 //remplissage des inconnues
454 for(i = 0; i < eqs.size(); i++) inconnues_parts[i] = eqs[i]->inconnue().valeurs();
455 dudt = inconnues;
456
457 //remplissage des 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); //pour ne pas resoudre en 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 /* si i == j, alors assembler_avec_inertie() se charge du produit matrice/vecteur : sinon, on doit le faire a la main */
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 // mise a jour
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 //on desalloue les tableaux de coeffs
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//Entree : Uk-1 ; Pk-1
573//Sortie Uk ; Pk
574//k designe une 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 //Construction de matrice et resu
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()) //si l'interface blocs est disponible, on l'utilise
606 eqnNS.assembler_blocs_avec_inertie({{ "vitesse", &matrice }}, resu);
607 else //sinon, on passe par ajouter/contribuer
608 {
609 resu -= gradP;
610 eqnNS.assembler_avec_inertie(matrice,current,resu);
611 }
612
613 solveur->reinit();
614
615 //Resolution du systeme A[Uk-1]U* = -BtP* + Sv + Ss + (M/dt)Uk-1
616 //current = U*
617 solveur.resoudre_systeme(matrice,resu,current);
618
619 //Relaxation du champ de vitesse 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 //Construction de 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 //Calcul de secmem = BU* (en incompressible) BU* -drho/dt (en 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 //Resolution du systeme (BD-1Bt)P' = BU* en incompressible
653 // (BD-1Bt)P' = BU* -drho/dt en quasi-compressible
654 //correction_en_pression = P'
655 solveur_pression_.resoudre_systeme(matrice_en_pression_2.valeur(),
656 secmem,correction_en_pression);
657
658 //Resolution de DU' = BP'
659 //correction_en_vitesse = U'
660 calculer_correction_en_vitesse(correction_en_pression,gradP,correction_en_vitesse,matrice,gradient);
661
662 //Correction de la pression P = P* + beta_*P'
663 //Correction de la vitesse 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
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 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
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
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
Renvoie la discretisation associee a l'equation.
virtual void valider_iteration()
methode virtuelle permettant de corriger l'onconnue lors d'iterations implicites par exemple K-eps do...
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)
La valeur de l'inconnue sur le pas de temps a ete calculee.
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()
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.
virtual void dimensionner_matrice(Matrice_Morse &mat_morse)
virtual int has_interface_blocs() const
virtual double calculer_pas_de_temps() const
Calcul du prochain pas de temps.
const Nom & le_nom() const override
Renvoie le nom du champ.
classe Fluide_Dilatable_base Cette classe represente un d'un fluide dilatable,
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)
transforme v en un tableau parallele ayant la structure md.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
void copy(const MD_Vector_base &)
construction d'un objet MD_Vector par copie d'un objet existant.
Definition MD_Vector.cpp:26
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Operation de multiplication-accumulation (saxpy) matrice vecteur.
virtual void dimensionner(int N, int M)
virtual const Matrice & get_bloc(int i, int j) const
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
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).
Classe Matrice Classe generique de la hierarchie des matrices.
Definition Matrice.h:34
virtual int check_unknown_range() const
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
Operateur_Div & operateur_divergence()
Renvoie l'operateur de calcul de la divergence associe a l'equation.
Operateur_Grad & operateur_gradient()
Renvoie l'operateur de calcul du gradient associe a l'equation.
int has_interface_blocs() const override
void reassembler_pression_si_necessaire()
Matrice & matrice_pression()
SolveurSys & solveur_pression()
Renvoie le solveur en pression (version const).
Champ_Inc_base & pression()
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual int debute_par(const char *const n) const
Definition Nom.cpp:319
const std::string & getString() const
Definition Nom.h:92
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur_Div Classe generique de la hierarchie des operateurs calculant la divergence
Classe Operateur_Grad Classe generique de la hierarchie des operateurs calculant le gradient.
classe Parametre_implicite Un objet Parametre_implicite est un objet regroupant les differentes
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
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
bool is_dilatable() const
virtual void mettre_a_jour(double temps)
Effectue une mise a jour en temps du probleme.
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
classe SETS (semi-implicite + etapes de stabilisation, a la TRACE)
Definition SETS.h:35
class Schema_Temps_base
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.
double seuil_diffusion_implicite() const
int nb_pas_dt() const
Renvoie le nombre de pas de temps effectues.
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 Un SolveurSys represente n'importe qu'elle classe
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)
Classe de base des flux de sortie.
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")