DPsim
GpuMagmaAdapter.cpp
1 /* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2  * EONERC, RWTH Aachen University
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7  *********************************************************************************/
8 
9 #include "magma_types.h"
10 #include <cusolverSp.h>
11 #include <dpsim/GpuMagmaAdapter.h>
12 
13 using namespace DPsim;
14 
15 namespace DPsim {
17  magma_dmfree(&mDevSysMat, mMagmaQueue);
18  magma_dmfree(&mDevRhsVec, mMagmaQueue);
19  magma_dmfree(&mDevLhsVec, mMagmaQueue);
20 
21  magma_queue_destroy(mMagmaQueue);
22  magma_finalize();
23 }
24 
25 void GpuMagmaAdapter::performFactorization(SparseMatrix &systemMatrix) {
26  int size = systemMatrix.rows();
27  int p_nnz = 0;
28  int p[size];
29  auto hMat = systemMatrix;
30  size_t nnz = hMat.nonZeros();
31  cusparseMatDescr_t descr_M = 0;
32 
33  cusolverSpHandle_t mCusolverhandle;
34  if (cusolverSpCreate(&mCusolverhandle) != CUSOLVER_STATUS_SUCCESS) {
35  //SPDLOG_LOGGER_ERROR(mSLog, "cusolverSpCreate returend an error");
36  return;
37  }
38  if (cusparseCreateMatDescr(&descr_M) != CUSPARSE_STATUS_SUCCESS) {
39  //SPDLOG_LOGGER_ERROR(mSLog, "cusolver returend an error");
40  return;
41  }
42 
43  if (cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ZERO) !=
44  CUSPARSE_STATUS_SUCCESS) {
45  //SPDLOG_LOGGER_ERROR(mSLog, "cusolver returend an error");
46  return;
47  }
48  if (cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL) !=
49  CUSPARSE_STATUS_SUCCESS) {
50  //SPDLOG_LOGGER_ERROR(mSLog, "cusolver returend an error");
51  return;
52  }
53 
54  if (cusolverSpDcsrzfdHost(mCusolverhandle, size, nnz, descr_M,
55  hMat.valuePtr(), hMat.outerIndexPtr(),
56  hMat.innerIndexPtr(), p,
57  &p_nnz) != CUSOLVER_STATUS_SUCCESS) {
58  //SPDLOG_LOGGER_ERROR(mSLog, "cusolverSpDcsrzfdHost returend an error");
59  return;
60  }
61 
62  // create Eigen::PermutationMatrix from the p
63  mTransp = std::unique_ptr<Eigen::PermutationMatrix<Eigen::Dynamic>>(
64  new Eigen::PermutationMatrix<Eigen::Dynamic>(
65  Eigen::Map<Eigen::Matrix<int, Eigen::Dynamic, 1>>(p, size, 1)));
66 
67  // apply permutation
68  //std::cout << "Before System Matrix:" << std::endl << hMat[0] << std::endl;
69  hMat = *mTransp * hMat;
70  //std::cout << "permutation:" << std::endl << mTransp->toDenseMatrix() << std::endl;
71  //std::cout << "inverse permutation:" << std::endl << mTransp->inverse().toDenseMatrix() << std::endl;
72  //std::cout << "System Matrix:" << std::endl << hMat[0] << std::endl;
73  magma_dcsrset(size, size, hMat.outerIndexPtr(), hMat.innerIndexPtr(),
74  hMat.valuePtr(), &mHostSysMat, mMagmaQueue);
75 
76  mMagmaOpts.solver_par.solver = Magma_PIDRMERGE;
77  mMagmaOpts.solver_par.restart = 8;
78  mMagmaOpts.solver_par.maxiter = 1000;
79  mMagmaOpts.solver_par.rtol = 1e-10;
80  mMagmaOpts.solver_par.maxiter = 1000;
81  mMagmaOpts.precond_par.solver = Magma_ILU;
82  mMagmaOpts.precond_par.levels = 0;
83  mMagmaOpts.precond_par.trisolver = Magma_CUSOLVE;
84 
85  magma_dsolverinfo_init(&mMagmaOpts.solver_par, &mMagmaOpts.precond_par,
86  mMagmaQueue);
87 
88  magma_dvinit(&mDevRhsVec, Magma_DEV, size, 1, 0.0, mMagmaQueue);
89  magma_dmtransfer(mHostSysMat, &mDevSysMat, Magma_CPU, Magma_DEV, mMagmaQueue);
90  magma_d_precondsetup(mDevSysMat, mDevRhsVec, &mMagmaOpts.solver_par,
91  &mMagmaOpts.precond_par, mMagmaQueue);
92 
93  cusolverSpDestroy(mCusolverhandle);
94  cusparseDestroyMatDescr(descr_M);
95 }
96 
98  magma_init();
99  magma_queue_create(0, &mMagmaQueue);
100  mHostSysMat = {Magma_CSR};
101  mDevSysMat = {Magma_CSR};
102  mHostRhsVec = {Magma_CSR};
103  mDevRhsVec = {Magma_CSR};
104  mHostLhsVec = {Magma_CSR};
105  mDevLhsVec = {Magma_CSR};
106 }
107 
109  SparseMatrix &systemMatrix,
110  std::vector<std::pair<UInt, UInt>> &listVariableSystemMatrixEntries) {
111  /* No preprocessing phase available yet */
112 }
113 
114 void GpuMagmaAdapter::factorize(SparseMatrix &systemMatrix) {
115  performFactorization(systemMatrix);
116 }
117 
118 void GpuMagmaAdapter::refactorize(SparseMatrix &systemMatrix) {
119  performFactorization(systemMatrix);
120 }
121 
123  SparseMatrix &systemMatrix,
124  std::vector<std::pair<UInt, UInt>> &listVariableSystemMatrixEntries) {
125  performFactorization(systemMatrix);
126 }
127 
128 Matrix GpuMagmaAdapter::solve(Matrix &mRightHandSideVector) {
129  Matrix leftSideVector = mRightHandSideVector;
130  int size = mRightHandSideVector.rows();
131  int one = 0;
132 
133  mRightHandSideVector = *mTransp * mRightHandSideVector;
134 
135  //Copy right vector to device
136  magma_dvset(size, 1, mRightHandSideVector.data(), &mHostRhsVec, mMagmaQueue);
137  magma_dmtransfer(mHostRhsVec, &mDevRhsVec, Magma_CPU, Magma_DEV, mMagmaQueue);
138  magma_dvinit(&mDevLhsVec, Magma_DEV, mHostRhsVec.num_rows,
139  mHostRhsVec.num_cols, 0.0, mMagmaQueue);
140 
141  // Solve
142  magma_d_solver(mDevSysMat, mDevRhsVec, &mDevLhsVec, &mMagmaOpts, mMagmaQueue);
143 
144  //Copy Solution back
145  magma_dmtransfer(mDevLhsVec, &mHostLhsVec, Magma_DEV, Magma_CPU, mMagmaQueue);
146  magma_dvcopy(mDevLhsVec, &size, &one, leftSideVector.data(), mMagmaQueue);
147 
148  return leftSideVector;
149 }
150 } // namespace DPsim
magma_d_matrix mHostLhsVec
LHS-Vector.
virtual void factorize(SparseMatrix &systemMatrix) override
factorization function with partial pivoting
virtual ~GpuMagmaAdapter()
Destructor.
virtual void refactorize(SparseMatrix &systemMatrix) override
refactorization without partial pivoting
magma_dopts mMagmaOpts
Solver-Handle.
magma_d_matrix mHostRhsVec
RHS-Vector.
virtual Matrix solve(Matrix &rightSideVector) override
solution function for a right hand side
magma_d_matrix mHostSysMat
Systemmatrix.
virtual void preprocessing(SparseMatrix &systemMatrix, std::vector< std::pair< UInt, UInt >> &listVariableSystemMatrixEntries) override
preprocessing function pre-ordering and scaling the matrix
virtual void partialRefactorize(SparseMatrix &systemMatrix, std::vector< std::pair< UInt, UInt >> &listVariableSystemMatrixEntries) override
partial refactorization withouth partial pivoting
GpuMagmaAdapter()
Constructor.