MatrixWrapper.hpp
Go to the documentation of this file.
1#ifndef OPM_MIXED_MATRIX_HEADER_INCLUDED
2#define OPM_MIXED_MATRIX_HEADER_INCLUDED
3
4
6
7#include <opm/common/ErrorMacros.hpp>
8
9#include <stdexcept>
10
11namespace Opm
12{
13
20template <class Vector>
22{
23 public:
24
25 // extract block size
26 static constexpr auto block_size = Vector::block_type::dimension;
27
33 {
34 nnz_=nnz;
35 M_ = bsr_alloc();
36 bsr_init(M_, nrows, nnz, block_size);
37 }
38
41
48 void update(double const *data);
49
54 void mv(const Vector& x, Vector& y) const;
55
61 void umv(const Vector& x, Vector& y) const;
62
69 void usmv(double alpha, const Vector& x, Vector& y) const;
70
72 int *rowptr(){return M_->rowptr;}
73
75 int *colidx(){return M_->colidx;}
76
77 int nrows() const {return M_->nrows;}
78
79 private:
80 int nnz_;
81 bsr_matrix *M_;
82};
83
93template <class Vector>
95mv(const Vector& x, Vector& y) const
96{
97 int constexpr b = block_size;
98 if constexpr(b==1){OPM_THROW(std::invalid_argument, "MixedMatrixWrapper::mv does not support block size == 1!\n");}
99 else if constexpr(b==2) bsr_vmspmv2(M_, &x[0][0], &y[0][0]);
100 else if constexpr(b==3) bsr_vmspmv3(M_, &x[0][0], &y[0][0]);
101 else if constexpr(b==4) bsr_vmspmv4(M_, &x[0][0], &y[0][0]);
102 else
103 {
104 int nrows = M_->nrows;
105 int *rowptr=M_->rowptr;
106 int *colidx=M_->colidx;
107 const float *data=M_->flt;
108
109 int constexpr bb = b*b;
110 double yy[bb];
111 for(int i=0;i<nrows;i++)
112 {
113 for(int k=0;k<bb;k++) yy[k] = 0.0;
114 for(int k=rowptr[i];k<rowptr[i+1];k++)
115 {
116 const float *AA=data+bb*k;
117
118 int j = colidx[k];
119 double const *xx = &x[0][0]+b*j;
120 for(int n=0;n<b;n++) for(int m=0;m<b;m++) yy[m+b*n] += AA[m+b*n]*xx[n];
121 }
122
123 // sum over columns
124 double z[b];
125 for(int m=0;m<b;m++) z[m] = yy[m];
126 for(int n=1;n<b;n++) for(int m=0;m<b;m++) z[m] += yy[m+b*n];
127
128 double *y_i = &y[0][0] + b*i;
129 for(int m=0;m<b;m++) y_i[m] = z[m];
130 }
131 }
132}
133
143template <class Vector>
145umv(const Vector& x, Vector& y) const
146{
147 int constexpr b = block_size;
148 if constexpr(b==1){OPM_THROW(std::invalid_argument, "MixedMatrixWrapper::umv does not support block size == 1!\n");}
149 else if constexpr(b==2) bsr_vmspumv2(M_, &x[0][0], &y[0][0], 1.0);
150 else if constexpr(b==3) bsr_vmspumv3(M_, &x[0][0], &y[0][0], 1.0);
151 else if constexpr(b==4) bsr_vmspumv4(M_, &x[0][0], &y[0][0], 1.0);
152 else {OPM_THROW(std::invalid_argument, "MixedMatrixWrapper::umv does not support block size == 1!\n");}
153}
154
165template <class Vector>
167usmv(double alpha, const Vector& x, Vector& y) const
168{
169 int constexpr b = block_size;
170 if constexpr(b==1){OPM_THROW(std::invalid_argument, "MixedMatrixWrapper::usmv does not support block size == 1!\n");}
171 else if constexpr(b==2) bsr_vmspumv2(M_, &x[0][0], &y[0][0], alpha);
172 else if constexpr(b==3) bsr_vmspumv3(M_, &x[0][0], &y[0][0], alpha);
173 else if constexpr(b==4) bsr_vmspumv4(M_, &x[0][0], &y[0][0], alpha);
174 else
175 {
176 int nrows = M_->nrows;
177 int *rowptr=M_->rowptr;
178 int *colidx=M_->colidx;
179 const float *data=M_->flt;
180
181 int constexpr bb = b*b;
182 double yy[bb];
183 for(int i=0;i<nrows;i++)
184 {
185 for(int k=0;k<bb;k++) yy[k] = 0.0;
186 for(int k=rowptr[i];k<rowptr[i+1];k++)
187 {
188 const float *AA=data+bb*k;
189
190 int j = colidx[k];
191 double const *xx = &x[0][0]+b*j;
192 for(int n=0;n<b;n++) for(int m=0;m<b;m++) yy[m+b*n] += AA[m+b*n]*xx[n];
193 }
194
195 // sum over columns
196 double z[b];
197 for(int m=0;m<b;m++) z[m] = yy[m];
198 for(int n=1;n<b;n++) for(int m=0;m<b;m++) z[m] += yy[m+b*n];
199
200 double *y_i = &y[0][0] + b*i;
201 for(int m=0;m<b;m++) y_i[m] += alpha*z[m];
202 }
203
204 }
205}
206
213template <class Vector>
215update(double const *data)
216{
217 // transpose each dense block to make them column-major
218 int constexpr b = block_size;
219 int constexpr bb=b*b;
220 double B[bb];
221 for(int k=0;k<nnz_;k++)
222 {
223 for(int i=0;i<b;i++) for(int j=0;j<b;j++) B[b*j+i] = data[bb*k + b*i + j];
224 for(int i=0;i<bb;i++) M_->flt[bb*k + i] = B[i];
225 }
226}
227
228
229} // namespace Opm
230#endif // OPM_MIXED_MATRIX_HEADER_INCLUDED
void bsr_vmspmv4(bsr_matrix *A, const double *x, double *y)
void bsr_vmspumv2(bsr_matrix *A, const double *x, double *y, double alpha)
Sparse matrix-vector multiplication in mixed precision.
void bsr_vmspmv2(bsr_matrix *A, const double *x, double *y)
Sparse matrix-vector multiplication in mixed precision.
void bsr_vmspumv3(bsr_matrix *A, const double *x, double *y, double alpha)
void bsr_vmspumv4(bsr_matrix *A, const double *x, double *y, double alpha)
bsr_matrix * bsr_alloc(void)
Create empty bsr matrix.
void bsr_vmspmv3(bsr_matrix *A, const double *x, double *y)
void bsr_free(bsr_matrix *A)
Delete bsr matrix.
void bsr_init(bsr_matrix *A, int nrows, int nnz, int b)
Initialize bsr matrix.
Wraps c-implementation of mixed-precision matrix.
Definition: MatrixWrapper.hpp:22
MixedMatrixWrapper(int nrows, int nnz)
constructor
Definition: MatrixWrapper.hpp:32
~MixedMatrixWrapper()
destructor
Definition: MatrixWrapper.hpp:40
void mv(const Vector &x, Vector &y) const
block-sparse matrix-vector multiplication (y = M.x)
Definition: MatrixWrapper.hpp:95
int * rowptr()
access row offset pointer
Definition: MatrixWrapper.hpp:72
void update(double const *data)
update matrix entries
Definition: MatrixWrapper.hpp:215
int * colidx()
access column index pointer
Definition: MatrixWrapper.hpp:75
void umv(const Vector &x, Vector &y) const
block-sparse matrix-vector multiplication with update (y += M.x)
Definition: MatrixWrapper.hpp:145
void usmv(double alpha, const Vector &x, Vector &y) const
block-sparse matrix-vector multiplication with scaled update (y += alpha * M.x)
Definition: MatrixWrapper.hpp:167
int nrows() const
Definition: MatrixWrapper.hpp:77
static constexpr auto block_size
Definition: MatrixWrapper.hpp:26
Definition: blackoilbioeffectsmodules.hh:45
Mixed-precision bsr matrix.
Definition: bsr.h:12
int * colidx
Definition: bsr.h:25
int * rowptr
Definition: bsr.h:23
int nrows
Definition: bsr.h:14