HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
tridiagScaLPK.c
Go to the documentation of this file.
1 
6 #ifdef with_scalapack
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <sys/time.h>
11 #include <string.h>
12 #ifndef serial
13 #include <mpi.h>
14 #endif
15 #include <tridiagLU.h>
16 
22 extern void pddtsv_();
23 
71 int tridiagScaLPK(
72  double *a,
73  double *b,
74  double *c,
75  double *x,
76  int n,
77  int ns,
78  void *r,
79  void *m
80  )
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 }
188 
189 #endif
double total_time
Definition: tridiagLU.h:101
Header file for TridiagLU.
double stage4_time
Definition: tridiagLU.h:105
double stage3_time
Definition: tridiagLU.h:104
double stage2_time
Definition: tridiagLU.h:103
double stage1_time
Definition: tridiagLU.h:102