Hermes2D  2.0
ogprojection_nox.cpp
Go to the documentation of this file.
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
19 #include "space.h"
20 #include "discrete_problem.h"
21 #include "newton_solver_nox.h"
22 #if(defined HAVE_NOX && defined HAVE_EPETRA && defined HAVE_TEUCHOS)
23 
24 namespace Hermes
25 {
26  namespace Hermes2D
27  {
28  template<typename Scalar>
29  OGProjectionNOX<Scalar>::OGProjectionNOX() : ndof(0)
30  {
31  }
32 
33  template<typename Scalar>
34  void OGProjectionNOX<Scalar>::project_internal(const Space<Scalar>* space, WeakForm<Scalar>* wf,
35  Scalar* target_vec, double newton_tol, int newton_max_iter)
36  {
37  // Sanity check.
38  if(space == NULL)
39  throw Hermes::Exceptions::Exception("this->space == NULL in project_internal().");
40 
41  // Get dimension of the space.
42  int ndof = space->get_num_dofs();
43 
44  // Initialize DiscreteProblem.
45  DiscreteProblem<Scalar> dp(wf, space);
46 
47  // Initial coefficient vector for the Newton's method.
48  Scalar* coeff_vec = new Scalar[ndof];
49  memset(coeff_vec, 0, ndof*sizeof(Scalar));
50 
51  const char* iterative_method = "GMRES"; // Name of the iterative method employed by AztecOO (ignored
52  // by the other solvers).
53  // Possibilities: gmres, cg, cgs, tfqmr, bicgstab.
54  const char* preconditioner = "New Ifpack"; // Name of the preconditioner employed by AztecOO
55  // Possibilities: None" - No preconditioning.
56  // "AztecOO" - AztecOO internal preconditioner.
57  // "New Ifpack" - Ifpack internal preconditioner.
58  // "ML" - Multi level preconditione
59  unsigned message_type = NOX::Utils::Error | NOX::Utils::Warning | NOX::Utils::OuterIteration | NOX::Utils::InnerIteration | NOX::Utils::Parameters | NOX::Utils::LinearSolverDetails;
60  // NOX error messages, see NOX_Utils.h.
61  double ls_tolerance = 1e-5; // Tolerance for linear system.
62  unsigned flag_absresid = 0; // Flag for absolute value of the residuum.
63  double abs_resid = 1.0e-3; // Tolerance for absolute value of the residuum.
64  unsigned flag_relresid = 1; // Flag for relative value of the residuum.
65  double rel_resid = newton_tol; // Tolerance for relative value of the residuum.
66  int max_iters = newton_max_iter; // Max number of iterations.
67 
68  // Initialize NOX.
69  NewtonSolverNOX<Scalar> newton_nox(&dp);
70 
71  // Set NOX parameters.
72  newton_nox.set_verbose_output(false);
73  newton_nox.set_output_flags(message_type);
74  newton_nox.set_ls_type(iterative_method);
75  newton_nox.set_ls_tolerance(ls_tolerance);
76  newton_nox.set_conv_iters(max_iters);
77  if(flag_absresid)
78  newton_nox.set_conv_abs_resid(abs_resid);
79  if(flag_relresid)
80  newton_nox.set_conv_rel_resid(rel_resid);
81  newton_nox.set_precond(preconditioner);
82  newton_nox.set_precond_reuse("Rebuild");
83 
84  // Perform Newton's iteration via NOX
85  newton_nox.solve(coeff_vec);
86 
87  delete [] coeff_vec;
88 
89  if(target_vec != NULL)
90  for (int i = 0; i < ndof; i++)
91  target_vec[i] = newton_nox.get_sln_vector()[i];
92  }
93 
94  template<typename Scalar>
95  void OGProjectionNOX<Scalar>::project_global(const Space<Scalar>* space,
96  MatrixFormVol<Scalar>* custom_projection_jacobian,
97  VectorFormVol<Scalar>* custom_projection_residual,
98  Scalar* target_vec,
99  double newton_tol, int newton_max_iter)
100  {
101  // Define projection weak form.
102  WeakForm<Scalar>* proj_wf = new WeakForm<Scalar>(1);
103  proj_wf->add_matrix_form(custom_projection_jacobian);
104  proj_wf->add_vector_form(custom_projection_residual);
105 
106  // Call the main function.
107  project_internal(space, proj_wf, target_vec, newton_tol, newton_max_iter);
108 
109  // Clean up.
110  delete proj_wf;
111  }
112 
113  template<typename Scalar>
114  void OGProjectionNOX<Scalar>::project_global(const Space<Scalar>* space,
115  MeshFunction<Scalar>* source_meshfn, Scalar* target_vec,
116  ProjNormType proj_norm,
117  double newton_tol, int newton_max_iter)
118  {
119  // Sanity checks.
120  if(target_vec == NULL) throw Exceptions::NullException(3);
121 
122  // If projection norm is not provided, set it
123  // to match the type of the space.
124  ProjNormType norm = HERMES_UNSET_NORM;
125  if(proj_norm == HERMES_UNSET_NORM)
126  {
127  SpaceType space_type = space->get_type();
128  switch (space_type)
129  {
130  case HERMES_H1_SPACE: norm = HERMES_H1_NORM; break;
131  case HERMES_HCURL_SPACE: norm = HERMES_HCURL_NORM; break;
132  case HERMES_HDIV_SPACE: norm = HERMES_HDIV_NORM; break;
133  case HERMES_L2_SPACE: norm = HERMES_L2_NORM; break;
134  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjectionNOX<Scalar>::project_global().");
135  }
136  }
137  else norm = proj_norm;
138 
139  // Define temporary projection weak form.
140  WeakForm<Scalar>* proj_wf = new WeakForm<Scalar>(1);
141  proj_wf->set_ext(source_meshfn);
142  // Add Jacobian.
143  proj_wf->add_matrix_form(new ProjectionMatrixFormVol(0, 0, norm));
144  // Add Residual.
145  proj_wf->add_vector_form(new ProjectionVectorFormVol(0, norm));
146 
147  // Call main function.
148  project_internal(space, proj_wf, target_vec, newton_tol, newton_max_iter);
149 
150  // Clean up.
151  delete proj_wf;
152  }
153 
154  template<typename Scalar>
155  void OGProjectionNOX<Scalar>::project_global(const Space<Scalar>* space,
156  Solution<Scalar>* source_sln, Solution<Scalar>* target_sln,
157  ProjNormType proj_norm,
158  double newton_tol, int newton_max_iter)
159  {
160  if(proj_norm == HERMES_UNSET_NORM)
161  {
162  SpaceType space_type = space->get_type();
163  switch (space_type)
164  {
165  case HERMES_H1_SPACE: proj_norm = HERMES_H1_NORM; break;
166  case HERMES_HCURL_SPACE: proj_norm = HERMES_HCURL_NORM; break;
167  case HERMES_HDIV_SPACE: proj_norm = HERMES_HDIV_NORM; break;
168  case HERMES_L2_SPACE: proj_norm = HERMES_L2_NORM; break;
169  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjectionNOX<Scalar>::project_global().");
170  }
171  }
172 
173  // Calculate the coefficient vector.
174  int ndof = space->get_num_dofs();
175  Scalar* target_vec = new Scalar[ndof];
176  project_global(space, source_sln, target_vec, proj_norm, newton_tol, newton_max_iter);
177 
178  // Translate coefficient vector into a Solution.
179  Solution<Scalar>::vector_to_solution(target_vec, space, target_sln);
180 
181  // Clean up.
182  delete [] target_vec;
183  }
184 
185  template<typename Scalar>
186  void OGProjectionNOX<Scalar>::project_global(Hermes::vector<const Space<Scalar>*> spaces,
187  Hermes::vector<MeshFunction<Scalar>*> source_meshfns,
188  Scalar* target_vec, Hermes::vector<ProjNormType> proj_norms,
189  double newton_tol, int newton_max_iter)
190  {
191  int n = spaces.size();
192 
193  // Sanity checks.
194  if(n != source_meshfns.size()) throw Exceptions::LengthException(1, 2, n, source_meshfns.size());
195  if(target_vec == NULL) throw Exceptions::NullException(3);
196  if(!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
197 
198  int start_index = 0;
199  for (int i = 0; i < n; i++)
200  {
201  if(proj_norms.empty())
202  project_global(spaces[i], source_meshfns[i], target_vec + start_index, HERMES_UNSET_NORM, newton_tol, newton_max_iter);
203  else
204  project_global(spaces[i], source_meshfns[i], target_vec + start_index, proj_norms[i], newton_tol, newton_max_iter);
205  spaces[i]->assign_dofs(start_index);
206  start_index += spaces[i]->get_num_dofs();
207  }
208  }
209 
210  template<typename Scalar>
211  void OGProjectionNOX<Scalar>::project_global(Hermes::vector<const Space<Scalar>*> spaces, Hermes::vector<Solution<Scalar>*> source_slns,
212  Scalar* target_vec, Hermes::vector<ProjNormType> proj_norms,
213  double newton_tol, int newton_max_iter)
214  {
215  int n = spaces.size();
216 
217  // Sanity checks.
218  if(n != source_slns.size()) throw Exceptions::LengthException(1, 2, n, source_slns.size());
219  if(target_vec == NULL) throw Exceptions::NullException(3);
220  if(!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
221 
222  int start_index = 0;
223  for (int i = 0; i < n; i++)
224  {
225  if(proj_norms.empty())
226  project_global(spaces[i], source_slns[i], target_vec + start_index, HERMES_UNSET_NORM, newton_tol, newton_max_iter);
227  else
228  project_global(spaces[i], source_slns[i], target_vec + start_index, proj_norms[i], newton_tol, newton_max_iter);
229  start_index += spaces[i]->get_num_dofs();
230  }
231  }
232 
233  template<typename Scalar>
234  void OGProjectionNOX<Scalar>::project_global(Hermes::vector<const Space<Scalar>*> spaces, Hermes::vector<Solution<Scalar>*> source_slns,
235  Hermes::vector<Solution<Scalar>*> target_slns,
236  Hermes::vector<ProjNormType> proj_norms, bool delete_old_meshes,
237  double newton_tol, int newton_max_iter)
238  {
239  int n = spaces.size();
240 
241  // Sanity checks.
242  if(n != source_slns.size()) throw Exceptions::LengthException(1, 2, n, source_slns.size());
243  if(n != target_slns.size()) throw Exceptions::LengthException(1, 2, n, target_slns.size());
244  if(!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
245 
246  int start_index = 0;
247  for (int i = 0; i < n; i++)
248  {
249  if(proj_norms.empty())
250  project_global(spaces[i], source_slns[i], target_slns[i], HERMES_UNSET_NORM, newton_tol, newton_max_iter);
251  else
252  project_global(spaces[i], source_slns[i], target_slns[i], proj_norms[i], newton_tol, newton_max_iter);
253  start_index += spaces[i]->get_num_dofs();
254  }
255  }
256 
257  template class HERMES_API OGProjectionNOX<double>;
258  // template class HERMES_API OGProjectionNOX<std::complex<double> >; //complex version of nox solver is not implemented
259  }
260 }
261 
262 #endif