MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
superlu.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "../config/config.hpp"
13
14#ifdef MFEM_USE_SUPERLU
15#ifdef MFEM_USE_MPI
16
17#include "superlu.hpp"
18
19// SuperLU header
20#include "superlu_ddefs.h"
21
22#if XSDK_INDEX_SIZE == 64 && !(defined(HYPRE_BIGINT) || defined(HYPRE_MIXEDINT))
23#error "Mismatch between HYPRE (32bit) and SuperLU (64bit) integer types"
24#endif
25#if XSDK_INDEX_SIZE == 32 && (defined(HYPRE_BIGINT) || defined(HYPRE_MIXEDINT))
26#error "Mismatch between HYPRE (64bit) and SuperLU (32bit) integer types"
27#endif
28
29#if SUPERLU_DIST_MAJOR_VERSION > 6 || \
30 (SUPERLU_DIST_MAJOR_VERSION == 6 && SUPERLU_DIST_MINOR_VERSION >= 3)
31#define ScalePermstruct_t dScalePermstruct_t
32#define LUstruct_t dLUstruct_t
33#define SOLVEstruct_t dSOLVEstruct_t
34#define ZeroLblocks dZeroLblocks
35#define ZeroUblocks dZeroUblocks
36#define Destroy_LU dDestroy_LU
37#define SolveFinalize dSolveFinalize
38#define ScalePermstructInit dScalePermstructInit
39#define ScalePermstructFree dScalePermstructFree
40#define LUstructFree dLUstructFree
41#define LUstructInit dLUstructInit
42#endif
43
44#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
45 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
46#define DeAllocLlu_3d dDeAllocLlu_3d
47#define DeAllocGlu_3d dDeAllocGlu_3d
48#define Destroy_A3d_gathered_on_2d dDestroy_A3d_gathered_on_2d
49#endif
50
51unsigned int sqrti(unsigned int a)
52{
53 unsigned int rem = 0;
54 unsigned int root = 0;
55 unsigned short len = sizeof(int); len <<= 2;
56 unsigned short shift = (unsigned short)((len << 1) - 2);
57
58 for (int i = 0; i < len; i++)
59 {
60 root <<= 1;
61 rem = ((rem << 2) + (a >> shift));
62 a <<= 2;
63 root ++;
64 if (root <= rem)
65 {
66 rem -= root;
67 root++;
68 }
69 else
70 {
71 root--;
72 }
73 }
74 return (root >> 1);
75}
76
77int GetGridRows(MPI_Comm comm, int npdep)
78{
79 int np;
80 MPI_Comm_size(comm, &np);
81 MFEM_VERIFY(npdep > 0 && np % npdep == 0 && !(npdep & (npdep - 1)),
82 "SuperLUSolver: 3D partition depth must be a power of two "
83 "and evenly divide the number of processors!");
84 int nr = (int)sqrti((unsigned int)(np / npdep));
85 while (np % nr != 0 && nr > 0)
86 {
87 nr--;
88 }
89 MFEM_VERIFY(nr > 0,
90 "SuperLUSolver: Unable to determine processor grid for np = " << np);
91 return nr;
92}
93
94int GetGridCols(MPI_Comm comm, int npdep, int nr)
95{
96 int np;
97 MPI_Comm_size(comm, &np);
98 int nc = np / (nr * npdep);
99 MFEM_VERIFY(nr * nc * npdep == np,
100 "SuperLUSolver: Impossible processor partition!");
101 return nc;
102}
103
104namespace mfem
105{
106
108 int num_loc_rows,
109 HYPRE_BigInt first_loc_row,
110 HYPRE_BigInt glob_nrows,
111 HYPRE_BigInt glob_ncols,
112 int *I, HYPRE_BigInt *J,
113 double *data)
114 : comm_(comm)
115{
116 // Set mfem::Operator member data
117 height = num_loc_rows;
118 width = num_loc_rows;
119
120 // Allocate SuperLU's SuperMatrix struct
121 rowLocPtr_ = new SuperMatrix;
122 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
123 A->Store = NULL;
124
125 int_t m = glob_nrows;
126 int_t n = glob_ncols;
127 int_t nnz_loc = I[num_loc_rows];
128 int_t m_loc = num_loc_rows;
129 int_t fst_row = first_loc_row;
130
131 double *nzval = NULL;
132 int_t *colind = NULL;
133 int_t *rowptr = NULL;
134
135 if (!(nzval = doubleMalloc_dist(nnz_loc)))
136 {
137 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for nzval!");
138 }
139 for (int_t i = 0; i < nnz_loc; i++)
140 {
141 nzval[i] = data[i];
142 }
143
144 if (!(colind = intMalloc_dist(nnz_loc)))
145 {
146 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for colind!")
147 }
148 for (int_t i = 0; i < nnz_loc; i++)
149 {
150 colind[i] = J[i];
151 }
152
153 if (!(rowptr = intMalloc_dist(m_loc+1)))
154 {
155 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for rowptr!")
156 }
157 for (int_t i = 0; i <= m_loc; i++)
158 {
159 rowptr[i] = I[i];
160 }
161
162 // Assign the matrix data to SuperLU's SuperMatrix structure
163 dCreate_CompRowLoc_Matrix_dist(A, m, n, nnz_loc, m_loc, fst_row,
164 nzval, colind, rowptr,
165 SLU_NR_loc, SLU_D, SLU_GE);
166
167 // Save global number of rows and columns of the matrix
168 num_global_rows_ = m;
169 num_global_cols_ = n;
170}
171
173{
174 const HypreParMatrix *APtr = dynamic_cast<const HypreParMatrix *>(&op);
175 MFEM_VERIFY(APtr, "Not a compatible matrix type");
176 comm_ = APtr->GetComm();
177
178 // Set mfem::Operator member data
179 height = op.Height();
180 width = op.Width();
181
182 // Allocate SuperLU's SuperMatrix struct
183 rowLocPtr_ = new SuperMatrix;
184 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
185 A->Store = NULL;
186
187 // First cast the parameter to a hypre_ParCSRMatrix
188 hypre_ParCSRMatrix *parcsr_op =
189 (hypre_ParCSRMatrix *)const_cast<HypreParMatrix &>(*APtr);
190
191 // Create the SuperMatrix A by taking the internal data from a
192 // hypre_CSRMatrix
193 APtr->HostRead();
194 hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
195 APtr->HypreRead();
196 HYPRE_Int *Iptr = csr_op->i;
197#if MFEM_HYPRE_VERSION >= 21600
198 HYPRE_BigInt *Jptr = csr_op->big_j;
199#else
200 HYPRE_Int *Jptr = csr_op->j;
201#endif
202 int_t m = parcsr_op->global_num_rows;
203 int_t n = parcsr_op->global_num_cols;
204 int_t fst_row = parcsr_op->first_row_index;
205 int_t nnz_loc = csr_op->num_nonzeros;
206 int_t m_loc = csr_op->num_rows;
207
208 // We copy the data from the hypre_CSRMatrix because SuperLU_DIST will
209 // free the memory assuming it has been allocated with its *Malloc_dist
210 // wrappers
211 double *nzval = NULL;
212 int_t *colind = NULL;
213 int_t *rowptr = NULL;
214
215 if (!(nzval = doubleMalloc_dist(nnz_loc)))
216 {
217 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for nzval!");
218 }
219 for (int_t i = 0; i < nnz_loc; i++)
220 {
221 nzval[i] = csr_op->data[i];
222 }
223
224 if (!(colind = intMalloc_dist(nnz_loc)))
225 {
226 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for colind!")
227 }
228 for (int_t i = 0; i < nnz_loc; i++)
229 {
230 colind[i] = Jptr[i];
231 }
232
233 if (!(rowptr = intMalloc_dist(m_loc+1)))
234 {
235 MFEM_ABORT("SuperLURowLocMatrix: Malloc failed for rowptr!")
236 }
237 for (int_t i = 0; i <= m_loc; i++)
238 {
239 rowptr[i] = Iptr[i];
240 }
241
242 // Assign the matrix data to SuperLU's SuperMatrix structure
243 dCreate_CompRowLoc_Matrix_dist(A, m, n, nnz_loc, m_loc, fst_row,
244 nzval, colind, rowptr,
245 SLU_NR_loc, SLU_D, SLU_GE);
246
247 // Everything has been copied so delete the structure
248 hypre_CSRMatrixDestroy(csr_op);
249
250 // Save global number of rows and columns of the matrix
251 num_global_rows_ = m;
252 num_global_cols_ = n;
253}
254
256{
257 SuperMatrix *A = (SuperMatrix *)rowLocPtr_;
258 Destroy_CompRowLoc_Matrix_dist(A);
259 delete A;
260}
261
262SuperLUSolver::SuperLUSolver(MPI_Comm comm, int npdep)
263 : nprow_(GetGridRows(comm, npdep)),
264 npcol_(GetGridCols(comm, npdep, nprow_)),
265 npdep_(npdep),
266 APtr_(NULL),
267 nrhs_(0)
268{
269 Init(comm);
270}
271
273 : SuperLUSolver(A.GetComm(), npdep)
274{
275 SetOperator(A);
276}
277
279{
280 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
281
282 ScalePermstruct_t *ScalePermstruct = (ScalePermstruct_t *)ScalePermstructPtr_;
283 LUstruct_t *LUstruct = (LUstruct_t *)LUstructPtr_;
284 SOLVEstruct_t *SOLVEstruct = (SOLVEstruct_t *)SOLVEstructPtr_;
285
286#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
287 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
288 if (npdep_ > 1)
289 {
290 gridinfo3d_t *grid3d = (gridinfo3d_t *)gridPtr_;
291
292 if (APtr_)
293 {
294 if (grid3d->zscp.Iam == 0)
295 {
296 // Process layer 0
297 Destroy_LU(APtr_->GetGlobalNumColumns(), &(grid3d->grid2d),
298 LUstruct);
299 SolveFinalize(options, SOLVEstruct);
300 }
301 else
302 {
303 // Process layers not equal 0
304 DeAllocLlu_3d(APtr_->GetGlobalNumColumns(), LUstruct, grid3d);
305 DeAllocGlu_3d(LUstruct);
306 }
307 Destroy_A3d_gathered_on_2d(SOLVEstruct, grid3d);
308 ScalePermstructFree(ScalePermstruct);
309 LUstructFree(LUstruct);
310 }
311
312 superlu_gridexit3d(grid3d);
313 delete grid3d;
314 }
315 else
316#endif
317 {
318 gridinfo_t *grid = (gridinfo_t *)gridPtr_;
319
320 if (APtr_)
321 {
322 Destroy_LU(APtr_->GetGlobalNumColumns(), grid, LUstruct);
323 SolveFinalize(options, SOLVEstruct);
324 ScalePermstructFree(ScalePermstruct);
325 LUstructFree(LUstruct);
326 }
327
328 superlu_gridexit(grid);
329 delete grid;
330 }
331
332 delete options;
333 delete ScalePermstruct;
334 delete LUstruct;
335 delete SOLVEstruct;
336}
337
338void SuperLUSolver::Init(MPI_Comm comm)
339{
340 optionsPtr_ = new superlu_dist_options_t;
341 ScalePermstructPtr_ = new ScalePermstruct_t;
342 LUstructPtr_ = new LUstruct_t;
343 SOLVEstructPtr_ = new SOLVEstruct_t;
344
345 // Initialize process grid
346#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
347 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
348 if (npdep_ > 1)
349 {
350 gridPtr_ = new gridinfo3d_t;
351 superlu_gridinit3d(comm, nprow_, npcol_, npdep_, (gridinfo3d_t *)gridPtr_);
352 }
353 else
354#endif
355 {
356 gridPtr_ = new gridinfo_t;
357 MFEM_VERIFY(npdep_ == 1,
358 "SuperLUSolver: 3D partitioning is only available for "
359 "SuperLU_DIST version >= 7.2.0!");
360 superlu_gridinit(comm, nprow_, npcol_, (gridinfo_t *)gridPtr_);
361 }
362
363 // Set default options:
364 // options.Fact = DOFACT;
365 // options.Equil = YES;
366 // options.ParSymbFact = NO;
367 // options.ColPerm = METIS_AT_PLUS_A;
368 // options.RowPerm = LargeDiag_MC64;
369 // options.ReplaceTinyPivot = NO;
370 // options.IterRefine = SLU_DOUBLE;
371 // options.Trans = NOTRANS;
372 // options.SolveInitialized = NO;
373 // options.RefineInitialized = NO;
374 // options.PrintStat = YES;
375 // options.lookahead_etree = NO;
376 // options.num_lookaheads = 10;
377 // options.superlu_acc_offload = 1;
378 // options.SymPattern = NO;
379 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
380 set_default_options_dist(options);
381#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
382 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
383 if (npdep_ > 1)
384 {
385 options->Algo3d = YES;
386 }
387#endif
388}
389
391{
392 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
393 yes_no_t opt = print_stat ? YES : NO;
394 options->PrintStat = opt;
395}
396
398{
399 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
400 yes_no_t opt = equil ? YES : NO;
401 options->Equil = opt;
402}
403
405{
406 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
407 colperm_t opt = (colperm_t)col_perm;
408 if (opt == MY_PERMC)
409 {
410 MFEM_ABORT("SuperLUSolver::SetColumnPermutation does not yet support "
411 "MY_PERMC!");
412 }
413 else if (opt == PARMETIS)
414 {
415 options->ParSymbFact = YES;
416 }
417 options->ColPerm = opt;
418}
419
421{
422 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
423 rowperm_t opt = (rowperm_t)row_perm;
424 if (opt == MY_PERMR)
425 {
426 MFEM_ABORT("SuperLUSolver::SetRowPermutation does not yet support "
427 "MY_PERMR!");
428 }
429 options->RowPerm = opt;
430}
431
433{
434 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
435 IterRefine_t opt = (IterRefine_t)iter_ref;
436 options->IterRefine = opt;
437}
438
440{
441 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
442 yes_no_t opt = rtp ? YES : NO;
443 options->ReplaceTinyPivot = opt;
444}
445
446void SuperLUSolver::SetNumLookAheads(int num_lookaheads)
447{
448 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
449 options->num_lookaheads = num_lookaheads;
450}
451
453{
454 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
455 yes_no_t opt = etree ? YES : NO;
456 options->lookahead_etree = opt;
457}
458
460{
461 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
462 yes_no_t opt = sym ? YES : NO;
463 options->SymPattern = opt;
464}
465
467{
468 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
469 yes_no_t opt = par ? YES : NO;
470 options->ParSymbFact = opt;
471}
472
474{
475 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
476 fact_t opt = (fact_t)fact;
477 options->Fact = opt;
478}
479
481{
482 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
483 options->superlu_acc_offload = offload;
484}
485
487{
488 // Verify that we have a compatible operator
489 bool LUStructInitialized = (APtr_ != NULL);
490 APtr_ = dynamic_cast<const SuperLURowLocMatrix *>(&op);
491 MFEM_VERIFY(APtr_, "SuperLUSolver::SetOperator: Not a SuperLURowLocMatrix!");
492
493 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
494
495 ScalePermstruct_t *ScalePermstruct = (ScalePermstruct_t *)ScalePermstructPtr_;
496 LUstruct_t *LUstruct = (LUstruct_t *)LUstructPtr_;
497
498 gridinfo_t *grid;
499#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
500 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
501 gridinfo3d_t *grid3d = NULL;
502 if (npdep_ > 1)
503 {
504 grid3d = (gridinfo3d_t *)gridPtr_;
505 grid = NULL;
506 }
507 else
508#endif
509 {
510 grid = (gridinfo_t *)gridPtr_;
511 }
512
513 // Set mfem::Operator member data
514 MFEM_VERIFY(!LUStructInitialized ||
515 (height == op.Height() && width == op.Width()),
516 "SuperLUSolver::SetOperator: Inconsistent new matrix size!");
517 height = op.Height();
518 width = op.Width();
519
520 if (!LUStructInitialized)
521 {
522 // Initialize ScalePermstruct and LUstruct once for all operators (must
523 // have same dimensions)
524 ScalePermstructInit(APtr_->GetGlobalNumRows(),
525 APtr_->GetGlobalNumColumns(), ScalePermstruct);
526 LUstructInit(APtr_->GetGlobalNumColumns(), LUstruct);
527 options->Fact = DOFACT;
528 }
529 else
530 {
531 // A previous matrix has already been set and factored
532 switch (options->Fact)
533 {
534 case DOFACT:
535 MFEM_ABORT("SuperLUSolver::SetOperator: Previous matrix was never used!");
536 break;
537 case SamePattern_SameRowPerm:
538 {
539 // Just zero the LU factors
540#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
541(SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
542 if (npdep_ > 1)
543 {
544 if (grid3d->zscp.Iam == 0)
545 {
546 ZeroLblocks(grid3d->iam, APtr_->GetGlobalNumColumns(),
547 &(grid3d->grid2d), LUstruct);
548 ZeroUblocks(grid3d->iam, APtr_->GetGlobalNumColumns(),
549 &(grid3d->grid2d), LUstruct);
550 }
551 }
552 else
553#endif
554 {
555 ZeroLblocks(grid->iam, APtr_->GetGlobalNumColumns(),
556 grid, LUstruct);
557 ZeroUblocks(grid->iam, APtr_->GetGlobalNumColumns(),
558 grid, LUstruct);
559 }
560 }
561 break;
562 case SamePattern:
563 case FACTORED:
564 {
565 // Delete factors from the prior factorization
566#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
567(SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
568 if (npdep_ > 1)
569 {
570 if (grid3d->zscp.Iam == 0)
571 {
572 Destroy_LU(APtr_->GetGlobalNumColumns(), &(grid3d->grid2d),
573 LUstruct);
574 }
575 else
576 {
577 DeAllocLlu_3d(APtr_->GetGlobalNumColumns(), LUstruct,
578 grid3d);
579 DeAllocGlu_3d(LUstruct);
580 }
581 }
582 else
583#endif
584 {
585 Destroy_LU(APtr_->GetGlobalNumColumns(), grid, LUstruct);
586 }
587 }
588 break;
589 default:
590 MFEM_ABORT("SuperLUSolver::SetOperator: Unexpected value for "
591 "options->Fact!");
592 break;
593 }
594 if (options->Fact == FACTORED) { options->Fact = DOFACT; }
595 }
596}
597
598void SuperLUSolver::Mult(const Vector &x, Vector &y) const
599{
601 Array<Vector *> Y(1);
602 X[0] = &x;
603 Y[0] = &y;
604 ArrayMult(X, Y);
605}
606
608 Array<Vector *> &Y) const
609{
610 MFEM_ASSERT(APtr_ != NULL,
611 "SuperLU Error: The operator must be set before"
612 " the system can be solved.");
613 SuperMatrix *A = (SuperMatrix *)APtr_->InternalData();
614 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
615
616 ScalePermstruct_t *ScalePermstruct = (ScalePermstruct_t *)ScalePermstructPtr_;
617 LUstruct_t *LUstruct = (LUstruct_t *)LUstructPtr_;
618 SOLVEstruct_t *SOLVEstruct = (SOLVEstruct_t *)SOLVEstructPtr_;
619
620 gridinfo_t *grid;
621#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
622 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
623 gridinfo3d_t *grid3d = NULL;
624 if (npdep_ > 1)
625 {
626 grid3d = (gridinfo3d_t *)gridPtr_;
627 grid = NULL;
628 }
629 else
630#endif
631 {
632 grid = (gridinfo_t *)gridPtr_;
633 }
634
635 // SuperLU overwrites x with y, so copy x to y and pass that to the solve
636 // routine. Due to issues with repeated solves and changes in the number
637 // of RHS vectors, this is not supported.
638 MFEM_ASSERT(X.Size() == Y.Size(),
639 "Number of columns mismatch in SuperLUSolver::Mult!");
640 MFEM_VERIFY(nrhs_ < 1 || nrhs_ == X.Size(),
641 "SuperLUSolver does not support multiple solves with different "
642 "numbers of RHS vectors!");
643 int ldx = Height();
644 if (X.Size() == 1)
645 {
646 MFEM_ASSERT(X[0] && Y[0], "Missing Vector in SuperLUSolver::Mult!");
647 sol_.MakeRef(*Y[0], 0, Y[0]->Size());
648 sol_ = *X[0];
649 nrhs_ = 1;
650 }
651 else
652 {
653 if (nrhs_ < 1)
654 {
655 MFEM_ASSERT(X[0], "Missing Vector in SuperLUSolver::Mult!");
656 sol_.SetSize(X.Size() * ldx, *X[0]);
657 nrhs_ = X.Size();
658 }
659 for (int i = 0; i < nrhs_; i++)
660 {
661 MFEM_ASSERT(X[i], "Missing Vector in SuperLUSolver::Mult!");
662 Vector s(sol_, i * ldx, ldx);
663 s = *X[i];
664 sol_.SyncMemory(s); // Update flags for sol_ if updated on device
665 }
666 }
667
668 // Solve the system
669 double *B = sol_.HostReadWrite(), *berr;
670 if (!(berr = doubleMalloc_dist(nrhs_)))
671 {
672 MFEM_ABORT("SuperLUSolver::Mult: Malloc failed for berr!");
673 }
674 SuperLUStat_t stat;
675 PStatInit(&stat);
676 int info = -1;
677#if SUPERLU_DIST_MAJOR_VERSION > 7 || \
678 (SUPERLU_DIST_MAJOR_VERSION == 7 && SUPERLU_DIST_MINOR_VERSION >= 2)
679 if (npdep_ > 1)
680 {
681 pdgssvx3d(options, A, ScalePermstruct, B, ldx, nrhs_,
682 grid3d, LUstruct, SOLVEstruct, berr, &stat, &info);
683 }
684 else
685#endif
686 {
687 pdgssvx(options, A, ScalePermstruct, B, ldx, nrhs_,
688 grid, LUstruct, SOLVEstruct, berr, &stat, &info);
689 }
690 HandleError(info);
691 SUPERLU_FREE(berr);
692 PStatFree(&stat);
693 options->Fact = FACTORED;
694
695 // Copy solution into output (no need to do anything for single RHS since
696 // solution is written directly into output Vector)
697 if (nrhs_ == 1)
698 {
699 sol_.SyncAliasMemory(*Y[0]);
700 }
701 else
702 {
703 for (int i = 0; i < nrhs_; i++)
704 {
705 MFEM_ASSERT(Y[i], "Missing Vector in SuperLUSolver::Mult!");
706 Vector s(sol_, i * ldx, ldx);
707 *Y[i] = s;
708 }
709 }
710}
711
713{
714 // Set flag for transpose solve
715 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
716 options->Trans = TRANS;
717 Mult(x, y);
718
719 // Reset the flag
720 options->Trans = NOTRANS;
721}
722
724 Array<Vector *> &Y) const
725{
726 // Set flag for transpose solve
727 superlu_dist_options_t *options = (superlu_dist_options_t *)optionsPtr_;
728 options->Trans = TRANS;
729 ArrayMult(X, Y);
730
731 // Reset the flag
732 options->Trans = NOTRANS;
733}
734
735void SuperLUSolver::HandleError(int info) const
736{
737 if (info != 0)
738 {
739 SuperMatrix *A = (SuperMatrix *)APtr_->InternalData();
740 if (info < 0)
741 {
742 switch (-info)
743 {
744 case 1:
745 MFEM_ABORT("SuperLUSolver: SuperLU options are invalid!");
746 break;
747 case 2:
748 MFEM_ABORT("SuperLUSolver: Matrix A (in Ax=b) is invalid!");
749 break;
750 case 5:
751 MFEM_ABORT("SuperLUSolver: Vector b dimension (in Ax=b) is "
752 "invalid!");
753 break;
754 case 6:
755 MFEM_ABORT("SuperLUSolver: Number of right-hand sides is "
756 "invalid!");
757 break;
758 default:
759 MFEM_ABORT("SuperLUSolver: Parameter with index "
760 << -info << "invalid (1-indexed)!");
761 break;
762 }
763 }
764 else if (info <= A->ncol)
765 {
766 MFEM_ABORT("SuperLUSolver: Found a singular matrix, U("
767 << info << "," << info << ") is exactly zero!");
768 }
769 else if (info > A->ncol)
770 {
771 MFEM_ABORT("SuperLUSolver: Memory allocation error with "
772 << info - A->ncol << " bytes already allocated!");
773 }
774 else
775 {
776 MFEM_ABORT("Unknown SuperLU error: info = " << info << "!");
777 }
778 }
779}
780
781} // namespace mfem
782
783#endif // MFEM_USE_MPI
784#endif // MFEM_USE_SUPERLU
int Size() const
Return the logical size of the array.
Definition array.hpp:192
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
void HypreRead() const
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
Definition hypre.hpp:941
void HostRead() const
Update the internal hypre_ParCSRMatrix object, A, to be on host.
Definition hypre.hpp:924
MPI_Comm GetComm() const
MPI communicator.
Definition hypre.hpp:610
A class to initialize the size of a Tensor.
Definition dtensor.hpp:57
Abstract operator.
Definition operator.hpp:27
int width
Dimension of the input / number of columns in the matrix.
Definition operator.hpp:30
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int height
Dimension of the output / number of rows in the matrix.
Definition operator.hpp:29
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
SuperLURowLocMatrix(MPI_Comm comm, int num_loc_rows, HYPRE_BigInt first_loc_row, HYPRE_BigInt glob_nrows, HYPRE_BigInt glob_ncols, int *I, HYPRE_BigInt *J, double *data)
Creates a general parallel matrix from a local CSR matrix on each processor described by the I,...
Definition superlu.cpp:107
void * InternalData() const
Definition superlu.hpp:137
HYPRE_BigInt GetGlobalNumColumns() const
Get the number of global columns in this matrix.
Definition superlu.hpp:146
HYPRE_BigInt GetGlobalNumRows() const
Get the number of global rows in this matrix.
Definition superlu.hpp:143
SuperLUSolver(MPI_Comm comm, int npdep=1)
Constructor with MPI_Comm parameter.
Definition superlu.cpp:262
void ArrayMultTranspose(const Array< const Vector * > &X, Array< Vector * > &Y) const
Factor and solve the transposed linear systems for all i in the X and Y arrays.
Definition superlu.cpp:723
void SetColumnPermutation(superlu::ColPerm col_perm)
Specify how to permute the columns of the matrix.
Definition superlu.cpp:404
void SetDeviceOffload(bool offload)
Specify whether to offload numerical factorization onto the device (default true if SuperLU_DIST has ...
Definition superlu.cpp:480
void SetRowPermutation(superlu::RowPerm row_perm)
Specify how to permute the rows of the matrix.
Definition superlu.cpp:420
void SetParSymbFact(bool par)
Specify whether to perform parallel symbolic factorization (default false)
Definition superlu.cpp:466
void * ScalePermstructPtr_
Definition superlu.hpp:293
~SuperLUSolver()
Default destructor.
Definition superlu.cpp:278
const SuperLURowLocMatrix * APtr_
Definition superlu.hpp:282
void SetReplaceTinyPivot(bool rtp)
Specify whether to replace tiny diagonals encountered during pivot with (default false)
Definition superlu.cpp:439
void SetNumLookAheads(int num_lookaheads)
Specify the number of levels in the look-ahead factorization (default 10)
Definition superlu.cpp:446
void MultTranspose(const Vector &x, Vector &y) const
Factor and solve the transposed linear system .
Definition superlu.cpp:712
void SetFact(superlu::Fact fact)
Specify what information has been provided ahead of time about the factorization of A.
Definition superlu.cpp:473
void ArrayMult(const Array< const Vector * > &X, Array< Vector * > &Y) const
Factor and solve the linear systems for all i in the X and Y arrays.
Definition superlu.cpp:607
void SetEquilibriate(bool equil)
Specify whether to equilibrate the system scaling to make the rows and columns have unit norms....
Definition superlu.cpp:397
void Mult(const Vector &x, Vector &y) const
Factor and solve the linear system .
Definition superlu.cpp:598
void SetLookAheadElimTree(bool etree)
Specifies whether to use the elimination tree computed from the serial symbolic factorization to perf...
Definition superlu.cpp:452
void SetSymmetricPattern(bool sym)
Specify whether the matrix has a symmetric pattern to avoid extra work (default false)
Definition superlu.cpp:459
void SetOperator(const Operator &op)
Set the operator/matrix.
Definition superlu.cpp:486
void SetIterativeRefine(superlu::IterRefine iter_ref)
Specify how to handle iterative refinement.
Definition superlu.cpp:432
void SetPrintStatistics(bool print_stat)
Specify whether to print the solver statistics (default true)
Definition superlu.cpp:390
Vector data type.
Definition vector.hpp:82
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
Definition vector.hpp:275
void SyncMemory(const Vector &v) const
Update the memory location of the vector to match v.
Definition vector.hpp:272
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
Definition vector.hpp:540
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition vector.hpp:709
HYPRE_Int HYPRE_BigInt
real_t a
Definition lissajous.cpp:41
ColPerm
Define the type of column permutation.
Definition superlu.hpp:58
IterRefine
Define how to do iterative refinement.
Definition superlu.hpp:80
Fact
Define the information that is provided about the matrix factorization ahead of time.
Definition superlu.hpp:94
unsigned int sqrti(unsigned int a)
Definition superlu.cpp:51
int GetGridCols(MPI_Comm comm, int npdep, int nr)
Definition superlu.cpp:94
int GetGridRows(MPI_Comm comm, int npdep)
Definition superlu.cpp:77