Hello,
I solved the problem, it has to do with ScaLapack tool subroutine PDELSET, which distributes global matrix into local ones. Apparently, this routine changes a Lower triangular global matrix into Upper triangular local matrix.
In the example of last post, global matrix A = 1, 4, 5, 0, 2, 6, 0, 0, 3
which corresponds to Lower triangular matrix M1:
1 0 0
4 2 0
5 6 3
I then distribute this matrix into 4 processes (npcol=nprow=2), with nB=2. I found out that the local matrix is, however, Upper triangular. E.g. the local matrix for myrow=mycol=0 is
1 0 4 2
i.e., a perfect column-major 2X2 upper triangular matrix:
1 4
0 2
=============
Following are my C++ code and output.
- Code: Select all
#include <iostream>
#include <fstream>
#include "blacs.h" // for Cblacs_ ...
#include "scalapack.h" // for numroc_, descinit_, pdelset_, pdsyev_
#include "mpi.h" // for mpi calls
using namespace std;
void get_eigenvalue_para(int nA, double **A, double *v);
main(int ac, char **av)
{
int mpirank, mpisize;
double **A, *v;
int dimA;
MPI_Init(&ac, &av);
MPI_Comm_rank(MPI_COMM_WORLD, &mpirank);
MPI_Comm_size(MPI_COMM_WORLD, &mpisize);
dimA=3;
A = new double* [dimA];
A[0] = new double [dimA*dimA];
A[1] = A[0] + dimA;
A[2] = A[1] + dimA;
v = new double[dimA];
A[0][0] = 1.; A[0][1] = 4.; A[0][2] = 5.;
A[1][0] = 0.; A[1][1] = 2.; A[1][2] = 6.;
A[2][0] = 0.; A[2][1] = 0.; A[2][2] = 3.;
if (mpirank==0) {
cout << "Global matrix elements are:\n";
for (int i=0; i<dimA*dimA; ++i)
cout << '\t' << A[0][i];
cout << endl;
}
get_eigenvalue_para(dimA, A, v);
if (mpirank==0) {
cout << "EIGENVALUES:\n";
for (int i=0; i<dimA; ++i)
cout << '\t' << v[i];
cout << endl;
}
//delete2D(A);
delete[] A[0];
delete[] A;
delete[] v;
MPI_Finalize();
return 0;
}
void get_eigenvalue_para(int nA, double **A, double *v) {
char letterR = 'R';
char letterN = 'N';
char letterU = 'U';
int izero = 0;
int ione = 1;
// mpi variables
int mpirank, mpisize;
// grid variables
int icntx, nprow=2, npcol=2, myrow, mycol;
Cblacs_pinfo (mpirank, mpisize);
char flnm[10];
sprintf(flnm, "out%d", mpirank);
ofstream fl(flnm);
Cblacs_get (-1, 0, icntx);
Cblacs_gridinit(icntx, letterR, nprow, npcol);
Cblacs_gridinfo(icntx, nprow, npcol, myrow, mycol);
// if not in grid, do nothing
if (myrow == -1) return;
// =========================================================
// real calculation begins
// =========================================================
int iwork;
double *lA, *work;
// local eigenvector matrix lZ is not referenced
// when only calculate eigenvalue.
// set it to zero to avoid compiler complaining
//
double *lZ = 0;
int nB = 2;
int mlA, nlA;
int desclA[9], desclZ[9];
int info;
// calc size of local matrix
mlA = numroc_(nA, nB, myrow, izero, nprow);
nlA = numroc_(nA, nB, mycol, izero, npcol);
lA = new double[mlA*nlA];
iwork = (mlA>1 ? mlA : 1);
descinit_(desclA, nA, nA, nB, nB, izero, izero, icntx, iwork, info);
descinit_(desclZ, nA, nA, nB, nB, izero, izero, icntx, iwork, info);
// set local matrix
for (int i=1; i<=nA; ++i)
for (int j=1; j<=nA; ++j)
pdelset_(lA, i, j, desclA, A[i-1][j-1]);
// write debug info into different files
fl << "On process: " << mpirank
<< ", local matrix size = " << mlA << 'X' << nlA
<< "\nLocal matrix elements are:";
for (int i=0; i<mlA*nlA; ++i)
fl << '\t' << lA[i];
fl << endl;
// get correct size of work array
work = new double[2];
iwork = -1;
pdsyev_(letterN, letterU, nA,
lA, ione, ione, desclA, v,
lZ, ione, ione, desclZ, work, iwork, info);
iwork = (int)work[0];
delete[] work;
// real calculation
work = new double[iwork];
pdsyev_(letterN, letterU, nA,
lA, ione, ione, desclA, v,
lZ, ione, ione, desclZ, work, iwork, info);
delete[] lA;
delete[] work;
fl.close();
Cblacs_gridexit(icntx);
return;
}
Screen output:
Global matrix elements are:
1 4 5 0 2 6 0 0 3
EIGENVALUES:
-3.66868 -2.50729 12.176
Content of output file "out0"
On process: 0, local matrix size = 2X2
Local matrix elements are: 1 0 4 2
Content of output file "out1"
On process: 1, local matrix size = 2X1
Local matrix elements are: 5 6
Content of output file "out2"
On process: 2, local matrix size = 1X2
Local matrix elements are: 0 0
Content of output file "out3"
On process: 3, local matrix size = 1X1
Local matrix elements are: 3