HermesCommon  2.0
amesos_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://hpfem.org/.
5 //
6 // Hermes2D 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 // Hermes2D 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 Hermes2D; 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 HAVE_AMESOS
24 #include "amesos_solver.h"
25 #include "callstack.h"
26 #include "Amesos_ConfigDefs.h"
27 
28 namespace Hermes
29 {
30  namespace Solvers
31  {
32  template<typename Scalar> Amesos AmesosSolver<Scalar>::factory;
33 
34  template<typename Scalar>
35  AmesosSolver<Scalar>::AmesosSolver(const char *solver_type, EpetraMatrix<Scalar> *m, EpetraVector<Scalar> *rhs)
36  : DirectSolver<Scalar>(HERMES_FACTORIZE_FROM_SCRATCH), m(m), rhs(rhs)
37  {
38  solver = factory.Create(solver_type, problem);
39  assert(solver != NULL);
40  // WARNING: Amesos does not use RCP to allocate the Amesos_BaseSolver,
41  // so don't forget to delete it!
42  // ( Amesos.cpp, line 88, called from factory.Create():
43  // return new Amesos_Klu(LinearProblem); )
44  }
45 
46  template<typename Scalar>
47  AmesosSolver<Scalar>::~AmesosSolver()
48  {
49  delete solver;
50  }
51 
52  template<typename Scalar>
53  bool AmesosSolver<Scalar>::is_available(const char *name)
54  {
55  return factory.Query(name);
56  }
57 
58  template<typename Scalar>
59  void AmesosSolver<Scalar>::set_use_transpose(bool use_transpose)
60  {
61  solver->SetUseTranspose(use_transpose);
62  }
63 
64  template<typename Scalar>
65  bool AmesosSolver<Scalar>::use_transpose()
66  {
67  return solver->UseTranspose();
68  }
69 
70  template<typename Scalar>
71  int AmesosSolver<Scalar>::get_matrix_size()
72  {
73  return m->size;
74  }
75 
76  template<>
77  bool AmesosSolver<double>::solve()
78  {
79  assert(m != NULL);
80  assert(rhs != NULL);
81 
82  assert(m->size == rhs->size);
83 
84  problem.SetOperator(m->mat);
85  problem.SetRHS(rhs->vec);
86  Epetra_Vector x(*rhs->std_map);
87  problem.SetLHS(&x);
88 
89  if(!setup_factorization())
90  {
91  this->warn("AmesosSolver: LU factorization could not be completed");
92  return false;
93  }
94 
95  int status = solver->Solve();
96  if(status != 0)
97  {
98  throw Hermes::Exceptions::Exception("AmesosSolver: Solution failed.");
99  return false;
100  }
101 
102  this->tick();
103  this->time = this->accumulated();
104 
105  delete [] this->sln;
106  this->sln = new double[m->size];
107  // copy the solution into sln vector
108  memset(this->sln, 0, m->size * sizeof(double));
109 
110  for (unsigned int i = 0; i < m->size; i++) this->sln[i] = x[i];
111 
112  return true;
113  }
114 
115  template<>
116  bool AmesosSolver<std::complex<double> >::solve()
117  {
118  assert(m != NULL);
119  assert(rhs != NULL);
120 
121  assert(m->size == rhs->size);
122 
123  throw Hermes::Exceptions::Exception("AmesosSolver<Scalar>::solve() not yet implemented for complex problems");
124 
125  if(!setup_factorization())
126  {
127  this->warn("AmesosSolver: LU factorization could not be completed");
128  return false;
129  }
130 
131  int status = solver->Solve();
132  if(status != 0)
133  {
134  throw Hermes::Exceptions::Exception("AmesosSolver: Solution failed.");
135  return false;
136  }
137 
138  this->tick();
139  this->time = this->accumulated();
140 
141  delete [] this->sln;
142  this->sln = new std::complex<double>[m->size];
143  // copy the solution into sln vector
144  memset(this->sln, 0, m->size * sizeof(std::complex<double>));
145 
146  return true;
147  }
148 
149  template<typename Scalar>
150  bool AmesosSolver<Scalar>::setup_factorization()
151  {
152  // Perform both factorization phases for the first time.
153  int eff_fact_scheme;
154  if(this->factorization_scheme != HERMES_FACTORIZE_FROM_SCRATCH &&
155  solver->NumSymbolicFact() == 0 && solver->NumNumericFact() == 0)
156  eff_fact_scheme = HERMES_FACTORIZE_FROM_SCRATCH;
157  else
158  eff_fact_scheme = this->factorization_scheme;
159 
160  int status;
161  switch(eff_fact_scheme)
162  {
164  //debug_log("Factorizing symbolically.");
165  status = solver->SymbolicFactorization();
166  if(status != 0)
167  {
168  this->warn("Symbolic factorization failed.");
169  return false;
170  }
171 
174  status = solver->NumericFactorization();
175  if(status != 0)
176  {
177  this->warn("Numeric factorization failed.");
178  return false;
179  }
180  }
181 
182  return true;
183  }
184 
185  template class HERMES_API AmesosSolver<double>;
186  template class HERMES_API AmesosSolver<std::complex<double> >;
187  }
188 }
189 #endif