TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Solv_Optimal.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#include <Solv_Optimal.h>
16#include <Param.h>
17#include <LecFicDistribueBin.h>
18#include <LecFicDiffuse.h>
19#include <Matrice_Bloc.h>
20#include <Matrice_Morse_Sym.h>
21#include <SFichier.h>
22#include <petsc_for_kernel.h>
23#undef setbit // Car sinon conflit avec Petsc
24#include <MD_Vector_tools.h>
25#include <Perf_counters.h>
26
27Implemente_instanciable(Test_solveur,"Test_solveur",Interprete);
28// XD test_solveur interprete test_solveur BRACE To test several solvers
29// XD attr fichier_secmem chaine fichier_secmem OPT Filename containing the second member B
30// XD attr fichier_matrice chaine fichier_matrice OPT Filename containing the matrix A
31// XD attr fichier_solution chaine fichier_solution OPT Filename containing the solution x
32// XD attr nb_test entier nb_test OPT Number of tests to measure the time resolution (one preconditionnement)
33// XD attr impr rien impr OPT To print the convergence solver
34// XD attr solveur solveur_sys_base solveur OPT To specify a solver
35// XD attr fichier_solveur chaine fichier_solveur OPT To specify a file containing a list of solvers
36// XD attr genere_fichier_solveur floattant genere_fichier_solveur OPT To create a file of the solver with a threshold
37// XD_CONT convergence
38// XD attr seuil_verification floattant seuil_verification OPT Check if the solution satisfy ||Ax-B||<precision
39// XD attr pas_de_solution_initiale rien pas_de_solution_initiale OPT Resolution isn\'t initialized with the solution x
40// XD attr ascii rien ascii OPT Ascii files
41
42Implemente_instanciable_sans_constructeur_ni_destructeur(Solv_Optimal,"Solv_Optimal",solv_iteratif);
43// XD optimal solveur_sys_base optimal BRACE Optimal is a solver which tests several solvers of the previous list to
44// XD_CONT choose the fastest one for the considered linear system.
45// XD attr seuil floattant seuil REQ Convergence threshold
46// XD attr impr rien impr OPT To print the convergency of the fastest solver
47// XD attr quiet rien quiet OPT To disable printing of information
48// XD attr save_matrice|save_matrix rien save_matrice OPT To save the linear system (A, x, B) into a file
49// XD attr frequence_recalc entier frequence_recalc OPT To set a time step period (by default, 100) for re-checking the
50// XD_CONT fatest solver
51// XD attr nom_fichier_solveur chaine nom_fichier_solveur OPT To specify the file containing the list of the tested
52// XD_CONT solvers
53// XD attr fichier_solveur_non_recree rien fichier_solveur_non_recree OPT To avoid the creation of the file containing
54// XD_CONT the list
55
57{
58 return s;
59}
60
62{
63 return is;
64}
65
66void test_un_solveur(SolveurSys& solveur, const Matrice_Base& matrice, const DoubleVect& secmem, DoubleVect& solution, int nmax, ArrOfDouble& temps, double seuil_verification=DMAXFLOAT)
67{
68 DoubleVect solution_ref(solution);
69 int n=temps.size_array();
70 statistics().create_custom_counter("Custom solver",1);
71 for (int i=0; i<n; i++)
72 {
73 solution=solution_ref;
74
75 // etape de resolution
76 statistics().begin_count("Custom solver",statistics().get_last_opened_counter_level()+1);
77 double t_0,t;
78 t_0 = statistics().get_total_time("Custom solver");
79 Cout<<"------------------------------------"<<finl;
80 Cout<<"Try " << i << " of solver " << solveur <<finl;
81 //solveur->fixer_limpr(0);
82 solveur.nommer("test_solver");
83
84 solveur.resoudre_systeme(matrice,secmem,solution);
85 t = statistics().get_time_since_last_open("Custom solver");
86 statistics().end_count("Custom solver");
87 // on recupere un delta time et non un time absolu !!
88 DoubleVect test(secmem);
89 test*=-1;
90 matrice.ajouter_multvect(solution,test);
91 //test-=secmem;
92 double norme=mp_norme_vect(test);
93 double time_resol = t-t_0;
94 Cout<<"CPU= " <<time_resol<<" s , ||Ax -b||= " << norme << finl;
96 temps[i]=Process::mp_max(time_resol);
97
98 if (norme>seuil_verification)
99 {
100 Cerr<<"residue calculated greater than the threshold value indicated ("<<seuil_verification<<")"<<finl;
101 Cerr<<" one will not use the solver "<<solveur<<finl;
102 temps=1.e37;
103 }
104 }
105}
106int test_solveur(SolveurSys& solveur, const Matrice_Base& matrice , const DoubleVect& secmem , DoubleVect& solution , int nmax, ArrOfDouble& temps, Entree& list_solveur, double seuil_verification=DMAXFLOAT)
107{
108 DoubleVect solution_ref(solution);
109 int numero=0,numero_best=-1;
110 double best_time=1e36;
111 Motcle motsolveur("solveur"),motlu;
112 list_solveur >> motlu;
113 int dernier=temps.size_array()-1;
114 while (list_solveur.good())
115 {
116 if (motlu!=motsolveur)
117 {
118 Cerr<<" One expected "<<motsolveur <<" and not "<<motlu<<finl;
120 }
121 numero++;
122 SolveurSys newsolveur;
123 list_solveur>>newsolveur;
124 solution=solution_ref;
125 test_un_solveur(newsolveur, matrice, secmem ,solution, nmax, temps, seuil_verification);
126 if (temps[dernier]<best_time)
127 {
128 solveur=newsolveur;
129 best_time=temps[dernier];
130 numero_best=numero;
131 }
132 list_solveur>>motlu;
133 }
134 if (numero_best==-1)
135 {
136 Cerr<<" None of the tested solvers give the expected residue" <<finl;
137 Cerr<< " does the same solver must be kept ? "<<finl;
138 // exit();
139 }
140 temps=best_time;
141 return numero_best;
142}
143/*! @brief genere un fichier de solveur a tester different selon si la matrice peut etre resolue avec ou sans GCP
144 *
145 */
146void generate_defaut(const Matrice_Base& matrice, const double seuil, Sortie& sortie, int limpr=0)
147{
148 Nom impr(" impr " );
149 if (limpr==0) impr=" ";
150 if (limpr==-1) impr=" quiet ";
152 {
153 if((!sub_type(Matrice_Morse_Sym,matrice))&&(!sub_type(Matrice_Bloc,matrice)))
154 {
155 sortie <<" solveur gmres { diag seuil "<<seuil <<" "<<impr<<"}"<<finl;
156#ifdef __PETSCKSP_H
157 sortie <<" solveur petsc bicgstab { precond diag { } seuil "<<seuil <<" "<<impr<<"}"<<finl;
158#endif
159 }
160 else
161 {
162 // on a une matrice de type pression (?)
163 // Mise a jour des solveurs testes 24/05/2012
164 sortie <<" solveur gcp { precond ssor { omega 1.6 } seuil "<<seuil <<" "<<impr<<"}"<<finl;
165#ifdef __PETSCKSP_H
166 sortie <<" solveur petsc gcp { precond ssor { omega 1.6 } seuil "<<seuil <<" "<<impr<<"}"<<finl;
167 if (Process::nproc()<512)
168 sortie <<" solveur petsc cholesky { impr }"<< finl;
169 else
170 {
171 // Pour les tres grands calculs on bascule de Cholesky a BICGSTAB ILU_SP(1) par bloc
172 sortie <<" solveur petsc bicgstab { precond block_jacobi_icc { level 1 } seuil "<<seuil <<" "<<impr<<"}"<<finl;
173 // Voire CG ILU_SP(1) par bloc car BICGSTAB peut avoir du mal a converger lors de la projection initiale...
174 sortie <<" solveur petsc gcp { precond block_jacobi_icc { level 1 } seuil "<<seuil <<" "<<impr<<"}"<<finl;
175 }
176 // SPAI n'a jamais fait ses preuves (comme tous les preconditionnements de Hypre), on l'enleve
177 //sortie <<" solveur petsc gcp { precond spai { level 2 epsilon 0.2 } seuil "<<seuil <<" "<<impr<<"}"<<finl;
178#endif
179 }
180 }
181}
183{
184 Matrice matrice;
185 DoubleVect secmem,solution;
186 Nom fichier_secmem("Secmem.sa");
187 Nom fichier_solution("Solution.sa");
188 Nom fichier_matrice("Matrice.sa");
189 Nom fichier_solveur;
190 bool pas_de_solution_init=false;
191 bool ascii = false;
192 bool limpr_ = false;
193 double seuil_verification=DMAXFLOAT;
194 SolveurSys solveur;
195 double seuil_list=0;
196 int nb_test=2; // On teste 2 fois un solveur car la premiere fois, le cout du preconditionnement peut penaliser
197 Param param((*this).que_suis_je());
198 param.ajouter("fichier_secmem",&fichier_secmem); // nom du fichier contenant le second membre (Secmem.sa par defaut)
199 param.ajouter("fichier_matrice",&fichier_matrice); // nom du fichier contenant la matrice (Matrice.sa par defaut)
200 param.ajouter("fichier_solution",&fichier_solution); // nom du fichier contenant la solution (Solution.sa par defaut)
201 param.ajouter("nb_test",&nb_test); // nb de resolution pour mesurer le temps (un seul preconditionnemt)
202 param.ajouter_flag("impr",&limpr_); // impr des solveurs
203 param.ajouter("solveur",&solveur); // pour specifier un solveur
204 param.ajouter("fichier_solveur",&fichier_solveur); // pour specifier un fichier contenant des solveurs
205 param.ajouter("genere_fichier_solveur",&seuil_list); // genere le fichier de solveur avec un seuil donne
206 param.ajouter("seuil_verification",&seuil_verification); // verifie si la soulution trouvee par la resolution est telle que Ax -b < seuil_verification
207 param.ajouter_flag("pas_de_solution_initiale",&pas_de_solution_init); // pas_de_solution_initiale : on n'initialise pas la resolution avec la solution
208 param.ajouter_flag("ascii",&ascii); // dans le cas ou les fichiers sont ascii
210 int binaire=1;
211 if (ascii)
212 binaire=0;
213 // On relit la matrice et le secmem
214 {
215 LecFicDistribue entree;
216 entree.set_bin(binaire);
217 entree.ouvrir(fichier_matrice);
218 entree>>matrice;
219 Cout<<" size of system "<<matrice.valeur( ).nb_colonnes()<<finl;
220 //matrice->imprimer_formatte(Cout);
221 }
222 {
223 LecFicDistribue entree;
224 entree.set_bin(binaire);
225 entree.ouvrir(fichier_secmem);
227 Cout<<" size of system "<<secmem.size_totale()<<finl;
228 }
229
230
231 if (pas_de_solution_init)
232 {
233 solution=secmem;
234 solution=0.;
235 }
236 else
237 {
238 LecFicDistribue entree;
239 entree.set_bin(binaire);
240 entree.ouvrir(fichier_solution);
241
243 Cout<<" size of system "<<solution.size_totale()<<finl;
244 solution.set_md_vector(secmem.get_md_vector());
245 }
246
247 if (seuil_list!=0)
248 {
249 if (fichier_solveur==Nom())
250 fichier_solveur="list_solveur";
251 if (je_suis_maitre())
252 {
253 SFichier list_solveur(fichier_solveur);
254 generate_defaut(matrice,seuil_list,list_solveur,limpr_);
255 }
256 }
257
258 secmem.echange_espace_virtuel();
259 solution.echange_espace_virtuel();
260 ArrOfDouble temps(nb_test);
261 if (fichier_solveur==Nom())
262 test_un_solveur(solveur, matrice , secmem , solution , -10, temps,seuil_verification);
263 else
264 {
265 LecFicDiffuse list_solveur(fichier_solveur);
266 int numero_best=test_solveur(solveur, matrice , secmem , solution , -10, temps,list_solveur,seuil_verification);
267 Cout <<"------------------------------------------------"<<finl;
268 Cout <<"Best solver : number "<<numero_best<<" "<<solveur<<finl;
269 Cout <<"Best CPU time = "<<temps[0]<<finl;
270 Cout <<"------------------------------------------------"<<finl;
271 }
272 return is;
273}
274
275static int numero_solv_optimal=0; // numero du solveur pour avoir des noms de fichiers solveurs par defaut differents pour chaque solveur
276Solv_Optimal::Solv_Optimal():n_resol_(0),n_reinit_(0)
277{
278 freq_recalc_ = (int)(pow(2.0,(double)((sizeof(int)*8)-1))-1);
279 freq_recalc_ = 100;
280 fichier_solveur_="solveurs_";
281 fichier_solveur_+=Nom(numero_solv_optimal);
282 numero_solv_optimal++;
283
284}
285Solv_Optimal::~Solv_Optimal()
286{
287 if (le_solveur_) Cerr<<" The solver used by Solv_Optimal was "<<le_solveur_<<finl;
288}
290{
291 return s;
292}
293
295{
296 bool impr = false;
297 bool quiet = false;
298 Param param((*this).que_suis_je());
299 param.ajouter("seuil",&seuil_,Param::REQUIRED); // seuil de resolution
300 param.ajouter_flag("impr",&impr); // active impression des solveurs
301 param.ajouter_flag("quiet",&quiet);
302 param.ajouter("save_matrice|save_matrix",&save_matrice_); // pour sauvegarder A,x,b
303 param.ajouter("frequence_recalc",&freq_recalc_); // frequence pour reevaluer le solveur optimal
304 param.ajouter("nom_fichier_solveur",&fichier_solveur_); //nom du fichier contenant les solveurs testes
305 param.ajouter_flag("fichier_solveur_non_recree",&fichier_solveur_non_recree_); // si flag mis alors le fichier n'est pas cree au debut du calcul
306 param.lire_avec_accolades_depuis(is);
307 fixer_limpr(impr);
308 if (quiet)
309 fixer_limpr(-1);
310
311 return is;
312}
313
314/*! @brief methode clef de Solv_Optimal a la premiere iteration
315 *
316 * genere le fichier fichier_solveur_ contenant la liste des solveurs a tester
317 * prend le premier solveur du fichier
318 * A la 3 ite et avec la frequence freq_recalc_ cherche le solveur le + rapide, en prenant en compte le fait que la matrice a change ou non
319 * appel test_solveur
320 *
321 */
322void Solv_Optimal::prepare_resol(const Matrice_Base& matrice, const DoubleVect& secmem, DoubleVect& solution, int nmax)
323{
324 if (n_resol_==0)
325 {
326 // premiere chose on genere le fichier par defaut, puis on cree le solveur avec le premier du fichier
327
329 {
330 SFichier list_solveur(fichier_solveur_);
331 generate_defaut(matrice,seuil_,list_solveur,limpr());
332 }
333 LecFicDiffuse list_solveur2(fichier_solveur_);
334 Nom mot;
335 list_solveur2>>mot;
336 list_solveur2>>le_solveur_;
337 }
338 // OK
339 n_resol_++;
340 if ((n_resol_>=3)&&((n_resol_-3)%freq_recalc_==0))
341 {
342 LecFicDiffuse list_solveur(fichier_solveur_);
343 int nb_ite;
344 if (n_reinit_<2)
345 nb_ite=2; // Matrice constante (on resout 2 fois pour ne retenir que le 2eme temps exempt d'eventuel preconditionnement)
346 else
347 nb_ite=1; // Matrice non constante (on resout 1 seul fois)
348 ArrOfDouble temps(nb_ite);
349 statistics().end_count(STD_COUNTERS::system_solver,0,0);
350 int numero_best=test_solveur(le_solveur_, matrice , secmem , solution , nmax, temps,list_solveur,seuil_);
351 statistics().begin_count(STD_COUNTERS::system_solver,statistics().get_last_opened_counter_level()+1);
352 Cout <<"------------------------------------------------"<<finl;
353 Cout <<"Best solver : number "<<numero_best<<" "<<le_solveur_<<finl;
354 Cout <<"Best CPU time = "<<temps[0]<<finl;
355 Cout <<"------------------------------------------------"<<finl;
356 if (je_suis_maitre())
357 {
358 Nom best("best_");
359 best+=fichier_solveur_;
360 SFichier sf(best);
361 sf << le_solveur_ <<finl;
362 }
363 }
364}
365int Solv_Optimal::resoudre_systeme(const Matrice_Base& matrice, const DoubleVect& secmem, DoubleVect& solution)
366{
367 prepare_resol(matrice,secmem,solution,-20);
368 return le_solveur_->resoudre_systeme( matrice, secmem, solution);
369}
370int Solv_Optimal::resoudre_systeme(const Matrice_Base& matrice, const DoubleVect& secmem, DoubleVect& solution, int nmax)
371{
372 prepare_resol(matrice,secmem,solution, nmax);
373 return le_solveur_->resoudre_systeme( matrice, secmem, solution, nmax );
374}
375
376
378{
379 n_reinit_++;
380 if (le_solveur_)
381 le_solveur_->reinit();
382}
383
384
385
386
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int good()
Definition Entree.cpp:270
void set_bin(bool bin) override
Change le mode d'ecriture du fichier.
Definition Entree.cpp:291
Classe de base des objets "interprete".
Definition Interprete.h:38
Cette classe implemente les operateurs et les methodes virtuelles de la classe EFichier de la facon s...
Cette classe implemente les operateurs et les methodes virtuelles de la classe EFichier de la facon s...
int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::in) override
Ouvre le fichier avec les parametres mode et prot donnes Ces parametres sont les parametres de la met...
static void restore_vector_with_md(DoubleVect &, Entree &)
restores a vector saved by dump_vector_with_md.
Classe Matrice_Base Classe de base de la hierarchie des matrices.
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Operation de multiplication-accumulation (saxpy) matrice vecteur.
Classe Matrice_Morse_Sym Represente une matrice M (creuse) symetrique stockee au format Morse.
Classe Matrice Classe generique de la hierarchie des matrices.
Definition Matrice.h:34
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:76
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
int lire_avec_accolades_depuis(Entree &is)
Parse the parameter block { ... } from is.
Definition Param.cpp:32
static double mp_max(double)
Definition Process.cpp:376
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void imprimer_ram_totale(int all_process=0)
Definition Process.cpp:651
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
int resoudre_systeme(const Matrice_Base &, const DoubleVect &, DoubleVect &) override
SolveurSys le_solveur_
bool fichier_solveur_non_recree_
void reinit() override
void prepare_resol(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution, int nmax=100)
methode clef de Solv_Optimal a la premiere iteration
int limpr() const
void fixer_limpr(int l)
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)
void nommer(const Nom &nom) override
Definition SolveurSys.h:37
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
virtual void set_md_vector(const MD_Vector &)
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")
Entree & interpreter(Entree &) override