Hermes2D  2.0
linear_solver.cpp
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 "linear_solver.h"
23 
24 using namespace Hermes::Algebra;
25 
26 namespace Hermes
27 {
28  namespace Hermes2D
29  {
30  template<typename Scalar>
31  LinearSolver<Scalar>::LinearSolver() : dp(new DiscreteProblemLinear<Scalar>()), sln_vector(NULL), own_dp(true)
32  {
33  this->init();
34  }
35 
36  template<typename Scalar>
37  LinearSolver<Scalar>::LinearSolver(DiscreteProblemLinear<Scalar>* dp) : dp(dp), sln_vector(NULL), own_dp(false)
38  {
39  this->init();
40  }
41 
42  template<typename Scalar>
43  LinearSolver<Scalar>::LinearSolver(const WeakForm<Scalar>* wf, const Space<Scalar>* space) : dp(new DiscreteProblemLinear<Scalar>(wf, space)), sln_vector(NULL), own_dp(true)
44  {
45  this->init();
46  }
47 
48  template<typename Scalar>
49  LinearSolver<Scalar>::LinearSolver(const WeakForm<Scalar>* wf, Hermes::vector<const Space<Scalar>*> spaces) : dp(new DiscreteProblemLinear<Scalar>(wf, spaces)), sln_vector(NULL), own_dp(true)
50  {
51  this->init();
52  }
53 
54  template<typename Scalar>
55  void LinearSolver<Scalar>::init()
56  {
57  this->jacobian = create_matrix<Scalar>();
58  this->residual = create_vector<Scalar>();
59  this->matrix_solver = create_linear_solver<Scalar>(this->jacobian, this->residual);
60  this->set_verbose_output(true);
61  }
62 
63  template<typename Scalar>
65  {
66  if(static_cast<DiscreteProblem<Scalar>*>(this->dp)->get_weak_formulation() == NULL)
67  return false;
68  if(static_cast<DiscreteProblem<Scalar>*>(this->dp)->get_spaces().size() == 0)
69  return false;
70  return true;
71  }
72 
73  template<typename Scalar>
75  {
76  Hermes::vector<Space<Scalar>*> spaces;
77  for(unsigned int i = 0; i < this->dp->get_spaces().size(); i++)
78  spaces.push_back(const_cast<Space<Scalar>*>(this->dp->get_space(i)));
79 
81  const_cast<WeakForm<Scalar>*>(this->dp->wf)->set_current_time(time);
82  }
83 
84  template<typename Scalar>
86  {
87  (static_cast<DiscreteProblem<Scalar>*>(this->dp))->set_weak_formulation(wf);
88  }
89 
90  template<typename Scalar>
91  void LinearSolver<Scalar>::set_time_step(double time_step)
92  {
93  const_cast<WeakForm<Scalar>*>(this->dp->wf)->set_current_time_step(time_step);
94  }
95 
96  template<typename Scalar>
97  SparseMatrix<Scalar>* LinearSolver<Scalar>::get_jacobian()
98  {
99  return this->jacobian;
100  }
101 
102  template<typename Scalar>
104  {
105  return this->residual;
106  }
107 
108  template<typename Scalar>
109  void LinearSolver<Scalar>::set_spaces(Hermes::vector<const Space<Scalar>*> spaces)
110  {
111  static_cast<DiscreteProblem<Scalar>*>(this->dp)->set_spaces(spaces);
112  }
113 
114  template<typename Scalar>
116  {
117  static_cast<DiscreteProblem<Scalar>*>(this->dp)->set_space(space);
118  }
119 
120  template<typename Scalar>
121  Hermes::vector<const Space<Scalar>*> LinearSolver<Scalar>::get_spaces() const
122  {
123  return static_cast<DiscreteProblem<Scalar>*>(this->dp)->get_spaces();
124  }
125 
126  template<typename Scalar>
128  {
129  delete jacobian;
130  delete residual;
131  delete matrix_solver;
132  if(own_dp)
133  delete this->dp;
134  else
135  static_cast<DiscreteProblem<Scalar>*>(this->dp)->have_matrix = false;
136  }
137 
138  template<typename Scalar>
140  {
141  this->check();
142 
143  this->tick();
144 
145  this->on_initialization();
146 
147  dp->assemble(this->jacobian, this->residual);
148  if(this->output_rhsOn && (this->output_rhsIterations == -1 || this->output_rhsIterations >= 1))
149  {
150  char* fileName = new char[this->RhsFilename.length() + 5];
151  if(this->RhsFormat == Hermes::Algebra::DF_MATLAB_SPARSE)
152  sprintf(fileName, "%s%i.m", this->RhsFilename.c_str(), 1);
153  else
154  sprintf(fileName, "%s%i", this->RhsFilename.c_str(), 1);
155  FILE* rhs_file = fopen(fileName, "w+");
156  residual->dump(rhs_file, this->RhsVarname.c_str(), this->RhsFormat, this->rhs_number_format);
157  fclose(rhs_file);
158  }
159  if(this->output_matrixOn && (this->output_matrixIterations == -1 || this->output_matrixIterations >= 1))
160  {
161  char* fileName = new char[this->matrixFilename.length() + 5];
162  if(this->matrixFormat == Hermes::Algebra::DF_MATLAB_SPARSE)
163  sprintf(fileName, "%s%i.m", this->matrixFilename.c_str(), 1);
164  else
165  sprintf(fileName, "%s%i", this->matrixFilename.c_str(), 1);
166  FILE* matrix_file = fopen(fileName, "w+");
167 
168  jacobian->dump(matrix_file, this->matrixVarname.c_str(), this->matrixFormat, this->matrix_number_format);
169  fclose(matrix_file);
170  }
171 
172  this->matrix_solver->solve();
173 
174  this->sln_vector = matrix_solver->get_sln_vector();
175 
176  this->on_finish();
177 
178  this->tick();
179  this->info("\tLinear solver solution duration: %f s.\n", this->last());
180  }
181 
182  template<typename Scalar>
184  {
185  return sln_vector;
186  }
187 
188  template class HERMES_API LinearSolver<double>;
189  template class HERMES_API LinearSolver<std::complex<double> >;
190  }
191 }