TridiagLU  1.0
Scalable, parallel solver for tridiagonal system of equations
tridiagScaLPK.c File Reference

Wrapper function to solve tridiagonal systems using ScaLAPACK's pddtsv. More...

#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#include <mpi.h>
#include <tridiagLU.h>

Go to the source code of this file.

Functions

void pddtsv_ ()
 
int tridiagScaLPK (double *a, double *b, double *c, double *x, int n, int ns, void *r, void *m)
 

Detailed Description

Wrapper function to solve tridiagonal systems using ScaLAPACK's pddtsv.

Author
Debojyoti Ghosh

Definition in file tridiagScaLPK.c.

Function Documentation

void pddtsv_ ( )

ScaLAPACK's parallel tridiagonal solver: See http://www.netlib.org/scalapack/explore-html/d7/d86/pddtsv_8f_source.html for its documentation.

int tridiagScaLPK ( double *  a,
double *  b,
double *  c,
double *  x,
int  n,
int  ns,
void *  r,
void *  m 
)

Solve tridiagonal (non-periodic) systems of equations using ScaLAPACK's pddtsv: This function can solve multiple independent systems with one call. The systems need not share the same left- or right-hand-sides.

  • This function is compiled only with the compilation flag "-Dwith_scalapack" is specified.
  • This function calls the ScaLAPACK function for solving tridiagonal systems individually for each system, and thus may not be efficient.

Array layout: The arguments a, b, c, and x are local 1D arrays (containing this processor's part of the subdiagonal, diagonal, superdiagonal, and right-hand-side) of size (n X ns), where n is the local size of the system, and ns is the number of independent systems to solve. The ordering of the elements in these arrays is as follows:

  • Elements of the same row for each of the independent systems are stored adjacent to each other.

For example, consider the following systems:

\begin{equation} \left[\begin{array}{ccccc} b_0^k & c_0^k & & & \\ a_1^k & b_1^k & c_1^k & & \\ & a_2^k & b_2^k & c_2^k & & \\ & & a_3^k & b_3^k & c_3^k & \\ & & & a_4^k & b_4^k & c_4^k \\ \end{array}\right] \left[\begin{array}{c} x_0^k \\ x_1^k \\ x_2^k \\ x_3^k \\ x_4^k \end{array}\right] = \left[\begin{array}{c} r_0^k \\ r_1^k \\ r_2^k \\ r_3^k \\ r_4^k \end{array}\right]; \ \ k= 1,\cdots,ns \end{equation}

and let \( ns = 3\). Note that in the code, \(x\) and \(r\) are the same array x.

Then, the array b must be a 1D array with the following layout of elements:
[
b_0^0, b_0^1, b_0^2, (diagonal element of the first row in each system)
b_1^0, b_1^1, b_1^2, (diagonal element of the second row in each system)
...,
b_{n-1}^0, b_{n-1}^1, b_{n-1}^2 (diagonal element of the last row in each system)
]
The arrays a, c, and x are stored similarly.

Notes:

  • This function does not preserve the sub-diagonal, diagonal, super-diagonal elements and the right-hand-sides.
  • The input array x contains the right-hand-side on entering the function, and the solution on exiting it.
Parameters
aArray containing the sub-diagonal elements
bArray containing the diagonal elements
cArray containing the super-diagonal elements
xRight-hand side; will contain the solution on exit
nLocal size of the system on this processor
nsNumber of systems to solve
rObject of type TridiagLU
mMPI communicator

Definition at line 71 of file tridiagScaLPK.c.

81 {
82  TridiagLU *params = (TridiagLU*) r;
83  int rank,nproc,nglobal,nrhs,i,s,ia,ib,desca[9],descb[9],ierr,
84  lwork;
85  double *dl,*d,*du,*rhs,*work;
86  struct timeval start,end;
87 
88 #ifdef serial
89  rank = 0;
90  nproc = 1;
91  nglobal=n;
92 #else
93  MPI_Comm *comm = (MPI_Comm*) m;
94 
95  if (comm) {
96  MPI_Comm_size(*comm,&nproc);
97  MPI_Comm_rank(*comm,&rank);
98  } else {
99  rank = 0;
100  nproc = 1;
101  }
102  MPI_Allreduce(&n,&nglobal,1,MPI_INT,MPI_SUM,*comm);
103 #endif
104 
105  /* check */
106  if (nglobal%n != 0) {
107  if (!rank) {
108  fprintf(stderr,"Error: The ScaLAPACK wrapper can only handle cases where the global ");
109  fprintf(stderr,"size of system is an integer multiple of no. of processes.\n");
110  }
111  return(1);
112  }
113 
114  if (!params) {
115  fprintf(stderr,"Error in tridiagLU(): NULL pointer passed for parameters.\n");
116  return(1);
117  }
118 
119 
120  nrhs = 1;
121  ia = 1;
122  ib = 1;
123 
124  lwork = (12*nproc+3*n) + ( (8*nproc) > (10*nproc+4*nrhs) ? (8*nproc) : (10*nproc+4*nrhs) );
125 
126  desca[0] = 501;
127  desca[1] = params->blacs_ctxt;
128  desca[2] = nglobal;
129  desca[3] = n;
130  desca[4] = 0;
131  desca[5] = 0;
132  desca[6] = 0;
133  desca[7] = 0;
134  desca[8] = 0;
135 
136  descb[0] = 502;
137  descb[1] = params->blacs_ctxt;
138  descb[2] = nglobal;
139  descb[3] = n;
140  descb[4] = 0;
141  descb[5] = n;
142  descb[6] = 0;
143  descb[7] = 0;
144  descb[8] = 0;
145 
146  dl = (double*) calloc (n,sizeof(double));
147  d = (double*) calloc (n,sizeof(double));
148  du = (double*) calloc (n,sizeof(double));
149  rhs = (double*) calloc (n,sizeof(double));
150  work = (double*) calloc(lwork,sizeof(double));
151 
152  params->total_time = 0.0;
153  params->stage1_time = 0.0;
154  params->stage2_time = 0.0;
155  params->stage3_time = 0.0;
156  params->stage4_time = 0.0;
157  for (s=0; s<ns; s++) {
158 
159  for (i=0; i<n; i++) {
160  dl[i] = a[i*ns+s];
161  d [i] = b[i*ns+s];
162  du[i] = c[i*ns+s];
163  rhs[i]= x[i*ns+s];
164  }
165 
166  /* call the ScaLAPACK function */
167  gettimeofday(&start,NULL);
168  pddtsv_(&nglobal,&nrhs,dl,d,du,&ia,desca,rhs,&ib,descb,work,&lwork,&ierr);
169  gettimeofday(&end,NULL);
170  if (ierr) return(ierr);
171 
172  for (i=0; i<n; i++) x[i*ns+s] = rhs[i];
173 
174  long long walltime;
175  walltime = ((end.tv_sec * 1000000 + end.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec));
176  params->total_time += (double) walltime / 1000000.0;
177  }
178 
179 
180  free(dl);
181  free(d);
182  free(du);
183  free(rhs);
184  free(work);
185 
186  return(0);
187 }
double stage3_time
Definition: tridiagLU.h:101
double stage2_time
Definition: tridiagLU.h:100
int blacs_ctxt
Definition: tridiagLU.h:105
double stage1_time
Definition: tridiagLU.h:99
double stage4_time
Definition: tridiagLU.h:102
void pddtsv_()
double total_time
Definition: tridiagLU.h:98