b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2superlu_solver.H
1//------------------------------------------------------------------------
2// b2superlu_solver.H --
3//
4//
5// written by Mathias Doreille
6//
7// Copyright (c) 2004-2012 SMR Engineering & Development SA
8// 2502 Bienne, Switzerland
9//
10// All Rights Reserved. Proprietary source code. The contents of
11// this file may not be disclosed to third parties, copied or
12// duplicated in any form, in whole or in part, without the prior
13// written permission of SMR.
14//------------------------------------------------------------------------
15
16#ifndef __B2SUPERLU_SOLVER_H__
17#define __B2SUPERLU_SOLVER_H__
18
19extern "C" {
20#include <SuperLU/dsp_defs.h>
21}
22
23#include "b2sparse_solver.H"
24
25namespace b2000 { namespace b2linalg {
26class Generic_SuperLU {
27public:
28 void Init_SuperMatrix_Store(SuperMatrix* A) { A->Store = 0; }
29
30 void Create_CompCol_Matrix(
31 SuperMatrix* A, int m, int n, int nnz, double* nzval, int* rowind, int* colptr,
32 Stype_t stype, Mtype_t mtype) {
33 dCreate_CompCol_Matrix(A, m, n, nnz, nzval, rowind, colptr, stype, SLU_D, mtype);
34 }
35
36 void Destroy_CompCol_Matrix(SuperMatrix* A) {
37 if (A->Store) {
38 SUPERLU_FREE(((NCformat*)A->Store)->rowind);
39 SUPERLU_FREE(((NCformat*)A->Store)->colptr);
40 SUPERLU_FREE(((NCformat*)A->Store)->nzval);
41 }
42 SUPERLU_FREE(A->Store);
43 }
44
45 void Create_Dense_Matrix(
46 SuperMatrix* X, int m, int n, double* x, int ldx, Stype_t stype, Mtype_t mtype) {
47 dCreate_Dense_Matrix(X, m, n, x, ldx, stype, SLU_D, mtype);
48 }
49
50 void Destroy_Dense_Matrix(SuperMatrix* A) {
51 if (A->Store) { SUPERLU_FREE(((DNformat*)A->Store)->nzval); }
52 SUPERLU_FREE(A->Store);
53 }
54
55 void Destroy_SuperNode_Matrix(SuperMatrix* A) {
56 if (A->Store) {
57 SUPERLU_FREE(((SCformat*)A->Store)->rowind);
58 SUPERLU_FREE(((SCformat*)A->Store)->rowind_colptr);
59 SUPERLU_FREE(((SCformat*)A->Store)->nzval);
60 SUPERLU_FREE(((SCformat*)A->Store)->nzval_colptr);
61 SUPERLU_FREE(((SCformat*)A->Store)->col_to_sup);
62 SUPERLU_FREE(((SCformat*)A->Store)->sup_to_col);
63 }
64 SUPERLU_FREE(A->Store);
65 }
66
67 void gssvx(
68 superlu_options_t* options, SuperMatrix* A, int* perm_c, int* perm_r, int* etree,
69 char* equed, double* R, double* C, SuperMatrix* L, SuperMatrix* U, void* work, int lwork,
70 SuperMatrix* B, SuperMatrix* X, double* recip_pivot_growth, double* rcond, double* ferr,
71 double* berr, mem_usage_t* mem_usage, SuperLUStat_t* stat, int* info) {
72 dgssvx(
73 options, A, perm_c, perm_r, etree, equed, R, C, L, U, work, lwork, B, X,
74 recip_pivot_growth, rcond, ferr, berr, mem_usage, stat, info);
75 }
76};
77
78template <typename T>
79class SuperLU_LDLt_sparse_direct_solver : public LDLt_sparse_solver<T>, public Generic_SuperLU {
80public:
81 SuperLU_LDLt_sparse_direct_solver()
82 : size(0),
83 nnz(0),
84 colind(0),
85 rowind(),
86 value(0),
87 colptr1(0),
88 rowind1(0),
89 nzval1(0),
90 perm_c(0),
91 perm_r(0),
92 etree(0),
93 equed(0),
94 R(0),
95 C(0) {
96 Init_SuperMatrix_Store(&L);
97 Init_SuperMatrix_Store(&U);
98 Init_SuperMatrix_Store(&A);
99 }
100
101 ~SuperLU_LDLt_sparse_direct_solver() {
102 delete[] perm_c;
103 delete[] perm_r;
104 delete[] etree;
105 delete[] R;
106 delete[] C;
107 Destroy_SuperNode_Matrix(&L);
108 Destroy_CompCol_Matrix(&U);
109 Destroy_CompCol_Matrix(&A);
110 }
111
112 void init(
113 size_t size_, size_t nnz_, const size_t* colind_, const size_t* rowind_, const T* value_,
114 int connectivity, const Dictionary& dictionary) {
115 size = size_;
116 nnz = nnz_;
117 colind = colind_;
118 rowind = rowind_;
119 value = value_;
120
121 delete[] perm_c;
122 perm_c = new int[size];
123 delete[] perm_r;
124 perm_r = new int[size];
125 delete[] etree;
126 etree = new int[size];
127 equed = 'N';
128 delete[] R;
129 R = new T[size];
130 delete[] C;
131 C = new T[size];
132
133 set_default_options(&options);
134 options.SymmetricMode = YES;
135 options.Equil = NO;
136 // options.IterRefine = EXTRA;
137 // options.DiagPivotThresh = 0.0;
138 options.ConditionNumber = YES;
139 }
140
141 void update_value() { options.Fact = SamePattern; }
142
143 void resolve(
144 size_t s, size_t nrhs, const T* b, size_t ldb, T* x, size_t ldx,
145 char left_or_right = ' ') {
146 if (left_or_right == 'L' || left_or_right == 'R') { UnimplementedError() << THROW; }
147 SuperLUStat_t stat;
148 StatInit(&stat);
149 int info;
150 mem_usage_t mem_usage;
151 T rpg;
152 T rcond;
153 std::vector<T> ferr(s);
154 std::vector<T> berr(s);
155
156 SuperMatrix B, X;
157 Create_Dense_Matrix(&B, s, nrhs, const_cast<double*>(b), ldb, SLU_DN, SLU_GE);
158 Create_Dense_Matrix(&X, s, nrhs, x, ldx, SLU_DN, SLU_GE);
159
160 if (options.Fact != FACTORED) {
161 Destroy_SuperNode_Matrix(&L);
162 Destroy_CompCol_Matrix(&U);
163 Destroy_CompCol_Matrix(&A);
164 colptr1 = (int*)SUPERLU_MALLOC((size + 2) * sizeof(int));
165 colptr1[0] = colptr1[1] = 0;
166 colptr1 += 2;
167 for (size_t j = 0; j != size; ++j) { colptr1[j] = colind[j + 1] - colind[j]; }
168 for (size_t j = 0; j != size; ++j) {
169 const size_t i_end = colind[j + 1];
170 for (size_t i = colind[j] + 1; i < i_end; ++i) { ++colptr1[rowind[i]]; }
171 }
172 --colptr1;
173 for (size_t j = 0; j != size; ++j) { colptr1[j + 1] += colptr1[j]; }
174 int nnz1 = colptr1[size];
175 int* rowind1 = (int*)SUPERLU_MALLOC(nnz1 * sizeof(int));
176 T* nzval1 = (T*)SUPERLU_MALLOC(nnz1 * sizeof(T));
177 for (size_t j = 0; j != size; ++j) {
178 size_t i = colind[j];
179 const size_t i_end = colind[j + 1];
180 int ii = colptr1[j];
181 colptr1[j] += i_end - i;
182 std::copy(rowind + i, rowind + i_end, rowind1 + ii);
183 std::copy(value + i, value + i_end, nzval1 + ii);
184 for (++i; i < i_end; ++i) {
185 int ii = colptr1[rowind[i]]++;
186 rowind1[ii] = j;
187 nzval1[ii] = value[i];
188 }
189 }
190 --colptr1;
191
192 /*
193 for (size_t j = 0; j != size; ++j) {
194 for (int i = colptr1[j]; i != colptr1[j+1]; ++i)
195 std::cout << "(" << rowind1[i] << "," << nzval1[i] << ") ";
196 std::cout << std::endl;
197 }
198 std::cout << std::endl;
199 */
200
201 Create_CompCol_Matrix(&A, size, size, nnz1, nzval1, rowind1, colptr1, SLU_NC, SLU_GE);
202 }
203
204 gssvx(&options, &A, perm_c, perm_r, etree, &equed, R, C, &L, &U, 0, 0, &B, &X, &rpg, &rcond,
205 &ferr[0], &berr[0], &mem_usage, &stat, &info);
206
207 std::cout << "factorisation, rcond = " << rcond << std::endl;
208
209 Destroy_SuperMatrix_Store(&B);
210 Destroy_SuperMatrix_Store(&X);
211 StatFree(&stat);
212
213 if (info > 0 && info <= int(s)) {
214 Exception() << "The matrix entrie L(" << info << "," << info
215 << ") of the factorised matrix is exactly zero. The factorization has been "
216 "completed, but the factor U is exactly singular, so the solution and "
217 "error bounds could not be computed."
218 << THROW;
219 }
220 if (info == int(s) + 1) {
221 Exception() << "The factorised matrix L is nonsingular, but this condition number is "
222 "less than machine precision, meaning that the matrix is singular to "
223 "working precision."
224 << THROW;
225 }
226 if (info) { Exception() << THROW; }
227
228 options.Fact = FACTORED;
229 }
230
231 void resolve(size_t s, size_t nrhs, T* bx, size_t ldbx, char left_or_right = ' ') {
232 size_t ss = s * nrhs;
233 T* x = new T[ss];
234 resolve(s, nrhs, bx, ldbx, x, s, left_or_right);
235 if (ldbx == s) {
236 std::copy(x, x + ss, bx);
237 } else {
238 T* xx = x;
239 T* xx_end = xx + ss;
240 while (xx < xx_end) {
241 std::copy(xx, xx + s, bx);
242 xx += s;
243 bx += ldbx;
244 }
245 }
246 delete[] x;
247 }
248
249private:
250 size_t size;
251 size_t nnz;
252 const size_t* colind;
253 const size_t* rowind;
254 const T* value;
255
256 int* colptr1;
257 int* rowind1;
258 T* nzval1;
259
260 SuperMatrix A, L, U;
261 int* perm_c;
262 int* perm_r;
263 int* etree;
264 char equed;
265 T* R;
266 T* C;
267 superlu_options_t options;
268};
269
270template <typename T>
271class SuperLU_LDLt_extension_sparse_direct_solver : public LDLt_extension_sparse_solver<T>,
272 public Generic_SuperLU {
273public:
274 SuperLU_LDLt_extension_sparse_direct_solver()
275 : size(0),
276 nnz(0),
277 colind(0),
278 rowind(),
279 value(0),
280 size_ext(0),
281 colptr1(0),
282 rowind1(0),
283 nzval1(0),
284 perm_c(0),
285 perm_r(0),
286 etree(0),
287 equed(0),
288 R(0),
289 C(0) {
290 Init_SuperMatrix_Store(&L);
291 Init_SuperMatrix_Store(&U);
292 Init_SuperMatrix_Store(&A);
293 }
294
295 ~SuperLU_LDLt_extension_sparse_direct_solver() {
296 delete[] perm_c;
297 delete[] perm_r;
298 delete[] etree;
299 delete[] R;
300 delete[] C;
301 Destroy_SuperNode_Matrix(&L);
302 Destroy_CompCol_Matrix(&U);
303 Destroy_CompCol_Matrix(&A);
304 }
305
306 void init(
307 size_t size_, size_t nnz_, const size_t* colind_, const size_t* rowind_, const T* value_,
308 size_t size_ext_, int connectivity, const Dictionary& dictionary) {
309 size = size_;
310 nnz = nnz_;
311 colind = colind_;
312 rowind = rowind_;
313 value = value_;
314 size_ext = size_ext_;
315
316 delete[] perm_c;
317 perm_c = new int[size + size_ext];
318 delete[] perm_r;
319 perm_r = new int[size + size_ext];
320 delete[] etree;
321 etree = new int[size + size_ext];
322 equed = 'N';
323 delete[] R;
324 R = new T[size + size_ext];
325 delete[] C;
326 C = new T[size + size_ext];
327
328 set_default_options(&options);
329 options.SymmetricMode = YES;
330 options.Equil = YES;
331 options.IterRefine = EXTRA;
332 // options.DiagPivotThresh = 0.0;
333 options.ConditionNumber = YES;
334 }
335
336 void update_value() { options.Fact = SamePattern; }
337
338 void resolve(
339 size_t s, size_t nrhs, const T* b, size_t ldb, T* x, size_t ldx, const T* ma = 0,
340 const T* mb = 0, const T* mc = 0, char left_or_right = ' ') {
341 if (left_or_right == 'L' || left_or_right == 'R') { UnimplementedError() << THROW; }
342 SuperLUStat_t stat;
343 StatInit(&stat);
344 int info;
345 mem_usage_t mem_usage;
346 T rpg;
347 T rcond;
348 std::vector<T> ferr(s);
349 std::vector<T> berr(s);
350
351 SuperMatrix B, X;
352 Create_Dense_Matrix(&B, s, nrhs, const_cast<double*>(b), ldb, SLU_DN, SLU_GE);
353 Create_Dense_Matrix(&X, s, nrhs, x, ldx, SLU_DN, SLU_GE);
354
355 if (ma != 0 && mb != 0 && mc != 0 && options.Fact == FACTORED) {
356 options.Fact = SamePattern;
357 }
358
359 if (options.Fact != FACTORED) {
360 Destroy_SuperNode_Matrix(&L);
361 Destroy_CompCol_Matrix(&U);
362 Destroy_CompCol_Matrix(&A);
363 colptr1 = (int*)SUPERLU_MALLOC((size + size_ext + 1) * sizeof(int));
364 colptr1[0] = colptr1[1] = 0;
365 colptr1 += 2;
366 for (size_t j = 0; j != size; ++j) {
367 colptr1[j] = colind[j + 1] - colind[j] + size_ext;
368 }
369 for (size_t j = 0; j != size; ++j) {
370 const size_t i_end = colind[j + 1];
371 for (size_t i = colind[j] + 1; i < i_end; ++i) { ++colptr1[rowind[i]]; }
372 }
373 --colptr1;
374 for (size_t j = 0; j != size; ++j) { colptr1[j + 1] += colptr1[j]; }
375 int nnz1 = colptr1[size] + size + 1;
376 int* rowind1 = (int*)SUPERLU_MALLOC(nnz1 * sizeof(int));
377 T* nzval1 = (T*)SUPERLU_MALLOC(nnz1 * sizeof(T));
378 for (size_t j = 0; j != size; ++j) {
379 size_t i = colind[j];
380 const size_t i_end = colind[j + 1];
381 int ii = colptr1[j];
382 colptr1[j] += i_end - i;
383 std::copy(rowind + i, rowind + i_end, rowind1 + ii);
384 std::copy(value + i, value + i_end, nzval1 + ii);
385 for (++i; i < i_end; ++i) {
386 int ii = colptr1[rowind[i]]++;
387 rowind1[ii] = j;
388 nzval1[ii] = value[i];
389 }
390 }
391
392 // Add the extension matrix mb, ma and mc
393 if (ma == 0 || mb == 0 || mc == 0) { Exception() << THROW; }
394 for (size_t j = 0; j != size; ++j) {
395 int& ii = colptr1[j];
396 for (size_t i = 0; i != size_ext; ++i, ++ii) {
397 rowind1[ii] = size + i;
398 nzval1[ii] = mb[j + i * size];
399 }
400 }
401
402 --colptr1;
403
404 {
405 for (size_t i = 0; i != size_ext; ++i) {
406 size_t ii = colptr1[size + i];
407 colptr1[size + i + 1] = ii + size + size_ext;
408 for (size_t j = 0; j != size; ++j, ++ii) {
409 rowind1[ii] = j;
410 nzval1[ii] = ma[j + i * size];
411 }
412 for (size_t j = 0; j != size_ext; ++j, ++ii) {
413 rowind1[ii] = j + size;
414 nzval1[ii] = mc[j + i * size_ext];
415 }
416 }
417 }
418
419 for (size_t j = 0; j != size + size_ext; ++j) {
420 for (int i = colptr1[j]; i != colptr1[j + 1]; ++i) {
421 std::cout << "(" << rowind1[i] << "," << nzval1[i] << ") ";
422 }
423 std::cout << std::endl;
424 }
425 std::cout << std::endl;
426
427 Create_CompCol_Matrix(
428 &A, size + size_ext, size + size_ext, nnz1, nzval1, rowind1, colptr1, SLU_NC,
429 SLU_GE);
430 }
431
432 gssvx(&options, &A, perm_c, perm_r, etree, &equed, R, C, &L, &U, 0, 0, &B, &X, &rpg, &rcond,
433 &ferr[0], &berr[0], &mem_usage, &stat, &info);
434
435 std::cout << "factorisation, rcond = " << rcond << std::endl;
436
437 Destroy_SuperMatrix_Store(&B);
438 Destroy_SuperMatrix_Store(&X);
439 StatFree(&stat);
440
441 if (info > 0 && info <= int(s)) {
442 Exception() << "The matrix entrie L(" << info << "," << info
443 << ") of the factorised matrix is exactly zero. The factorization has been "
444 "completed, but the factor U is exactly singular, so the solution and "
445 "error bounds could not be computed."
446 << THROW;
447 }
448 if (info == int(s) + 1) {
449 Exception() << "The factorised matrix L is nonsingular, but this condition number is "
450 "less than machine precision, meaning that the matrix is singular to "
451 "working precision."
452 << THROW;
453 }
454 if (info) { Exception() << THROW; }
455
456 options.Fact = FACTORED;
457 }
458
459 void resolve(
460 size_t s, size_t nrhs, T* bx, size_t ldbx, const T* ma = 0, const T* mb = 0,
461 const T* mc = 0, char left_or_right = ' ') {
462 size_t ss = s * nrhs;
463 T* x = new T[ss];
464 resolve(s, nrhs, bx, ldbx, x, s, ma, mb, mc, left_or_right);
465 if (ldbx == s) {
466 std::copy(x, x + ss, bx);
467 } else {
468 T* xx = x;
469 T* xx_end = xx + ss;
470 while (xx < xx_end) {
471 std::copy(xx, xx + s, bx);
472 xx += s;
473 bx += ldbx;
474 }
475 }
476 delete[] x;
477 }
478
479private:
480 size_t size;
481 size_t nnz;
482 const size_t* colind;
483 const size_t* rowind;
484 const T* value;
485
486 size_t size_ext;
487
488 int* colptr1;
489 int* rowind1;
490 T* nzval1;
491
492 SuperMatrix A, L, U;
493 int* perm_c;
494 int* perm_r;
495 int* etree;
496 char equed;
497 T* R;
498 T* C;
499 superlu_options_t options;
500};
501
502}} // namespace b2000::b2linalg
503
504#endif
#define THROW
Definition b2exception.H:198
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314