DPsim
magma.c
1 #include <dpsim/MNASolverDynInterface.h>
2 
3 #include <stdio.h>
4 #include <string.h>
5 
6 #include <cusolverSp.h>
7 #include <magma_types.h>
8 #include <magma_v2.h>
9 #include <magmasparse.h>
10 
11 int dps_magma_init(struct dpsim_csr_matrix *matrix);
12 int dps_magma_decomp(struct dpsim_csr_matrix *matrix);
13 int dps_magma_solve(double *rhs_values, double *lhs_values);
14 void dps_magma_log(const char *str);
15 void dps_magma_cleanup(void);
16 
18  int size;
19  int nnz;
20  int *perm_map;
21  double *rhs_buffer;
23  magma_dopts mMagmaOpts;
24  magma_queue_t mMagmaQueue;
25 
27  magma_d_matrix mHostSysMat;
28  magma_d_matrix mDevSysMat;
29 
31  magma_d_matrix mHostRhsVec;
32  magma_d_matrix mDevRhsVec;
34  magma_d_matrix mHostLhsVec;
35  magma_d_matrix mDevLhsVec;
36 } data;
37 
38 static const char *PLUGIN_NAME = "libdps_magma";
39 static struct dpsim_mna_plugin dps_magma_plugin = {
40  .log =
41  dps_magma_log, //a properly working dpsim will override this with the spdlog logger
42  .init = dps_magma_init,
43  .lu_decomp = dps_magma_decomp,
44  .solve = dps_magma_solve,
45  .cleanup = dps_magma_cleanup,
46 };
47 
48 struct dpsim_mna_plugin *get_mna_plugin(const char *name) {
49  if (name == NULL || strcmp(name, PLUGIN_NAME) != 0) {
50  printf("error: name mismatch\n");
51  return NULL;
52  }
53  return &dps_magma_plugin;
54 }
55 
56 int dps_magma_init(struct dpsim_csr_matrix *matrix) {
57  dps_magma_plugin.log("initialize");
58  magma_init();
59  magma_queue_create(0, &data.mMagmaQueue);
60  data.mHostSysMat.storage_type = Magma_CSR;
61  data.mDevSysMat.storage_type = Magma_CSR;
62  data.mHostRhsVec.storage_type = Magma_CSR;
63  data.mDevRhsVec.storage_type = Magma_CSR;
64  data.mHostLhsVec.storage_type = Magma_CSR;
65  data.mDevLhsVec.storage_type = Magma_CSR;
66  data.rhs_buffer = (double *)malloc(sizeof(double) * matrix->row_number);
67  data.perm_map = (int *)malloc(sizeof(int) * matrix->row_number);
68 
69  return dps_magma_decomp(matrix);
70 }
71 
72 int dps_magma_decomp(struct dpsim_csr_matrix *matrix) {
73  int perm_size = 0;
74  data.size = matrix->row_number;
75  data.nnz = matrix->nnz;
76  dps_magma_plugin.log("decomp");
77  cusparseMatDescr_t descr_M = 0;
78 
79  cusolverSpHandle_t mCusolverhandle;
80  if (cusolverSpCreate(&mCusolverhandle) != CUSOLVER_STATUS_SUCCESS) {
81  dps_magma_plugin.log("cusolverSpCreate returend an error");
82  return 1;
83  }
84  if (cusparseCreateMatDescr(&descr_M) != CUSPARSE_STATUS_SUCCESS) {
85  dps_magma_plugin.log("returend an error");
86  return 1;
87  }
88 
89  if (cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ZERO) !=
90  CUSPARSE_STATUS_SUCCESS) {
91  dps_magma_plugin.log("cusolver returend an error");
92  return 1;
93  }
94  if (cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL) !=
95  CUSPARSE_STATUS_SUCCESS) {
96  dps_magma_plugin.log("cusolver returend an error");
97  return 1;
98  }
99 
100  if (cusolverSpDcsrzfdHost(mCusolverhandle, matrix->row_number, matrix->nnz,
101  descr_M, matrix->values, matrix->rowIndex,
102  matrix->colIndex, data.perm_map,
103  &perm_size) != CUSOLVER_STATUS_SUCCESS) {
104  dps_magma_plugin.log("cusolverSpDcsrzfdHost returend an error");
105  return 1;
106  }
107 
108  size_t bufferSize = 0;
109  int *q = (int *)malloc(sizeof(int) * matrix->row_number);
110  int *map = (int *)malloc(sizeof(int) * matrix->nnz);
111  double *old_values = (double *)malloc(sizeof(double) * matrix->nnz);
112  for (int i = 0; i <= matrix->row_number; ++i) {
113  q[i] = i;
114  }
115  for (int i = 0; i <= matrix->nnz; ++i) {
116  map[i] = i;
117  old_values[i] = matrix->values[i];
118  }
119 
120  if (cusolverSpXcsrperm_bufferSizeHost(
121  mCusolverhandle, matrix->row_number, matrix->row_number, matrix->nnz,
122  descr_M, matrix->rowIndex, matrix->colIndex, data.perm_map, q,
123  &bufferSize) != CUSOLVER_STATUS_SUCCESS) {
124  dps_magma_plugin.log("cusolverSpXcsrperm_bufferSizeHost returend an error");
125  return 1;
126  }
127 
128  void *buffer = malloc(bufferSize);
129 
130  if (cusolverSpXcsrpermHost(mCusolverhandle, matrix->row_number,
131  matrix->row_number, matrix->nnz, descr_M,
132  matrix->rowIndex, matrix->colIndex, data.perm_map,
133  q, map, buffer) != CUSOLVER_STATUS_SUCCESS) {
134  dps_magma_plugin.log("cusolverSpXcsrpermHost returend an error");
135  return 1;
136  }
137 
138  for (int i = 0; i <= matrix->nnz; ++i) {
139  matrix->values[i] = old_values[map[i]];
140  }
141 
142  magma_dcsrset(matrix->row_number, matrix->row_number, matrix->rowIndex,
143  matrix->colIndex, matrix->values, &data.mHostSysMat,
144  data.mMagmaQueue);
145 
146  data.mMagmaOpts.solver_par.solver = Magma_PIDRMERGE;
147  data.mMagmaOpts.solver_par.restart = 8;
148  data.mMagmaOpts.solver_par.maxiter = 1000;
149  data.mMagmaOpts.solver_par.rtol = 1e-10;
150  data.mMagmaOpts.solver_par.maxiter = 1000;
151  data.mMagmaOpts.precond_par.solver = Magma_ILU;
152  data.mMagmaOpts.precond_par.levels = 0;
153  data.mMagmaOpts.precond_par.trisolver = Magma_CUSOLVE;
154 
155  magma_dsolverinfo_init(&data.mMagmaOpts.solver_par,
156  &data.mMagmaOpts.precond_par, data.mMagmaQueue);
157 
158  magma_dvinit(&data.mDevRhsVec, Magma_DEV, matrix->row_number, 1, 0.0,
159  data.mMagmaQueue);
160  magma_dmtransfer(data.mHostSysMat, &data.mDevSysMat, Magma_CPU, Magma_DEV,
161  data.mMagmaQueue);
162  magma_d_precondsetup(data.mDevSysMat, data.mDevRhsVec,
163  &data.mMagmaOpts.solver_par,
164  &data.mMagmaOpts.precond_par, data.mMagmaQueue);
165 
166  free(buffer);
167  free(q);
168  free(map);
169  free(old_values);
170  cusparseDestroyMatDescr(descr_M);
171  cusolverSpDestroy(mCusolverhandle);
172 
173  return 0;
174 }
175 
176 int dps_magma_solve(double *rhs_values, double *lhs_values) {
177  int one = 0;
178  dps_magma_plugin.log("solve");
179 
180  for (int i = 0; i <= data.size; ++i) {
181  data.rhs_buffer[i] = rhs_values[data.perm_map[i]];
182  }
183  //
184  //Copy right vector to device
185  magma_dvset(data.size, 1, data.rhs_buffer, &data.mHostRhsVec,
186  data.mMagmaQueue);
187  magma_dmtransfer(data.mHostRhsVec, &data.mDevRhsVec, Magma_CPU, Magma_DEV,
188  data.mMagmaQueue);
189  magma_dvinit(&data.mDevLhsVec, Magma_DEV, data.mHostRhsVec.num_rows,
190  data.mHostRhsVec.num_cols, 0.0, data.mMagmaQueue);
191 
192  // Solve
193  magma_d_solver(data.mDevSysMat, data.mDevRhsVec, &data.mDevLhsVec,
194  &data.mMagmaOpts, data.mMagmaQueue);
195 
196  //Copy Solution back
197  magma_dmtransfer(data.mDevLhsVec, &data.mHostLhsVec, Magma_DEV, Magma_CPU,
198  data.mMagmaQueue);
199  magma_dvcopy(data.mDevLhsVec, &data.size, &one, lhs_values, data.mMagmaQueue);
200 
201  //Apply inverse Permutation: TODO: This seems to be wrong, but why?
202  //this->mLeftSideVector = mTransp->inverse() * this->mLeftSideVector;
203 
204  // Components' states will be updated by the post-step tasks
205  return 0;
206 }
207 
208 void dps_magma_cleanup(void) {
209  dps_magma_plugin.log("cleanup");
210  magma_dmfree(&data.mDevSysMat, data.mMagmaQueue);
211  magma_dmfree(&data.mDevRhsVec, data.mMagmaQueue);
212  magma_dmfree(&data.mDevLhsVec, data.mMagmaQueue);
213 
214  magma_queue_destroy(data.mMagmaQueue);
215  magma_finalize();
216  free(data.perm_map);
217  free(data.rhs_buffer);
218 }
219 
220 void dps_magma_log(const char *str) { puts(str); }
magma_d_matrix mHostLhsVec
LHS-Vector.
Definition: magma.c:34
magma_dopts mMagmaOpts
Solver-Handle.
Definition: magma.c:23
magma_d_matrix mHostRhsVec
RHS-Vector.
Definition: magma.c:31
magma_d_matrix mHostSysMat
Systemmatrix.
Definition: magma.c:27