FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
mkl_dss.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#ifdef FEAT_HAVE_MKL
9#include <kernel/solver/mkl_dss.hpp>
10FEAT_DISABLE_WARNINGS
11#include <mkl_dss.h>
12FEAT_RESTORE_WARNINGS
13
14namespace FEAT
15{
16 namespace Solver
17 {
18 MKLDSS::MKLDSS(const MatrixType& system_matrix) :
19 BaseClass(),
20 _system_matrix(system_matrix),
21 _mkl_dss_handle(nullptr)
22 {
23 }
24
25 MKLDSS::~MKLDSS()
26 {
27 }
28
29 void MKLDSS::init_symbolic()
30 {
31 BaseClass::init_symbolic();
32 XASSERT(_mkl_dss_handle == nullptr);
33
34 MKL_INT ret = 0;
35 MKL_INT opt = 0;
36 MKL_INT neq = static_cast<MKL_INT>(_system_matrix.rows());
37 MKL_INT nze = static_cast<MKL_INT>(_system_matrix.used_elements());
38
39 // create DSS handle
40 opt = MKL_DSS_TERM_LVL_ERROR + MKL_DSS_ZERO_BASED_INDEXING;
41#ifdef DEBUG
42 opt += MKL_DSS_MSG_LVL_WARNING;
43#endif
44 ret = ::dss_create(_mkl_dss_handle, opt);
45
46 switch(ret)
47 {
48 case MKL_DSS_SUCCESS:
49 break;
50 case MKL_DSS_OUT_OF_MEMORY:
51 throw SolverException("MKL DSS: out of memory");
52 default:
53 throw SolverException("MKL DSS: unknown error");
54 }
55
56 // get matrix index arrays and convert to MKL_INT if necessary
57 std::vector<MKL_INT> row_ptr_v, col_idx_v;
58 const Index* a_row_ptr = _system_matrix.row_ptr();
59 const Index* a_col_idx = _system_matrix.col_ind();
60 const MKL_INT* row_ptr = nullptr;
61 const MKL_INT* col_idx = nullptr;
62 if constexpr(sizeof(Index) == sizeof(MKL_INT))
63 {
64 row_ptr = reinterpret_cast<const MKL_INT*>(a_row_ptr);
65 col_idx = reinterpret_cast<const MKL_INT*>(a_col_idx);
66 }
67 else
68 {
69 row_ptr_v.resize(std::size_t(neq+1u));
70 col_idx_v.resize(std::size_t(nze));
71 for(Index i(0); i <= Index(neq); ++i)
72 row_ptr_v[i] = static_cast<MKL_INT>(a_row_ptr[i]);
73 for(Index i(0); i < Index(nze); ++i)
74 col_idx_v[i] = static_cast<MKL_INT>(a_col_idx[i]);
75 row_ptr = row_ptr_v.data();
76 col_idx = col_idx_v.data();
77 }
78
79 // validate matrix structure
80#ifdef DEBUG
81 for(Index i(0); i < Index(neq); ++i)
82 {
83 bool have_diag = false;
84 for(Index j = Index(row_ptr[i]); j < Index(row_ptr[i+1u]); ++j)
85 {
86 have_diag = have_diag || (Index(col_idx[j]) == i);
87 if((j+1u < Index(row_ptr[i+1u])) && (col_idx[j+1u] <= col_idx[j]))
88 throw InvalidMatrixStructureException("MKL DSS: non-ascending column indices detected");
89 }
90 if(!have_diag)
91 throw InvalidMatrixStructureException("MKL DSS: missing main diagonal entry");
92 }
93#endif
94
95 // set matrix structure
96 opt = MKL_DSS_NON_SYMMETRIC;
97 ret = ::dss_define_structure(_mkl_dss_handle, opt, row_ptr, neq, neq, col_idx, nze);
98
99 switch(ret)
100 {
101 case MKL_DSS_SUCCESS:
102 break;
103 case MKL_DSS_OUT_OF_MEMORY:
104 throw SolverException("MKL DSS: out of memory");
105 case MKL_DSS_STRUCTURE_ERR:
106 throw InvalidMatrixStructureException("MKL DSS: invalid matrix structure");
107 default:
108 throw SolverException("MKL DSS: unknown error");
109 }
110
111 // reorder matrix
112 opt = MKL_DSS_AUTO_ORDER;
113 ret = ::dss_reorder(_mkl_dss_handle, opt, nullptr);
114
115 switch(ret)
116 {
117 case MKL_DSS_SUCCESS:
118 break;
119 case MKL_DSS_OUT_OF_MEMORY:
120 throw SolverException("MKL DSS: out of memory");
121 default:
122 throw SolverException("MKL DSS: unknown error");
123 }
124 }
125
126 void MKLDSS::done_symbolic()
127 {
128 if(_mkl_dss_handle)
129 {
130 MKL_INT opt = MKL_DSS_TERM_LVL_ERROR;
131#ifdef DEBUG
132 opt += MKL_DSS_MSG_LVL_WARNING;
133#endif
134 ::dss_delete(_mkl_dss_handle, opt);
135 _mkl_dss_handle = nullptr;
136 }
137 BaseClass::done_symbolic();
138 }
139
140 void MKLDSS::init_numeric()
141 {
142 BaseClass::init_numeric();
143 XASSERT(_mkl_dss_handle != nullptr);
144
145 MKL_INT ret = 0;
146 MKL_INT opt = MKL_DSS_INDEFINITE;
147
148 ret = ::dss_factor_real(_mkl_dss_handle, opt, _system_matrix.val());
149
150 switch(ret)
151 {
152 case MKL_DSS_SUCCESS:
153 break;
154 case MKL_DSS_OUT_OF_MEMORY:
155 throw SolverException("MKL DSS: out of memory");
156 case MKL_DSS_ZERO_PIVOT:
157 throw SingularMatrixException("MKL DSS: zero pivot encountered");
158 default:
159 throw SolverException("MKL DSS: unknown error");
160 }
161 }
162
163 void MKLDSS::done_numeric()
164 {
165 // nothing to do here
166 BaseClass::done_numeric();
167 }
168
169 Status MKLDSS::apply(VectorType& vec_sol, const VectorType& vec_rhs)
170 {
171 MKL_INT opt = 0;
172 MKL_INT nrhs = 1;
173 MKL_INT ret = ::dss_solve_real(_mkl_dss_handle, opt, vec_rhs.elements(), nrhs, vec_sol.elements());
174 return (ret == MKL_DSS_SUCCESS ? Status::success : Status::aborted);
175 }
176 } // namespace Solver
177} // namespace FEAT
178#else
179// insert dummy function to suppress linker warnings
180void dummy_function_mkldss() {}
181#endif // FEAT_HAVE_MKL
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
FEAT Kernel base header.
MKLDSS(const MatrixType &system_matrix)
Constructor.
Status
Solver status return codes enumeration.
Definition: base.hpp:47
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.