MIDAPACK - MIcrowave Data Analysis PACKage  1.1b
Parallel software tools for high performance CMB DA analysis
 All Data Structures Files Functions Variables Typedefs Groups Pages
mapmatc.c
Go to the documentation of this file.
1 
9 #ifdef W_MPI
10  #include <mpi.h>
11 #endif
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "mapmatc.h"
16 
17 int CMatInit(CMat *A, int r, int *m, int *nnz, int **indices, double **values, int flag
18 #ifdef W_MPI
19  ,MPI_Comm comm
20 #endif
21  ){
22  int M, k, *tmp_indices;
23  A->r = r; // set number of local rows
24  A->m = m; //
25  A->nnz = nnz; //
26  A->disp = (int *) malloc((A->r+1)*sizeof(int)); // allocate disp array
27  A->disp[0]=0;
28 // printf(" %d\t%d\t%d\n", A->m[0], A->nnz[0], A->disp[0]);
29  for(k=1; k<=A->r; k++){
30  A->disp[k]=A->disp[k-1]+A->m[k-1]*A->nnz[k-1];
31  // if(k!=A->r)
32  // printf(" %d\t%d\t", A->m[k], A->nnz[k]);
33  // printf(" %d\n", A->disp[k]);
34  }
35  A->indices = indices; //
36  A->values = values;
37  /*int i, j;
38  for(k=0; k<A->r; k++){
39  for(i=0; i<A->m[k]*A->nnz[k]; i+=A->nnz[k]){
40  for(j=0; j<A->nnz[k]; j++){
41  printf(" %d ", A->indices[k][i+j]);
42  }
43  }
44  printf("\n");
45  }*/
46  tmp_indices = (int *) malloc(A->disp[A->r]*sizeof(int)); // allocate a tmp copy of indices tab to sort
47  for(k=0; k<A->r; k++){
48  memcpy(tmp_indices+A->disp[k], A->indices[k], A->m[k]*A->nnz[k]*sizeof(int)); // copy
49  }
50 
51  A->lcount = ssort(tmp_indices, A->disp[A->r], 0); // sequential sort tmp_indices (flag:3=counting sort)
52  A->lindices = (int *) malloc((A->lcount)*sizeof(int)); //
53  memcpy(A->lindices, tmp_indices, (A->lcount) *sizeof(int)); // copy tmp_indices into lindices and free
54  free(tmp_indices);
55 
56  for(k=0; k<A->r; k++){
57  sindex(A->lindices, A->lcount, A->indices[k], A->nnz[k]*A->m[k]); // transform indices tab in local indices tab
58  }
59  /*for(k=0; k<A->r; k++){
60  for(i=0; i<A->m[k]*A->nnz[k]; i+=A->nnz[k]){
61  for(j=0; j<A->nnz[k]; j++){
62  printf(" %d ", A->indices[k][i+j]);
63  }
64  }
65  printf("\n");
66  }*/
67  //printf("cmat init 0\n");
68 #ifdef W_MPI
69  A->comm = comm; // link communivcator
70  return CMatComShape(A, flag); // build communication scheme
71 #endif
72 }
73 
74 
75 int CMatFree(CMat *A){
76  free(A->disp);
77  free(A->lindices);
78 #ifdef W_MPI
79  if(A->flag != NONE){ //if necessary free communication tab
80  if(A->R) //
81  free(A->R); //
82  if(A->nR) //
83  free(A->nR); //
84  if(A->S) //
85  free(A->S); //
86  if(A->nS)
87  free(A->nS);
88  }
89 #endif
90  return 0;
91 }
92 
93 
94 
95 #ifdef W_MPI
96 int CMatComShape(CMat *mat, int flag){
97  //printf("commshape 0\n");
98  int size;
99  mat->flag = flag;
100  MPI_Comm_size(mat->comm, &size);
101  if(flag==BUTTERFLY){
102  if(is_pow_2(size)==0){
103  mat->flag=flag;
104  mat->steps = log_2(size);
105  }
106  else{
107  mat->flag=RING;
108  mat->steps = size;
109  }
110  }
111  else if(flag==NONE){
112  mat->flag=flag;
113  return 0;
114  }
115  else{
116  mat->flag=flag;
117  mat->steps = size;
118  }
119  mat->S = (int** ) malloc(mat->steps * sizeof(int* )); /*<allocate sending maps tab*/
120  mat->R = (int** ) malloc(mat->steps * sizeof(int* )); /*<allocate receiving maps tab*/
121  mat->nS = (int* ) malloc(mat->steps * sizeof(int)); /*<allocate sending map sizes tab*/
122  mat->nR = (int* ) malloc(mat->steps * sizeof(int)); /*<allocate receiving map size tab*/
123 
124  if(mat->flag == BUTTERFLY){
125  butterfly_init(mat->lindices, mat->lcount, mat->R, mat->nR, mat->S, mat->nS, &(mat->com_indices), &(mat->com_count), mat->steps, mat->comm);
126  }
127  else{
128  ring_init(mat->lindices, mat->lcount, mat->R, mat->nR, mat->S, mat->nS, mat->steps, mat->comm);
129  mat->com_count = mat->lcount;
130  mat->com_indices = mat->lindices;
131  }
132  //printf("commshape 1\n");
133  return 0;
134 }
135 #endif
136 
137 
138 
139 int CMatVecProd(CMat *A, double *xvalues, double* yvalues, int pflag){
140  int i, j, k;
141  int l;
142  for(i=0; i<A->disp[A->r]; i++)
143  yvalues[i] = 0.0;
144  l=0;
145  for(k=0; k<A->r; k++){ //coarse levels
146  for(i=0; i<A->m[k]; i+=A->nnz[k]){ //rows
147  for(j=0; j<A->nnz[k]; j++){ //non-zero per row
148  yvalues[l] += A->values[k][i+j] * xvalues[A->indices[k][i+j]];
149  }
150  l++;
151  }
152  }
153  return 0;
154 }
155 
156 
157 
158 
159 int CTrMatVecProd(CMat *A, double *in_values, double* out_values, int pflag){
160  int i, j, k;
161  int l;
162  int nSmax, nRmax;
163  double *lvalues;
164 
165  lvalues = (double *) malloc(A->lcount *sizeof(double)); /*<allocate and set to 0.0 local values*/
166  for(i=0; i < A->lcount; i++)
167  lvalues[i]=0.0;
168 
169  l=0;
170  for(k=0; k<A->r; k++){ //coarse levels
171  for(i=0; i<A->m[k]; i+=A->nnz[k]){ //rows
172  for(j=0; j<A->nnz[k]; j++){ //non-zero per row
173  lvalues[A->indices[k][i+j]] += A->values[k][i+j] * in_values[l];
174  }
175  l++;
176  }
177  }
178  memcpy(out_values, lvalues, (A->lcount) *sizeof(double)); /*<copy local values into result values*/
179 #ifdef W_MPI
180  nRmax=0;
181  nSmax=0;
182 
183  if(A->flag == BUTTERFLY){ /*<branch butterfly*/
184  for(k=0; k< A->steps; k++) /*compute max communication buffer size*/
185  if(A->nR[k] > nRmax)
186  nRmax = A->nR[k];
187  for(k=0; k< A->steps; k++)
188  if(A->nS[k] > nSmax)
189  nSmax = A->nS[k];
190 
191  double *com_val;
192  com_val=(double *) malloc( A->com_count *sizeof(double));
193  for(i=0; i < A->com_count; i++){
194  com_val[i]=0.0;
195  }
196  m2m(lvalues, A->lindices, A->lcount, com_val, A->com_indices, A->com_count);
197  butterfly_reduce(A->R, A->nR, nRmax, A->S, A->nS, nSmax, com_val, A->steps, A->comm);
198  m2m(com_val, A->com_indices, A->com_count, out_values, A->lindices, A->lcount);
199  free(com_val);
200  }
201  else if(A->flag == RING){
202  for(k=1; k< A->steps; k++) /*compute max communication buffer size*/
203  if(A->nR[k] > nRmax)
204  nRmax = A->nR[k];
205 
206  nSmax = nRmax;
207  ring_reduce(A->R, A->nR, nRmax, A->S, A->nS, nSmax, lvalues, out_values, A->steps, A->comm);
208  }
209  else if(A->flag == NONBLOCKING){
210  ring_nonblocking_reduce(A->R, A->nR, A->S, A->nS, lvalues, out_values, A->steps, A->comm);
211  }
212  else if(A->flag == NOEMPTY){
213  int ne=0;
214  for(k=1; k< A->steps; k++)
215  if(A->nR[k]!=0)
216  ne++;
217  ring_noempty_reduce(A->R, A->nR, ne, A->S, A->nS, ne, lvalues, out_values, A->steps, A->comm);
218  }
219  else{
220  return 1;
221  }
222 #endif
223  free(lvalues);
224  return 0;
225 }
226 
227 
228