TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Solv_GCP_NS.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 <Solv_GCP_NS.h>
17#include <Matrice_Bloc_Sym.h>
18#include <TRUSTTab_parts.h>
19#include <Motcle.h>
20#include <Param.h>
21#include <Perf_counters.h>
22
23Implemente_instanciable(Solv_GCP_NS, "Solv_GCP_NS", solv_iteratif);
24// XD gcp_ns solv_gcp gcp_ns INHERITS_BRACE not_set
25// XD attr solveur0 solveur_sys_base solveur0 REQ Solver type.
26// XD attr solveur1 solveur_sys_base solveur1 REQ Solver type.
27
29{
30 return s;
31}
32
34{
35 Param param(que_suis_je());
36 set_param(param);
37 param.lire_avec_accolades_depuis(is);
38 return is;
39}
40
41void Solv_GCP_NS::set_param(Param& param) const
42{
43 param.ajouter_non_std("impr", (this));
44 param.ajouter("seuil", &seuil_);
45 param.ajouter_non_std("solveur0", (this));
46 param.ajouter_non_std("solveur1", (this));
47 param.ajouter("precond", &le_precond_);
48 param.ajouter_non_std("quiet", (this));
49}
50
52{
53 int retval = 1;
54
55 if (mot == "impr")
56 fixer_limpr(1);
57 else if (mot == "quiet")
58 fixer_limpr(-1);
59 else if (mot == "solveur0")
60 {
61 is >> solveur_poisson0;
62 solveur_poisson0.nommer("poisson_solver0");
63 }
64 else if (mot == "solveur1")
65 {
66 is >> solveur_poisson1;
67 solveur_poisson1.nommer("poisson_solver1");
68 }
69 else
70 retval = -1;
71
72 return retval;
73}
74
75static inline void corriger(DoubleVect& X, double alpha, double beta, const DoubleVect& X1, const DoubleVect& X0, int prems, int n)
76{
77 int sz = prems + n;
78 int i = 0;
79 for (; i < prems; i++)
80 X(i) += beta * X0(i);
81 for (; i < sz; i++)
82 X(i) += alpha * X1(i - prems);
83}
84
85static inline void injecter(const DoubleVect& X, DoubleVect& tmp, int prems, int n)
86{
87 int sz = prems + n;
88 for (int i = prems; i < sz; i++)
89 tmp(i) = X(i - prems);
90}
91static inline void extraire(DoubleVect& X, const DoubleVect& tmp, int prems, int n)
92{
93 int sz = prems + n;
94 for (int i = prems; i < sz; i++)
95 X(i - prems) = tmp(i);
96}
97
98inline void erreur()
99{
100 Cerr << "The dedicated solver GCP_NS can be used only for blocks symetric matrixes" << finl;
101 Cerr << "containing 2*2 blocks for VEF discretization P0+P1." << finl;
103}
104
105int Solv_GCP_NS::resoudre_systeme(const Matrice_Base& matrice, const DoubleVect& secmem, DoubleVect& solution, int niter_max)
106{
107 // A00 X0 + A01 X1 = F0
108 // A10 X0 + A11 X1 = F1
109 // X1 = A11^(-1) (F1 - A10 X0)
110 // X0 = (A00 -A01 A11^(-1) A10) (F0 - A01 A11^(-1) F1)
111 //
112 // Gradient conjugue sur ce systeme preconditionne par A00
113 //
114 //Cerr << "resoudre_systeme : secmem" << secmem << finl;
115
116 //int n = secmem.size();
117 assert(solution.size_totale() == secmem.size_totale());
118 const int n = secmem.size_totale();
119
120 const Matrice_Bloc_Sym& matbloc = ref_cast(Matrice_Bloc_Sym, matrice);
121 if (matbloc.nb_bloc_lignes() != 2 || matbloc.nb_bloc_colonnes() != 2)
122 erreur();
123
124 const Matrice_Base& A00 = matbloc.get_bloc(0, 0);
125 const Matrice_Base& A01 = matbloc.get_bloc(0, 1);
126 const Matrice_Base& A11 = matbloc.get_bloc(1, 1);
127 int n0 = A00.nb_lignes();
128 int n1 = A11.nb_lignes();
129 const trustIdType nmax_min = 100, nmaxmax=10000000;
130 trustIdType nmax0 = std::max(Process::mp_sum(n), nmax_min);
131 int nmax = static_cast<int>(std::min(nmax0, nmaxmax));
132 int niter = 0;
133 double dold, dnew, alfa;
134
135 solution = 0.0;
136 // Creation de tableaux distribues X1 et F1 sur les sommets
137 ConstDoubleTab_parts mo_solution(solution);
138 DoubleVect X1 = mo_solution[1];
139 // DoubleVect X1;
140 // champ.domaine().creer_tableau_sommets(X1);
141 DoubleVect F1(X1);
142 if (X1.size_totale() != n1)
143 erreur();
144
145 //DoubleVect resu(solution);
146
147 // Creation de tableaux distribues X0 et F0 sur les elements
148 //DoubleVect X0;
149 //champ.domaine().creer_tableau_elements(X0);
150 // ConstDoubleTab_parts mo_solution(solution);
151 DoubleVect X0 = mo_solution[0];
152 DoubleVect F0(X0);
153 if (X0.size_totale() != n0)
154 erreur();
155
156 //F0 :
157 extraire(F0, secmem, 0, n0);
158 DoubleVect residu(F0);
159 //F1 :
160 extraire(F1, secmem, n0, n1);
161 // X1 = A11^(-1) F1
162 solveur_poisson1.resoudre_systeme(A11, F1, X1);
163 injecter(X1, solution, n0, n1);
164 // F0=A01 X1
165 A01.multvect(X1, F0);
166 // residu=-F0+A01 X1
167 residu -= F0;
168 residu *= -1;
169 DoubleVect g(F0);
170 double norme = mp_norme_vect(residu);
171 if (le_precond_)
172 le_precond_->preconditionner(A00, residu, g);
173 else
174 solveur_poisson0.resoudre_systeme(A00, residu, g);
175
176 DoubleVect p(g);
177 p *= -1.;
178
179 dold = mp_prodscal(residu, g);
180 dnew = dold;
181 if (limpr() > -1)
182 Cout << "GCP NS residue = " << norme << " " << finl;
183 double s = 0;
184 while ((norme > seuil_) && (niter++ < nmax))
185 {
186 // F1=A10 p
188 A01.multvectT(p, F1);
189 // X1=-A11^(-1) A10p
190 if ((limpr() == 1) && (je_suis_maitre()))
191 Cout << "Solveur1: ";
192 solveur_poisson1.resoudre_systeme(A11, F1, X1);
193 X1 *= -1.;
194 //F0=(A00 -A01 A11^(-1) A10) p
196 A01.multvect(X1, F0);
197 A00.ajouter_multvect(p, F0);
198 s = mp_prodscal(F0, p);
199 alfa = dold / (s);
200 corriger(solution, alfa, alfa, X1, p, n0, n1);
201 residu.ajoute(alfa, F0);
202 norme = mp_norme_vect(residu);
203 if (norme > seuil_ && dnew > 0)
204 {
205 if ((limpr() == 1) && (je_suis_maitre()))
206 Cout << "Solveur0: ";
207 if (le_precond_)
208 le_precond_->preconditionner(A00, residu, g);
209 else
210 solveur_poisson0.resoudre_systeme(A00, residu, g);
211 dnew = mp_prodscal(residu, g);
212 p *= (dnew / dold);
213 p -= g;
214 dold = dnew;
215 if (dnew < 0)
216 {
217 Cerr << "Error : dnew<0 in GCP NS solver." << finl;
218 Cerr << "Try to reduce the threshold value of solveur0" << finl;
219 Cerr << "to a value inferior to those of the GCP NS solver." << finl;
220 exit();
221 }
222 }
223 if ((limpr() == 1) && (je_suis_maitre()))
224 {
225 Cout << "GCP NS residue = " << norme << " " << finl;
226 if ((niter % 15) == 0)
227 Cout << finl;
228 }
229 }
230 if (norme > seuil_)
231 {
232 Cerr << "No convergence after : " << niter << " iterations\n";
233 Cerr << " Residue : " << norme << "\n";
234 }
235 solution.echange_espace_virtuel();
236 return (niter);
237}
238
239int Solv_GCP_NS::resoudre_systeme(const Matrice_Base& la_matrice, const DoubleVect& secmem, DoubleVect& solution)
240{
241 statistics().end_count(STD_COUNTERS::system_solver,-1,0);
242 int res = resoudre_systeme(la_matrice, secmem, solution, 1000000);
243 statistics().begin_count(STD_COUNTERS::system_solver,statistics().get_last_opened_counter_level()+1);
244 return res;
245}
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Classe Matrice_Base Classe de base de la hierarchie des matrices.
virtual DoubleVect & multvectT(const DoubleVect &, DoubleVect &) const
Multiplication d'un vecteur par la matrice transposee.
virtual int nb_lignes() const =0
Return local number of lines (=size on the current proc).
virtual DoubleVect & multvect(const DoubleVect &, DoubleVect &) const
Multiplication d'un vecteur par la matrice.
virtual DoubleVect & ajouter_multvect(const DoubleVect &x, DoubleVect &r) const
Operation de multiplication-accumulation (saxpy) matrice vecteur.
const Matrice & get_bloc(int i, int j) const override
int nb_bloc_lignes() const
int nb_bloc_colonnes(void) const
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
friend class Entree
Definition Objet_U.h:76
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 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(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
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
SolveurSys solveur_poisson0
Definition Solv_GCP_NS.h:41
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
int resoudre_systeme(const Matrice_Base &, const DoubleVect &, DoubleVect &) override
void set_param(Param &param) const override
SolveurSys solveur_poisson1
Definition Solv_GCP_NS.h:40
int limpr() const
void fixer_limpr(int l)
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
void ajoute(_SCALAR_TYPE_ alpha, const TRUSTVect &y, Mp_vect_options opt=VECT_ALL_ITEMS)
Definition TRUSTVect.tpp:52
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")