Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Matrix.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Matrix.cc (C) 2000-2022 */
9/* */
10/* Matrix d'algèbre linéraire. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Array.h"
15#include "arcane/utils/FatalErrorException.h"
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/Numeric.h"
18#include "arcane/utils/ArgumentException.h"
19#include "arcane/utils/NotImplementedException.h"
20#include "arcane/utils/TraceInfo.h"
21#include "arcane/utils/StringBuilder.h"
22
23#include "arcane/utils/ValueConvert.h"
24
25#include "arcane/matvec/Matrix.h"
26#include "arcane/matvec/Vector.h"
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane::MatVec
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
39class MatrixImpl
40{
41 public:
42 MatrixImpl() : m_nb_reference(0), m_nb_row(0), m_nb_column(0), m_nb_element(0) {}
43 MatrixImpl(Integer nb_row,Integer nb_column);
44 private:
45 void operator=(const Matrix& rhs);
46 public:
47 MatrixImpl* clone()
48 {
49 MatrixImpl* m2 = new MatrixImpl();
50 m2->m_nb_row = m_nb_row;
51 m2->m_nb_column = m_nb_column;
52 m2->m_nb_element = m_nb_element;
53 m2->m_values = m_values.clone();
54 m2->m_rows_index = m_rows_index.clone();
55 m2->m_columns = m_columns.clone();
56 return m2;
57 }
58 private:
59 public:
60 Integer nbRow() const { return m_nb_row; }
61 Integer nbColumn() const { return m_nb_column; }
62 void setRowsSize(IntegerConstArrayView rows_size);
63 void setValues(IntegerConstArrayView columns,RealConstArrayView values);
64 void dump(std::ostream& o);
65 RealConstArrayView values() const { return m_values; }
66 RealArrayView values() { return m_values; }
67 Real value(Integer row,Integer column) const;
68 IntegerConstArrayView rowsIndex() const { return m_rows_index; }
69 IntegerConstArrayView columns() const { return m_columns; }
70 IntegerArrayView rowsIndex() { return m_rows_index; }
71 IntegerArrayView columns() { return m_columns; }
72 void setValue(Integer row,Integer column,Real value);
73 void sortDiagonale();
74 void assemble();
75 public:
76 void checkValid();
77 public:
78 void addReference()
79 {
80 ++m_nb_reference;
81 }
82 void removeReference()
83 {
84 --m_nb_reference;
85 if (m_nb_reference==0)
86 delete this;
87 }
88 private:
89 Integer m_nb_reference;
90 Integer m_nb_row;
91 Integer m_nb_column;
92 Integer m_nb_element;
93 SharedArray<Real> m_values;
94 SharedArray<Integer> m_rows_index;
95 SharedArray<Integer> m_columns;
96};
97
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102MatrixImpl::
103MatrixImpl(Integer nb_row,Integer nb_column)
104: m_nb_reference(0)
105, m_nb_row(nb_row)
106, m_nb_column(nb_column)
107, m_nb_element(0)
108, m_rows_index(m_nb_row+1)
109{
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115Matrix::
116Matrix(Integer nb_row,Integer nb_column)
117: m_impl(new MatrixImpl(nb_row,nb_column))
118{
119 m_impl->addReference();
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124
125Matrix::
126Matrix(MatrixImpl* impl)
127: m_impl(impl)
128{
129 if (m_impl)
130 m_impl->addReference();
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
136Matrix::
137Matrix(const Matrix& rhs)
138: m_impl(rhs.m_impl)
139{
140 if (m_impl)
141 m_impl->addReference();
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147void Matrix::
148operator=(const Matrix& rhs)
149{
150 if (rhs.m_impl)
151 rhs.m_impl->addReference();
152 if (m_impl)
153 m_impl->removeReference();
154 m_impl = rhs.m_impl;
155}
156
157/*---------------------------------------------------------------------------*/
158/*---------------------------------------------------------------------------*/
159
160Matrix::
161~Matrix()
162{
163 if (m_impl)
164 m_impl->removeReference();
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
170Integer Matrix::
171nbRow() const
172{
173 return m_impl->nbRow();
174}
175
176/*---------------------------------------------------------------------------*/
177/*---------------------------------------------------------------------------*/
178
181{
182 return m_impl->sortDiagonale();
183}
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187
188Integer Matrix::
189nbColumn() const
190{
191 return m_impl->nbColumn();
192}
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
198clone() const
199{
200 MatrixImpl* m = m_impl->clone();
201 return Matrix(m);
202}
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
208rowsIndex() const
209{
210 return m_impl->rowsIndex();
211}
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
217dump(std::ostream& o) const
218{
219 m_impl->dump(o);
220}
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
227{
228 m_impl->setValue(row,column,value);
229}
230
231/*---------------------------------------------------------------------------*/
232/*---------------------------------------------------------------------------*/
233
235value(Integer row,Integer column) const
236{
237 return m_impl->value(row,column);
238}
239
240/*---------------------------------------------------------------------------*/
241/*---------------------------------------------------------------------------*/
242
248
249/*---------------------------------------------------------------------------*/
250/*---------------------------------------------------------------------------*/
251
254{
255 m_impl->setRowsSize(rows_size);
256}
257
258/*---------------------------------------------------------------------------*/
259/*---------------------------------------------------------------------------*/
260
262values() const
263{
264 return m_impl->values();
265}
266
267/*---------------------------------------------------------------------------*/
268/*---------------------------------------------------------------------------*/
269
271values()
272{
273 return m_impl->values();
274}
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
278
280columns()
281{
282 return m_impl->columns();
283}
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
289rowsIndex()
290{
291 return m_impl->rowsIndex();
292}
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
298columns() const
299{
300 return m_impl->columns();
301}
302
303/*---------------------------------------------------------------------------*/
304/*---------------------------------------------------------------------------*/
305
306DiagonalPreconditioner::
307DiagonalPreconditioner(const Matrix& matrix)
308: m_inverse_diagonal(matrix.nbRow())
309{
310 Integer size = m_inverse_diagonal.size();
311 IntegerConstArrayView rows_index = matrix.rowsIndex();
313 RealConstArrayView mat_values = matrix.values();
314 RealArrayView vec_values = m_inverse_diagonal.values();
315 for( Integer i=0, is=size; i<is; ++i ){
316 for( Integer z=rows_index[i] ,zs=rows_index[i+1]; z<zs; ++z ){
317 Integer mj = columns[z];
318 if (mj==i)
319 vec_values[i] = mat_values[z];
320 }
321 }
322#if 0
323 cout << "DIAG1=";
324 m_inverse_diagonal.dump(cout);
325 cout << "\n";
326#endif
327 const double epsilon = std::numeric_limits<Real>::min();
328
329 // Inverse la diagonale si la valeur n'est pas inférieure à l'epsilon de Real
330 // (sinon cela génère un FPE)
331 for( Integer i=0; i<size; ++i ){
332 Real v = vec_values[i];
333 bool is_zero = v>-epsilon && v<epsilon;
334 vec_values[i] = (is_zero) ? 1.0 : (1.0 / v);
335 }
336
337#if 0
338 cout << "DIAG2=";
339 m_inverse_diagonal.dump(cout);
340 cout << "\n";
341#endif
342}
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
346
347void DiagonalPreconditioner::
348apply(Vector& out_vec,const Vector& vec)
349{
350 Integer size = m_inverse_diagonal.size();
351 RealConstArrayView inverse_diagonal_values = m_inverse_diagonal.values();
352 RealConstArrayView vec_values = vec.values();
353 RealArrayView out_vec_values = out_vec.values();
354 for( Integer i=0; i<size; ++i )
355 out_vec_values[i] = vec_values[i] * inverse_diagonal_values[i];
356}
357
358/*---------------------------------------------------------------------------*/
359/*---------------------------------------------------------------------------*/
360
361void MatrixOperation::
362matrixVectorProduct(const Matrix& mat,const Vector& vec,Vector& out_vec)
363{
364 Integer nb_row = mat.nbRow();
365 Integer nb_column = mat.nbColumn();
366 //cout << "** MATRIX ROW=" << nb_row << " COL=" << nb_column
367 // << " intput_size=" << vec.size()
368 // << " output_size=" << out_vec.size()
369 // << "\n";
370 if (nb_column!=vec.size())
371 throw ArgumentException("MatrixVectorProduct","Bad size for input vector");
372 if (nb_row!=out_vec.size())
373 throw ArgumentException("MatrixVectorProduct","Bad size for output_vector");
374 IntegerConstArrayView rows_index = mat.rowsIndex();
375 IntegerConstArrayView columns = mat.columns();
376 RealConstArrayView mat_values = mat.values();
377 RealConstArrayView vec_values = vec.values();
378 RealArrayView out_vec_values = out_vec.values();
379
380 for( Integer i=0, is=nb_row; i<is; ++i ){
381 Real sum = 0.0;
382 for( Integer z=rows_index[i] ,zs=rows_index[i+1]; z<zs; ++z ){
383 Integer mj = columns[z];
384 Real mv = mat_values[z];
385 //cout << "ADD vec=" << vec_values[mj] << " mv=" << mv << " sum=" << sum << '\n';
386 sum += vec_values[mj]*mv;
387 }
388 out_vec_values[i] = sum;
389 }
390}
391
392Real MatrixOperation::
393dot(const Vector& vec)
394{
395 Integer size = vec.size();
396 RealConstArrayView vec_values = vec.values();
397 Real v = 0.0;
398 for( Integer i=0; i<size; ++i )
399 v += vec_values[i] * vec_values[i];
400 return v;
401}
402
403Real MatrixOperation::
404dot(const Vector& vec1,const Vector& vec2)
405{
406 Real v = 0.0;
407 Integer size = vec1.size();
408 RealConstArrayView vec1_values = vec1.values();
409 RealConstArrayView vec2_values = vec2.values();
410 for( Integer i=0; i<size; ++i ){
411 v += vec1_values[i] * vec2_values[i];
412 //cout << " i=" << i << " v=" << v << '\n';
413 }
414 return v;
415}
416
417void MatrixOperation::
418negateVector(Vector& vec)
419{
420 Integer size = vec.size();
421 RealArrayView vec_values = vec.values();
422 for( Integer i=0; i<size; ++i )
423 vec_values[i] = -vec_values[i];
424}
425
426void MatrixOperation::
427scaleVector(Vector& vec,Real mul)
428{
429 Integer size = vec.size();
430 RealArrayView vec_values = vec.values();
431 for( Integer i=0; i<size; ++i )
432 vec_values[i] *= mul;
433}
434
435void MatrixOperation::
436addVector(Vector& out_vec,const Vector& vec)
437{
438 Integer size = vec.size();
439 RealConstArrayView vec_values = vec.values();
440 RealArrayView out_vec_values = out_vec.values();
441 for( Integer i=0; i<size; ++i )
442 out_vec_values[i] += vec_values[i];
443}
444
445/*---------------------------------------------------------------------------*/
446/*---------------------------------------------------------------------------*/
447
448void ConjugateGradientSolver::
449_applySolver(const Matrix& a,const Vector& b,Vector& x,Real epsilon,IPreconditioner* p)
450{
451 MatrixOperation mat_op;
452 Integer vec_size = a.nbRow();
453 Vector r(vec_size);
454
455 // r = b - Ax
456 mat_op.matrixVectorProduct(a,x,r);
457 mat_op.negateVector(r);
458 mat_op.addVector(r,b);
459
460 m_nb_iteration = 0;
461 m_residual_norm = 0.0;
462
463 /*cout << " R=";
464 r.dump(cout);
465 cout << '\n';*/
466
467 Vector d(r.size());
468 if (p)
469 p->apply(d,r);
470 else
471 d.copy(r);
472
473 Vector q(r.size());
474 Vector t(r.size());
475 Vector s(r.size());
476 Real delta_new = 0.0;
477 //Real r0=mat_op.dot(r);
478 if (p){
479 delta_new = mat_op.dot(r,d);
480 }
481 else
482 delta_new = mat_op.dot(r);
483#if 0
484 cout << "R=";
485 r.dump(cout);
486 cout << "\n";
487 cout << "D=";
488 d.dump(cout);
489 cout << "\n";
490#endif
491 //Real norm0 = r.normInf();
492 Real delta0 = delta_new;
493 //cout << " TOL=" << epsilon << " delta0=" << delta0 << '\n';
494 //cout << " deltanew=" << delta_new << '\n';
495 Integer nb_iter = 0;
496 for( nb_iter=0; nb_iter<m_max_iteration; ++nb_iter ){
497 if (delta_new < epsilon*epsilon*delta0)
498 break;
499#if 0
500 // Si on utilise la norme inf
501 {
502 Real norm = r.normInf();
503 cout << " norm=" << norm << " norm0=" << norm0 << '\n';
504 if (norm < epsilon * norm0)
505 break;
506 }
507#endif
508
509 //cout << "delta_new=" << delta_new << '\n';
510 // q = A * d
511 mat_op.matrixVectorProduct(a,d,q);
512 Real alpha = delta_new / mat_op.dot(d,q);
513
514 // x = x + alpha * d
515 t.copy(d);
516 mat_op.scaleVector(t,alpha);
517 mat_op.addVector(x,t);
518
519#if 0
520 // r = b - Ax
521 mat_op.matrixVectorProduct(a,x,r);
522 mat_op.negateVector(r);
523 mat_op.addVector(r,b);
524#endif
525 // r = r - alpha * q
526 mat_op.scaleVector(q,-alpha);
527 mat_op.addVector(r,q);
528
529 if (p)
530 p->apply(s,r);
531 Real delta_old = delta_new;
532 if (p)
533 delta_new = mat_op.dot(r,s);
534 else
535 delta_new = mat_op.dot(r);
536 Real beta = delta_new / delta_old;
537 //cout << " alpha=" << alpha << " beta=" << beta << " delta_new=" << delta_new << '\n';
538 // d = beta * d + s
539 mat_op.scaleVector(d,beta);
540 if (p){
541 //mat_op.addVector(s,r);
542 mat_op.addVector(d,s);
543 }
544 else
545 mat_op.addVector(d,r);
546 //cout << '\n';
547 }
548 //cout << " X=";
549 //x.dump(cout);
550 //cout << '\n';
551 //cout << "NB ITER=" << nb_iter << " epsilon=" << epsilon
552 // << " delta0=" << delta0
553 // << " delta_new=" << delta_new << " r=" << mat_op.dot(r) << " r0=" << r0 << '\n';
554 m_nb_iteration = nb_iter;
555 m_residual_norm = delta_new;
556}
557
558/*---------------------------------------------------------------------------*/
559/*---------------------------------------------------------------------------*/
560
561void ConjugateGradientSolver::
562_applySolverAsHypre(const Matrix& a,const Vector& b,Vector& x,Real tol,
563 IPreconditioner* precond)
564{
565 //cout << "** APPLY ARCANE_SOLVER PCG using hypre method\n";
566 ARCANE_CHECK_POINTER(precond);
567
568 MatrixOperation mat_op;
569 Integer vec_size = a.nbRow();
570 Vector r(vec_size);
571 Vector p(vec_size);
572
573 const bool is_two_norm = true;
574 Real bi_prod = 0.0;
575 if (is_two_norm){
576 bi_prod = mat_op.dot(b,b);
577 }
578 else{
579 precond->apply(p,b);
580 bi_prod = mat_op.dot(p,b);
581 }
582 Real eps = tol*tol;
583 //TODO: regarder stop_crit
584
585 // r = b - Ax
586 mat_op.matrixVectorProduct(a,x,r);
587 mat_op.negateVector(r);
588 mat_op.addVector(r,b);
589
590 m_nb_iteration = 0;
591 m_residual_norm = 0.0;
592
593 /*cout << " R=";
594 r.dump(cout);
595 cout << '\n';*/
596
597 Vector tmp_x(x.size());
598
599 Vector d(r.size());
600 Vector s(r.size());
601 d.copy(r);
602 // p = C*r
603 precond->apply(p,r);
604
605 /* gamma = <r,p> */
606 Real gamma = mat_op.dot(r,p);
607
608 Real i_prod = 0.0;
609
610 //Real delta_new = 0.0;
611 //Real r0=mat_op.dot(r);
612 //if (p){
613 // delta_new = mat_op.dot(r,d);
614 //}
615 //else
616 // delta_new = mat_op.dot(r);
617#if 0
618 cout << "R=";
619 r.dump(cout);
620 cout << "\n";
621 cout << "D=";
622 d.dump(cout);
623 cout << "\n";
624#endif
625 //Real delta0 = delta_new;
626 //cout << "** TOL=" << tol << " bi_prod=" << bi_prod << '\n';
627 //cout << " deltanew=" << delta_new << '\n';
628 Integer nb_iter = 0;
629 for( nb_iter=0; nb_iter<m_max_iteration; ++nb_iter ){
630
631 // s = A * p
632 mat_op.matrixVectorProduct(a,p,s);
633
634 /* alpha = gamma / <s,p> */
635 Real sdotp = mat_op.dot(s, p);
636
637 Real alpha = gamma / sdotp;
638
639 Real gamma_old = gamma;
640
641 /* x = x + alpha*p */
642 mat_op.matrixVectorProduct(a,p,tmp_x);
643 mat_op.addVector(x,tmp_x);
644
645 /* r = r - alpha*s */
646 tmp_x.copy(s);
647 mat_op.scaleVector(tmp_x,-alpha);
648 mat_op.addVector(r,tmp_x);
649
650 /* s = C*r */
651 precond->apply(s,r);
652
653 /* gamma = <r,s> */
654 gamma = mat_op.dot(r,s);
655
656 /* set i_prod for convergence test */
657 if (is_two_norm)
658 i_prod = mat_op.dot(r,r);
659 else
660 i_prod = gamma;
661
662 //cout << "** sdotp=" << sdotp << " i_prod=" << i_prod << " bi_prod=" << bi_prod << '\n';
663
664 /* check for convergence */
665 if (i_prod / bi_prod < eps){
666#if 0
667 if (rel_change && i_prod > guard_zero_residual)
668 {
669 pi_prod = (*(pcg_functions->InnerProd))(p,p);
670 xi_prod = (*(pcg_functions->InnerProd))(x,x);
671 ratio = alpha*alpha*pi_prod/xi_prod;
672 if (ratio < eps)
673 {
674 (pcg_data -> converged) = 1;
675 break;
676 }
677 }
678 else
679 {
680#endif
681 //(pcg_data -> converged) = 1;
682 break;
683#if 0
684 }
685#endif
686 }
687
688 /* beta = gamma / gamma_old */
689 Real beta = gamma / gamma_old;
690
691 //cout << " alpha=" << alpha << " beta=" << beta << " delta_new=" << gamma << '\n';
692
693 /* p = s + beta p */
694 tmp_x.copy(p);
695 mat_op.scaleVector(tmp_x,beta);
696 mat_op.addVector(tmp_x,s);
697 p.copy(tmp_x);
698 }
699 //cout << " X=";
700 //x.dump(cout);
701 //cout << '\n';
702 //cout << "NB ITER=" << nb_iter << " epsilon=" << epsilon
703 // << " delta0=" << delta0
704 // << " delta_new=" << delta_new << " r=" << mat_op.dot(r) << " r0=" << r0 << '\n';
705 m_nb_iteration = nb_iter;
706 m_residual_norm = gamma;
707}
708
709/*---------------------------------------------------------------------------*/
710/*---------------------------------------------------------------------------*/
711
712bool ConjugateGradientSolver::
713solve(const Matrix& a,const Vector& b,Vector& x,Real epsilon,IPreconditioner* p)
714{
715 //epsilon = 1e-12;
716 //x.values().fill(0.0);
717 m_nb_iteration = 0;
718 m_residual_norm = 0.0;
719 //_doConjugateGradient(a,b,x,epsilon,&p);
720 cout.precision(20);
721 const bool do_print = false;
722 if (do_print){
723 cout << "A=";
724 a.dump(cout);
725 cout << '\n';
726 cout << "b=";
727 b.dump(cout);
728 cout << '\n';
729 }
730
731 DiagonalPreconditioner p2(a);
732 if (!p)
733 p = &p2;
734 _applySolver(a,b,x,epsilon,p);
735
736 if (do_print){
737 cout << "\n\nSOLUTION\nx=";
738 x.dump(cout);
739 cout << '\n';
740 }
741
742 return false;
743}
744
745/*---------------------------------------------------------------------------*/
746/*---------------------------------------------------------------------------*/
747
748static void
749_testArcaneMatrix1()
750{
751 Integer s = 5;
752 Matrix m(s,s);
753 Matrix m1(Matrix::read("test.mat"));
754 cout << "** o=" << m.nbRow() << '\n';
755 cout << "** M1=";
756 m1.dump(cout);
757 cout << '\n';
758 Vector v1(10);
759 for( Integer i=0; i<10; ++i ){
760 v1.values()[i] = (Real)(i+1);
761 }
762 Real epsilon = 1.0e-10;
763 {
764 Vector v2(10);
765 MatrixOperation mat_op;
766 Vector r(5);
767 mat_op.matrixVectorProduct(m1,v1,v2);
768 cout << "** V1=";
769 v1.dump(cout);
770 cout << "\n";
771 cout << "** V2=";
772 v2.dump(cout);
773 cout << "\n";
774 Vector b3(10);
775 for( Integer i=0; i<10; ++i ){
776 b3.values()[i] = (Real)(i+1);
777 }
778 Vector x3(10);
781 solver.solve(m1,b3,x3,epsilon,&p);
782 }
783
784 IntegerUniqueArray rows_size(s);
785 rows_size[0] = 5;
786 rows_size[1] = 2;
787 rows_size[2] = 2;
788 rows_size[3] = 2;
789 rows_size[4] = 2;
790 m.setRowsSize(rows_size);
791 RealUniqueArray values(13);
792 IntegerUniqueArray columns(13);
793 values[0] = 9.0;
794 values[1] = 1.5;
795 values[2] = 6.0;
796 values[3] = 0.75;
797 values[4] = 3.0;
798
799 values[5] = 1.5;
800 values[6] = 0.5;
801
802 values[7] = 6.0;
803 values[8] = 0.5;
804
805 values[9] = 0.75;
806 values[10] = 5.0 / 8.0;
807
808 values[11] = 3.0;
809 values[12] = 16.0;
810
811 columns[0] = 0;
812 columns[1] = 1;
813 columns[2] = 2;
814 columns[3] = 3;
815 columns[4] = 4;
816 columns[5] = 0;
817 columns[6] = 1;
818 columns[7] = 0;
819 columns[8] = 2;
820 columns[9] = 0;
821 columns[10] = 3;
822 columns[11] = 0;
823 columns[12] = 4;
824 m.setValues(columns,values);
825 m.dump(cout);
826 cout << '\n';
827 Vector b(5);
828 RealArrayView rav(b.values());
829 rav[0] = 1.0;
830 rav[1] = 1.0;
831 rav[2] = 1.0;
832 rav[3] = 3.0;
833 rav[4] = 1.0;
834 Vector x(5);
836 solver.solve(m,b,x,epsilon);
837}
838
839/*---------------------------------------------------------------------------*/
840/*---------------------------------------------------------------------------*/
841
842void _testArcaneMatrix2(Integer matrix_number)
843{
844 cout.precision(16);
845 cout.flags(std::ios::scientific);
846 String dir_name = "test-matrix";
847 StringBuilder ext_name;
848 ext_name += matrix_number;
849 ext_name += ".00000";
850 Matrix m(Matrix::readHypre(dir_name+"/MATRIX_matrix"+ext_name.toString()));
851 Vector b(Vector::readHypre(dir_name+"/MATRIX_b"+ext_name.toString()));
852 Vector xref(Vector::readHypre(dir_name+"/MATRIX_x"+ext_name.toString()));
853 Vector x(m.nbRow());
854 cout << "** XREF=" << xref.size() << '\n';
855 //m.dump(cout);
856 cout << '\n';
857 {
858 Real epsilon = 1.0e-15;
859 {
861 solver.solve(m,b,x,epsilon);
862 }
863 MatrixOperation mat_op;
864 mat_op.negateVector(xref);
865 mat_op.addVector(xref,x);
866 //xref.dump(cout);
867 Real x_norm = mat_op.dot(x);
868 Real diff_norm = mat_op.dot(xref);
869 cout << "** MATRIX_NUMBER = " << matrix_number;
870 if (!math::isNearlyZero(x_norm)){
871 cout << "** norm=" << x_norm << " REL=" << diff_norm/x_norm << '\n';
872 }
873 else
874 cout << "** norm=" << x_norm << " DIFF=" << diff_norm << '\n';
875 cout << '\n';
876 }
877 {
878 Real epsilon = 1.0e-15;
879 x.values().fill(0.0);
880 {
883 solver.solve(m,b,x,epsilon,&p);
884 }
885 MatrixOperation mat_op;
886 mat_op.negateVector(xref);
887 mat_op.addVector(xref,x);
888 //xref.dump(cout);
889 Real x_norm = mat_op.dot(x);
890 Real diff_norm = mat_op.dot(xref);
891 cout << "** PRECOND MATRIX_NUMBER = " << matrix_number;
892 if (!math::isNearlyZero(x_norm)){
893 cout << "** norm=" << x_norm << " REL=" << diff_norm/x_norm << '\n';
894 }
895 else
896 cout << "** norm=" << x_norm << " DIFF=" << diff_norm << '\n';
897 cout << '\n';
898 }
899}
900
901/*---------------------------------------------------------------------------*/
902/*---------------------------------------------------------------------------*/
903
904extern "C" void _testArcaneMatrix()
905{
906 _testArcaneMatrix1();
907 //for( Integer i=1; i<15; ++i )
908 //_testArcaneMatrix2(i);
909 exit(0);
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
915void MatrixImpl::
916setRowsSize(IntegerConstArrayView rows_size)
917{
918 Integer index = 0;
919 for( Integer i=0, is=m_nb_row; i<is; ++i ){
920 m_rows_index[i] = index;
921 index += rows_size[i];
922 }
923 m_rows_index[m_nb_row] = index;
924 m_nb_element = index;
925 m_columns.resize(index);
926 m_columns.fill(-1);
927 m_values.resize(index);
928}
929
930/*---------------------------------------------------------------------------*/
931/*---------------------------------------------------------------------------*/
932
933void MatrixImpl::
934setValues(IntegerConstArrayView columns,RealConstArrayView values)
935{
936 m_columns.copy(columns);
937 m_values.copy(values);
938 if (arcaneIsCheck())
939 checkValid();
940}
941
942/*---------------------------------------------------------------------------*/
943/*---------------------------------------------------------------------------*/
944
945void MatrixImpl::
946checkValid()
947{
948 IntegerConstArrayView columns = m_columns;
949 IntegerConstArrayView rows_index = m_rows_index;
950
951 Integer nb_column = m_nb_column;
952 for( Integer row=0, nb_row = m_nb_row; row<nb_row; ++row ){
953 for( Integer j=rows_index[row],js=rows_index[row+1]; j<js; ++j ){
954 if (columns[j]>=nb_column || columns[j]<0){
955 cout << "BAD COLUMN VALUE for row=" << row << " column=" << columns[j]
956 << " column_index=" << j
957 << " nb_column=" << nb_column << " nb_row=" << nb_row << '\n';
958 throw FatalErrorException("MatrixImpl::checkValid");
959 }
960 }
961 }
962}
963
964/*---------------------------------------------------------------------------*/
965/*---------------------------------------------------------------------------*/
966
967Real MatrixImpl::
968value(Integer row,Integer column) const
969{
970 IntegerConstArrayView rows_index = m_rows_index;
971 IntegerConstArrayView columns = m_columns;
972 RealConstArrayView values = m_values;
973
974 for( Integer z=rows_index[row], zs=rows_index[row+1]; z<zs; ++z ){
975 if (columns[z]==column)
976 return values[z];
977 }
978 return 0.0;
979}
980
981/*---------------------------------------------------------------------------*/
982/*---------------------------------------------------------------------------*/
983
984void MatrixImpl::
985setValue(Integer row,Integer column,Real value)
986{
987 IntegerConstArrayView rows_index = m_rows_index;
988 IntegerArrayView columns = m_columns;
989#ifdef ARCANE_CHECK
990 if (row>=m_nb_row)
991 throw ArgumentException("MatrixImpl::setValue","Invalid row");
992 if (column>=m_nb_column)
993 throw ArgumentException("MatrixImpl::setValue","Invalid column");
994 if (row<0)
995 throw ArgumentException("MatrixImpl::setValue","Invalid row");
996 if (column<0)
997 throw ArgumentException("MatrixImpl::setValue","Invalid column");
998#endif
999 for( Integer j=rows_index[row],js=rows_index[row+1]; j<js; ++j ){
1000 if (columns[j]==(-1) || columns[j]==column){
1001 columns[j] = column;
1002 m_values[j] = value;
1003 return;
1004 }
1005 }
1006 throw ArgumentException("Matrix::setValue","column not found");
1007}
1008
1009/*---------------------------------------------------------------------------*/
1010/*---------------------------------------------------------------------------*/
1011
1012void MatrixImpl::
1013sortDiagonale()
1014{
1015 assemble();
1016 if (arcaneIsCheck()){
1017 checkValid();
1018 }
1019 // Trie la diagonale pour qu'elle soit le premièr élément de la ligne
1020 IntegerConstArrayView rows_index = m_rows_index;
1021 IntegerArrayView columns = m_columns;
1022 RealArrayView values = m_values;
1023 for( Integer row=0, nb_row = m_nb_row; row<nb_row; ++row ){
1024 Integer first_col = rows_index[row];
1025 for( Integer j=first_col,js=rows_index[row+1]; j<js; ++j ){
1026 if (columns[j]==row){
1027 Integer c = columns[first_col];
1028 Real v = values[first_col];
1029 columns[first_col] = columns[j];
1030 values[first_col] = values[j];
1031 columns[j] = c;
1032 values[j] = v;
1033 }
1034 }
1035 }
1036 if (arcaneIsCheck())
1037 checkValid();
1038}
1039
1040/*---------------------------------------------------------------------------*/
1041/*---------------------------------------------------------------------------*/
1042
1043void MatrixImpl::
1044assemble()
1045{
1046 IntegerConstArrayView rows_index = m_rows_index;
1047 IntegerArrayView columns = m_columns;
1048 RealConstArrayView values = m_values;
1049
1050 SharedArray<Integer> new_rows_index(m_nb_row+1);
1051 SharedArray<Integer> new_columns;
1052 SharedArray<Real> new_values;
1053
1054 new_rows_index[0] = 0;
1055 for( Integer row=0, nb_row = m_nb_row; row<nb_row; ++row ){
1056 Integer first_col = rows_index[row];
1057 for( Integer j=first_col,js=rows_index[row+1]; j<js; ++j ){
1058 if (columns[j]>=0){
1059 new_columns.add(columns[j]);
1060 new_values.add(values[j]);
1061 }
1062 }
1063 new_rows_index[row+1] = new_columns.size();
1064 }
1065
1066 m_rows_index = new_rows_index;
1067 m_columns = new_columns;
1068 m_values = new_values;
1069 m_nb_element = new_values.size();
1070 if (arcaneIsCheck())
1071 checkValid();
1072}
1073
1074/*---------------------------------------------------------------------------*/
1075/*---------------------------------------------------------------------------*/
1076
1077void MatrixImpl::
1078dump(std::ostream& o)
1079{
1080 o << "(Matrix nb_row=" << m_nb_row << " nb_col=" << m_nb_column << ")\n";
1081 //Integer index = 0;
1082 for( Integer i=0, is=m_nb_row; i<is; ++i ){
1083 o << "[" << i << "] ";
1084 Real sum = 0.0;
1085 for( Integer z=m_rows_index[i] ,zs=m_rows_index[i+1]; z<zs; ++z ){
1086 Integer j = m_columns[z];
1087 Real v = m_values[z];
1088 sum += v;
1089 o << " ["<<j<<"]="<<v;
1090 }
1091 o << " S=" << sum << '\n';
1092 }
1093 //o << ")";
1094}
1095
1096/*---------------------------------------------------------------------------*/
1097/*---------------------------------------------------------------------------*/
1098
1100read(const String& filename)
1101{
1102 std::ifstream ifile(filename.localstr());
1103 Integer nb_x = 0;
1104 Integer nb_y = 0;
1105 ifile >> ws >> nb_x >> ws >> nb_y;
1106 //cout << "** ** N=" << nb_x << ' ' << nb_y << '\n';
1107 if (nb_x!=nb_y)
1108 throw FatalErrorException("Matrix::read","not a square matrix");
1109 Matrix m(nb_x,nb_y);
1110 IntegerUniqueArray rows_size(nb_x);
1113 for( Integer x=0; x<nb_x; ++x ){
1114 Integer nb_column = 0;
1115 for( Integer y=0; y<nb_y; ++y ){
1116 Real v =0.0;
1117 ifile >> v;
1118 if (!math::isZero(v)){
1119 columns.add(y);
1120 values.add(v);
1121 ++nb_column;
1122 }
1123 }
1124 rows_size[x] = nb_column;
1125 }
1126 m.setRowsSize(rows_size);
1128 return m;
1129}
1130
1131/*---------------------------------------------------------------------------*/
1132/*---------------------------------------------------------------------------*/
1133
1135readHypre(const String& filename)
1136{
1137 std::ifstream ifile(filename.localstr());
1138 Integer nb_x = 0;
1139 Integer nb_y = 0;
1140 Integer nb_value = 0;
1141 Integer xf;
1142 ifile >> ws >> nb_x >> ws >> nb_y;
1143 ifile >> ws >> xf >> ws >> xf >> ws >> xf;
1144 ifile >> ws >> nb_value >> ws >> xf;
1145 ifile >> ws >> xf >> ws >> xf;
1146 ifile >> ws >> xf >> ws >> xf;
1147 //cout << "** ** N=" << nb_x << ' ' << nb_y << '\n';
1148 if (nb_x!=nb_y)
1149 throw FatalErrorException(A_FUNCINFO,"not a square matrix");
1150 Matrix m(nb_x,nb_y);
1151 IntegerUniqueArray rows_size(nb_x);
1154
1155 Integer nb_column = 0;
1156 Integer last_row = 0;
1157 for( Integer i=0; i<nb_value; ++i ){
1158 Integer x = 0;
1159 Integer y = 0;
1160 Real v = 0.0;
1161 ifile >> ws >> x >> ws >> y >> ws >> v;
1162 if (x!=last_row){
1163 // Nouvelle ligne.
1164 rows_size[last_row] = nb_column;
1165 nb_column = 0;
1166 last_row = x;
1167 }
1168 columns.add(y);
1169 values.add(v);
1170 ++nb_column;
1171 }
1172 rows_size[last_row] = nb_column;
1173 m.setRowsSize(rows_size);
1175 return m;
1176}
1177
1178/*---------------------------------------------------------------------------*/
1179/*---------------------------------------------------------------------------*/
1180
1181} // End namespace Arcane::MatVec
1182
1183/*---------------------------------------------------------------------------*/
1184/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Exception lorsqu'une erreur fatale est survenue.
Interface d'un préconditionneur.
Matrice avec stockage CSR.
Definition Matrix.cc:40
Matrice avec stockage CSR.
MatrixImpl * m_impl
Implémentation.
static Matrix readHypre(const String &filename)
Lit la matrice au format Hypre.
Definition Matrix.cc:1135
void sortDiagonale()
Arrange le stockage pour que la diagonale soit le premier élément.
Definition Matrix.cc:180
IntegerConstArrayView rowsIndex() const
Indices des premiers éléments de chaque ligne.
Definition Matrix.cc:208
Real value(Integer row, Integer column) const
Retourne la valeur d'un élément de la matrice.
Definition Matrix.cc:235
void setRowsSize(IntegerConstArrayView rows_size)
Positionne le nombre d'éléments non nuls de chaque ligne.
Definition Matrix.cc:253
void setValues(IntegerConstArrayView columns, RealConstArrayView values)
Positionne les valeurs des éléments de la matrice.
Definition Matrix.cc:244
IntegerConstArrayView columns() const
Indices des colonnes des valeurs.
Definition Matrix.cc:298
void setValue(Integer row, Integer column, Real value)
Positionne la valeur d'un élément de la matrice.
Definition Matrix.cc:226
static Matrix read(const String &filename)
Lit la matrice au format X Y.
Definition Matrix.cc:1100
void dump(std::ostream &o) const
Imprime la matrice.
Definition Matrix.cc:217
RealConstArrayView values() const
Valeurs de la matrice.
Definition Matrix.cc:262
Matrix clone() const
Clone la matrice.
Definition Matrix.cc:198
Vecteur d'algèbre linéraire.
static Vector readHypre(const String &file_name)
Initialise un vecteur en utilisant un fichier au format Hypre.
Definition Vector.cc:210
Vecteur 1D de données avec sémantique par référence.
SharedArray< T > clone() const
Clone le tableau.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
Int32 Integer
Type représentant un entier.
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:544
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:436
double Real
Type représentant un réel.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:434
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:573
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:546
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:575