FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
superlu.cpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
7
8#if defined(FEAT_HAVE_SUPERLU_DIST) && defined(FEAT_HAVE_MPI)
9
10FEAT_DISABLE_WARNINGS
11#define VTUNE 0
12#include <superlu_ddefs.h>
13FEAT_RESTORE_WARNINGS
14
15#include <vector>
16
17namespace FEAT
18{
19 namespace Solver
20 {
21 namespace SuperLU_Aux
22 {
24 class Core
25 {
26 public:
27 typedef int_t IT;
28 typedef double DT;
29
31 MPI_Comm _comm;
33 gridinfo_t slu_grid;
35 superlu_dist_options_t slu_opts;
37 SuperLUStat_t slu_stats;
39 SuperMatrix slu_matrix;
41 NRformat_loc slu_matrix_store;
43 dScalePermstruct_t slu_scale_perm;
45 dLUstruct_t slu_lu_struct;
47 dSOLVEstruct_t slu_solve_struct;
49 int slu_info;
50 const IT slu_dof_offset, slu_num_owned_dofs, slu_num_global_dofs, slu_num_nonzeros;
51
54 std::vector<IT> slu_row_ptr, slu_col_idx, slu_col_idx2;
56 std::vector<double> slu_mat_val;
58 std::vector<double> slu_vector;
60 std::vector<double> slu_v_berr;
61
64 bool was_factorized;
65
66 public:
67 explicit Core(const void* comm, Index num_global_dofs, Index my_dof_offset,
68 Index num_owned_dofs, Index num_nonzeros) :
69 _comm(*reinterpret_cast<const MPI_Comm*>(comm)),
70 slu_info(0),
71 slu_dof_offset(IT(my_dof_offset)),
72 slu_num_owned_dofs(IT(num_owned_dofs)),
73 slu_num_global_dofs(IT(num_global_dofs)),
74 slu_num_nonzeros(IT(num_nonzeros)),
75 was_factorized(false)
76 {
77 // first of all, memclear all SuperLU structures just to be safe
78 memset(&slu_grid, 0, sizeof(gridinfo_t));
79 memset(&slu_opts, 0, sizeof(superlu_dist_options_t));
80 memset(&slu_stats, 0, sizeof(SuperLUStat_t));
81 memset(&slu_matrix, 0, sizeof(SuperMatrix));
82 memset(&slu_matrix_store, 0, sizeof(NRformat_loc));
83 memset(&slu_scale_perm, 0, sizeof(dScalePermstruct_t));
84 memset(&slu_lu_struct, 0, sizeof(dLUstruct_t));
85 memset(&slu_solve_struct, 0, sizeof(dSOLVEstruct_t));
86
87 // set up grid
88 int ranks(0);
89 MPI_Comm_size(_comm, &ranks);
90 superlu_gridinit(_comm, ranks, 1, &slu_grid);
91
92 // allocate matrix and vector arrays
93 slu_row_ptr.resize(num_owned_dofs+1u);
94 slu_col_idx.resize(num_nonzeros);
95 slu_col_idx2.resize(num_nonzeros);
96 slu_mat_val.resize(num_nonzeros);
97 slu_vector.resize(num_owned_dofs);
98 slu_v_berr.resize(num_owned_dofs);
99
100 // setup SuperLU matrix
101 slu_matrix.Stype = SLU_NR_loc; // CSR, local
102 slu_matrix.Dtype = SLU_D; // double
103 slu_matrix.Mtype = SLU_GE; // generic matrix
104 slu_matrix.nrow = slu_num_global_dofs;
105 slu_matrix.ncol = slu_num_global_dofs; // always square
106 slu_matrix.Store = &slu_matrix_store;
107
108 // setup SuperLU matrix storage
109 slu_matrix_store.nnz_loc = slu_num_nonzeros;
110 slu_matrix_store.m_loc = slu_num_owned_dofs;
111 slu_matrix_store.fst_row = slu_dof_offset;
112 slu_matrix_store.nzval = slu_mat_val.data();
113 slu_matrix_store.rowptr = slu_row_ptr.data();
114 slu_matrix_store.colind = slu_col_idx2.data(); // use copy here
115 }
116
117 ~Core()
118 {
119 PStatFree(&slu_stats);
120 dLUstructFree(&slu_lu_struct);
121 dScalePermstructFree(&slu_scale_perm);
122 dSolveFinalize(&slu_opts, &slu_solve_struct);
123 superlu_gridexit(&slu_grid);
124 }
125
126 void init_symbolic()
127 {
128 // copy column indices arrays, because SuperLU permutes them
129 memcpy(slu_col_idx2.data(), slu_col_idx.data(), sizeof(IT)*slu_col_idx.size());
130
131 // set up default options
132 set_default_options_dist(&slu_opts);
133
134 // don't print statistics to cout
135 slu_opts.PrintStat = NO;
136
137 // replace tiny pivots
138 slu_opts.ReplaceTinyPivot = YES;
139
140 // initialize scale perm structure
141 dScalePermstructInit(slu_num_global_dofs, slu_num_global_dofs, &slu_scale_perm);
142
143 // initialize LU structure
144 dLUstructInit(slu_num_global_dofs, &slu_lu_struct);
145
146 // initialize the statistics
147 PStatInit(&slu_stats);
148 }
149
150 int init_numeric()
151 {
152 // reset column-index array because it might have been
153 // overwritten by the previous factorization call
154 memcpy(slu_col_idx2.data(), slu_col_idx.data(), sizeof(IT)*slu_col_idx.size());
155
156 // have we already factorized before?
157 slu_opts.Fact = (was_factorized ? SamePattern : DOFACT);
158
159 // call the solver routine to factorize the matrix
160 pdgssvx(
161 &slu_opts,
162 &slu_matrix,
163 &slu_scale_perm,
164 nullptr,
165 int(slu_num_owned_dofs),
166 0,
167 &slu_grid,
168 &slu_lu_struct,
169 &slu_solve_struct,
170 slu_v_berr.data(),
171 &slu_stats,
172 &slu_info);
173
174 // factorization successful?
175
176 if(slu_info == 0)
177 {
178 // okay, remember that we have factorized
179 was_factorized = true;
180 }
181
182 // okay
183 return slu_info;
184 }
185
186 void done_numeric()
187 {
188 dDestroy_LU(slu_matrix.nrow, &slu_grid, &slu_lu_struct);
189 }
190
191 int solve()
192 {
193 // matrix was already factorized in set_matrix_values() call
194 slu_opts.Fact = FACTORED;
195
196 // call the solver routine
197 pdgssvx(
198 &slu_opts,
199 &slu_matrix,
200 &slu_scale_perm,
201 slu_vector.data(),
202 int(slu_num_owned_dofs),
203 1,
204 &slu_grid,
205 &slu_lu_struct,
206 &slu_solve_struct,
207 slu_v_berr.data(),
208 &slu_stats,
209 &slu_info);
210
211 // return the result
212 return slu_info;
213 }
214 }; // class Core
215
216 void* create_core(const void* comm, Index num_global_dofs, Index dof_offset,
217 Index num_owned_dofs, Index num_nonzeros)
218 {
219 return new Core(comm, num_global_dofs, dof_offset, num_owned_dofs, num_nonzeros);
220 }
221
222 void destroy_core(void* core)
223 {
224 delete reinterpret_cast<Core*>(core);
225 }
226
227 int_t* get_row_ptr(void* core)
228 {
229 return reinterpret_cast<Core*>(core)->slu_row_ptr.data();
230 }
231
232 int_t* get_col_idx(void* core)
233 {
234 return reinterpret_cast<Core*>(core)->slu_col_idx.data();
235 }
236
237 double* get_mat_val(void* core)
238 {
239 return reinterpret_cast<Core*>(core)->slu_mat_val.data();
240 }
241
242 double* get_vector(void* core)
243 {
244 return reinterpret_cast<Core*>(core)->slu_vector.data();
245 }
246
247 void init_symbolic(void* core)
248 {
249 reinterpret_cast<Core*>(core)->init_symbolic();
250 }
251
252 int init_numeric(void* core)
253 {
254 return reinterpret_cast<Core*>(core)->init_numeric();
255 }
256
257 void done_numeric(void* core)
258 {
259 reinterpret_cast<Core*>(core)->done_numeric();
260 }
261
262 int solve(void* core)
263 {
264 return reinterpret_cast<Core*>(core)->solve();
265 }
266 } // namespace SuperLU_Aux
267 } // namespace Solver
268} // namespace FEAT
269
270#else
271// insert dummy function to suppress linker warnings
272void dummy_superlu_function() {}
273#endif // defined(FEAT_HAVE_SUPERLU_DIST) && defined(FEAT_HAVE_MPI)
FEAT Kernel base header.
Status solve(SolverBase< Vector_ > &solver, Vector_ &vec_sol, const Vector_ &vec_rhs, const Matrix_ &matrix, const Filter_ &filter)
Solve linear system with initial solution guess.
Definition: base.hpp:347
FEAT namespace.
Definition: adjactor.hpp:12