Arcane  v3.14.10.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/*---------------------------------------------------------------------------*/
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
226setValue(Integer row,Integer column,Real value)
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
245{
246 m_impl->setValues(columns,values);
247}
248
249/*---------------------------------------------------------------------------*/
250/*---------------------------------------------------------------------------*/
251
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();
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);
779 DiagonalPreconditioner p(m1);
780 ConjugateGradientSolver solver;
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);
835 ConjugateGradientSolver solver;
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 {
860 ConjugateGradientSolver solver;
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 {
881 DiagonalPreconditioner p(m);
882 ConjugateGradientSolver solver;
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);
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 }
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);
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.
1165 nb_column = 0;
1166 last_row = x;
1167 }
1168 columns.add(y);
1169 values.add(v);
1170 ++nb_column;
1171 }
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.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
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
static Vector readHypre(const String &file_name)
Initialise un vecteur en utilisant un fichier au format Hypre.
Definition Vector.cc:210
Integer size() const
Nombre d'éléments du vecteur.
Definition Vector.cc:140
RealArrayView values()
Valeurs du vecteur.
Definition Vector.cc:149
Vue modifiable d'un tableau d'un type T.
void copy(Span< const T > rhs)
Copie les valeurs de rhs dans l'instance.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
Vue constante d'un tableau de type T.
Exception lorsqu'une erreur fatale est survenue.
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
Vecteur 1D de données avec sémantique par valeur (style STL).
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:151
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:615
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:646
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:521
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:519
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:644
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:617
Int32 Integer
Type représentant un entier.