Hermes2D  3.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/discrete_problem.h"
21 #include "solver/nox_solver.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  void OGProjectionNOX<Scalar>::project_internal(SpaceSharedPtr<Scalar> space, WeakForm<Scalar>* wf,
30  Scalar* target_vec, double newton_tol, int newton_max_iter)
31  {
32  // Sanity check.
33  if (space == nullptr)
34  throw Hermes::Exceptions::Exception("this->space == nullptr in project_internal().");
35 
36  // Get dimension of the space.
37  int ndof = space->get_num_dofs();
38 
39  // Initialize DiscreteProblem.
40  DiscreteProblemNOX<Scalar> dp(wf, space);
41 
42  // Initial coefficient vector for the Newton's method.
43  Scalar* coeff_vec = calloc_with_check<Scalar>(ndof);
44 
45  // Name of the iterative method employed by AztecOO (ignored
46  const char* iterative_method = "GMRES";
47  // by the other solvers).
48  // Possibilities: gmres, cg, cgs, tfqmr, bicgstab.
49  // Name of the preconditioner employed by AztecOO
50  const char* preconditioner = "New Ifpack";
51  // Possibilities: None" - No preconditioning.
52  // "AztecOO" - AztecOO internal preconditioner.
53  // "new_ Ifpack" - Ifpack internal preconditioner.
54  // "ML" - Multi level preconditione
55  unsigned message_type = NOX::Utils::Error | NOX::Utils::Warning | NOX::Utils::OuterIteration | NOX::Utils::InnerIteration | NOX::Utils::Parameters | NOX::Utils::LinearSolverDetails;
56  // NOX error messages, see NOX_Utils.h.
57  // Tolerance for linear system.
58  double ls_tolerance = 1e-5;
59  // Flag for absolute value of the residuum.
60  unsigned flag_absresid = 0;
61  // Tolerance for absolute value of the residuum.
62  double abs_resid = 1.0e-3;
63  // Flag for relative value of the residuum.
64  unsigned flag_relresid = 1;
65  // Tolerance for relative value of the residuum.
66  double rel_resid = newton_tol;
67  // Max number of iterations.
68  int max_iters = newton_max_iter;
69 
70  // Initialize NOX.
71  NewtonSolverNOX<Scalar> newton_nox(&dp);
72 
73  // Set NOX parameters.
74  newton_nox.set_verbose_output(false);
75  newton_nox.set_output_flags(message_type);
76  newton_nox.set_ls_type(iterative_method);
77  newton_nox.set_ls_tolerance(ls_tolerance);
78  newton_nox.set_conv_iters(max_iters);
79  if (flag_absresid)
80  newton_nox.set_conv_abs_resid(abs_resid);
81  if (flag_relresid)
82  newton_nox.set_conv_rel_resid(rel_resid);
83  newton_nox.set_precond(preconditioner);
84  newton_nox.set_precond_reuse("Rebuild");
85 
86  // Perform Newton's iteration via NOX
87  newton_nox.solve(coeff_vec);
88 
89  free_with_check(coeff_vec);
90 
91  if (target_vec != nullptr)
92  for (int i = 0; i < ndof; i++)
93  target_vec[i] = newton_nox.get_sln_vector()[i];
94  }
95 
96  template<typename Scalar>
97  void OGProjectionNOX<Scalar>::project_global(SpaceSharedPtr<Scalar> space,
98  MatrixFormVol<Scalar>* custom_projection_jacobian,
99  VectorFormVol<Scalar>* custom_projection_residual,
100  Scalar* target_vec,
101  double newton_tol, int newton_max_iter)
102  {
103  // Define projection weak form.
104  WeakForm<Scalar>* proj_wf = new WeakForm<Scalar>(1);
105  proj_wf->add_matrix_form(custom_projection_jacobian);
106  proj_wf->add_vector_form(custom_projection_residual);
107 
108  // Call the main function.
109  project_internal(space, proj_wf, target_vec, newton_tol, newton_max_iter);
110 
111  // Clean up.
112  delete proj_wf;
113  }
114 
115  template<typename Scalar>
116  void OGProjectionNOX<Scalar>::project_global(SpaceSharedPtr<Scalar> space,
117  MeshFunction<Scalar>* source_meshfn, Scalar* target_vec,
118  NormType proj_norm,
119  double newton_tol, int newton_max_iter)
120  {
121  // Sanity checks.
122  if (target_vec == nullptr) throw Exceptions::NullException(3);
123 
124  // If projection norm is not provided, set it
125  // to match the type of the space.
126  NormType norm = HERMES_UNSET_NORM;
127  if (proj_norm == HERMES_UNSET_NORM)
128  {
129  SpaceType space_type = space->get_type();
130  switch (space_type)
131  {
132  case HERMES_H1_SPACE: norm = HERMES_H1_NORM; break;
133  case HERMES_HCURL_SPACE: norm = HERMES_HCURL_NORM; break;
134  case HERMES_HDIV_SPACE: norm = HERMES_HDIV_NORM; break;
135  case HERMES_L2_SPACE: norm = HERMES_L2_NORM; break;
136  case HERMES_L2_MARKERWISE_CONST_SPACE: norm = HERMES_L2_NORM; break;
137  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjectionNOX<Scalar>::project_global().");
138  }
139  }
140  else norm = proj_norm;
141 
142  // Define temporary projection weak form.
143  WeakForm<Scalar>* proj_wf = new WeakForm<Scalar>(1);
144  proj_wf->set_ext(source_meshfn);
145  // Add Jacobian.
146  proj_wf->add_matrix_form(new ProjectionMatrixFormVol(0, 0, norm));
147  // Add Residual.
148  proj_wf->add_vector_form(new ProjectionVectorFormVol(0, norm));
149 
150  // Call main function.
151  project_internal(space, proj_wf, target_vec, newton_tol, newton_max_iter);
152 
153  // Clean up.
154  delete proj_wf;
155  }
156 
157  template<typename Scalar>
158  void OGProjectionNOX<Scalar>::project_global(SpaceSharedPtr<Scalar> space,
159  MeshFunctionSharedPtr<Scalar> source_meshfn, Scalar* target_vec,
160  NormType proj_norm,
161  double newton_tol, int newton_max_iter)
162  {
163  project_global(space, source_meshfn.get(), target_vec, proj_norm, newton_tol, newton_max_iter);
164  }
165 
166  template<typename Scalar>
167  void OGProjectionNOX<Scalar>::project_global(SpaceSharedPtr<Scalar> space,
168  MeshFunctionSharedPtr<Scalar> source_sln, MeshFunctionSharedPtr<Scalar> target_sln,
169  NormType proj_norm,
170  double newton_tol, int newton_max_iter)
171  {
172  if (proj_norm == HERMES_UNSET_NORM)
173  {
174  SpaceType space_type = space->get_type();
175  switch (space_type)
176  {
177  case HERMES_H1_SPACE: proj_norm = HERMES_H1_NORM; break;
178  case HERMES_HCURL_SPACE: proj_norm = HERMES_HCURL_NORM; break;
179  case HERMES_HDIV_SPACE: proj_norm = HERMES_HDIV_NORM; break;
180  case HERMES_L2_SPACE: proj_norm = HERMES_L2_NORM; break;
181  case HERMES_L2_MARKERWISE_CONST_SPACE: proj_norm = HERMES_L2_NORM; break;
182  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjectionNOX<Scalar>::project_global().");
183  }
184  }
185 
186  // Calculate the coefficient vector.
187  int ndof = space->get_num_dofs();
188  Scalar* target_vec = malloc_with_check<Scalar>(ndof);
189  project_global(space, source_sln, target_vec, proj_norm, newton_tol, newton_max_iter);
190 
191  // Translate coefficient vector into a Solution.
192  Solution<Scalar>::vector_to_solution(target_vec, space, target_sln);
193 
194  // Clean up.
195  free_with_check(target_vec);
196  }
197 
198  template<typename Scalar>
199  void OGProjectionNOX<Scalar>::project_global(std::vector<SpaceSharedPtr<Scalar> > spaces,
200  std::vector<MeshFunction<Scalar>* > source_meshfns,
201  Scalar* target_vec, std::vector<NormType> proj_norms,
202  double newton_tol, int newton_max_iter)
203  {
204  int n = spaces.size();
205 
206  // Sanity checks.
207  if (n != source_meshfns.size()) throw Exceptions::LengthException(1, 2, n, source_meshfns.size());
208  if (target_vec == nullptr) throw Exceptions::NullException(3);
209  if (!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
210 
211  int start_index = 0;
212  for (int i = 0; i < n; i++)
213  {
214  if (proj_norms.empty())
215  project_global(spaces[i], source_meshfns[i], target_vec + start_index, HERMES_UNSET_NORM, newton_tol, newton_max_iter);
216  else
217  project_global(spaces[i], source_meshfns[i], target_vec + start_index, proj_norms[i], newton_tol, newton_max_iter);
218  spaces[i]->assign_dofs(start_index);
219  start_index += spaces[i]->get_num_dofs();
220  }
221  }
222 
223  template<typename Scalar>
224  void OGProjectionNOX<Scalar>::project_global(std::vector<SpaceSharedPtr<Scalar> > spaces, std::vector<MeshFunctionSharedPtr<Scalar> > source_slns,
225  Scalar* target_vec, std::vector<NormType> proj_norms,
226  double newton_tol, int newton_max_iter)
227  {
228  int n = spaces.size();
229 
230  // Sanity checks.
231  if (n != source_slns.size()) throw Exceptions::LengthException(1, 2, n, source_slns.size());
232  if (target_vec == nullptr) throw Exceptions::NullException(3);
233  if (!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
234 
235  int start_index = 0;
236  for (int i = 0; i < n; i++)
237  {
238  if (proj_norms.empty())
239  project_global(spaces[i], source_slns[i], target_vec + start_index, HERMES_UNSET_NORM, newton_tol, newton_max_iter);
240  else
241  project_global(spaces[i], source_slns[i], target_vec + start_index, proj_norms[i], newton_tol, newton_max_iter);
242  start_index += spaces[i]->get_num_dofs();
243  }
244  }
245 
246  template<typename Scalar>
247  void OGProjectionNOX<Scalar>::project_global(std::vector<SpaceSharedPtr<Scalar> > spaces, std::vector<MeshFunctionSharedPtr<Scalar> > source_slns,
248  std::vector<MeshFunctionSharedPtr<Scalar> > target_slns,
249  std::vector<NormType> proj_norms, bool delete_old_meshes,
250  double newton_tol, int newton_max_iter)
251  {
252  int n = spaces.size();
253 
254  // Sanity checks.
255  if (n != source_slns.size()) throw Exceptions::LengthException(1, 2, n, source_slns.size());
256  if (n != target_slns.size()) throw Exceptions::LengthException(1, 2, n, target_slns.size());
257  if (!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
258 
259  int start_index = 0;
260  for (int i = 0; i < n; i++)
261  {
262  if (proj_norms.empty())
263  project_global(spaces[i], source_slns[i], target_slns[i], HERMES_UNSET_NORM, newton_tol, newton_max_iter);
264  else
265  project_global(spaces[i], source_slns[i], target_slns[i], proj_norms[i], newton_tol, newton_max_iter);
266  start_index += spaces[i]->get_num_dofs();
267  }
268  }
269 
270  template class HERMES_API OGProjectionNOX < double > ;
271  //complex version of nox solver is not implemented
272  // template class HERMES_API OGProjectionNOX<std::complex<double> >;
273  }
274 }
275 
276 #endif
Definition: adapt.h:24
Orthogonal projection via NOX (matrix-free).