FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
direct_sparse_solver_umfpack.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
6// includes, FEAT
8#include <kernel/backend.hpp>
9#include <kernel/solver/direct_sparse_solver.hpp>
10
11#ifdef FEAT_HAVE_UMFPACK
12
13FEAT_DISABLE_WARNINGS
14#include <umfpack.h>
15FEAT_RESTORE_WARNINGS
16
17// use 32-bit indices for UMFPACK
18#define FEAT_DSS_UMFPACK_I32
19
20namespace FEAT
21{
22 namespace Solver
23 {
24 namespace DSS
25 {
26#ifdef FEAT_DSS_UMFPACK_I64
27 static_assert(sizeof(UMFPACK_IT) == 8, "DirectSparseSolver: UMFPACK: index type size mismatch!");
28#else
29 static_assert(sizeof(UMFPACK_IT) == 4, "DirectSparseSolver: UMFPACK: index type size mismatch!");
30#endif
31
37 class UMFPACK_Core
38 {
39 public:
40 // UMFPACK control array
41 double control[UMFPACK_CONTROL];
42 // UMFPACK info array
43 double info[UMFPACK_INFO];
44 // UMFPACK opaque symbolic object
45 void* symbolic;
46 // UMFPACK opaque numeric object
47 void* numeric;
48
49 UMFPACK_IT num_global_dofs, dof_offset, num_owned_dofs, num_owned_nzes;
50 std::vector<UMFPACK_IT> row_ptr, col_idx;
51 std::vector<UMFPACK_DT> mat_val, rhs_val, sol_val;
52
53 explicit UMFPACK_Core(const Dist::Comm& comm, Index num_global_dofs_, Index dof_offset_,
54 Index num_owned_dofs_, Index num_owned_nzes_, Index DOXY(num_global_nzes_)) :
55 symbolic(nullptr),
56 numeric(nullptr),
57 num_global_dofs(UMFPACK_IT(num_global_dofs_)),
58 dof_offset(UMFPACK_IT(dof_offset_)),
59 num_owned_dofs(UMFPACK_IT(num_owned_dofs_)),
60 num_owned_nzes(UMFPACK_IT(num_owned_nzes_))
61 {
62#ifdef FEAT_HAVE_MPI
63 XASSERTM(comm.size() == 1, "DirectSparseSolver UMFPACK core can only be used on 1 MPI process!");
64#else
65 // prevent unused parameter warnings
66 (void)comm;
67#endif
68
69 // allocate matrix and vector arrays
70 row_ptr.resize(std::size_t(num_owned_dofs+1), 0u);
71 col_idx.resize(std::size_t(num_owned_nzes), 0u);
72 mat_val.resize(std::size_t(num_owned_nzes), 0.0);
73 rhs_val.resize(std::size_t(num_owned_dofs), 0.0);
74 sol_val.resize(std::size_t(num_owned_dofs), 0.0);
75
76#ifdef FEAT_DSS_UMFPACK_I64
77 ::umfpack_dl_defaults(control);
78#else
79 ::umfpack_di_defaults(control);
80#endif
81 control[UMFPACK_PRL] = 1;
82 }
83
84 ~UMFPACK_Core()
85 {
86 if(numeric != nullptr)
87 {
88#ifdef FEAT_DSS_UMFPACK_I64
89 ::umfpack_dl_free_numeric(&numeric);
90#else
91 ::umfpack_di_free_numeric(&numeric);
92#endif
93 }
94 if(symbolic != nullptr)
95 {
96#ifdef FEAT_DSS_UMFPACK_I64
97 ::umfpack_dl_free_symbolic(&symbolic);
98#else
99 ::umfpack_di_free_symbolic(&symbolic);
100#endif
101 }
102 }
103
104 void init_symbolic()
105 {
106 XASSERT(symbolic == nullptr);
107
108 int status =
109#ifdef FEAT_DSS_UMFPACK_I64
110 ::umfpack_dl_symbolic
111#else
112 ::umfpack_di_symbolic
113#endif
114 (num_owned_dofs, num_owned_dofs, row_ptr.data(), col_idx.data(), mat_val.data(), &symbolic, control, info);
115
116 // check status code
117 switch(status)
118 {
119 case UMFPACK_OK:
120 break;
121 case UMFPACK_ERROR_out_of_memory:
122 throw DirectSparseSolverException("UMFPACK", "out of memory");
123 case UMFPACK_ERROR_invalid_matrix:
124 throw DirectSparseSolverException("UMFPACK", "invalid matrix structure");
125 case UMFPACK_ERROR_internal_error:
126 throw DirectSparseSolverException("UMFPACK", "internal error");
127 default:
128 throw DirectSparseSolverException("UMFPACK", "unknown error");
129 }
130 }
131
132 void init_numeric()
133 {
134 XASSERT(symbolic != nullptr);
135 XASSERT(numeric == nullptr);
136
137 int status =
138#ifdef FEAT_DSS_UMFPACK_I64
139 ::umfpack_dl_numeric
140#else
141 ::umfpack_di_numeric
142#endif
143 (row_ptr.data(), col_idx.data(), mat_val.data(), symbolic, &numeric, control, info);
144
145 // check status code
146 switch(status)
147 {
148 case UMFPACK_OK:
149 break;
150 case UMFPACK_ERROR_out_of_memory:
151 throw DirectSparseSolverException("UMFPACK", "out of memory");
152 case UMFPACK_ERROR_invalid_matrix:
153 throw DirectSparseSolverException("UMFPACK", "invalid matrix structure");
154 case UMFPACK_WARNING_singular_matrix:
155 throw DirectSparseSolverException("UMFPACK", "singular matrix");
156 case UMFPACK_ERROR_different_pattern:
157 throw DirectSparseSolverException("UMFPACK", "different pattern");
158 case UMFPACK_ERROR_internal_error:
159 throw DirectSparseSolverException("UMFPACK", "internal error");
160 default:
161 throw DirectSparseSolverException("UMFPACK", "unknown error");
162 }
163 }
164
165 void done_numeric()
166 {
167 XASSERT(numeric != nullptr);
168#ifdef FEAT_DSS_UMFPACK_I64
169 ::umfpack_dl_free_numeric(&numeric);
170#else
171 ::umfpack_di_free_numeric(&numeric);
172#endif
173 numeric = nullptr;
174 }
175
176 void solve()
177 {
178 int status =
179#ifdef FEAT_DSS_UMFPACK_I64
180 ::umfpack_dl_solve
181#else
182 ::umfpack_di_solve
183#endif
184 (UMFPACK_At, row_ptr.data(), col_idx.data(), mat_val.data(), sol_val.data(), rhs_val.data(), numeric, control, info);
185
186 // check status code
187 switch(status)
188 {
189 case UMFPACK_OK:
190 break;
191 case UMFPACK_ERROR_out_of_memory:
192 throw DirectSparseSolverException("UMFPACK", "out of memory");
193 case UMFPACK_WARNING_singular_matrix:
194 throw DirectSparseSolverException("UMFPACK", "singular matrix");
195 case UMFPACK_ERROR_internal_error:
196 throw DirectSparseSolverException("UMFPACK", "internal error");
197 default:
198 throw DirectSparseSolverException("UMFPACK", "unknown error");
199 }
200 }
201 };
202
203 void* create_umfpack_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
204 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes)
205 {
206 return new UMFPACK_Core(*comm, num_global_dofs, dof_offset, num_owned_dofs, num_owned_nzes, num_global_nzes);
207 }
208
209 void destroy_umfpack_core(void* core)
210 {
211 XASSERT(core != nullptr);
212 delete reinterpret_cast<UMFPACK_Core*>(core);
213 }
214
215 UMFPACK_IT* get_umfpack_row_ptr(void* core)
216 {
217 XASSERT(core != nullptr);
218 return reinterpret_cast<UMFPACK_Core*>(core)->row_ptr.data();
219 }
220
221 UMFPACK_IT* get_umfpack_col_idx(void* core)
222 {
223 XASSERT(core != nullptr);
224 return reinterpret_cast<UMFPACK_Core*>(core)->col_idx.data();
225 }
226
227 UMFPACK_DT* get_umfpack_mat_val(void* core)
228 {
229 XASSERT(core != nullptr);
230 return reinterpret_cast<UMFPACK_Core*>(core)->mat_val.data();
231 }
232
233 UMFPACK_DT* get_umfpack_rhs_val(void* core)
234 {
235 XASSERT(core != nullptr);
236 return reinterpret_cast<UMFPACK_Core*>(core)->rhs_val.data();
237 }
238
239 UMFPACK_DT* get_umfpack_sol_val(void* core)
240 {
241 XASSERT(core != nullptr);
242 return reinterpret_cast<UMFPACK_Core*>(core)->sol_val.data();
243 }
244
245 void init_umfpack_symbolic(void* core)
246 {
247 XASSERT(core != nullptr);
248 reinterpret_cast<UMFPACK_Core*>(core)->init_symbolic();
249 }
250
251 void init_umfpack_numeric(void* core)
252 {
253 XASSERT(core != nullptr);
254 reinterpret_cast<UMFPACK_Core*>(core)->init_numeric();
255 }
256
257 void done_umfpack_numeric(void* core)
258 {
259 XASSERT(core != nullptr);
260 reinterpret_cast<UMFPACK_Core*>(core)->done_numeric();
261 }
262
263 void solve_umfpack(void* core)
264 {
265 XASSERT(core != nullptr);
266 reinterpret_cast<UMFPACK_Core*>(core)->solve();
267 }
268 } // namespace DSS
269 } // namespace Solver
270} // namespace FEAT
271
272#else // no FEAT_HAVE_UMFPACK
273
274void feat_direct_sparse_solver_umfpack_dummy()
275{
276}
277
278#endif // FEAT_HAVE_UMFPACK
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
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