HermesCommon  2.0
aztecoo_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_AZTECOO
24 #include "aztecoo_solver.h"
25 #include "callstack.h"
26 #include "Komplex_LinearProblem.h"
27 
28 namespace Hermes
29 {
30  namespace Solvers
31  {
32  template<typename Scalar>
33  AztecOOSolver<Scalar>::AztecOOSolver(EpetraMatrix<Scalar> *m, EpetraVector<Scalar> *rhs)
34  : IterSolver<Scalar>(), m(m), rhs(rhs)
35  {
36  pc = NULL;
37  }
38 
39  template<typename Scalar>
40  AztecOOSolver<Scalar>::~AztecOOSolver()
41  {
42  }
43 
44  template<typename Scalar>
45  void AztecOOSolver<Scalar>::set_solver(const char *name)
46  {
47  int az_solver;
48  if(name)
49  {
50  if(strcasecmp(name, "gmres") == 0) az_solver = AZ_gmres;
51  else if(strcasecmp(name, "cg") == 0) az_solver = AZ_cg;
52  else if(strcasecmp(name, "cgs") == 0) az_solver = AZ_cgs;
53  else if(strcasecmp(name, "tfqmr") == 0) az_solver = AZ_tfqmr;
54  else if(strcasecmp(name, "bicgstab") == 0) az_solver = AZ_bicgstab;
55  else az_solver = AZ_gmres;
56  }
57  else
58  {
59  az_solver = AZ_gmres;
60  }
61 
62  aztec.SetAztecOption(AZ_solver, az_solver);
63  }
64 
65  template<typename Scalar>
66  void AztecOOSolver<Scalar>::set_tolerance(double tol)
67  {
68  this->tolerance = tol;
69  }
70 
71  template<typename Scalar>
72  void AztecOOSolver<Scalar>::set_max_iters(int iters)
73  {
74  this->max_iters = iters;
75  }
76 
77  template<typename Scalar>
78 
79  void AztecOOSolver<Scalar>::set_precond(Precond<Scalar> *pc)
80  {
81  this->precond_yes = true;
82  this->pc = pc;
83  }
84 
85  template<typename Scalar>
86  void AztecOOSolver<Scalar>::set_precond(const char *name)
87  {
88  int az_precond;
89  if(name)
90  {
91  if(strcasecmp(name, "none") == 0)
92  az_precond = AZ_none;
93  else if(strcasecmp(name, "jacobi") == 0)
94  az_precond = AZ_Jacobi;
95  else if(strcasecmp(name, "neumann") == 0)
96  az_precond = AZ_Neumann;
97  else if(strcasecmp(name, "least-squares") == 0)
98  az_precond = AZ_ls;
99  else
100  az_precond = AZ_none;
101  }
102  else
103  az_precond = AZ_none; //asi by to melo byt nastaveno
104 
105  this->precond_yes = (az_precond != AZ_none);
106  aztec.SetAztecOption(AZ_precond, az_precond);
107  }
108 
109  template<typename Scalar>
110  void AztecOOSolver<Scalar>::set_option(int option, int value)
111  {
112  aztec.SetAztecOption(option, value);
113  }
114 
115  template<typename Scalar>
116  void AztecOOSolver<Scalar>::set_param(int param, double value)
117  {
118  aztec.SetAztecParam(param, value);
119  }
120 
121  template<typename Scalar>
122  int AztecOOSolver<Scalar>::get_matrix_size()
123  {
124  return m->size;
125  }
126 
127  template<>
128  bool AztecOOSolver<double>::solve()
129  {
130  assert(m != NULL);
131  assert(rhs != NULL);
132  assert(m->size == rhs->size);
133 
134  // no output
135  aztec.SetAztecOption(AZ_output, AZ_none); // AZ_all | AZ_warnings | AZ_last | AZ_summary
136 
137  // setup the problem
138  aztec.SetUserMatrix(m->mat);
139  aztec.SetRHS(rhs->vec);
140  Epetra_Vector x(*rhs->std_map);
141  aztec.SetLHS(&x);
142 
143  if(pc != NULL)
144  {
145  Epetra_Operator *op = pc->get_obj();
146  assert(op != NULL); // can work only with Epetra_Operators
147  aztec.SetPrecOperator(op);
148  }
149 
150  // solve it
151  aztec.Iterate(this->max_iters, this->tolerance);
152 
153  this->tick();
154  this->time = this->accumulated();
155 
156  delete [] this->sln;
157  this->sln = new double[m->size];
158  memset(this->sln, 0, m->size * sizeof(double));
159 
160  // copy the solution into sln vector
161  for (unsigned int i = 0; i < m->size; i++) this->sln[i] = x[i];
162  return true;
163  }
164 
165  template<>
166  bool AztecOOSolver<std::complex<double> >::solve()
167  {
168  assert(m != NULL);
169  assert(rhs != NULL);
170  assert(m->size == rhs->size);
171 
172  // no output
173  aztec.SetAztecOption(AZ_output, AZ_none); // AZ_all | AZ_warnings | AZ_last | AZ_summary
174 
175  double c0r = 1.0, c0i = 0.0;
176  double c1r = 0.0, c1i = 1.0;
177 
178  Epetra_Vector xr(*rhs->std_map);
179  Epetra_Vector xi(*rhs->std_map);
180 
181  Komplex_LinearProblem kp(c0r, c0i, *m->mat, c1r, c1i, *m->mat_im, xr, xi, *rhs->vec, *rhs->vec_im);
182  Epetra_LinearProblem *lp = kp.KomplexProblem();
183  aztec.SetProblem(*lp,true);
184 
185  // solve it
186  aztec.Iterate(this->max_iters, this->tolerance);
187 
188  kp.ExtractSolution(xr, xi);
189 
190  delete [] this->sln;
191  this->sln = new std::complex<double>[m->size];
192  memset(this->sln, 0, m->size * sizeof(std::complex<double>));
193 
194  // copy the solution into sln vector
195  for (unsigned int i = 0; i < m->size; i++) this->sln[i] = std::complex<double>(xr[i], xi[i]);
196  return true;
197  }
198 
199  template<typename Scalar>
200  int AztecOOSolver<Scalar>::get_num_iters()
201  {
202  return aztec.NumIters();
203  }
204 
205  template<typename Scalar>
206  double AztecOOSolver<Scalar>::get_residual()
207  {
208  return aztec.TrueResidual();
209  }
210 
211  template class HERMES_API AztecOOSolver<double>;
212  template class HERMES_API AztecOOSolver<std::complex<double> >;
213  }
214 }
215 #endif