TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Solveur_Masse_base.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 <Solveur_Masse_base.h>
17#include <TRUSTTab_parts.h>
18#include <Equation_base.h>
19#include <Champ_Uniforme.h>
20#include <Matrice_Morse.h>
21#include <TRUSTTrav.h>
22#include <Debog.h>
23#include <Device.h>
24
25Implemente_base_sans_constructeur(Solveur_Masse_base,"Solveur_Masse_base",Objet_U);
26
27Solveur_Masse_base::Solveur_Masse_base() : has_coefficient_temporel_(0), penalisation_flag_(1), penalisation_(0) {}
28
29Sortie& Solveur_Masse_base::printOn(Sortie& os) const { return os; }
30Entree& Solveur_Masse_base::readOn(Entree& is) { return is; }
31
32/*! @brief DOES NOTHING - to override in derived classes.
33 *
34 * Mise a jour en temps du solveur de masse.
35 *
36 * @param (double) le pas de temps de mise a jour
37 */
41
42/*! @brief DOES NOTHING - to override in derived classes.
43 *
44 * Reset current time.
45 * @param (double) new current time.
46 */
48{
49}
50
51/*! @brief DOES NOTHING
52 *
53 * Eventuellement a surcharger dans les classes derivees
54 * si la matrice de masse necessite un assemblage.
55 * Assemble le solveur de masse (en general la matrice de masse)
56 */
60
61/*! @brief permet de choisir le nom du coefficient temporelle que l'on veut utiliser pour appliquer
62 *
63 * verifie que le champ exsite bien
64 *
65 */
67{
70 if (name == "no_coeff")
71 {
73 return;
74 }
75
77 {
78 /* Do nothing */
79 }
80 else
81 {
82 Cerr << name_of_coefficient_temporel_ << " not understood by " << equation().que_suis_je() << finl;
84 }
85}
86
87/*! @brief renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie appliquer_impl(x)
88 *
89 * Return M-1.x
90 */
91DoubleTab& Solveur_Masse_base::appliquer(DoubleTab& x) const
92{
94 {
95 OBS_PTR(Champ_base) ref_coeff;
97
98 DoubleTab values;
99 if (sub_type(Champ_Uniforme, ref_coeff.valeur()))
100 {
101 const Champ_Uniforme& coeff = ref_cast(Champ_Uniforme,ref_coeff.valeur());
102 values = coeff.valeurs();
103 }
104 else if (sub_type(Champ_Inc_base,ref_coeff.valeur()))
105 {
106 const Champ_Inc_base& coeff = ref_cast(Champ_Inc_base,ref_coeff.valeur());
107 values.ref(coeff.valeurs());
108
109 }
110 else if (sub_type(Champ_Fonc_base,ref_coeff.valeur()))
111 {
112 const Champ_Fonc_base& coeff = ref_cast(Champ_Fonc_base,ref_coeff.valeur());
113 values.ref(coeff.valeurs());
114
115 }
116 else if (sub_type(Champ_Don_base,ref_coeff.valeur()))
117 {
118 DoubleTab nodes;
120 ref_coeff->valeur_aux(nodes,values);
121 }
122
123 Debog::verifier("Solveur_Masse_base::appliquer coeffs",values);
124 //tab_divide_any_shape(x, values, VECT_REAL_ITEMS);
125 DoubleTab_parts values_parts(values);
126 tab_divide_any_shape(x, values_parts[0], VECT_REAL_ITEMS);
127 }
128 return appliquer_impl(x); // M-1.x
129}
130
131// Add M/dt into matrix
132Matrice_Base& Solveur_Masse_base::ajouter_masse(double dt, Matrice_Base& matrice, int penalisation_flag) const
133{
134 Matrice_Morse& matmo=ref_cast(Matrice_Morse, matrice);
136 {
137 penalisation_flag_ = penalisation_flag;
138 DoubleTrav inco(equation().inconnue().valeurs());
139 ajouter_blocs({{ equation().inconnue().le_nom().getString(), &matmo }}, inco, dt, {}, 0); //on tente ajouter_blocs()
140 return matrice;
141 }
142
143 DoubleTrav tab_diag(equation().inconnue().valeurs());
144 const int sz = equation().inconnue().valeurs().dimension_tot(0) * tab_diag.line_size();
145 tab_diag=1.;
146 appliquer(tab_diag); // M-1
147 int prems=0;
148 if(penalisation_flag)
149 {
150 ToDo_Kokkos("critical");
151 if (penalisation_==0)
152 {
153 double penal=0;
154 for(int i=0; i<sz; i++)
155 penal=std::max(penal, matmo(i,i));
156 penal=mp_max(penal);
157 penalisation_=(mp_max_vect(tab_diag)/dt + penal)*1.e3;
158 prems=1;
159 }
160 for(int i=0; i<sz; i++)
161 {
162 if (tab_diag.addr()[i]==0)
163 {
164 if(prems)
165 {
166 matmo(i,i)+=penalisation_;
167 prems=0;
168 }
169 matmo(i,i)+=penalisation_/dt;
170 }
171 else
172 matmo(i,i)+=1./(tab_diag.addr()[i]*dt); // M/dt
173 }
174 }
175 else
176 {
177 CDoubleArrView diag = static_cast<const ArrOfDouble&>(tab_diag).view_ro();
178 Matrice_Morse_View mat;
179 mat.set(matmo);
180 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), sz, KOKKOS_LAMBDA(
181 const int i)
182 {
183 if (diag(i) != 0)
184 mat.add(i, i, 1. / (diag(i) * dt)); // M/dt
185 });
186 end_gpu_timer(__KERNEL_NAME__);
187 }
188 return matrice;
189}
190
191// Add M*y/dt to x
192DoubleTab& Solveur_Masse_base::ajouter_masse(double dt, DoubleTab& tab_x, const DoubleTab& tab_y, int penalisation_flag, bool use_old_volumes) const
193{
195 {
196 penalisation_flag_ = penalisation_flag;
197 const std::string& nom_inco = equation().inconnue().le_nom().getString();
198 ajouter_blocs({}, tab_x, dt, {{nom_inco,tab_y}}, 0); //on tente ajouter_blocs()
199 return tab_x;
200 }
201
202 // Optional ALE RHS pre-scaling: y_scaled = (V_old/V_new) ⊙ y
203 const DoubleTab* py = &tab_y;
204 DoubleTrav y_scaled;
205 if (use_old_volumes)
206 {
207 y_scaled = tab_y;
209 py = &y_scaled;
210 }
211
212 int sz = py->size();
213 DoubleTrav tab_diag;
214 tab_diag.copy(equation().inconnue().valeurs(), RESIZE_OPTIONS::NOCOPY_NOINIT);
215 tab_diag=1.;
216 appliquer(tab_diag); // M-1
217 if (penalisation_flag)
218 {
219 if (penalisation_==0)
220 penalisation_ = mp_max_vect(tab_diag)*1.e3;
221 }
222 else
223 penalisation_=1;
224
225 double penalisation = penalisation_;
226 CDoubleArrView diag = static_cast<const ArrOfDouble&>(tab_diag).view_ro();
227 CDoubleArrView y = static_cast<const ArrOfDouble&>(*py).view_ro();
228 DoubleArrView x = static_cast<ArrOfDouble&>(tab_x).view_rw();
229 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), sz, KOKKOS_LAMBDA(const int i)
230 {
231 if (diag(i)==0)
232 x(i)=penalisation*y(i);
233 else
234 x(i)+=1./(diag(i)*dt)*y(i);
235 });
236 end_gpu_timer(__KERNEL_NAME__);
237 //x.echange_espace_virtuel();Debog::verifier("Solveur_Masse::ajouter_masse",x);
238 return tab_x;
239}
240
241Matrice_Base& Solveur_Masse_base::ajouter_masse_dt_local(DoubleVect& dt_locaux, Matrice_Base& matrice, int penalisation) const
242{
243 Matrice_Morse& matmo=ref_cast(Matrice_Morse, matrice);
244 int sz=matmo.nb_lignes();;
245 DoubleTrav diag(equation().inconnue().valeurs());
246 diag=1.;
247 appliquer(diag); // M-1
248 int prems=0;
249 if(penalisation)
250 {
251 if (penalisation_==0)
252 {
253 double penal=0;
254 for(int i=0; i<sz; i++)
255 penal=std::max(penal, matmo(i,i));
256 penal=mp_max(penal);
257 penalisation_=(mp_max_vect(diag)/dt_locaux.local_max_vect() + penal)*1.e3;
258 prems=1;
259 }
260 }
261 else
262 penalisation_=0;
263 ToDo_Kokkos("critical");
264 for(int i=0; i<sz; i++)
265 {
266 if (diag.addr()[i]==0)
267 {
268 if(prems)
269 {
270 matmo(i,i)+=penalisation_;
271 prems=0;
272 }
273 matmo(i,i)+=penalisation_/dt_locaux[i];
274 }
275 else
276 matmo(i,i)+=1./(diag.addr()[i]*dt_locaux[i]);
277 }
278 return matrice;
279}
280
281DoubleTab& Solveur_Masse_base::ajouter_masse_dt_local(DoubleVect& dt_locaux, DoubleTab& x, const DoubleTab& y, int penalisation) const
282{
283 int sz=y.size();
284 DoubleTrav diag;
285 diag.copy(equation().inconnue().valeurs(), RESIZE_OPTIONS::NOCOPY_NOINIT);
286 diag=1.;
287 appliquer(diag);
288 if (penalisation)
289 {
290 if (penalisation_==0)
291 penalisation_ = mp_max_vect(diag)*1.e3;
292 }
293 else
294 penalisation_=1;
295 ToDo_Kokkos("critical");
296 for(int i=0; i<sz; i++)
297 {
298 if (diag.addr()[i]==0)
299 x.addr()[i]=penalisation_*y.addr()[i];
300 else
301 x.addr()[i]+=1./(diag.addr()[i]*dt_locaux[i])*y.addr()[i];
302
303 }
304 return x;
305}
306
307void Solveur_Masse_base::get_masse_dt_local(DoubleVect& m_dt_locaux, DoubleVect& dt_locaux, int penalisation)
308{
309 int sz=dt_locaux.size();
310 DoubleTab diag;
311 diag.copy(equation().inconnue().valeurs(), RESIZE_OPTIONS::NOCOPY_NOINIT);
312 diag=1.;
313 appliquer(diag);
314 if (penalisation)
315 {
316 if (penalisation_==0)
317 penalisation_ = mp_max_vect(diag)*1.e3;
318 }
319 else
320 penalisation_=1;
321 ToDo_Kokkos("critical");
322 for(int i=0; i<sz; i++)
323 {
324 if (diag.addr()[i]==0)
325 m_dt_locaux[i]=0.;
326 else
327 m_dt_locaux[i]=(1./diag.addr()[i])*dt_locaux[i];
328
329 }
330 m_dt_locaux.echange_espace_virtuel();
331
332 //Debog::verifier("Solveur_Masse::ajouter_masse",x);
333}
334
335
336void Solveur_Masse_base::get_masse_divide_by_local_dt(DoubleVect& m_dt_locaux, DoubleVect& dt_locaux, int penalisation)
337{
338 int sz=dt_locaux.size();
339 DoubleTab diag;
340 diag.copy(equation().inconnue().valeurs(), RESIZE_OPTIONS::NOCOPY_NOINIT);
341 diag=1.;
342 appliquer(diag);
343 if (penalisation)
344 {
345 if (penalisation_==0)
346 penalisation_ = mp_max_vect(diag)*1.e3;
347 }
348 else
349 penalisation_=1;
350 ToDo_Kokkos("critical");
351 for(int i=0; i<sz; i++)
352 {
353 if (diag.addr()[i]==0)
354 m_dt_locaux[i]=0.;
355 else
356 m_dt_locaux[i]=(1./diag.addr()[i])/dt_locaux[i];
357
358 }
359 m_dt_locaux.echange_espace_virtuel();
360
361 //Debog::verifier("Solveur_Masse::ajouter_masse",x);
362
363}
364
365DoubleTab& Solveur_Masse_base::corriger_solution(DoubleTab& tab_x, const DoubleTab& tab_y, int incr) const
366{
367 int sz = tab_y.dimension_tot(0) * tab_y.line_size();
368 DoubleTrav tab_diag(equation().inconnue().valeurs());
369 tab_diag=1.;
370 appliquer(tab_diag); // M-1
371 // Si x et y sont sur le device, on deporte l'execution sur le device:
372 bool kernelOnDevice = tab_x.checkDataOnDevice(tab_y);
373 if (kernelOnDevice)
374 {
375 CDoubleArrView diag = static_cast<const ArrOfDouble&>(tab_diag).view_ro();
376 CDoubleArrView y = static_cast<const ArrOfDouble&>(tab_y).view_ro();
377 DoubleArrView x = static_cast<ArrOfDouble&>(tab_x).view_wo();
378 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), sz, KOKKOS_LAMBDA(const int i)
379 {
380 if (diag[i]<1.e-12)
381 x[i] = y[i];
382 });
383 end_gpu_timer(__KERNEL_NAME__, kernelOnDevice);
384 }
385 else
386 {
387 for(int i=0; i<sz; i++)
388 if (tab_diag.addr()[i]<1.e-12)
389 tab_x.addr()[i] = tab_y.addr()[i];
390 }
391 return tab_x;
392}
393
394// Ajout d'une methode dimensionner()
395// qui dimensionne la matrice a la diagonale quand
396// tous les operateurs sont negligeables
397// Le code est celui utilise dans la version Noyau de Equation_base::dimensionner_matrice()
399{
401 {
402 dimensionner_blocs({{ equation().inconnue().le_nom().getString(), &matrix }}, {}); //on tente dimensionner_blocs
403 return;
404 }
405 const DoubleTab& champ_inconnue = equation().inconnue().valeurs();
406 int size = champ_inconnue.dimension_tot(0) * champ_inconnue.line_size();
407
408 IntTab indice(size, 2);
409 for(int i=0; i<size; ++i)
410 {
411 indice(i,0) = indice(i,1) = i;
412 }
413 matrix.dimensionner(indice);
414}
415
416void Solveur_Masse_base::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
417{
418 Process::exit(que_suis_je() + " : dimensionner_blocs not coded!");
419}
420
421void Solveur_Masse_base::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, double dt, const tabs_t& semi_impl, int resoudre_en_increments) const
422{
423 Process::exit(que_suis_je() + " : ajouter_blocs not coded!");
424}
425
426// Ajout d'une methode completer
427// Ne fait rien par defaut
429
430// Ajout d'une methode preparer_calcul
431// Ne fait rien par defaut
433
classe Champ_Don_base classe de base des Champs donnes (non calcules)
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & remplir_coord_noeuds(DoubleTab &) const =0
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
virtual void apply_old_to_new_volume_scaling(DoubleTab &tab, const Domaine_dis_base &dvf) const
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Champ_Inc_base & inconnue() const =0
const Champ_base & get_champ(const Motcle &nom) const override
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
Classe Matrice_Base Classe de base de la hierarchie des matrices.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
int nb_lignes() const override
Return local number of lines (=size on the current proc).
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
OBS_PTR(Equation_base) mon_equation
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
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
static double mp_max(double)
Definition Process.cpp:376
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
virtual void dimensionner(Matrice_Morse &matrix) const
virtual void assembler()
DOES NOTHING.
virtual Matrice_Base & ajouter_masse_dt_local(DoubleVect &dt_locaux, Matrice_Base &matrice, int penalisation=1) const
virtual void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={}) const
virtual void get_masse_divide_by_local_dt(DoubleVect &m_dt_locaux, DoubleVect &dt_locaux, int penalisation=1)
virtual void get_masse_dt_local(DoubleVect &m_dt_locaux, DoubleVect &dt_locaux, int penalisation=1)
virtual Matrice_Base & ajouter_masse(double dt, Matrice_Base &matrice, int penalisation=1) const
virtual DoubleTab & appliquer_impl(DoubleTab &x) const =0
virtual DoubleTab & corriger_solution(DoubleTab &x, const DoubleTab &y, int incr=0) const
virtual void preparer_calcul()
virtual void resetTime(double temps)
DOES NOTHING - to override in derived classes.
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
void set_name_of_coefficient_temporel(const Nom &)
permet de choisir le nom du coefficient temporelle que l'on veut utiliser pour appliquer
virtual int has_interface_blocs() const
virtual void mettre_a_jour(double temps)
DOES NOTHING - to override in derived classes.
virtual void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, double dt, const tabs_t &semi_impl, int resoudre_en_increments) const
Classe de base des flux de sortie.
Definition Sortie.h:52
_TYPE_ * addr()
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
void copy(const TRUSTTab &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:622
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_TYPE_ local_max_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:154
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")