1use super::loader::*;
2use crate::enums::{MatrixType, SolverType};
3use crate::{PanuaPardisoError, PardisoData, PardisoError, PardisoInterface};
4use std::ffi::c_void;
5
6pub struct PanuaPardisoSolver {
7 _data: PardisoData,
8 _dparm: [f64; 64],
9}
10
11impl PanuaPardisoSolver {
12 pub(crate) fn pardisoinit_impl(
13 data: &mut PardisoData,
14 dparm: &mut [f64; 64],
15 mtype: MatrixType,
16 solver: SolverType,
17 ) -> Result<(), PanuaPardisoError> {
18 let ptrs = panua_ptrs()?;
19
20 let mut error: i32 = 0;
21 let pt = data.pt.as_mut_ptr() as *mut c_void;
22 let mtype = mtype as i32;
23 let solver = solver as i32;
24 let iparm = data.iparm.as_mut_ptr();
25 let dparm = dparm.as_mut_ptr();
26
27 (ptrs.pardisoinit)(pt, &mtype, &solver, iparm, dparm, &mut error);
28
29 if error != 0 {
30 return Err(PanuaPardisoError::from(error));
31 }
32 Ok(())
33 }
34}
35
36impl PanuaPardisoSolver {
37 pub fn get_dparm(&self, i: usize) -> f64 {
38 self._dparm[i]
39 }
40 pub fn get_dparms(&self) -> &[f64; 64] {
41 &self._dparm
42 }
43 pub fn set_dparm(&mut self, i: usize, value: f64) {
44 self._dparm[i] = value;
45 }
46}
47
48impl PardisoInterface for PanuaPardisoSolver {
49 fn data(&self) -> &PardisoData {
50 &self._data
51 }
52 fn data_mut(&mut self) -> &mut PardisoData {
53 &mut self._data
54 }
55
56 fn new() -> Result<Self, PardisoError> {
57 if !PanuaPardisoSolver::is_loaded() {
58 return Err(PanuaPardisoError::LibraryLoadFailure)?;
59 }
60 if !PanuaPardisoSolver::is_licensed() {
61 return Err(PanuaPardisoError::LibraryLicenseFailure)?;
62 }
63
64 let data = PardisoData::default();
65 let dparm = [0.0; 64];
66 Ok(Self {
67 _data: data,
68 _dparm: dparm,
69 })
70 }
71
72 fn pardisoinit(&mut self) -> Result<(), PardisoError> {
73 let mtype = self.get_matrix_type();
74 let solver = self.get_solver();
75 let data = &mut self._data;
76 let dparm = &mut self._dparm;
77
78 Ok(PanuaPardisoSolver::pardisoinit_impl(
79 data, dparm, mtype, solver,
80 )?)
81 }
82
83 fn pardiso(
84 &mut self,
85 a: &[f64],
86 ia: &[i32],
87 ja: &[i32],
88 b: &mut [f64],
89 x: &mut [f64],
90 n: i32,
91 nrhs: i32,
92 ) -> Result<(), PardisoError> {
93 let ptrs = panua_ptrs()?;
94
95 let mut error = 0;
96 let pt = self.data_mut().pt.as_mut_ptr() as *mut c_void;
97 let maxfct = self.data().maxfct;
98 let mnum = self.data().mnum;
99 let mtype = self.get_matrix_type() as i32;
100 let phase = self.data().phase as i32;
101 let a = a.as_ptr();
102 let ia = ia.as_ptr();
103 let ja = ja.as_ptr();
104 let b = b.as_mut_ptr();
105 let x = x.as_mut_ptr();
106 let perm = self.data_mut().perm.as_mut_ptr();
107 let iparm = self.data_mut().iparm.as_mut_ptr();
108 let msglvl = self.data().msglvl as i32;
109 let dparm = self._dparm.as_mut_ptr();
110
111 (ptrs.pardiso)(
112 pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x,
113 &mut error, dparm,
114 );
115
116 if error != 0 {
117 let error = PanuaPardisoError::from(error);
118 return Err(PardisoError::from(error));
119 }
120 Ok(())
121 }
122
123 fn name(&self) -> &'static str {
124 "panua"
125 }
126
127 fn is_licensed() -> bool {
128 crate::panua::interface::panua_is_licensed()
129 }
130
131 fn is_loaded() -> bool {
132 panua_ptrs().is_ok()
133 }
134
135 fn get_num_threads(&self) -> Result<i32, PardisoError> {
136 Ok(self.data().iparm[2])
137 }
138}
139
140impl PanuaPardisoSolver {
142 pub fn pardiso_chkmatrix(
143 &self,
144 mtype: MatrixType,
145 n: i32,
146 a: &[f64],
147 ia: &[i32],
148 ja: &[i32],
149 ) -> Result<(), PanuaPardisoError> {
150 let ptrs = panua_ptrs()?;
151
152 let mut error = 0;
153 let mtype = mtype as i32;
154 let a = a.as_ptr();
155 let ia = ia.as_ptr();
156 let ja = ja.as_ptr();
157
158 (ptrs.pardiso_chkmatrix)(&mtype, &n, a, ia, ja, &mut error);
159
160 if error != 0 {
161 return Err(PanuaPardisoError::from(error));
162 }
163 Ok(())
164 }
165
166 pub fn pardiso_chkvec(&self, n: i32, nrhs: i32, b: &[f64]) -> Result<(), PanuaPardisoError> {
167 let ptrs = panua_ptrs()?;
168
169 let mut error = 0;
170 let b = b.as_ptr();
171
172 (ptrs.pardiso_chkvec)(&n, &nrhs, b, &mut error);
173
174 if error != 0 {
175 return Err(PanuaPardisoError::from(error));
176 }
177 Ok(())
178 }
179
180 #[allow(clippy::too_many_arguments)]
181 pub fn pardiso_printstats(
182 &self,
183 mtype: MatrixType,
184 n: i32,
185 a: &[f64],
186 ia: &[i32],
187 ja: &[i32],
188 nrhs: i32,
189 b: &[f64],
190 ) -> Result<(), PanuaPardisoError> {
191 let ptrs = panua_ptrs()?;
192
193 let mut error = 0;
194 let mtype = mtype as i32;
195 let a = a.as_ptr();
196 let ia = ia.as_ptr();
197 let ja = ja.as_ptr();
198 let b = b.as_ptr();
199
200 (ptrs.pardiso_printstats)(&mtype, &n, a, ia, ja, &nrhs, b, &mut error);
201
202 if error != 0 {
203 return Err(PanuaPardisoError::from(error));
204 }
205 Ok(())
206 }
207}
208
209impl Drop for PanuaPardisoSolver {
210 fn drop(&mut self) {
211 self.release();
212 }
213}