1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Dario Mangoni, Radu Serban
13 // =============================================================================
14
15
16 #include "chrono_pardisoproject/ChPardisoProjectEngine.h"
17 #include "chrono/parallel/ChOpenMP.h"
18
19
20 /* PARDISO prototype. */
21 extern "C" void pardisoinit (void *, int *, int *, int *, double *, int *);
22 extern "C" void pardiso (void *, int *, int *, int *, int *, int *,
23 double *, int *, int *, int *, int *, int *,
24 int *, double *, double *, int *, double *);
25 extern "C" void pardiso_chkmatrix (int *, int *, double *, int *, int *, int *);
26 extern "C" void pardiso_chkvec (int *, int *, double *, int *);
27 extern "C" void pardiso_printstats (int *, int *, double *, int *, int *, int *, double *, int *);
28 extern "C" void pardiso_get_schur(void*, int*, int*, int*, double*, int*, int*);
29
30 namespace chrono {
31
ChPardisoProjectEngine(parproj_SYM symmetry)32 ChPardisoProjectEngine::ChPardisoProjectEngine(parproj_SYM symmetry) :symmetry(symmetry) {
33 Reinit();
34 }
35
~ChPardisoProjectEngine()36 ChPardisoProjectEngine::~ChPardisoProjectEngine() {
37 PardisoProjectCall(parproj_PHASE::END);
38 }
39
SetProblem(const ChSparseMatrix & Z,ChVectorRef rhs,ChVectorRef sol)40 void ChPardisoProjectEngine::SetProblem(const ChSparseMatrix& Z, ChVectorRef rhs, ChVectorRef sol) {
41 SetMatrix(Z);
42 SetRhsVector(rhs);
43 SetSolutionVector(sol);
44 }
45
SetMatrix(const ChSparseMatrix & Z,bool isZeroIndexed)46 void ChPardisoProjectEngine::SetMatrix(const ChSparseMatrix& Z, bool isZeroIndexed) {
47 this->SetMatrix(
48 Z.rows(),
49 const_cast<int*>(Z.outerIndexPtr()),
50 const_cast<int*>(Z.innerIndexPtr()),
51 const_cast<double*>(Z.valuePtr()),
52 false
53 );
54 matOneIndexedFormat = !isZeroIndexed;
55 }
56
SetMatrix(int n,int * ia,int * ja,double * a,bool isZeroIndexed)57 void ChPardisoProjectEngine::SetMatrix(int n, int *ia, int *ja, double *a, bool isZeroIndexed) {
58 this->n = n;
59 this->a = a;
60 this->ia = ia;
61 this->ja = ja;
62 matOneIndexedFormat = !isZeroIndexed;
63 }
64
SetMatrixSymmetry(parproj_SYM symmetry)65 void ChPardisoProjectEngine::SetMatrixSymmetry(parproj_SYM symmetry) {
66 PardisoProjectCall(parproj_PHASE::END);
67 this->symmetry = symmetry;
68 Reinit();
69 }
70
SetRhsVector(ChVectorRef b)71 void ChPardisoProjectEngine::SetRhsVector(ChVectorRef b) {
72 this->b = b.data();
73 }
74
SetRhsVector(double * b)75 void ChPardisoProjectEngine::SetRhsVector(double* b) {
76 this->b = b;
77 }
78
SetSolutionVector(ChVectorRef x)79 void ChPardisoProjectEngine::SetSolutionVector(ChVectorRef x) {
80 this->x = x.data();
81 }
82
SetSolutionVector(double * x)83 void ChPardisoProjectEngine::SetSolutionVector(double* x) {
84 this->x = x;
85 }
86
87
PardisoProjectCall(parproj_PHASE phase)88 int ChPardisoProjectEngine::PardisoProjectCall(parproj_PHASE phase) {
89 int phase_int = phase;
90 int mtype_int = symmetry;
91
92 SetOneIndexedFormat(); // make sure that is one-based format
93
94 pardiso (pt, &maxfct, &mnum, &mtype_int, &phase_int, &n, a, ia, ja, &idum, &nrhs, iparm, &msglvl, b, x, &error, dparm);
95
96 return error;
97 }
98
99
CheckMatrix(bool print)100 int ChPardisoProjectEngine::CheckMatrix(bool print){
101 /* -------------------------------------------------------------------- */
102 /* .. pardiso_chk_matrix(...) */
103 /* Checks the consistency of the given matrix. */
104 /* Use this functionality only for debugging purposes */
105 /* -------------------------------------------------------------------- */
106 bool matOneIndexedFormat_bkp = this->matOneIndexedFormat;
107 SetOneIndexedFormat();
108 int mtype_int = symmetry;
109 pardiso_chkmatrix(&mtype_int, &n, a, ia, ja, &error);
110 if (!matOneIndexedFormat_bkp) SetZeroIndexedFormat();
111
112 if (error != 0) {
113 if (print)
114 printf("\nERROR in consistency of matrix: %d", error);
115 return error;
116 } else
117 printf("\nMatrix consistency check passed\n");
118 return error;
119 }
120
CheckMatrixStats(bool print)121 int ChPardisoProjectEngine::CheckMatrixStats(bool print) {
122 /* -------------------------------------------------------------------- */
123 /* .. pardiso_printstats(...) */
124 /* prints information on the matrix to STDOUT. */
125 /* Use this functionality only for debugging purposes */
126 /* -------------------------------------------------------------------- */
127 bool matOneIndexedFormat_bkp = this->matOneIndexedFormat;
128 SetOneIndexedFormat();
129 int mtype_int = symmetry;
130 pardiso_printstats(&mtype_int, &n, a, ia, ja, &nrhs, b, &error);
131 if (!matOneIndexedFormat_bkp) SetZeroIndexedFormat();
132
133 if (error != 0) {
134 if (print)
135 printf("\nERROR in matrix stats: %d", error);
136 return error;
137 } else
138 printf("\nMatrix stats passed\n");
139 return error;
140 }
141
142
CheckRhsVectors(bool print)143 int ChPardisoProjectEngine::CheckRhsVectors(bool print){
144 /* -------------------------------------------------------------------- */
145 /* .. pardiso_chkvec(...) */
146 /* Checks the given vectors for infinite and NaN values */
147 /* Input parameters (see PARDISO user manual for a description): */
148 /* Use this functionality only for debugging purposes */
149 /* -------------------------------------------------------------------- */
150 bool matOneIndexedFormat_bkp = this->matOneIndexedFormat;
151 SetOneIndexedFormat();
152 pardiso_chkvec (&n, &nrhs, b, &error);
153 if (!matOneIndexedFormat_bkp) SetZeroIndexedFormat();
154
155 if (error != 0) {
156 if (print)
157 printf("\nERROR in right hand side: %d", error);
158 return error;
159 } else
160 printf("\nRhs check passed\n");
161 return error;
162 }
163
GetSchurComplement(ChSparseMatrix & Z,int nrows)164 void ChPardisoProjectEngine::GetSchurComplement(ChSparseMatrix& Z, int nrows) {
165 SetIPARM(38-1, nrows);
166 PardisoProjectCall(ChPardisoProjectEngine::parproj_PHASE::ANALYZE_FACTORIZE);
167 int schurNNZ = GetIPARM(39-1);
168 Z.resize(nrows, nrows);
169 Z.reserve(schurNNZ);
170 int *iS, *jS;
171 double* S;
172 getMatrixInternalArrays(Z, &iS, &jS, &S);
173 int mtype_int = symmetry;
174 pardiso_get_schur(pt, &maxfct, &mnum, &mtype_int, S, iS, jS);
175 }
176
shiftInternalMatrixIndices(int val)177 void ChPardisoProjectEngine::shiftInternalMatrixIndices(int val) {
178 shiftMatrixIndices(ia, ja, a, n, val, matOneIndexedFormat);
179 }
180
shiftMatrixIndices(int * ext_ia,int * ext_ja,double * ext_a,int ext_n,int val,bool isOneIndexed)181 void ChPardisoProjectEngine::shiftMatrixIndices(int* ext_ia, int* ext_ja, double* ext_a, int ext_n, int val, bool isOneIndexed) {
182 int nnz = isOneIndexed ? ext_ia[ext_n]-1 : ext_ia[ext_n];
183 for (int i = 0; i < ext_n + 1; i++) {
184 ext_ia[i] += val;
185 }
186 for (int i = 0; i < nnz; i++) {
187 ext_ja[i] += val;
188 }
189 }
190
getMatrixInternalArrays(ChSparseMatrix & sparseMat,int ** ext_ia,int ** ext_ja,double ** ext_a)191 bool ChPardisoProjectEngine::getMatrixInternalArrays(ChSparseMatrix& sparseMat, int** ext_ia, int** ext_ja, double** ext_a) {
192 *ext_ia = sparseMat.outerIndexPtr();
193 *ext_ja = sparseMat.innerIndexPtr();
194 *ext_a = sparseMat.valuePtr();
195 return false;
196 }
197
SetZeroIndexedFormat()198 inline void ChPardisoProjectEngine::SetZeroIndexedFormat() {
199 if (matOneIndexedFormat)
200 shiftInternalMatrixIndices(-1);
201 matOneIndexedFormat = false;
202 }
203
SetOneIndexedFormat()204 inline void ChPardisoProjectEngine::SetOneIndexedFormat() {
205 if (!matOneIndexedFormat)
206 shiftInternalMatrixIndices(+1);
207 matOneIndexedFormat = true;
208 }
209
210 /// Set the solver type. \p directsparse = true for direct sparse solver, false for multi-recursive iterative solver.
211 /// \warning{This function triggers a Reinit()}
212
SetSolverType(bool directsparse)213 inline void ChPardisoProjectEngine::SetSolverType(bool directsparse) {
214 solver = directsparse ? 0 : 1;
215 //SetIPARM(32-1, directsparse ? 0 : 1);
216 Reinit();
217 }
218
Reinit()219 void ChPardisoProjectEngine::Reinit() {
220 this->iparm[2] = ChOMP::GetNumProcs();
221
222 int mtype_int = symmetry;
223 pardisoinit(pt, &mtype_int, &solver, iparm, dparm, &error);
224
225 if (error != 0)
226 {
227 if (error == -10 )
228 printf("No license file found \n");
229 if (error == -11 )
230 printf("License is expired \n");
231 if (error == -12 )
232 printf("Wrong username or hostname \n");
233 //return 1;
234 }
235 else
236 printf("[PARDISO]: License check was successful ... \n");
237 }
238
SetMessageLevel(int msglvl)239 void ChPardisoProjectEngine::SetMessageLevel(int msglvl) {
240 if (msglvl == 0 || msglvl == 1)
241 this->msglvl = msglvl;
242 }
243
244
245 } // namespace chrono
246