Extension: Matrix functions
#include "dg/matrix/matrix.h"
mcg.h
Go to the documentation of this file.
1#pragma once
2#include <cusp/dia_matrix.h>
3#include <cusp/coo_matrix.h>
4
5//#include <cusp/print.h>
6#include "dg/algorithm.h"
7#include "tridiaginv.h"
8#include "matrixfunction.h"
9
14namespace dg{
15namespace mat{
16
35template< class ContainerType>
36class MCG
37{
38 public:
40 using HCooMatrix = cusp::coo_matrix<int, value_type, cusp::host_memory>;
41 using HDiaMatrix = cusp::dia_matrix<int, value_type, cusp::host_memory>;
42 using HVec = dg::HVec;
44 MCG(){}
51 MCG( const ContainerType& copyable, unsigned max_iterations)
52 {
53 m_ap = m_p = m_r = copyable;
54 m_max_iter = max_iterations;
55 set_iter( max_iterations);
56 }
57
60 void set_max( unsigned new_max) {
61 m_max_iter = new_max;
62 set_iter( new_max);
63 }
64
67 unsigned get_max() const {return m_max_iter;}
68
71 void set_verbose( bool verbose){ m_verbose = verbose;}
72
75 value_type get_bnorm() const{return m_bnorm;}
76
78 template<class ...Params>
79 void construct( Params&& ...ps)
80 {
81 //construct and swap
82 *this = MCG( std::forward<Params>( ps)...);
83 }
87 unsigned get_iter() const {return m_iter;}
97 template< class MatrixType, class DiaMatrixType, class ContainerType0,
98 class ContainerType1, class ContainerType2>
99 void Ry( MatrixType&& A, const DiaMatrixType& T,
100 const ContainerType0& y, ContainerType1& x,
101 const ContainerType2& b)
102 {
103 dg::blas1::copy(0., x);
104
105 dg::blas1::copy( b, m_r);
106
107 dg::blas1::copy( m_r, m_p );
108
109 dg::blas1::axpby( y[0], m_r, 1., x); //Compute x= R y
110 for ( unsigned i=0; i<y.size()-1; i++)
111 {
112 dg::blas2::symv( std::forward<MatrixType>(A), m_p, m_ap);
113 value_type alphainv = i==0 ? T.values( i,1) :
114 T.values(i,1) + T.values( i-1,2);
115 value_type beta = -T.values( i,2)/alphainv;
116 dg::blas1::axpby( -1./alphainv, m_ap, 1., m_r);
117 dg::blas1::axpby(1., m_r, beta, m_p );
118 dg::blas1::axpby( y[i+1], m_r, 1., x); //Compute x= R y
119 }
120 }
145 template< class MatrixType, class ContainerType0, class ContainerType1>
146 const HDiaMatrix& operator()( MatrixType&& A, const ContainerType0& b,
147 const ContainerType1& weights, value_type eps = 1e-12,
148 value_type nrmb_correction = 1., value_type res_fac = 1.)
149 {
150#ifdef MPI_VERSION
151 int rank;
152 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
153#endif //MPI
154 value_type nrmzr_old = dg::blas2::dot( b, weights, b);
155 value_type nrmb = sqrt(nrmzr_old);
156 m_bnorm = nrmb;
157 if( m_verbose)
158 {
159 DG_RANK0 std::cout << "# Norm of b "<<nrmb <<"\n";
160 DG_RANK0 std::cout << "# Res factor "<<res_fac <<"\n";
161 DG_RANK0 std::cout << "# Residual errors: \n";
162 }
163 if( nrmb == 0)
164 {
165 set_iter(1);
166 return m_TH;
167 }
168 dg::blas1::copy( b, m_r);
169 dg::blas1::copy( m_r, m_p );
170
171 value_type alpha = 0, beta = 0, nrmzr_new = 0, alpha_old = 0., beta_old = 0.;
172 for( unsigned i=0; i<m_max_iter; i++)
173 {
174 alpha_old = alpha, beta_old = beta;
175 dg::blas2::symv( std::forward<MatrixType>(A), m_p, m_ap);
176 alpha = nrmzr_old /dg::blas2::dot( m_p, weights, m_ap);
177 dg::blas1::axpby( -alpha, m_ap, 1., m_r);
178 nrmzr_new = dg::blas2::dot( m_r, weights, m_r);
179 beta = nrmzr_new/nrmzr_old;
180 if(m_verbose)
181 {
182 DG_RANK0 std::cout << "# ||r||_W = " << sqrt(nrmzr_new) << "\tat i = " << i << "\n";
183 }
184 if( i == 0)
185 {
186 m_TH.values(i,0) = 0.;
187 m_TH.values(i,1) = 1./alpha;
188 m_TH.values(i,2) = -beta/alpha;
189 }
190 else
191 {
192 m_TH.values(i,0) = -1./alpha_old;
193 m_TH.values(i,1) = 1./alpha + beta_old/alpha_old;
194 m_TH.values(i,2) = -beta/alpha;
195 }
196 if( res_fac*sqrt( nrmzr_new)
197 < eps*(nrmb + nrmb_correction))
198 {
199 set_iter(i+1);
200 break;
201 }
202 dg::blas1::axpby(1., m_r, beta, m_p );
203 nrmzr_old=nrmzr_new;
204 }
205
206 return m_TH;
207 }
215 HVec e1H(m_iter, 0.);
216 e1H[0] = 1.;
217 return e1H;
218 }
219 private:
222 void set_iter( unsigned new_iter) {
223 // The alignment (which is the pitch of the underlying values)
224 // of m_max_iter preserves the existing elements
225 m_TH.resize(new_iter, new_iter, 3*new_iter-2, 3, m_max_iter);
226 m_TH.diagonal_offsets[0] = -1;
227 m_TH.diagonal_offsets[1] = 0;
228 m_TH.diagonal_offsets[2] = 1;
229 m_iter = new_iter;
230 }
231 ContainerType m_r, m_ap, m_p;
232 unsigned m_max_iter, m_iter;
233 HDiaMatrix m_TH;
234 bool m_verbose = false;
235 value_type m_bnorm = 0.;
236};
237
256template<class Container>
258{
259 public:
261 using HDiaMatrix = cusp::dia_matrix<int, value_type, cusp::host_memory>;
262 using HCooMatrix = cusp::coo_matrix<int, value_type, cusp::host_memory>;
263 using HArray2d = cusp::array2d< value_type, cusp::host_memory>;
264 using HArray1d = cusp::array1d< value_type, cusp::host_memory>;
265 using HVec = dg::HVec;
274 MCGFuncEigen( const Container& copyable, unsigned max_iterations)
275 {
276 m_e1H.assign(max_iterations, 0.);
277 m_e1H[0] = 1.;
278 m_yH.assign(max_iterations, 1.);
279 m_mcg.construct(copyable, max_iterations);
280 }
282 template<class ...Params>
283 void construct( Params&& ...ps)
284 {
285 //construct and swap
286 *this = MCGFuncEigen( std::forward<Params>( ps)...);
287 }
303 template < class MatrixType, class ContainerType0, class ContainerType1 ,
304 class ContainerType2, class UnaryOp>
305 unsigned operator()(ContainerType0& x, UnaryOp f,
306 MatrixType&& A, const ContainerType1& b,
307 const ContainerType2& weights, value_type eps,
308 value_type nrmb_correction, value_type res_fac )
309 {
310 if( sqrt(dg::blas2::dot(b, weights, b)) == 0)
311 {
312 dg::blas1::copy( b, x);
313 return 0;
314 }
315 //Compute x (with initODE with gemres replacing cg invert)
316 m_TH = m_mcg(std::forward<MatrixType>(A), b, weights, eps,
317 nrmb_correction, res_fac);
318 unsigned iter = m_mcg.get_iter();
319 //resize
320 m_alpha.resize(iter);
321 m_delta.resize(iter,1.);
322 m_beta.resize(iter-1);
323 m_evals.resize(iter);
324 m_evecs.resize(iter,iter);
325 m_e1H.resize(iter, 0.);
326 m_e1H[0] = 1.;
327 m_yH.resize(iter);
328 //fill diagonal entries of similarity transformed T matrix (now symmetric)
329 for(unsigned i = 0; i<iter; i++)
330 {
331 m_alpha[i] = m_TH.values(i,1);
332 if (i<iter-1) {
333 if (m_TH.values(i,2) > 0.) m_beta[i] = sqrt(m_TH.values(i,2)*m_TH.values(i+1,0)); // sqrt(b_i * c_i)
334 else if (m_TH.values(i,2) < 0.) m_beta[i] = -sqrt(m_TH.values(i,2)*m_TH.values(i+1,0)); //-sqrt(b_i * c_i)
335 else m_beta[i] = 0.;
336 }
337 if (i>0) m_delta[i] = m_delta[i-1]*sqrt(m_TH.values(i,0)/m_TH.values(i-1,2));
338 }
339 //Compute Eigendecomposition
340 cusp::lapack::stev(m_alpha, m_beta, m_evals, m_evecs);
341 //convert to COO matrix format
342// cusp::print(m_evals);
343 cusp::convert(m_evecs, m_EH);
344 cusp::transpose(m_EH, m_EHt);
345 //Compute f(T) e1 = D E f(Lambda) E^t D^{-1} e1
346 dg::blas1::pointwiseDivide(m_e1H, m_delta, m_e1H);
347 dg::blas2::symv(m_EHt, m_e1H, m_yH);
348 dg::blas1::transform(m_evals, m_e1H, [f] (double x){
349 try{
350 return f(x);
351 }
352 catch(boost::exception& e) //catch boost overflow error
353 {
354 return 0.;
355 }
356 });
357 dg::blas1::pointwiseDot(m_e1H, m_yH, m_e1H);
358 dg::blas2::symv(m_EH, m_e1H, m_yH);
359 dg::blas1::pointwiseDot(m_yH, m_delta, m_yH);
360 //Compute x = R f(T) e_1
361 m_mcg.Ry(std::forward<MatrixType>(A), m_TH, m_yH, x, b);
362
363 return iter;
364 }
365 private:
366 HVec m_e1H, m_yH;
367 HDiaMatrix m_TH;
368 HCooMatrix m_EH, m_EHt;
369 HArray2d m_evecs;
370 HArray1d m_alpha, m_beta, m_delta, m_evals;
372
373};
374} //namespace mat
375} //namespace dg
376
EXPERIMENTAL Shortcut for solve via exploiting first a Krylov projection achieved by the M-CG method...
Definition: mcg.h:258
dg::get_value_type< Container > value_type
Definition: mcg.h:260
cusp::coo_matrix< int, value_type, cusp::host_memory > HCooMatrix
Definition: mcg.h:262
dg::HVec HVec
Definition: mcg.h:265
cusp::dia_matrix< int, value_type, cusp::host_memory > HDiaMatrix
Definition: mcg.h:261
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: mcg.h:283
cusp::array1d< value_type, cusp::host_memory > HArray1d
Definition: mcg.h:264
MCGFuncEigen()
Allocate nothing, Call construct method before usage.
Definition: mcg.h:267
MCGFuncEigen(const Container &copyable, unsigned max_iterations)
Construct MCGFuncEigen.
Definition: mcg.h:274
cusp::array2d< value_type, cusp::host_memory > HArray2d
Definition: mcg.h:263
unsigned operator()(ContainerType0 &x, UnaryOp f, MatrixType &&A, const ContainerType1 &b, const ContainerType2 &weights, value_type eps, value_type nrmb_correction, value_type res_fac)
Compute via M-CG method and Eigen decomposition.
Definition: mcg.h:305
EXPERIMENTAL Tridiagonalize and approximate via CG algorithm. A is self-adjoint in the weights .
Definition: mcg.h:37
value_type get_bnorm() const
Norm of b from last call to operator()
Definition: mcg.h:75
void set_verbose(bool verbose)
Set or unset debugging output during iterations.
Definition: mcg.h:71
unsigned get_max() const
Get the current maximum number of iterations.
Definition: mcg.h:67
const HDiaMatrix & operator()(MatrixType &&A, const ContainerType0 &b, const ContainerType1 &weights, value_type eps=1e-12, value_type nrmb_correction=1., value_type res_fac=1.)
Tridiagonalize the system using CG.
Definition: mcg.h:146
void Ry(MatrixType &&A, const DiaMatrixType &T, const ContainerType0 &y, ContainerType1 &x, const ContainerType2 &b)
Compute x = R y.
Definition: mcg.h:99
cusp::coo_matrix< int, value_type, cusp::host_memory > HCooMatrix
Definition: mcg.h:40
dg::get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition: mcg.h:39
dg::HVec HVec
Definition: mcg.h:42
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: mcg.h:79
cusp::dia_matrix< int, value_type, cusp::host_memory > HDiaMatrix
Definition: mcg.h:41
void set_max(unsigned new_max)
Set the maximum number of iterations.
Definition: mcg.h:60
MCG()
Allocate nothing, Call construct method before usage.
Definition: mcg.h:44
MCG(const ContainerType &copyable, unsigned max_iterations)
Allocate memory for the mcg method.
Definition: mcg.h:51
unsigned get_iter() const
Get the number of iterations in the last call to operator() (size of T)
Definition: mcg.h:87
HVec make_e1()
Return the vector with size get_iter()
Definition: mcg.h:214
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
void transform(const ContainerType1 &x, ContainerType &y, UnaryOp op)
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
void pointwiseDivide(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
void pointwiseDot(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
get_value_type< MatrixType > dot(const ContainerType1 &x, const MatrixType &m, const ContainerType2 &y)
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
void transpose(unsigned nx, unsigned ny, const ContainerType &in, ContainerType &out)
dg::MIHMatrix_t< real_type > convert(const dg::IHMatrix_t< real_type > &global, const ConversionPolicy &policy)
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
thrust::host_vector< double > HVec
Classes for Krylov space approximations of a Matrix-Vector product.
#define DG_RANK0