I meet a serious problem when I was coding my programme. Firstly, I will state my implementation.
I have a Conjugate Gradient Implementation to solve linear system. In my densematrixvector.h, I have two classes, denseMatrix
and denseVector
, and I put these two arrays into the function template < class M, class V > int ConjugateGradient(const M &A, const V &b, V &x, const int &maxstep, const int &eps)
, here, M
is denseMatrix
, V
is denseVector
.
In function ConjugateGradient
, I am using a function void gemv(const double &alpha, const DenseMatrix &A, const DenseVector &x, const double &beta, DenseVector &y)
to solve the linear system.
But this code did not take advantage of the sparsity of the matrix. So I want to modify the code so that it does. In particular, the matrix type passed to the ConjugateGradient
function represent dense matrix. I want to modify the code to pass it sparse matrix in ccs format. this class transfers information of sparse matrix. So I modify the declaration of function gemv
like this:
template <class M, class V >void gemv(const double &alpha, const M &A, const V &x, const double &beta, V &y)
And the declaration of matCCS
is template < class T >class matCCS
.
finally, my computer tells me that undefined reference to
.
and the code I attach below.
Please help me. Thank you in advance.
mainconjugategradientmethodmatCCS.cc
#include "densematrixvector.h"
#include "ConjugateGradient.h"
#include <iostream>
#include "sparseMatrix.h"
int main(){
matCOO<double> Acoo;
readMatrixMarket("small.mtx", Acoo);
matCCS<double> A; // constuct a CCS matrix
COOtoCCS(Acoo, A); // convert the COO matrix Acoo to CCS A
int m, n;
m=A.m;
n=A.n;
DenseVector x;
DenseVector b;
int nx = 1;
double * xt = new double [m*nx];
for (int i = 0; i < m ;++i) xt[i] =1.;
x.a= xt;
x.n = n;
int nrhs = 1;
double * bt = new double [m*nrhs];
for (int i = 0; i < m ;++i) bt[i] =0.;
b.a = bt;
b.n = n;
int nstep = ConjugateGradient(A, b, x, 100, 0.001);
if (nstep > 0){
std::cout << "converged in nstep " <<nstep << std::endl;
std::cout<< " solution is " << x.a[0] << " " << x.a[1] << std::endl;
}
else {
std::cout << "CG could not converge " <<nstep << std::endl;
}
}
densematrixvector.cc
#include "densematrixvector.h"
#include <algorithm>
#include <iostream>
DenseVector::DenseVector():a(0), n(0), owner(false){};
DenseVector::DenseVector(const int & _n):a(new double[_n]), n(_n), owner(true)
{
std::fill(a,a+n, 0.);
};
DenseVector::DenseVector(const DenseVector &in):a(new double[in.n] ), n(in.n), owner(true){
std::copy(in.a, in.a+n, a);
};
DenseVector::~DenseVector(){
if(owner) delete []a;
owner =false;
};
int size(const DenseVector &in){
return in.n;
}
void copy(const DenseVector &x, DenseVector &y){
const int n = size(x);
if (n!=size(y)){ std::cout << " Size error in copy " << __FILE__ <<
__LINE__ << std::endl;}
std::copy(x.a, x.a+n, y.a);
}
double dot(const DenseVector & x, const DenseVector & y){
const int n = size(x);
if (n!=size(y)){ std::cout << " Size error in dot " << __FILE__ << __LINE__ << std::endl;}
return ddot_(n, x.a, 1, y.a, 1);
}
void scal(const double& alpha, DenseVector &x){
dscal_(size(x), alpha, x.a, 1);
}
void axpy( const double &alpha, const DenseVector & x, DenseVector &y){
const int n = size(x);
if (n!=size(y)){ std::cout << " Size error in axpy " << __FILE__ <<
__LINE__ << std::endl; throw;}
daxpy_(n, alpha, x.a, 1, y.a, 1 );
}
template <class M, class V>
void gemv(const double& alpha, const M &A, const V &x, const double &beta, V &y )
int m =A.m;
int n =A.n;
int nnz=A.nnz;
if ((size(x) != n) || (size(y) != m)) { std::cout << " Size error in gemv "` `<< __FILE__ << __LINE__ << std::endl; throw;}
//dgemv_('N', m,n, alpha, A.a, m, x.a, 1, beta, y.a, 1 );
for(int i=0; i<m; i++) {
y.a[i]=A.a[i]*x.a[A.lineindex[i]];
}
}
densematrixvector.h
#ifndef _densematrixvector_
#define _densematrixvector_
...
int size(const DenseVector &in);
void copy(const DenseVector &x, DenseVector &y );
double dot(const DenseVector & x, const DenseVector & y);
void scal(const double& alpha, DenseVector &x);
void axpy( const double &alpha, const DenseVector & x, DenseVector &y);
//void gemv(const double& alpha, const DenseMatrix &A, const DenseVector &x,
const double &beta, DenseVector & y );
template <class M, class V>
void gemv(const double& alpha, const M &A, const V &x, const double &beta, V &y );
...
#endif
ConjugateGradient.h
#include <iostream>
template <class M, class V>
int ConjugateGradient(const M & A, const V& b, V &x, const int & maxstep, const int &eps)
{
int n = size(b);
std::cout << n << std::endl;
//r = b - A x;
V r(b);
gemv(-1., A, x, 1., r);
...
The report error is attached below
[master@localhost part3ddis]$ g++ maintestconjugategradientmatCCS.cc densematrixvector.cc mmio.cc libsuperlu_4.3.a libblas.a -lgfortran
/tmp/ccg7iPUj.o: In function `int ConjugateGradient<DenseMatrix, DenseVector>(DenseMatrix const&, DenseVector const&, DenseVector&, int const&, int const&)':
maintestconjugategradientmatCCS.cc:(.text._Z17ConjugateGradientI11DenseMatrix11DenseVectorEiRKT_RKT0_RS5_RKiSA_[_Z17ConjugateGradientI11DenseMatrix11DenseVectorEiRKT_RKT0_RS5_RKiSA_]+0xb2): undefined reference to `void gemv<DenseMatrix, DenseVector>(double const&, DenseMatrix const&, DenseVector const&, double const&, DenseVector&)'
maintestconjugategradientmatCCS.cc:(.text._Z17ConjugateGradientI11DenseMatrix11DenseVectorEiRKT_RKT0_RS5_RKiSA_[_Z17ConjugateGradientI11DenseMatrix11DenseVectorEiRKT_RKT0_RS5_RKiSA_]+0x208): undefined reference to `void gemv<DenseMatrix, DenseVector>(double const&, DenseMatrix const&, DenseVector const&, double const&, DenseVector&)'
collect2: error: ld returned 1 exit status