Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F101938109
matrixfree_cg.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 15, 08:58
Size
4 KB
Mime Type
text/x-c++
Expires
Mon, Feb 17, 08:58 (2 d)
Engine
blob
Format
Raw Data
Handle
24249251
Attached To
rDLMA Diffusion limited mixed aggregation
matrixfree_cg.cpp
View Options
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/IterativeLinearSolvers>
#include <unsupported/Eigen/IterativeSolvers>
class
MatrixReplacement
;
using
Eigen
::
SparseMatrix
;
namespace
Eigen
{
namespace
internal
{
// MatrixReplacement looks-like a SparseMatrix, so let's inherits its traits:
template
<>
struct
traits
<
MatrixReplacement
>
:
public
Eigen
::
internal
::
traits
<
Eigen
::
SparseMatrix
<
double
>
>
{};
}
}
// Example of a matrix-free wrapper from a user type to Eigen's compatible type
// For the sake of simplicity, this example simply wrap a Eigen::SparseMatrix.
class
MatrixReplacement
:
public
Eigen
::
EigenBase
<
MatrixReplacement
>
{
public
:
// Required typedefs, constants, and method:
typedef
double
Scalar
;
typedef
double
RealScalar
;
typedef
int
StorageIndex
;
enum
{
ColsAtCompileTime
=
Eigen
::
Dynamic
,
MaxColsAtCompileTime
=
Eigen
::
Dynamic
,
IsRowMajor
=
false
};
Index
rows
()
const
{
return
mp_mat
->
rows
();
}
Index
cols
()
const
{
return
mp_mat
->
cols
();
}
template
<
typename
Rhs
>
Eigen
::
Product
<
MatrixReplacement
,
Rhs
,
Eigen
::
AliasFreeProduct
>
operator
*
(
const
Eigen
::
MatrixBase
<
Rhs
>&
x
)
const
{
return
Eigen
::
Product
<
MatrixReplacement
,
Rhs
,
Eigen
::
AliasFreeProduct
>
(
*
this
,
x
.
derived
());
}
// Custom API:
MatrixReplacement
()
:
mp_mat
(
0
)
{}
void
attachMyMatrix
(
const
SparseMatrix
<
double
>
&
mat
)
{
mp_mat
=
&
mat
;
}
const
SparseMatrix
<
double
>
my_matrix
()
const
{
return
*
mp_mat
;
}
private
:
const
SparseMatrix
<
double
>
*
mp_mat
;
};
// Implementation of MatrixReplacement * Eigen::DenseVector though a specialization of internal::generic_product_impl:
namespace
Eigen
{
namespace
internal
{
template
<
typename
Rhs
>
struct
generic_product_impl
<
MatrixReplacement
,
Rhs
,
SparseShape
,
DenseShape
,
GemvProduct
>
// GEMV stands for matrix-vector
:
generic_product_impl_base
<
MatrixReplacement
,
Rhs
,
generic_product_impl
<
MatrixReplacement
,
Rhs
>
>
{
typedef
typename
Product
<
MatrixReplacement
,
Rhs
>::
Scalar
Scalar
;
template
<
typename
Dest
>
static
void
scaleAndAddTo
(
Dest
&
dst
,
const
MatrixReplacement
&
lhs
,
const
Rhs
&
rhs
,
const
Scalar
&
alpha
)
{
// This method should implement "dst += alpha * lhs * rhs" inplace,
// however, for iterative solvers, alpha is always equal to 1, so let's not bother about it.
assert
(
alpha
==
Scalar
(
1
)
&&
"scaling is not implemented"
);
EIGEN_ONLY_USED_FOR_DEBUG
(
alpha
);
// Here we could simply call dst.noalias() += lhs.my_matrix() * rhs,
// but let's do something fancier (and less efficient):
for
(
Index
i
=
0
;
i
<
lhs
.
cols
();
++
i
)
dst
+=
rhs
(
i
)
*
lhs
.
my_matrix
().
col
(
i
);
}
};
}
}
int
main
()
{
int
n
=
10
;
Eigen
::
SparseMatrix
<
double
>
S
=
Eigen
::
MatrixXd
::
Random
(
n
,
n
).
sparseView
(
0.5
,
1
);
S
=
S
.
transpose
()
*
S
;
MatrixReplacement
A
;
A
.
attachMyMatrix
(
S
);
Eigen
::
VectorXd
b
(
n
),
x
;
b
.
setRandom
();
// Solve Ax = b using various iterative solver with matrix-free version:
{
Eigen
::
ConjugateGradient
<
MatrixReplacement
,
Eigen
::
Lower
|
Eigen
::
Upper
,
Eigen
::
IdentityPreconditioner
>
cg
;
cg
.
compute
(
A
);
x
=
cg
.
solve
(
b
);
std
::
cout
<<
"CG: #iterations: "
<<
cg
.
iterations
()
<<
", estimated error: "
<<
cg
.
error
()
<<
std
::
endl
;
}
{
Eigen
::
BiCGSTAB
<
MatrixReplacement
,
Eigen
::
IdentityPreconditioner
>
bicg
;
bicg
.
compute
(
A
);
x
=
bicg
.
solve
(
b
);
std
::
cout
<<
"BiCGSTAB: #iterations: "
<<
bicg
.
iterations
()
<<
", estimated error: "
<<
bicg
.
error
()
<<
std
::
endl
;
}
{
Eigen
::
GMRES
<
MatrixReplacement
,
Eigen
::
IdentityPreconditioner
>
gmres
;
gmres
.
compute
(
A
);
x
=
gmres
.
solve
(
b
);
std
::
cout
<<
"GMRES: #iterations: "
<<
gmres
.
iterations
()
<<
", estimated error: "
<<
gmres
.
error
()
<<
std
::
endl
;
}
{
Eigen
::
DGMRES
<
MatrixReplacement
,
Eigen
::
IdentityPreconditioner
>
gmres
;
gmres
.
compute
(
A
);
x
=
gmres
.
solve
(
b
);
std
::
cout
<<
"DGMRES: #iterations: "
<<
gmres
.
iterations
()
<<
", estimated error: "
<<
gmres
.
error
()
<<
std
::
endl
;
}
{
Eigen
::
MINRES
<
MatrixReplacement
,
Eigen
::
Lower
|
Eigen
::
Upper
,
Eigen
::
IdentityPreconditioner
>
minres
;
minres
.
compute
(
A
);
x
=
minres
.
solve
(
b
);
std
::
cout
<<
"MINRES: #iterations: "
<<
minres
.
iterations
()
<<
", estimated error: "
<<
minres
.
error
()
<<
std
::
endl
;
}
}
Event Timeline
Log In to Comment