TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Matrice_Dense.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 <Matrice_Dense.h>
17#include <fstream>
18#include <iostream>
19#include <Lapack.h>
20#include <Matrice_Morse.h>
21
22Implemente_instanciable_sans_constructeur(Matrice_Dense,"Matrice_Dense",Matrice_Base);
23
25{
26 int nb_lines = nb_lignes( );
27 int nb_cols = nb_colonnes( );
28 // s << nb_lines << " "<< nb_cols << "\n";
29 for(int i=0; i<nb_lines; i++)
30 {
31 for( int j=0; j<nb_cols; j++)
32 {
33 s << Matrix_( i , j )<<" ";
34 }
35 s << "\n";
36 }
37 return s;
38}
39
41{
42 return s;
43}
44
45
47{
48 int nb_lines = nb_lignes( );
49 int nb_cols = nb_colonnes( );
50 s << nb_lines << " ";
51 s << nb_cols << "\n\n";
52 for(int i=0; i<nb_lines; i++)
53 {
54 for(int j=0; j<nb_cols; j++)
55 {
56 s << Matrix_( i , j )<<" ";
57 }
58 s <<"\n";
59 }
60 return s;
61}
62
63
68
69Matrice_Dense::Matrice_Dense( const int nb_lines , const int nb_cols )
70{
71 dimensionner( nb_lines , nb_cols );
72}
73
74
75//This function allow to build a dense matrix from a file
76//the format expected is the following :
77// nb_lines nb_columns
78// first line values ...
79// second line values ...
80// ...
81// last line values ...
82void Matrice_Dense::read_from_file( const Nom& filename )
83{
84 std::ifstream file(filename, ios::in);
85 int nb_lines, nb_cols;
86
87 if( file )
88 {
89 file >> nb_lines ;
90 file >> nb_cols ;
91 dimensionner( nb_lines , nb_cols );
92 for( int i=0; i<nb_lines; i++)
93 {
94 for(int j=0; j<nb_cols; j++)
95 {
96 file >> Matrix_( i , j );
97 }
98 }
99 }
100 else
101 {
102 Cerr<<"Error in Matrice_Dense::read_from_file"<<finl;
103 Cerr<<"The file "<<filename<<" was not found or a problem occured while opening the file"<<finl;
104 Cerr<<"Aborting..."<<finl;
106 }
107}
108
109
110//input : a vector of coefficients organized lines by lines
111//for example, let's say that we have nbl lines and nbc columns
112//then the first nbc coefficients are coefficients associated to the first line of the matrix
113//then the next nbc coefficients are coefficients associated to the second line of the matrix, ect...
114//Warning : the user need to resize correctly the matrix before to call this function
116{
117 int nb_lines = nb_lignes( );
118 int nb_cols = nb_colonnes( );
119 assert( coefficients.size( ) == nb_lines * nb_cols );
120 dimensionner( nb_lines , nb_cols );
121 int counter=0;
122 for( int i=0; i<nb_lines; i++)
123 {
124 for(int j=0; j<nb_cols; j++)
125 {
126 Matrix_( i , j ) = coefficients( counter );
127 counter++;
128 }
129 }
130}
131
133{
134 int nb_lines = nb_lignes( );
135 int nb_cols = nb_colonnes( );
136 assert( coefficients.size( ) == nb_lines * nb_cols );
137 dimensionner( nb_lines , nb_cols );
138 int counter=0;
139 for(int j=0; j<nb_cols; j++)
140 {
141 for( int i=0; i<nb_lines; i++)
142 {
143 Matrix_( i , j ) = coefficients( counter );
144 counter++;
145 }
146 }
147}
148
149//this function fills the matrix morse_matrix
151{
152 int nb_lines = nb_lignes( );
153 int nb_cols = nb_colonnes( ) ;
154 int nnz = nb_lines * nb_cols ;
155
156 morse_matrix.dimensionner( nb_lines , nb_cols , nnz );
157
158 int size_tab1 = nb_lines + 1 ;
159 int size_tab2 = nnz ;
160 morse_matrix.get_set_tab1().resize( size_tab1 );
161 morse_matrix.get_set_tab2().resize( size_tab2 );
162 morse_matrix.get_set_coeff().resize( nnz );
163
164 for(int i=0; i<size_tab1; i++)
165 {
166 morse_matrix.get_set_tab1()( i ) = /*already registred*/i*nb_cols + /*fortran index*/ 1 ;
167 }
168 auto count = 0;
169 for(int i=0 ; i<nb_lines ; i++)
170 {
171 for(int j=0; j<nb_cols; j++)
172 {
173 morse_matrix.get_set_tab2()( count ) = j+1 ;
174 morse_matrix.get_set_coeff()( count ) = Matrix_( i , j );
175 count++;
176 }
177 }
178}
179
180
181void Matrice_Dense::dimensionner( const int nb_lines , const int nb_cols )
182{
183 Matrix_.resize( nb_lines , nb_cols );
184}
185
187{
188 return Matrix_.dimension( 0 );
189}
190
192{
193 return Matrix_.dimension( 1 );
194}
195
197{
198 int nb_lines = nb_lignes( );
199 int nb_cols = nb_colonnes( );
200 if( nb_lines == nb_cols )
201 {
202 return nb_lines ;
203 }
204 else
205 {
206 return 0 ;
207 }
208}
209
210/*! @brief Operation de multiplication-accumulation (saxpy) matrice vecteur.
211 *
212 * Operation: resu = resu + Matrix_ * x
213 *
214 */
215DoubleVect& Matrice_Dense::ajouter_multvect_( const DoubleVect& x , DoubleVect& resu ) const
216{
217 const int nb_lines = nb_lignes( ) ;
218 const int nb_cols = nb_colonnes( );
219 assert( x.size_array( ) == nb_cols );
220 //the test is in this order because size( ) maybe invalid
221 assert( resu.size_array( ) == nb_lines || resu.size( ) == nb_lines );
222
223 //for a given i such that 0 <= i <= nb_lines we have
224 //resu( i ) = resu( i ) + Matrix_( i , j ) * x( j )
225 //with 0 <= j <= nb_cols
226 for(int i=0; i<nb_lines; i++)
227 {
228 double old_resu = resu( i );
229 double prod_mat_vect = 0; // store the result of Matrix_( i , j ) * x( j ) with 0<= j <=nb_cols
230 for(int j=0; j<nb_cols; j++)
231 {
232 prod_mat_vect += Matrix_( i , j ) * x( j );
233 }
234 resu( i ) = old_resu + prod_mat_vect ;
235 }
236
237 return resu;
238}
239
240//set the coefficient Matrix( i , j ) at value
241void Matrice_Dense::set_coefficient( const int i , const int j , const double value )
242{
243 assert( i < nb_lignes( ) );
244 assert( j < nb_colonnes( ) );
245 Matrix_( i , j ) = value;
246}
247
249{
250 int nb_lines = nb_lignes( );
251 int nb_cols = nb_colonnes( );
252 transposed.dimensionner( nb_lines , nb_cols );
253 for(int j=0; j<nb_cols; j++)
254 {
255 for(int i=0; i<nb_lines; i++)
256 {
257 double value = Matrix_( i , j );
258 transposed.set_coefficient( j , i , value ) ;
259 }
260 }
261}
262
263// return a bool which indicates if the other matrix is the same or not
264// return true : Matrix_ and other_matrix are the same for a given tolerance tol
265// return false : Matrix_ and other_matrix are NOT the same for a given tolerance tol
266bool Matrice_Dense::is_the_same( const Matrice_Dense& other_matrix , const double tol ) const
267{
268 bool same = true;
269 int nb_lines = nb_lignes( );
270 int nb_cols = nb_colonnes( );
271 //check if the other has same number of lines/columns
272 if( other_matrix.nb_lignes( ) != nb_lines )
273 {
274 same = false;
275 }
276 if( other_matrix.nb_colonnes( ) != nb_cols )
277 {
278 same = false;
279 }
280 //check each coefficient
281 for(int i=0; i<nb_lines; i++)
282 {
283 for(int j=0; j<nb_cols; j++)
284 {
285 if( std::fabs( other_matrix( i , j ) - Matrix_( i , j )) >= tol )
286 {
287 same = false;
288 }
289 }
290 }
291 return same;
292}
293
294/*! @brief Operation de multiplication-accumulation (saxpy) matrice vecteur, par la matrice transposee.
295 *
296 * Operation: resu = resu + A^{T}*x
297 *
298 */
299DoubleVect& Matrice_Dense::ajouter_multvectT_(const DoubleVect& x,DoubleVect& resu) const
300{
301
302 const int nb_lines = nb_lignes( ) ;
303 const int nb_cols = nb_colonnes( );
304 assert( x.size_array( ) == nb_lines );
305 //the test is in this order because size( ) maybe invalid
306 assert( resu.size_array( ) == nb_cols || resu.size( ) == nb_cols );
307
308 //for a given i such that 0 <= i <= nb_cols we have
309 //resu( i ) = resu( i ) + Matrix_( j , i ) * x( j )
310 //with 0 <= j <= nb_lines
311 for(int i=0; i<nb_cols; i++)
312 {
313 double old_resu = resu( i );
314 double prod_mat_vect = 0;
315 for(int j=0; j<nb_lines; j++)
316 {
317 prod_mat_vect += Matrix_( j , i ) * x( j );
318 }
319 resu( i ) = old_resu + prod_mat_vect ;
320 }
321
322 return resu;
323}
324
325void Matrice_Dense::scale( const double x )
326{
327 const int nb_lines = nb_lignes( );
328 const int nb_cols = nb_colonnes( );
329 for(int i=0; i<nb_lines; i++)
330 {
331 for(int j=0; j<nb_cols; j++)
332 {
333 Matrix_( i , j ) *= x ;
334 }
335 }
336}
337
338
340{
341 const int nb_lines = nb_lignes( );
342 const int nb_cols = nb_colonnes( );
343 for(int i=0; i<nb_lines; i++)
344 {
345 for(int j=0; j<nb_cols; j++)
346 {
347 Matrix_( i , j ) = 0. ;
348 }
349 }
350}
351
352void Matrice_Dense::get_stencil( Stencil& stencil ) const
353{
354
355 const int nb_lines = nb_lignes( );
356 const int nb_cols = nb_colonnes( );
357
358 stencil.resize( 0, 2 );
359
360 for(int i=0; i<nb_lines; i++)
361 {
362 for(int j=0; j<nb_cols; j++)
363 {
364 stencil.append_line( i , j );
365 }
366 }
367
368 const int new_size = stencil.dimension( 0 );
369 stencil.resize( new_size, 2 );
370
371}
372
373
374DoubleTab& Matrice_Dense::ajouter_multTab_( const DoubleTab& x , DoubleTab& resu ) const
375{
376 Cerr<<"Error in Matrice_Dense::ajouter_multTab_ ."<<finl;
377 Cerr<<"This function is virtual pure in Matrice_Base but seems never used."<<finl;
378 Cerr<<"One should get rid off it."<<finl;
379 Cerr<<"Aborting..."<<finl;
381 return resu;
382}
383
385{
386 // This method compute the inverse of the matrix.
387 // It uses the LAPACK library.
388 const int nbLines = nb_lignes();
389 const int nbCols = nb_colonnes();
390 int infoerr = 0;
391 if (ipiv.size_array()!=nbLines)
392 {
393 ipiv.resize(nbLines);
394 work.resize(nbLines);
395 }
396
397 if (nbLines != nbCols)
398 {
399 Cerr << "Error in Matrice_Dense::inverse" << finl;
400 Cerr << "The matrix is not a square matrix !" << finl;
402 }
403
404 F77NAME(DGETRF)(&nbLines, &nbLines, Matrix_.addr(), &nbLines, ipiv.addr(), &infoerr);
405 assert(infoerr == 0);
406 F77NAME(DGETRI)(&nbLines, Matrix_.addr(), &nbLines, ipiv.addr(), work.addr(), &nbLines, &infoerr);
407 assert(infoerr == 0);
408
409 return;
410}
411
412/*! @brief Solves the linear system A*x = b using LU factorization
413 *
414 * This method solves a system of linear equations using LAPACK routines:
415 * - DGETRF for LU factorization
416 * - DGETRS for solving the system using the factored matrix
417 *
418 * @param[in] b Right-hand side vector of the system
419 * @param[out] x Solution vector of the system
420 *
421 * @pre The matrix must be square
422 * @pre The size of vectors b and x must match the matrix dimensions
423 *
424 * @throw Process::exit if LU factorization or solve step fails
425 */
426void Matrice_Dense::solve(const ArrOfDouble& b, ArrOfDouble& x)
427{
428 const int nbLines = nb_lignes();
429 const int nbCols = nb_colonnes();
430 int infoerr = 0;
431 if (ipiv.size_array()!=nbLines)
432 {
433 ipiv.resize(nbLines);
434 work.resize(nbLines);
435 }
436
437 if (nbLines != nbCols)
438 {
439 Cerr << "Error in Matrice_Dense::inverse" << finl;
440 Cerr << "The matrix is not a square matrix !" << finl;
442 }
443 F77NAME(DGETRF)(&nbLines, &nbLines, Matrix_.addr(), &nbLines, ipiv.addr(), &infoerr);
444 if (infoerr != 0) Process::exit("Error DGETRF in Matrice_Dense::solve");
445 char trans = 'T';
446 x = b;
447 int nb_rhs=1;
448 F77NAME(DGETRS)(&trans, &nbLines, &nb_rhs, Matrix_.addr(), &nbLines, ipiv.addr(), x.addr(), &nbLines, &infoerr);
449 if (infoerr != 0) Process::exit("Error DGETRS in Matrice_Dense::solve");
450 return;
451}
452
454{
455 // This method allows to perform the multiplication of two matrix.
456 // It is the "right" multiplication : (*this) * B = RES
457
458 assert(nb_colonnes() == B.nb_lignes());
459 assert(nb_lignes() == RES.nb_lignes());
460 assert(B.nb_colonnes() == RES.nb_colonnes());
461
462 for (int i = 0; i < nb_lignes(); ++i)
463 {
464 for (int j = 0; j < B.nb_colonnes(); ++j)
465 {
466 RES.set_coefficient(i, j, 0.0);
467 for (int k = 0; k < nb_colonnes(); ++k)
468 {
469 RES.set_coefficient(i, j, RES(i, j) + Matrix_(i, k) * B(k, j));
470 }
471 }
472 }
473 return;
474}
475
477{
478 assert( A.nb_lignes() == B.nb_lignes() );
479 assert( A.nb_colonnes() == B.nb_colonnes() );
480 Matrice_Dense resu(A.nb_lignes(), A.nb_colonnes());
481 for (int i=0; i<A.nb_lignes(); i++)
482 {
483 for (int j=0; j<A.nb_colonnes(); j++)
484 {
485 resu.set_coefficient(i,j,A(i,j)+B(i,j));
486 }
487 }
488 return resu;
489}
490
491Matrice_Dense operator*(const double& a, const Matrice_Dense& B)
492{
493 Matrice_Dense resu(B.nb_lignes(), B.nb_colonnes());
494 for (int i=0; i<B.nb_lignes(); i++)
495 {
496 for (int j=0; j<B.nb_colonnes(); j++)
497 {
498 resu.set_coefficient(i,j,a*B(i,j));
499 }
500 }
501 return resu;
502}
503
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.
void scale(const double x) override
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
void read_from_file(const Nom &filename)
int ordre() const override
If square matrix, returns number of lines, otherwise 0.
void build_matrix_from_coefficients_line_by_line(const DoubleVect &coefficients)
DoubleVect & ajouter_multvectT_(const DoubleVect &x, DoubleVect &r) const override
Operation de multiplication-accumulation (saxpy) matrice vecteur, par la matrice transposee.
void dimensionner(const int nb_lines, const int nb_cols)
void solve(const ArrOfDouble &b, ArrOfDouble &x)
Solves the linear system A*x = b using LU factorization.
void build_the_transposed(Matrice_Dense &transposed) const
void build_matrix_from_coefficients_column_by_column(const DoubleVect &coefficients)
int nb_lignes() const override
Return local number of lines (=size on the current proc).
friend Matrice_Dense operator+(const Matrice_Dense &A, const Matrice_Dense &B)
Sortie & imprimer_formatte(Sortie &s) const override
void convert_to_morse_matrix(Matrice_Morse &morse_matrix) const
friend Matrice_Dense operator*(const double &a, const Matrice_Dense &B)
bool is_the_same(const Matrice_Dense &other_matrix, const double tol=1e-14) const
void clean() override
void set_coefficient(const int i, const int j, const double value)
void multiplyToRight(const Matrice_Dense &B, Matrice_Dense &RES) const
DoubleTab & ajouter_multTab_(const DoubleTab &x, DoubleTab &r) const override
DoubleVect & ajouter_multvect_(const DoubleVect &x, DoubleVect &r) const override
Operation de multiplication-accumulation (saxpy) matrice vecteur.
void get_stencil(Stencil &stencil) const override
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()
auto & get_set_tab1()
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
friend class Sortie
Definition Objet_U.h:75
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 void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const
_TYPE_ * addr()
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
void append_line(_TYPE_)
Definition TRUSTTab.tpp:213
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45