HermesCommon  3.0
umfpack_solver.cpp
Go to the documentation of this file.
1 // This file is part of HermesCommon
2 //
3 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
4 // Email: hpfem-group@unr.edu, home page: http://www.hpfem.org/.
5 //
6 // Hermes is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the License,
9 // or (at your option) any later version.
10 //
11 // Hermes is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Hermes; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "config.h"
23 #ifdef WITH_UMFPACK
24 #include "umfpack_solver.h"
25 #include "common.h"
26 #include "util/memory_handling.h"
27 
28 #define umfpack_real_symbolic umfpack_di_symbolic
29 #define umfpack_real_numeric umfpack_di_numeric
30 #define umfpack_real_solve umfpack_di_solve
31 
32 #define umfpack_complex_symbolic umfpack_zi_symbolic
33 #define umfpack_complex_numeric umfpack_zi_numeric
34 #define umfpack_complex_solve umfpack_zi_solve
35 
36 namespace Hermes
37 {
38  namespace Solvers
39  {
40  template<typename Scalar>
42  {
43  Control[UMFPACK_PRL] = level;
44  }
45 
46  template<typename Scalar>
48  : DirectSolver<Scalar>(m, rhs), m(m), rhs(rhs), symbolic(nullptr), numeric(nullptr)
49  {
50  umfpack_di_defaults(Control);
51  }
52 
53  template<typename Scalar>
55  {
56  free();
57  }
58 
59  template<typename Scalar>
61  {
62  free_factorization_data();
63  }
64 
65  template<typename Scalar>
67  {
68  return m->get_size();
69  }
70 
71  template<>
73  {
74  // Perform both factorization phases for the first time.
75  if (reuse_scheme != HERMES_CREATE_STRUCTURE_FROM_SCRATCH && symbolic == nullptr && numeric == nullptr)
77 
78  int status;
79  switch (reuse_scheme)
80  {
82  if (symbolic != nullptr)
83  {
84  umfpack_di_free_symbolic(&symbolic);
85  memset(Info, 0, 90 * sizeof(double));
86  }
87 
88  // Factorizing symbolically.
89  status = umfpack_real_symbolic(m->get_size(), m->get_size(), m->get_Ap(), m->get_Ai(), m->get_Ax(), &symbolic, Control, Info);
90  if (status != UMFPACK_OK)
91  {
92  if (symbolic)
93  umfpack_di_free_symbolic(&symbolic);
94  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK symbolic factorization", status));
95  }
96 
99  if (numeric != nullptr)
100  {
101  umfpack_di_free_numeric(&numeric);
102  memset(Info + 0, 0, 90 * sizeof(double));
103  }
104 
105  // Factorizing numerically.
106  status = umfpack_real_numeric(m->get_Ap(), m->get_Ai(), m->get_Ax(), symbolic, &numeric, Control, Info);
107  if (status != UMFPACK_OK)
108  {
109  if (numeric)
110  umfpack_di_free_numeric(&numeric);
111  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK numeric factorization", status));
112  }
113  else
114  umfpack_di_report_info(Control, Info);
115  }
116 
117  return true;
118  }
119 
120  template<>
121  bool UMFPackLinearMatrixSolver<std::complex<double> >::setup_factorization()
122  {
123  // Perform both factorization phases for the first time.
124  int eff_fact_scheme;
125  if (reuse_scheme != HERMES_CREATE_STRUCTURE_FROM_SCRATCH && symbolic == nullptr && numeric == nullptr)
126  eff_fact_scheme = HERMES_CREATE_STRUCTURE_FROM_SCRATCH;
127  else
128  eff_fact_scheme = reuse_scheme;
129 
130  int status;
131  switch (eff_fact_scheme)
132  {
134  if (symbolic != nullptr)
135  umfpack_zi_free_symbolic(&symbolic);
136 
137  status = umfpack_complex_symbolic(m->get_size(), m->get_size(), m->get_Ap(), m->get_Ai(), (double *)m->get_Ax(), nullptr, &symbolic, nullptr, nullptr);
138  if (status != UMFPACK_OK)
139  {
140  if (symbolic)
141  umfpack_zi_free_symbolic(&symbolic);
142  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK symbolic factorization", status));
143  }
144 
147  if (numeric != nullptr)
148  umfpack_zi_free_numeric(&numeric);
149 
150  status = umfpack_complex_numeric(m->get_Ap(), m->get_Ai(), (double *)m->get_Ax(), nullptr, symbolic, &numeric, nullptr, nullptr);
151  if (status != UMFPACK_OK)
152  {
153  if (numeric)
154  umfpack_zi_free_numeric(&numeric);
155  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK numeric factorization", status));
156  }
157  }
158 
159  return true;
160  }
161 
162  template<>
164  {
165  if (symbolic != nullptr) umfpack_di_free_symbolic(&symbolic);
166  symbolic = nullptr;
167  if (numeric != nullptr) umfpack_di_free_numeric(&numeric);
168  numeric = nullptr;
169  }
170 
171  template<>
172  void UMFPackLinearMatrixSolver<std::complex<double> >::free_factorization_data()
173  {
174  if (symbolic != nullptr) umfpack_zi_free_symbolic(&symbolic);
175  symbolic = nullptr;
176  if (numeric != nullptr) umfpack_zi_free_numeric(&numeric);
177  numeric = nullptr;
178  }
179 
180  template<>
182  {
183  assert(m != nullptr);
184  assert(rhs != nullptr);
185  assert(m->get_size() == rhs->get_size());
186 
187  this->tick();
188 
189  if (!setup_factorization())
190  throw Exceptions::LinearMatrixSolverException("LU factorization could not be completed.");
191 
192  free_with_check(sln);
193 
194  sln = calloc_with_check<UMFPackLinearMatrixSolver<double>, double>(m->get_size(), this);
195  int status = umfpack_real_solve(UMFPACK_A, m->get_Ap(), m->get_Ai(), m->get_Ax(), sln, rhs->v, numeric, nullptr, nullptr);
196  if (status != UMFPACK_OK)
197  {
198  this->free_factorization_data();
199  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK solution", status));
200  }
201 
202  this->tick();
203  }
204 
205  template<>
207  {
208  assert(m != nullptr);
209  assert(rhs != nullptr);
210  assert(m->get_size() == rhs->get_size());
211 
212  this->tick();
213  if (!setup_factorization())
214  this->warn("LU factorization could not be completed.");
215 
216  free_with_check(sln);
217  sln = malloc_with_check<UMFPackLinearMatrixSolver<std::complex<double> >, std::complex<double> >(m->get_size(), this);
218 
219  memset(sln, 0, m->get_size() * sizeof(std::complex<double>));
220  int status = umfpack_complex_solve(UMFPACK_A, m->get_Ap(), m->get_Ai(), (double *)m->get_Ax(), nullptr, (double*)sln, nullptr, (double *)rhs->v, nullptr, numeric, nullptr, nullptr);
221  if (status != UMFPACK_OK)
222  {
223  this->free_factorization_data();
224  throw Exceptions::LinearMatrixSolverException(check_status("UMFPACK solution", status));
225  }
226 
227  this->tick();
228  time = this->accumulated();
229  }
230 
231  template<typename Scalar>
232  char* UMFPackLinearMatrixSolver<Scalar>::check_status(const char *fn_name, int status)
233  {
234  char* to_return = malloc_with_check<UMFPackLinearMatrixSolver<Scalar>, char>(100, this);
235 
236  switch (status)
237  {
238  case UMFPACK_OK: break;
239  case UMFPACK_WARNING_singular_matrix: sprintf(to_return, "%s: UMFPACK_WARNING_singular_matrix!", fn_name); break;
240  case UMFPACK_ERROR_out_of_memory: sprintf(to_return, "%s: UMFPACK_ERROR_out_of_memory!", fn_name); break;
241  case UMFPACK_ERROR_argument_missing: sprintf(to_return, "%s: UMFPACK_ERROR_argument_missing", fn_name); break;
242  case UMFPACK_ERROR_invalid_Symbolic_object: sprintf(to_return, "%s: UMFPACK_ERROR_invalid_Symbolic_object", fn_name); break;
243  case UMFPACK_ERROR_invalid_Numeric_object: sprintf(to_return, "%s: UMFPACK_ERROR_invalid_Numeric_object", fn_name); break;
244  case UMFPACK_ERROR_different_pattern: sprintf(to_return, "%s: UMFPACK_ERROR_different_pattern", fn_name); break;
245  case UMFPACK_ERROR_invalid_system: sprintf(to_return, "%s: UMFPACK_ERROR_invalid_system", fn_name); break;
246  case UMFPACK_ERROR_n_nonpositive: sprintf(to_return, "%s: UMFPACK_ERROR_n_nonpositive", fn_name); break;
247  case UMFPACK_ERROR_invalid_matrix: sprintf(to_return, "%s: UMFPACK_ERROR_invalid_matrix", fn_name); break;
248  case UMFPACK_ERROR_internal_error: sprintf(to_return, "%s: UMFPACK_ERROR_internal_error", fn_name); break;
249  default: sprintf(to_return, "%s: unknown error (%d)", fn_name, status); break;
250  }
251 
252  return to_return;
253  }
254 
255  template class HERMES_API UMFPackLinearMatrixSolver < double > ;
256  template class HERMES_API UMFPackLinearMatrixSolver < std::complex<double> > ;
257  }
258 }
259 #endif
General namespace for the Hermes library.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
Vector used with MUMPS solver.
Definition: vector.h:116
General CSC Matrix class. (can be used in umfpack, in that case use the CSCMatrix subclass...
Definition: cs_matrix.h:131
void set_output_level(double level)
For output (the array Info is filled regardless of the value of the level).
UMFPackLinearMatrixSolver(CSCMatrix< Scalar > *m, SimpleVector< Scalar > *rhs)
UMFPACK solver interface.
Encapsulation of UMFPACK linear solver.
pattern as the one already factorized.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
virtual int get_matrix_size()
Get size of matrix.