34 #include "superlu/slu_Cnames.h"
35 #include "superlu/supermatrix.h"
36 #include "superlu/slu_util.h"
39 #include "superlu/slu_sdefs.h"
42 #include "superlu/slu_ddefs.h"
45 #include "superlu/slu_cdefs.h"
48 #include "superlu/slu_zdefs.h"
57 inline void Create_CompCol_Matrix(SuperMatrix *A,
int m,
int n,
int nnz,
58 float *a,
int *ir,
int *jc) {
59 SuperLU_S::sCreate_CompCol_Matrix(A, m, n, nnz, a, ir, jc,
60 SLU_NC, SLU_S, SLU_GE);
63 inline void Create_CompCol_Matrix(SuperMatrix *A,
int m,
int n,
int nnz,
64 double *a,
int *ir,
int *jc) {
65 SuperLU_D::dCreate_CompCol_Matrix(A, m, n, nnz, a, ir, jc,
66 SLU_NC, SLU_D, SLU_GE);
69 inline void Create_CompCol_Matrix(SuperMatrix *A,
int m,
int n,
int nnz,
70 std::complex<float> *a,
int *ir,
int *jc) {
71 SuperLU_C::cCreate_CompCol_Matrix(A, m, n, nnz, (SuperLU_C::complex *)(a),
72 ir, jc, SLU_NC, SLU_C, SLU_GE);
75 inline void Create_CompCol_Matrix(SuperMatrix *A,
int m,
int n,
int nnz,
76 std::complex<double> *a,
int *ir,
int *jc) {
77 SuperLU_Z::zCreate_CompCol_Matrix(A, m, n, nnz,
78 (SuperLU_Z::doublecomplex *)(a), ir, jc,
79 SLU_NC, SLU_Z, SLU_GE);
84 inline void Create_Dense_Matrix(SuperMatrix *A,
int m,
int n,
float *a,
int k)
85 { SuperLU_S::sCreate_Dense_Matrix(A, m, n, a, k, SLU_DN, SLU_S, SLU_GE); }
86 inline void Create_Dense_Matrix(SuperMatrix *A,
int m,
int n,
double *a,
int k)
87 { SuperLU_D::dCreate_Dense_Matrix(A, m, n, a, k, SLU_DN, SLU_D, SLU_GE); }
88 inline void Create_Dense_Matrix(SuperMatrix *A,
int m,
int n,
89 std::complex<float> *a,
int k) {
90 SuperLU_C::cCreate_Dense_Matrix(A, m, n, (SuperLU_C::complex *)(a),
91 k, SLU_DN, SLU_C, SLU_GE);
93 inline void Create_Dense_Matrix(SuperMatrix *A,
int m,
int n,
94 std::complex<double> *a,
int k) {
95 SuperLU_Z::zCreate_Dense_Matrix(A, m, n, (SuperLU_Z::doublecomplex *)(a),
96 k, SLU_DN, SLU_Z, SLU_GE);
101 #define DECL_GSSV(NAMESPACE,FNAME,FLOATTYPE,KEYTYPE) \
102 inline void SuperLU_gssv(superlu_options_t *options, SuperMatrix *A, int *p, \
103 int *q, SuperMatrix *L, SuperMatrix *U, SuperMatrix *B, \
104 SuperLUStat_t *stats, int *info, KEYTYPE) { \
105 NAMESPACE::FNAME(options, A, p, q, L, U, B, stats, info); \
108 DECL_GSSV(SuperLU_S,sgssv,
float,
float)
109 DECL_GSSV(SuperLU_C,cgssv,
float,std::complex<float>)
110 DECL_GSSV(SuperLU_D,dgssv,
double,
double)
111 DECL_GSSV(SuperLU_Z,zgssv,
double,std::complex<double>)
115 #define DECL_GSSVX(NAMESPACE,FNAME,FLOATTYPE,KEYTYPE) \
116 inline float SuperLU_gssvx(superlu_options_t *options, SuperMatrix *A, \
117 int *perm_c, int *perm_r, int *etree, char *equed, \
118 FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \
119 SuperMatrix *U, void *work, int lwork, \
120 SuperMatrix *B, SuperMatrix *X, \
121 FLOATTYPE *recip_pivot_growth, \
122 FLOATTYPE *rcond, FLOATTYPE *ferr, FLOATTYPE *berr, \
123 SuperLUStat_t *stats, int *info, KEYTYPE) { \
124 NAMESPACE::mem_usage_t mem_usage; \
125 NAMESPACE::FNAME(options, A, perm_c, perm_r, etree, equed, R, C, L, \
126 U, work, lwork, B, X, recip_pivot_growth, rcond, \
127 ferr, berr, &mem_usage, stats, info); \
128 return mem_usage.for_lu; \
131 DECL_GSSVX(SuperLU_S,sgssvx,
float,
float)
132 DECL_GSSVX(SuperLU_C,cgssvx,
float,std::complex<float>)
133 DECL_GSSVX(SuperLU_D,dgssvx,
double,
double)
134 DECL_GSSVX(SuperLU_Z,zgssvx,
double,std::complex<double>)
141 int SuperLU_solve(
const gmm::csc_matrix<T> &csc_A, T *sol, T *rhs,
142 double& rcond_,
int permc_spec) {
150 typedef typename gmm::number_traits<T>::magnitude_type R;
152 int m = int(mat_nrows(csc_A)), n = int(mat_ncols(csc_A));
153 int nrhs = 1, info = 0, nz = int(
nnz(csc_A));
155 GMM_ASSERT1(nz != 0,
"Cannot factor a matrix full of zeros!");
156 GMM_ASSERT1(n == m,
"Cannot factor a non-square matrix");
158 if ((2 * nz / n) >= m)
159 GMM_WARNING2(
"CAUTION : it seems that SuperLU has a problem"
160 " for nearly dense sparse matrices");
162 superlu_options_t options;
163 set_default_options(&options);
164 options.ColPerm = NATURAL;
165 options.PrintStat = NO;
166 options.ConditionNumber = YES;
167 switch (permc_spec) {
168 case 1 : options.ColPerm = MMD_ATA;
break;
169 case 2 : options.ColPerm = MMD_AT_PLUS_A;
break;
170 case 3 : options.ColPerm = COLAMD;
break;
175 SuperMatrix SA, SL, SU, SB, SX;
176 Create_CompCol_Matrix(&SA, m, n, nz,
const_cast<T*
>(&csc_A.pr[0]),
177 const_cast<int *
>((
const int *)(&csc_A.ir[0])),
178 const_cast<int *
>((
const int *)(&csc_A.jc[0])));
179 Create_Dense_Matrix(&SB, m, nrhs, &rhs[0], m);
180 Create_Dense_Matrix(&SX, m, nrhs, &sol[0], m);
182 memset(&SL,0,
sizeof SL);
183 memset(&SU,0,
sizeof SU);
185 std::vector<int> etree(n);
187 std::vector<R> Rscale(m),Cscale(n);
188 std::vector<R> ferr(nrhs), berr(nrhs);
189 R recip_pivot_gross, rcond;
190 std::vector<int> perm_r(m), perm_c(n);
192 SuperLU_gssvx(&options, &SA, &perm_c[0], &perm_r[0],
208 if (SB.Store) Destroy_SuperMatrix_Store(&SB);
209 if (SX.Store) Destroy_SuperMatrix_Store(&SX);
210 if (SA.Store) Destroy_SuperMatrix_Store(&SA);
211 if (SL.Store) Destroy_SuperNode_Matrix(&SL);
212 if (SU.Store) Destroy_CompCol_Matrix(&SU);
214 GMM_ASSERT1(info != -333333333,
"SuperLU was cancelled.");
216 GMM_ASSERT1(info >= 0,
"SuperLU solve failed: info =" << info);
217 if (info > 0) GMM_WARNING1(
"SuperLU solve failed: info =" << info);
221 template int SuperLU_solve(
const gmm::csc_matrix<float> &csc_A,
float *sol,
float *rhs,
double& rcond_,
int permc_spec);
222 template int SuperLU_solve(
const gmm::csc_matrix<double> &csc_A,
double *sol,
double *rhs,
double& rcond_,
int permc_spec);
223 template int SuperLU_solve(
const gmm::csc_matrix<std::complex<float> > &csc_A, std::complex<float> *sol, std::complex<float> *rhs,
double& rcond_,
int permc_spec);
224 template int SuperLU_solve(
const gmm::csc_matrix<std::complex<double> > &csc_A, std::complex<double> *sol, std::complex<double> *rhs,
double& rcond_,
int permc_spec);
226 struct SuperLU_factor_impl_common {
227 mutable SuperMatrix SA, SL, SB, SU, SX;
228 mutable SuperLUStat_t stat;
229 mutable superlu_options_t options;
231 mutable bool is_init;
233 void free_supermatrix() {
235 if (SB.Store) Destroy_SuperMatrix_Store(&SB);
236 if (SX.Store) Destroy_SuperMatrix_Store(&SX);
237 if (SA.Store) Destroy_SuperMatrix_Store(&SA);
238 if (SL.Store) Destroy_SuperNode_Matrix(&SL);
239 if (SU.Store) Destroy_CompCol_Matrix(&SU);
242 SuperLU_factor_impl_common() : is_init(false) {}
243 virtual ~SuperLU_factor_impl_common() { free_supermatrix(); }
246 template <
typename T>
struct SuperLU_factor_impl :
public SuperLU_factor_impl_common {
247 typedef typename gmm::number_traits<T>::magnitude_type R;
249 std::vector<int> etree, perm_r, perm_c;
250 std::vector<R> Rscale, Cscale;
251 std::vector<R> ferr, berr;
254 void build_with(
const gmm::csc_matrix<T> &A,
int permc_spec);
255 void solve(
int transp);
258 template <
typename T>
259 void SuperLU_factor_impl<T>::build_with(
const gmm::csc_matrix<T> &A,
int permc_spec) {
268 int n = int(mat_nrows(A)), m = int(mat_ncols(A)), info = 0;
270 rhs.resize(m); sol.resize(m);
272 int nz = int(
nnz(A));
274 GMM_ASSERT1(nz != 0,
"Cannot factor a matrix full of zeros!");
275 GMM_ASSERT1(n == m,
"Cannot factor a non-square matrix");
277 set_default_options(&options);
278 options.ColPerm = NATURAL;
279 options.PrintStat = NO;
280 options.ConditionNumber = NO;
281 switch (permc_spec) {
282 case 1 : options.ColPerm = MMD_ATA;
break;
283 case 2 : options.ColPerm = MMD_AT_PLUS_A;
break;
284 case 3 : options.ColPerm = COLAMD;
break;
288 Create_CompCol_Matrix(&SA, m, n, nz,
const_cast<T*
>(&A.pr[0]),
289 const_cast<int *
>((
const int *)(&A.ir[0])),
290 const_cast<int *
>((
const int *)(&A.jc[0])));
291 Create_Dense_Matrix(&SB, m, 0, &rhs[0], m);
292 Create_Dense_Matrix(&SX, m, 0, &sol[0], m);
293 memset(&SL,0,
sizeof SL);
294 memset(&SU,0,
sizeof SU);
298 Rscale.resize(m); Cscale.resize(n); etree.resize(n);
299 ferr.resize(1); berr.resize(1);
300 R recip_pivot_gross, rcond;
301 perm_r.resize(m); perm_c.resize(n);
302 memory_used = SuperLU_gssvx(&options, &SA, &perm_c[0], &perm_r[0],
318 Destroy_SuperMatrix_Store(&SB);
319 Destroy_SuperMatrix_Store(&SX);
320 Create_Dense_Matrix(&SB, m, 1, &rhs[0], m);
321 Create_Dense_Matrix(&SX, m, 1, &sol[0], m);
324 GMM_ASSERT1(info != -333333333,
"SuperLU was cancelled.");
325 GMM_ASSERT1(info == 0,
"SuperLU solve failed: info=" << info);
329 template <
typename T>
330 void SuperLU_factor_impl<T>::solve(
int transp) {
331 options.Fact = FACTORED;
332 options.IterRefine = NOREFINE;
334 case SuperLU_factor<T>::LU_NOTRANSP: options.Trans = NOTRANS;
break;
335 case SuperLU_factor<T>::LU_TRANSP: options.Trans = TRANS;
break;
336 case SuperLU_factor<T>::LU_CONJUGATED: options.Trans = CONJ;
break;
337 default: GMM_ASSERT1(
false,
"invalid value for transposition option");
341 R recip_pivot_gross, rcond;
342 SuperLU_gssvx(&options, &SA, &perm_c[0], &perm_r[0],
358 GMM_ASSERT1(info == 0,
"SuperLU solve failed: info=" << info);
361 template<
typename T>
void
363 ((SuperLU_factor_impl<T>*)impl.get())->build_with(A,permc_spec);
366 template<
typename T>
void
368 ((SuperLU_factor_impl<T>*)impl.get())->solve(transp);
371 template<
typename T> std::vector<T> &
372 SuperLU_factor<T>::sol()
const {
373 return ((SuperLU_factor_impl<T>*)impl.get())->sol;
376 template<
typename T> std::vector<T> &
377 SuperLU_factor<T>::rhs()
const {
378 return ((SuperLU_factor_impl<T>*)impl.get())->rhs;
382 SuperLU_factor<T>::SuperLU_factor() {
383 impl = std::make_shared<SuperLU_factor_impl<T>>();
387 SuperLU_factor<T>::SuperLU_factor(
const SuperLU_factor& other) {
388 impl = std::make_shared<SuperLU_factor_impl<T>>();
389 GMM_ASSERT1(!(other.impl->is_init),
390 "copy of initialized SuperLU_factor is forbidden");
391 other.impl->is_init =
false;
394 template<
typename T> SuperLU_factor<T>&
395 SuperLU_factor<T>::operator=(
const SuperLU_factor& other) {
396 GMM_ASSERT1(!(other.impl->is_init) && !(impl->is_init),
397 "assignment of initialized SuperLU_factor is forbidden");
401 template<
typename T>
float
402 SuperLU_factor<T>::memsize()
const {
403 return impl->memory_used;
421 static int (*superlu_callback)();
424 extern "C" int handle_getfem_callback() {
425 if (superlu_callback)
return superlu_callback();
429 extern "C" void set_superlu_callback(
int (*cb)()) {
430 superlu_callback = cb;