FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
direct_sparse_solver.hpp
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#pragma once
7
8// includes, FEAT
10#include <kernel/backend.hpp>
11#include <kernel/solver/adp_solver_base.hpp>
12
13namespace FEAT
14{
15 namespace Solver
16 {
18
25 namespace DSS
26 {
28 // NVIDIA CUDSS
30#ifdef FEAT_HAVE_CUDSS
31 // cuDSS is available as backend
32 static constexpr bool have_cudss = true;
33
35 typedef double CUDSS_DT;
36
38 typedef std::int32_t CUDSS_IT;
39
40 void* create_cudss_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
41 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes);
42
43 void destroy_cudss_core(void* core);
44
45 CUDSS_IT* get_cudss_row_ptr(void* core);
46 CUDSS_IT* get_cudss_col_idx(void* core);
47 CUDSS_DT* get_cudss_mat_val(void* core);
48 CUDSS_DT* get_cudss_rhs_val(void* core);
49 CUDSS_DT* get_cudss_sol_val(void* core);
50
51 void init_cudss_symbolic(void* core);
52 void init_cudss_numeric(void* core);
53
54 void solve_cudss(void* core);
55
56 std::int64_t get_peak_mem_cudss_host(void* core);
57 std::int64_t get_peak_mem_cudss_device(void* core);
58#else
59 // cuDSS is not available as backend
60 static constexpr bool have_cudss = false;
61#endif // FEAT_HAVE_CUDSS
62
64 // INTEL MKL-DSS
66
67#ifdef FEAT_HAVE_MKL
68 // MKL-DSS is available as backend
69 static constexpr bool have_mkldss = true;
70
72 typedef double MKLDSS_DT;
73
76#ifdef MKL_ILP64
77 typedef long long MKLDSS_IT;
78#else
79 typedef int MKLDSS_IT;
80#endif
81
82 void* create_mkldss_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
83 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes);
84
85 void destroy_mkldss_core(void* core);
86
87 MKLDSS_IT* get_mkldss_row_ptr(void* core);
88 MKLDSS_IT* get_mkldss_col_idx(void* core);
89 MKLDSS_DT* get_mkldss_mat_val(void* core);
90 MKLDSS_DT* get_mkldss_rhs_val(void* core);
91 MKLDSS_DT* get_mkldss_sol_val(void* core);
92
93 void init_mkldss_symbolic(void* core);
94 void init_mkldss_numeric(void* core);
95
96 void solve_mkldss(void* core);
97
98 std::int64_t get_peak_mem_mkldss(void* core);
99#else
100 // MKL-DSS is not available as backend
101 static constexpr bool have_mkldss = false;
102#endif // FEAT_HAVE_MKL
103
105 // MUMPS
107#ifdef FEAT_HAVE_MUMPS
108 // SuperLU is available as backend
109 static constexpr bool have_mumps = true;
110
112 typedef double MUMPS_DT;
113
116 typedef std::int64_t MUMPS_IT;
117
118 void* create_mumps_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
119 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes);
120
121 void destroy_mumps_core(void* core);
122
123 MUMPS_IT* get_mumps_row_ptr(void* core);
124 MUMPS_IT* get_mumps_col_idx(void* core);
125 MUMPS_DT* get_mumps_mat_val(void* core);
126 MUMPS_DT* get_mumps_vector(void* core);
127
128 void init_mumps_symbolic(void* core);
129 void init_mumps_numeric(void* core);
130 void done_mumps_numeric(void* core);
131
132 void solve_mumps(void* core);
133#else
134 // MUMPS is not available as backend
135 static constexpr bool have_mumps = false;
136#endif // FEAT_HAVE_MUMPS_DIST
137
139 // SUPERLU_DIST
141#ifdef FEAT_HAVE_SUPERLU_DIST
142 // SuperLU is available as backend
143 static constexpr bool have_superlu = true;
144
146 typedef double SUPERLU_DT;
147
150#ifdef FEAT_TPL_SUPERLU_INT64
151 typedef std::int64_t SUPERLU_IT;
152#else
153 typedef int SUPERLU_IT;
154#endif
155
156 void* create_superlu_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
157 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes);
158
159 void destroy_superlu_core(void* core);
160
161 SUPERLU_IT* get_superlu_row_ptr(void* core);
162 SUPERLU_IT* get_superlu_col_idx(void* core);
163 SUPERLU_DT* get_superlu_mat_val(void* core);
164 SUPERLU_DT* get_superlu_vector(void* core);
165
166 void init_superlu_symbolic(void* core);
167 void init_superlu_numeric(void* core);
168 void done_superlu_numeric(void* core);
169
170 void solve_superlu(void* core);
171#else
172 // SuperLU is not available as backend
173 static constexpr bool have_superlu = false;
174#endif // FEAT_HAVE_SUPERLU_DIST
175
177 // UMFPACK (SuiteSparse)
179
180#ifdef FEAT_HAVE_UMFPACK
181 // UMFPACK is available as backend
182 static constexpr bool have_umfpack = true;
183
185 typedef double UMFPACK_DT;
186
189 typedef std::int32_t UMFPACK_IT;
190
191 void* create_umfpack_core(const Dist::Comm* comm, Index num_global_dofs, Index dof_offset,
192 Index num_owned_dofs, Index num_owned_nzes, Index num_global_nzes);
193
194 void destroy_umfpack_core(void* core);
195
196 UMFPACK_IT* get_umfpack_row_ptr(void* core);
197 UMFPACK_IT* get_umfpack_col_idx(void* core);
198 UMFPACK_DT* get_umfpack_mat_val(void* core);
199 UMFPACK_DT* get_umfpack_rhs_val(void* core);
200 UMFPACK_DT* get_umfpack_sol_val(void* core);
201
202 void init_umfpack_symbolic(void* core);
203 void init_umfpack_numeric(void* core);
204 void done_umfpack_numeric(void* core);
205
206 void solve_umfpack(void* core);
207#else
208 // UMFPACK is not available as backend
209 static constexpr bool have_umfpack = false;
210#endif // FEAT_HAVE_UMFPACK
211
213
215 static constexpr bool have_backend_local = have_cudss || have_mkldss || have_superlu || have_umfpack;
216
218 static constexpr bool have_backend_global = have_cudss || have_mkldss || have_superlu;
219
220 } // namespace DSS
222
226 enum class DSSBackend : int
227 {
228 none = 0x0000,
229 cudss = 0x0001,
230 mumps = 0x0002,
231 mkldss = 0x0004,
232 superlu = 0x0008,
233 umfpack = 0x0010,
234 all = 0x001F
235 };
236
238 static constexpr inline DSSBackend operator|(DSSBackend a, DSSBackend b)
239 {
240 return static_cast<DSSBackend>(static_cast<int>(a) | static_cast<int>(b));
241 }
242
244 static constexpr inline DSSBackend operator&(DSSBackend a, DSSBackend b)
245 {
246 return static_cast<DSSBackend>(static_cast<int>(a) & static_cast<int>(b));
247 }
248
250 static constexpr inline bool operator*(DSSBackend a)
251 {
252 // just check the interesting bits
253 return (static_cast<int>(a) & static_cast<int>(DSSBackend::all)) != 0;
254 }
255
257 static std::ostream& operator<<(std::ostream& os, DSSBackend a)
258 {
259 int n = 0;
260 if(*(a & DSSBackend::cudss))
261 {
262 if(++n > 1)
263 os << '|';
264 os << "cudss";
265 }
266 if(*(a & DSSBackend::mkldss))
267 {
268 if(++n > 1)
269 os << '|';
270 os << "mkldss";
271 }
272 if(*(a & DSSBackend::mumps))
273 {
274 if(++n > 1)
275 os << '|';
276 os << "mumps";
277 }
278 if(*(a & DSSBackend::superlu))
279 {
280 if(++n > 1)
281 os << '|';
282 os << "superlu";
283 }
284 if(*(a & DSSBackend::umfpack))
285 {
286 if(++n > 1)
287 os << '|';
288 os << "umfpack";
289 }
290 if(n <= 0)
291 os << "none";
292 return os;
293 }
294
295 //enum class DSSSystemHint
296 //{
297 // none = 0x0000,
298 // sym_struct = 0x0001, ///< matrix has symmetric structure
299 // sym_values = 0x0002, ///< matrix is symmetric
300 // pos_definite = 0x0004 ///< matrix is positive definite
301 //};
302
307 public SolverException
308 {
309 public:
310 explicit DirectSparseSolverException(const String& msg) :
311 SolverException("DirectSparseSolver: " + msg)
312 {
313 }
314
315 explicit DirectSparseSolverException(const String& backend, const String& msg) :
316 SolverException("DirectSparseSolver [" + backend + "]: " + msg)
317 {
318 }
319 }; // class DirectSparseSolverException
320
329 {
330 public:
332 DirectSparseSolverException("DirectSparseSolver: no suitable backend found")
333 {
334 }
335
337 DirectSparseSolverException("DirectSparseSolver: Backend not available: " + stringify(b))
338 {
339 }
340 }; // class DSSBackendNotFoundException
341
447 template<typename Matrix_, typename Filter_>
449 public ADPSolverBase<Matrix_, Filter_>
450 {
451 public:
460
462 static constexpr bool have_backend_cudss = DSS::have_cudss;
464 static constexpr bool have_backend_mkldss = DSS::have_mkldss;
466 static constexpr bool have_backend_mumps = DSS::have_mumps;
468 static constexpr bool have_backend_superlu = DSS::have_superlu;
470 static constexpr bool have_backend_umfpack = DSS::have_umfpack;
472 static constexpr bool have_backend_local = DSS::have_backend_local;
474 static constexpr bool have_backend_global = DSS::have_backend_global;
475
476 private:
478 std::deque<DSSBackend> _allowed_backends;
491
492 public:
506 explicit DirectSparseSolver(const MatrixType& matrix, const FilterType& filter) :
507 BaseClass(matrix, filter),
509 _preferred_backend(Backend::get_preferred_backend()),
510 _core_cudss(nullptr),
511 _core_mkldss(nullptr),
512 _core_mumps(nullptr),
513 _core_superlu(nullptr),
514 _core_umfpack(nullptr)
515 {
516 }
517
520 {
521 }
522
524 virtual String name() const override
525 {
526 String s = "DirectSparseSolver";
527 if(_core_cudss)
528 s += " [cuDSS]";
529 if(_core_mkldss)
530 s += " [MKL-DSS]";
531 if(_core_mumps)
532 s += " [MUMPS]";
533 if(_core_superlu)
534 s += " [SuperLU]";
535 if(_core_umfpack)
536 s += " [UMFPACK]";
537 return s;
538 }
539
552 static bool is_available(const MatrixType& matrix, const FilterType& DOXY(filter))
553 {
554 // For purely local matrices, everything except for SuperLU_DIST is applicable
555 if constexpr (MatrixType::is_local)
556 return have_backend_local;
557
558 if constexpr (MatrixType::is_global)
559 {
560 // potentially parallel case: check if we have a comm with more than 1 process
561 const Dist::Comm* comm = matrix.get_comm();
562 if((comm == nullptr) || (comm->size() <= 1))
563 return have_backend_local;
564
565 // MPI-parallel case with more than 1 process
566 return have_backend_global;
567 }
568
569 // we should never come out here
570 XABORTM("matrix type is neither local nor global!");
571 return false;
572 }
573
580 void push_allowed_backend_list(const String& backends)
581 {
582 std::deque<String> backs = backends.split_by_whitespaces();
584 }
585
592 void push_allowed_backend_list(const std::deque<String>& backends)
593 {
594 for(const auto& s : backends)
596 }
597
613 void push_allowed_backend(const String& backend)
614 {
616 std::deque<String> sbacks = backend.split_by_charset("|");
617 for(const String& s : sbacks)
618 {
619 if(s.compare_no_case("none") == 0)
620 b = b | DSSBackend::none;
621 else if(s.compare_no_case("all") == 0)
622 b = b | DSSBackend::all;
623 else if(s.compare_no_case("cudss") == 0)
624 b = b | DSSBackend::cudss;
625 else if(s.compare_no_case("mkldss") == 0)
626 b = b | DSSBackend::mkldss;
627 else if(s.compare_no_case("mkl-dss") == 0)
628 b = b | DSSBackend::mkldss;
629 else if(s.compare_no_case("mumps") == 0)
630 b = b | DSSBackend::mumps;
631 else if(s.compare_no_case("superlu") == 0)
632 b = b | DSSBackend::superlu;
633 else if(s.compare_no_case("umfpack") == 0)
634 b = b | DSSBackend::umfpack;
635 else
636 throw DirectSparseSolverException("DirectSparseSolver: unknown DSS backend: '" + backend + "'");
637 }
639 }
640
648 {
649 _allowed_backends.push_back(backend);
650 }
651
654 {
655 _allowed_backends.clear();
656 }
657
659 const std::deque<DSSBackend> get_allowed_backends() const
660 {
661 return _allowed_backends;
662 }
663
673 {
674 if(this->_core_umfpack)
675 return DSSBackend::umfpack;
676 if(this->_core_superlu)
677 return DSSBackend::superlu;
678 if(this->_core_mkldss)
679 return DSSBackend::mkldss;
680 if(this->_core_mumps)
681 return DSSBackend::mumps;
682 if(this->_core_cudss)
683 return DSSBackend::cudss;
684 return DSSBackend::none;
685 }
686
696 virtual void init_symbolic() override
697 {
699
700 // First of all, let's see if we're in a single-process scenario here
701 const Dist::Comm* comm = this->_get_comm();
702 const bool single_process = ((comm == nullptr) || (comm->size() <= 1));
703
704 // if the user didn't specify any allowed backends, then we'll try a default setting
705 if(_allowed_backends.empty())
706 {
707 // First, let's see if the user wanted a cuda-based solver
709 {
710 // Ok, try to create a cuDSS core then
711 if(!_create_core_cudss())
712 {
713 // Nope, apparently, cuDSS is not available
715 }
716 }
717
718 // Next, let's see if the user wanted a MKL-based solver
720 {
721 // Ok, try to create a MKL-DSS core then
723 {
724 // Nope, apparently, MKL-DSS is not available
726 }
727 }
728
729 // Now we're left with the generic case, in which we may choose any backend we see fit
730
731 // Let's try cuDSS first
733 return;
734
735 // Let's try MKL-DSS next
737 return;
738
739 // Let's try UMFPACK if we're in a single-process case next
740 if(single_process && _create_core_umfpack())
741 return;
742
743 // Let's try MUMPS next
745 return;
746
747 // Let's try SuperLU last
749 return;
750
751 // If we come out here, then we have failed to find a suitable backend...
753 }
754
755 // Let's loop over all allowed backends
756 for(auto ab : _allowed_backends)
757 {
758 // Let's try cuDSS first (if allowed)
760 return;
761
762 // Let's try MKL-DSS next (if allowed)
764 return;
765
766 // Let's try UMFPACK if we're in a single-process case next (if allowed)
767 if(*(ab & DSSBackend::umfpack) && single_process && _create_core_umfpack())
768 return;
769
770 // Let's try MUMPS next (if allowed)
772 return;
773
774 // Let's try SuperLU last (if allowed)
776 return;
777 }
778
779 // If we come out here, then we have failed to find a suitable backend...
781 }
782
786 virtual void done_symbolic() override
787 {
788#ifdef FEAT_HAVE_CUDSS
789 if(this->_core_cudss)
790 {
791 DSS::destroy_cudss_core(this->_core_cudss);
792 this->_core_cudss = nullptr;
793 }
794#endif // FEAT_HAVE_CUDSS
795#ifdef FEAT_HAVE_MKL
796 if(this->_core_mkldss)
797 {
798 DSS::destroy_mkldss_core(this->_core_mkldss);
799 this->_core_mkldss = nullptr;
800 }
801#endif // FEAT_HAVE_MKL
802#ifdef FEAT_HAVE_MUMPS
803 if(this->_core_mumps)
804 {
805 DSS::destroy_mumps_core(this->_core_mumps);
806 this->_core_mumps = nullptr;
807 }
808#endif // FEAT_HAVE_MUMPS
809#ifdef FEAT_HAVE_SUPERLU_DIST
810 if(this->_core_superlu)
811 {
812 DSS::destroy_superlu_core(this->_core_superlu);
813 this->_core_superlu = nullptr;
814 }
815#endif // FEAT_HAVE_SUPERLU_DIST
816#ifdef FEAT_HAVE_UMFPACK
817 if(this->_core_umfpack)
818 {
819 DSS::destroy_umfpack_core(this->_core_umfpack);
820 this->_core_umfpack = nullptr;
821 }
822#endif // FEAT_HAVE_UMFPACK
824 }
825
831 virtual void init_numeric() override
832 {
834#ifdef FEAT_HAVE_CUDSS
835 if(this->_core_cudss)
836 {
837 this->_upload_numeric(
838 DSS::get_cudss_mat_val(this->_core_cudss),
839 DSS::get_cudss_row_ptr(this->_core_cudss),
840 DSS::get_cudss_col_idx(this->_core_cudss));
841
842 DSS::init_cudss_numeric(this->_core_cudss);
843 }
844#endif // FEAT_HAVE_CUDSS
845#ifdef FEAT_HAVE_MKL
846 if(this->_core_mkldss)
847 {
848 this->_upload_numeric(
849 DSS::get_mkldss_mat_val(this->_core_mkldss),
850 DSS::get_mkldss_row_ptr(this->_core_mkldss),
851 DSS::get_mkldss_col_idx(this->_core_mkldss));
852
853 DSS::init_mkldss_numeric(this->_core_mkldss);
854 }
855#endif // FEAT_HAVE_MKL
856#ifdef FEAT_HAVE_MUMPS
857 if(this->_core_mumps)
858 {
859 this->_upload_numeric(
860 DSS::get_mumps_mat_val(this->_core_mumps),
861 DSS::get_mumps_row_ptr(this->_core_mumps),
862 DSS::get_mumps_col_idx(this->_core_mumps));
863
864 DSS::init_mumps_numeric(this->_core_mumps);
865 }
866#endif // FEAT_HAVE_MUMPS
867#ifdef FEAT_HAVE_SUPERLU_DIST
868 if(this->_core_superlu)
869 {
870 this->_upload_numeric(
871 DSS::get_superlu_mat_val(this->_core_superlu),
872 DSS::get_superlu_row_ptr(this->_core_superlu),
873 DSS::get_superlu_col_idx(this->_core_superlu));
874
875 DSS::init_superlu_numeric(this->_core_superlu);
876 }
877#endif // FEAT_HAVE_SUPERLU_DIST
878#ifdef FEAT_HAVE_UMFPACK
879 if(this->_core_umfpack)
880 {
881 this->_upload_numeric(
882 DSS::get_umfpack_mat_val(this->_core_umfpack),
883 DSS::get_umfpack_row_ptr(this->_core_umfpack),
884 DSS::get_umfpack_col_idx(this->_core_umfpack));
885
886 DSS::init_umfpack_numeric(this->_core_umfpack);
887 }
888#endif // FEAT_HAVE_UMFPACK
889 }
890
894 virtual void done_numeric() override
895 {
896#ifdef FEAT_HAVE_SUPERLU_DIST
897 if(this->_core_superlu)
898 {
899 DSS::done_superlu_numeric(this->_core_superlu);
900 }
901#endif // FEAT_HAVE_SUPERLU_DIST
902#ifdef FEAT_HAVE_UMFPACK
903 if(this->_core_umfpack)
904 {
905 DSS::done_umfpack_numeric(this->_core_umfpack);
906 }
907#endif // FEAT_HAVE_UMFPACK
909 }
910
921 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
922 {
923 // silence compiler warnings about unused variables if no backend is available
924 (void)vec_cor;
925 (void)vec_def;
926
927#ifdef FEAT_HAVE_CUDSS
928 if(this->_core_cudss)
929 {
930 // upload defect vector
931 this->_upload_vector(DSS::get_cudss_rhs_val(this->_core_cudss), vec_def);
932
933 // solve system via MKL DSS
934 try
935 {
936 DSS::solve_cudss(this->_core_cudss);
937 }
938 catch(const DirectSparseSolverException&)
939 {
940 return Status::aborted;
941 }
942 catch(...)
943 {
944 throw;
945 }
946
947 // download correction vector
948 this->_download_vector(vec_cor, DSS::get_cudss_sol_val(this->_core_cudss));
949
950 return Status::success;
951 }
952#endif // FEAT_HAVE_CUDSS
953#ifdef FEAT_HAVE_MKL
954 if(this->_core_mkldss)
955 {
956 // upload defect vector
957 this->_upload_vector(DSS::get_mkldss_rhs_val(this->_core_mkldss), vec_def);
958
959 // solve system via MKL DSS
960 try
961 {
962 DSS::solve_mkldss(this->_core_mkldss);
963 }
964 catch(const DirectSparseSolverException&)
965 {
966 return Status::aborted;
967 }
968 catch(...)
969 {
970 throw;
971 }
972
973 // download correction vector
974 this->_download_vector(vec_cor, DSS::get_mkldss_sol_val(this->_core_mkldss));
975
976 return Status::success;
977 }
978#endif // FEAT_HAVE_MKL
979#ifdef FEAT_HAVE_MUMPS
980 if(this->_core_mumps)
981 {
982 // upload defect vector
983 this->_upload_vector(DSS::get_mumps_vector(this->_core_mumps), vec_def);
984
985 // solve system via MUMPS
986 try
987 {
988 DSS::solve_mumps(this->_core_mumps);
989 }
990 catch(const DirectSparseSolverException&)
991 {
992 return Status::aborted;
993 }
994 catch(...)
995 {
996 throw;
997 }
998
999 // download correction vector
1000 this->_download_vector(vec_cor, DSS::get_mumps_vector(this->_core_mumps));
1001
1002 return Status::success;
1003 }
1004#endif // FEAT_HAVE_MUMPS
1005#ifdef FEAT_HAVE_SUPERLU_DIST
1006 if(this->_core_superlu)
1007 {
1008 // upload defect vector
1009 this->_upload_vector(DSS::get_superlu_vector(this->_core_superlu), vec_def);
1010
1011 // solve system via SuperLU
1012 try
1013 {
1014 DSS::solve_superlu(this->_core_superlu);
1015 }
1016 catch(const DirectSparseSolverException&)
1017 {
1018 return Status::aborted;
1019 }
1020 catch(...)
1021 {
1022 throw;
1023 }
1024
1025 // download correction vector
1026 this->_download_vector(vec_cor, DSS::get_superlu_vector(this->_core_superlu));
1027
1028 return Status::success;
1029 }
1030#endif // FEAT_HAVE_SUPERLU_DIST
1031#ifdef FEAT_HAVE_UMFPACK
1032 if(this->_core_umfpack)
1033 {
1034 // upload defect vector
1035 this->_upload_vector(DSS::get_umfpack_rhs_val(this->_core_umfpack), vec_def);
1036
1037 // solve system via UMFPACK
1038 try
1039 {
1040 DSS::solve_umfpack(this->_core_umfpack);
1041 }
1042 catch(const DirectSparseSolverException&)
1043 {
1044 return Status::aborted;
1045 }
1046 catch(...)
1047 {
1048 throw;
1049 }
1050
1051 // download correction vector
1052 this->_download_vector(vec_cor, DSS::get_umfpack_sol_val(this->_core_umfpack));
1053
1054 return Status::success;
1055 }
1056#endif // FEAT_HAVE_UMFPACK
1057
1058 return Status::aborted;
1059 }
1060
1061 private:
1064 {
1065#ifdef FEAT_HAVE_CUDSS
1066 // create cuDSS core
1067 this->_core_cudss = DSS::create_cudss_core(
1068 this->_get_comm(),
1069 this->_get_num_global_dofs(),
1070 this->_get_global_dof_offset(),
1071 this->_get_num_owned_dofs(),
1073 this->_get_num_global_nonzeros());
1074
1075 // upload matrix structure to cuDSS core
1077 DSS::get_cudss_row_ptr(this->_core_cudss),
1078 DSS::get_cudss_col_idx(this->_core_cudss));
1079
1080 // perform symbolic factorization of cuDSS core
1081 DSS::init_cudss_symbolic(this->_core_cudss);
1082
1083 return true;
1084#else
1085 return false;
1086#endif // FEAT_HAVE_CUDSS
1087 }
1088
1091 {
1092#ifdef FEAT_HAVE_MKL
1093 // create MKL DSS core
1094 this->_core_mkldss = DSS::create_mkldss_core(
1095 this->_get_comm(),
1096 this->_get_num_global_dofs(),
1097 this->_get_global_dof_offset(),
1098 this->_get_num_owned_dofs(),
1100 this->_get_num_global_nonzeros());
1101
1102 // upload matrix structure to MKL DSS core
1104 DSS::get_mkldss_row_ptr(this->_core_mkldss),
1105 DSS::get_mkldss_col_idx(this->_core_mkldss));
1106
1107 // perform symbolic factorization of MKL DSS core
1108 DSS::init_mkldss_symbolic(this->_core_mkldss);
1109
1110 return true;
1111#else
1112 return false;
1113#endif // FEAT_HAVE_MKL
1114 }
1115
1118 {
1119#ifdef FEAT_HAVE_MUMPS
1120 // create MUMPS core
1121 this->_core_mumps = DSS::create_mumps_core(
1122 this->_get_comm(),
1123 this->_get_num_global_dofs(),
1124 this->_get_global_dof_offset(),
1125 this->_get_num_owned_dofs(),
1127 this->_get_num_global_nonzeros());
1128
1129 // upload matrix structure to MUMPS core
1131 DSS::get_mumps_row_ptr(this->_core_mumps),
1132 DSS::get_mumps_col_idx(this->_core_mumps));
1133
1134 // perform symbolic factorization of MUMPS core
1135 DSS::init_mumps_symbolic(this->_core_mumps);
1136
1137 return true;
1138#else
1139 return false;
1140#endif // FEAT_HAVE_MUMPS
1141 }
1142
1145 {
1146#ifdef FEAT_HAVE_SUPERLU_DIST
1147 // create SuperLU core
1148 this->_core_superlu = DSS::create_superlu_core(
1149 this->_get_comm(),
1150 this->_get_num_global_dofs(),
1151 this->_get_global_dof_offset(),
1152 this->_get_num_owned_dofs(),
1154 this->_get_num_global_nonzeros());
1155
1156 // upload matrix structure to SuperLU core
1158 DSS::get_superlu_row_ptr(this->_core_superlu),
1159 DSS::get_superlu_col_idx(this->_core_superlu));
1160
1161 // perform symbolic factorization of SuperLU core
1162 DSS::init_superlu_symbolic(this->_core_superlu);
1163
1164 return true;
1165#else
1166 return false;
1167#endif // FEAT_HAVE_SUPERLU_DIST
1168 }
1169
1172 {
1173#ifdef FEAT_HAVE_UMFPACK
1174 // create UMFPACK core
1175 this->_core_umfpack = DSS::create_umfpack_core(
1176 this->_get_comm(),
1177 this->_get_num_global_dofs(),
1178 this->_get_global_dof_offset(),
1179 this->_get_num_owned_dofs(),
1181 this->_get_num_global_nonzeros());
1182
1183 // upload matrix structure to UMFPACK core
1185 DSS::get_umfpack_row_ptr(this->_core_umfpack),
1186 DSS::get_umfpack_col_idx(this->_core_umfpack));
1187
1188 // perform symbolic factorization of UMFPACK core
1189 DSS::init_umfpack_symbolic(this->_core_umfpack);
1190
1191 return true;
1192#else
1193 return false;
1194#endif // FEAT_HAVE_UMFPACK
1195 }
1196 }; // class DirectSparseSolver<...>
1197
1210 template<typename Matrix_, typename Filter_>
1211 std::shared_ptr<DirectSparseSolver<Matrix_, Filter_>> new_direct_sparse_solver(const Matrix_& matrix, const Filter_& filter)
1212 {
1213 return std::make_shared<DirectSparseSolver<Matrix_, Filter_>>(matrix, filter);
1214 }
1215
1228 template<typename Matrix_, typename Filter_>
1229 bool have_direct_sparse_solver(const Matrix_& matrix, const Filter_& filter)
1230 {
1232 }
1233 } // namespace Solver
1234} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
FEAT Kernel base header.
Backend support class.
Definition: backend.hpp:136
Communicator class.
Definition: dist.hpp:1349
int size() const
Returns the size of this communicator.
Definition: dist.hpp:1506
Base-Class for solvers based on Algebraic-DOF-Partitioning.
const Dist::Comm * _get_comm() const
void _upload_symbolic(RPT_ *row_ptr, CIT_ *col_idx)
Uploads the ADP matrix structure to the given arrays.
Index _get_num_owned_dofs() const
Index _get_global_dof_offset() const
void _download_vector(LocalVectorType &vector, const DTV_ *val)
Downloads the ADP vector values from the given array.
void _upload_vector(DTV_ *val, const LocalVectorType &vector)
Uploads the ADP vector values to the given array.
Index _get_num_global_nonzeros() const
MatrixType::VectorTypeL VectorType
the (local) vector type
Index _get_num_global_dofs() const
Filter_ FilterType
the (local) filter type
Index _get_adp_matrix_num_nzes() const
Matrix_ MatrixType
this specialization expects a local matrix
void _upload_numeric(DTV_ *val, const RPT_ *row_ptr, const CIT_ *col_idx)
Uploads the (filtered) ADP matrix values to the given array.
DirectSparseSolver backend not found exception.
Exception base class for errors occurring in DirectSparseSolver.
Front-end wrapper class for (parallel) third-party direct sparse solvers.
bool _create_core_umfpack()
Tries to create an UMFPACK backend core and returns true, if it succeeded.
virtual void init_numeric() override
Performs the numeric initialization of the solver.
static constexpr bool have_backend_global
specifies whether at least one backend for global systems is available
void push_allowed_backend_list(const String &backends)
Pushes a list of allowed backends into the backend queue.
void push_allowed_backend(const String &backend)
Pushes a combination of allowed backends into the backend queue.
PreferredBackend _preferred_backend
preferred backend of runtime at time of object creation
virtual void done_symbolic() override
Releases the symbolic factorization data and frees the backend.
ADPSolverBase< Matrix_, Filter_ > BaseClass
our base class
static constexpr bool have_backend_mkldss
specifies whether the MKL-DSS solver backend is available
static constexpr bool have_backend_mumps
specifies whether the MUMPS solver backend is available
static constexpr bool have_backend_cudss
specifies whether the cuDSS solver backend is available
void clear_allowed_backends()
Clears the deque of allowed backends.
BaseClass::VectorType VectorType
our (global or local) system vector type
bool _create_core_mkldss()
Tries to create a MKL-DSS backend core and returns true, if it succeeded.
void push_allowed_backend_list(const std::deque< String > &backends)
Pushes a deque of allowed backends into the backend queue.
static constexpr bool have_backend_umfpack
specifies whether the UMFPACK solver backend is available
void push_allowed_backend(DSSBackend backend)
Pushes a combination of allowed backends into the backend queue.
bool _create_core_superlu()
Tries to create a SuperLU backend core and returns true, if it succeeded.
bool _create_core_cudss()
Tries to create a cuDSS backend core and returns true, if it succeeded.
const std::deque< DSSBackend > get_allowed_backends() const
Returns a reference to the deque of allowed backends.
virtual ~DirectSparseSolver()
virtual destructor
virtual Status apply(VectorType &vec_cor, const VectorType &vec_def) override
Solves a linear system with the factorized system matrix.
virtual void done_numeric() override
Releases the numeric initialization data of the solver.
virtual void init_symbolic() override
Performs the symbolic initialization of the solver.
std::deque< DSSBackend > _allowed_backends
backends that the user allowed us to use
DirectSparseSolver(const MatrixType &matrix, const FilterType &filter)
Creates a new DirectSparseSolver object for the given system.
static constexpr bool have_backend_superlu
specifies whether the SuperLU solver backend is available
DSSBackend get_selected_backend() const
Returns the selected backend.
virtual String name() const override
Returns the name of the solver.
static constexpr bool have_backend_local
specifies whether at least one backend for local systems is available
BaseClass::MatrixType MatrixType
our (global or local) system matrix type
static bool is_available(const MatrixType &matrix, const FilterType &filter)
Checks whether a suitable backend for the given matrix and filter.
bool _create_core_mumps()
Tries to create a MUMPS backend core and returns true, if it succeeded.
BaseClass::FilterType FilterType
our (global or local) system filter type
virtual void init_symbolic()
Symbolic initialization method.
Definition: base.hpp:227
virtual void init_numeric()
Numeric initialization method.
Definition: base.hpp:237
virtual void done_symbolic()
Symbolic finalization method.
Definition: base.hpp:255
virtual void done_numeric()
Numeric finalization method.
Definition: base.hpp:246
Base-class for solver generated exceptions.
Definition: base.hpp:127
String class implementation.
Definition: string.hpp:47
std::deque< String > split_by_whitespaces() const
Splits the string by white-spaces.
Definition: string.hpp:519
std::deque< String > split_by_charset(const String &charset) const
Splits the string by a delimiter charset.
Definition: string.hpp:468
static constexpr DSSBackend operator&(DSSBackend a, DSSBackend b)
bit-wise AND operator for DSSBackend enum values
std::shared_ptr< DirectSparseSolver< Matrix_, Filter_ > > new_direct_sparse_solver(const Matrix_ &matrix, const Filter_ &filter)
Creates a new DirectSparseSolver object.
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ success
solving successful (convergence criterion fulfilled)
@ aborted
premature abort (solver aborted due to internal errors or preconditioner failure)
DSSBackend
Enumeration of allowed backends for DirectSparseSolver class.
@ umfpack
UMFPACK backend.
@ none
no backend allowed
@ all
all backends allowed
@ mkldss
MKL-DSS backend.
@ mumps
MUMPS backend.
@ superlu
SuperLU backend.
static constexpr DSSBackend operator|(DSSBackend a, DSSBackend b)
bit-wise OR operator for DSSBackend enum values
bool have_direct_sparse_solver(const Matrix_ &matrix, const Filter_ &filter)
Checks whether at least one DirectSparseSolver backend is available.
static constexpr bool operator*(DSSBackend a)
checks whether at least one of the bits in DSSBackend is selected
FEAT namespace.
Definition: adjactor.hpp:12
PreferredBackend
The backend that shall be used in all compute heavy calculations.
Definition: backend.hpp:124
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:993