Hermes2D  3.0
ogprojection.cpp
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/>.
15 
16 #include "projections/ogprojection.h"
17 #include "space.h"
18 #include "solver/linear_solver.h"
19 
20 namespace Hermes
21 {
22  namespace Hermes2D
23  {
24  template<typename Scalar>
26  {
27  // Sanity check.
28  if (wf == nullptr)
29  throw Hermes::Exceptions::NullException(1);
30  if (target_vec == nullptr)
31  throw Exceptions::NullException(2);
32 
33  // Initialize linear solver.
34  Hermes::Hermes2D::LinearSolver<Scalar> linear_solver(wf, space);
35  linear_solver.set_verbose_output(false);
36 
37  // Perform Newton iteration.
38  linear_solver.solve();
39 
40  memcpy(target_vec, linear_solver.get_sln_vector(), space->get_num_dofs() * sizeof(Scalar));
41  }
42 
43  template<typename Scalar>
45  MatrixFormVol<Scalar>* custom_projection_jacobian,
46  VectorFormVol<Scalar>* custom_projection_residual,
47  Scalar* target_vec)
48  {
49  // Define projection weak form.
51  proj_wf->add_matrix_form(custom_projection_jacobian);
52  proj_wf->add_vector_form(custom_projection_residual);
53 
54  // Call the main function.
55  project_internal(space, proj_wf, target_vec);
56  }
57 
58  template<typename Scalar>
60  MatrixFormVol<Scalar>* custom_projection_jacobian,
61  VectorFormVol<Scalar>* custom_projection_residual,
63  {
64  // Calculate the coefficient vector.
65  Scalar* target_vec = malloc_with_check<Scalar>(space->get_num_dofs());
66 
67  project_global(space, custom_projection_jacobian, custom_projection_residual, target_vec);
68 
69  // Translate coefficient vector into a Solution.
70  Solution<Scalar>::vector_to_solution(target_vec, space, target_sln);
71 
72  // Clean up.
73  free_with_check(target_vec);
74  }
75 
76  template<typename Scalar>
78  const std::vector<MatrixFormVol<Scalar>*>& custom_projection_jacobians,
79  const std::vector<VectorFormVol<Scalar>*>& custom_projection_residuals,
80  Scalar* target_vec)
81  {
82  // Sanity checks.
83  if (target_vec == nullptr) throw Exceptions::NullException(3);
84  // Sanity checks.
85  Helpers::check_length(custom_projection_jacobians, spaces);
86  Helpers::check_length(custom_projection_residuals, spaces);
87 
88  int start_index = 0, spaces_size = spaces.size();
89  for (int i = 0; i < spaces_size; i++)
90  {
91  project_global(spaces[i], custom_projection_jacobians[i], custom_projection_residuals[i], target_vec + start_index);
92  start_index += spaces[i]->get_num_dofs();
93  }
94  }
95 
96  template<typename Scalar>
98  const std::vector<MatrixFormVol<Scalar>*>& custom_projection_jacobians,
99  const std::vector<VectorFormVol<Scalar>*>& custom_projection_residuals,
100  const std::vector<MeshFunctionSharedPtr<Scalar> >& target_slns)
101  {
102  // Sanity checks.
103  Helpers::check_length(target_slns, spaces);
104  Helpers::check_length(custom_projection_jacobians, spaces);
105  Helpers::check_length(custom_projection_residuals, spaces);
106 
107  int spaces_size = spaces.size();
108  for (int i = 0; i < spaces_size; i++)
109  project_global(spaces[i], custom_projection_jacobians[i], custom_projection_residuals[i], target_slns[i]);
110  }
111 
112  template<typename Scalar>
114  MeshFunctionSharedPtr<Scalar> source_meshfn, Hermes::Algebra::Vector<Scalar>* target_vec,
115  NormType proj_norm)
116  {
117  if (target_vec->get_size() != space->get_num_dofs())
118  throw Exceptions::ValueException("target_vec->size", target_vec->get_size(), space->get_num_dofs());
119 
120  Scalar* vec = malloc_with_check<Scalar>(target_vec->get_size());
121  project_global(space, source_meshfn, vec, proj_norm);
122  target_vec->set_vector(vec);
123  free_with_check(vec);
124  }
125 
126  template<typename Scalar>
127  void OGProjection<Scalar>::project_global(SpaceSharedPtr<Scalar> space,
128  MeshFunctionSharedPtr<Scalar> source_meshfn, Scalar* target_vec,
129  NormType proj_norm)
130  {
131  // Sanity checks.
132  if (target_vec == nullptr)
133  throw Exceptions::NullException(3);
134 
135  // If projection norm is not provided, set it
136  // to match the type of the space.
137  NormType norm = HERMES_UNSET_NORM;
138  if (proj_norm == HERMES_UNSET_NORM)
139  {
140  SpaceType space_type = space->get_type();
141  switch (space_type)
142  {
143  case HERMES_H1_SPACE: norm = HERMES_H1_NORM; break;
144  case HERMES_HCURL_SPACE: norm = HERMES_HCURL_NORM; break;
145  case HERMES_HDIV_SPACE: norm = HERMES_HDIV_NORM; break;
146  case HERMES_L2_SPACE: norm = HERMES_L2_NORM; break;
147  case HERMES_L2_MARKERWISE_CONST_SPACE: norm = HERMES_L2_NORM; break;
148  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjection<Scalar>::project_global().");
149  }
150  }
151  else norm = proj_norm;
152 
153  // Define temporary projection weak form.
154  WeakFormSharedPtr<Scalar> proj_wf(new WeakForm<Scalar>(1));
155  proj_wf->set_verbose_output(false);
156  proj_wf->set_ext(source_meshfn);
157  // Add Jacobian.
158  proj_wf->add_matrix_form(new MatrixDefaultNormFormVol<Scalar>(0, 0, norm));
159  // Add Residual.
160  proj_wf->add_vector_form(new VectorDefaultNormFormVol<Scalar>(0, norm));
161 
162  // Call main function.
163  project_internal(space, proj_wf, target_vec);
164  }
165 
166  template<typename Scalar>
169  NormType proj_norm)
170  {
171  if (proj_norm == HERMES_UNSET_NORM)
172  {
173  SpaceType space_type = space->get_type();
174  switch (space_type)
175  {
176  case HERMES_H1_SPACE: proj_norm = HERMES_H1_NORM; break;
177  case HERMES_HCURL_SPACE: proj_norm = HERMES_HCURL_NORM; break;
178  case HERMES_HDIV_SPACE: proj_norm = HERMES_HDIV_NORM; break;
179  case HERMES_L2_SPACE: proj_norm = HERMES_L2_NORM; break;
180  case HERMES_L2_MARKERWISE_CONST_SPACE: proj_norm = HERMES_L2_NORM; break;
181  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjection<Scalar>::project_global().");
182  }
183  }
184 
185  // Calculate the coefficient vector.
186  Scalar* target_vec = malloc_with_check<Scalar>(space->get_num_dofs());
187  project_global(space, source_sln, target_vec, proj_norm);
188 
189  // Translate coefficient vector into a Solution.
190  Solution<Scalar>::vector_to_solution(target_vec, space, target_sln);
191 
192  // Clean up.
193  free_with_check(target_vec);
194  }
195 
196  template<typename Scalar>
198  Scalar* target_vec, std::vector<NormType> proj_norms)
199  {
200  // Sanity checks.
201  Helpers::check_length(source_slns, spaces);
202  if (target_vec == nullptr)
203  throw Exceptions::NullException(3);
204  if (!proj_norms.empty())
205  Helpers::check_length(proj_norms, spaces);
206 
207  int start_index = 0, spaces_size = spaces.size();
208  for (int i = 0; i < spaces_size; i++)
209  {
210  if (proj_norms.empty())
211  project_global(spaces[i], source_slns[i], target_vec + start_index, HERMES_UNSET_NORM);
212  else
213  project_global(spaces[i], source_slns[i], target_vec + start_index, proj_norms[i]);
214  start_index += spaces[i]->get_num_dofs();
215  }
216  }
217 
218  template<typename Scalar>
219  void OGProjection<Scalar>::project_global(std::vector<SpaceSharedPtr<Scalar> > spaces, std::vector<MeshFunctionSharedPtr<Scalar> > source_slns,
220  Hermes::Algebra::Vector<Scalar>* target_vec, std::vector<NormType> proj_norms)
221  {
222  if (target_vec->get_size() != Space<Scalar>::get_num_dofs(spaces))
223  throw Exceptions::ValueException("target_vec->size", target_vec->get_size(), Space<Scalar>::get_num_dofs(spaces));
224 
225  Scalar* vec = malloc_with_check<Scalar>(target_vec->get_size());
226  project_global(spaces, source_slns, vec, proj_norms);
227  target_vec->set_vector(vec);
228  free_with_check(vec);
229  }
230 
231  template<typename Scalar>
232  void OGProjection<Scalar>::project_global(std::vector<SpaceSharedPtr<Scalar> > spaces, std::vector<MeshFunctionSharedPtr<Scalar> > source_slns,
233  std::vector<MeshFunctionSharedPtr<Scalar> > target_slns, std::vector<NormType> proj_norms, bool delete_old_meshes)
234  {
235  int n = spaces.size();
236 
237  // Sanity checks.
238  if (n != source_slns.size())
239  throw Exceptions::LengthException(1, 2, n, source_slns.size());
240  if (n != target_slns.size())
241  throw Exceptions::LengthException(1, 2, n, target_slns.size());
242  if (!proj_norms.empty() && n != proj_norms.size())
243  throw Exceptions::LengthException(1, 5, n, proj_norms.size());
244 
245  for (int i = 0; i < n; i++)
246  {
247  if (proj_norms.empty())
248  project_global(spaces[i], source_slns[i], target_slns[i], HERMES_UNSET_NORM);
249  else
250  project_global(spaces[i], source_slns[i], target_slns[i], proj_norms[i]);
251  }
252  }
253 
254  template class HERMES_API OGProjection < double > ;
255  template class HERMES_API OGProjection < std::complex<double> > ;
256  }
257 }
Definition: adapt.h:24
Scalar * get_sln_vector()
Get sln vector.
Used to pass the instances of Space around.
Definition: space.h:34
virtual void set_verbose_output(bool to_set)
See Hermes::Mixins::Loggable.
int get_num_dofs() const
Returns the number of basis functions contained in the space.
Definition: space.cpp:286
Represents the weak formulation of a PDE problem.
Definition: global.h:86
static void project_internal(SpaceSharedPtr< Scalar > space, WeakFormSharedPtr< Scalar > proj_wf, Scalar *target_vec)
virtual void solve(Scalar *coeff_vec)
Used to pass the instances of WeakForm around.
Definition: weakform.h:55
Abstract, base class for matrix Volumetric form - i.e. MatrixForm, where the integration is with resp...
Definition: weakform.h:45
Represents the solution of a PDE.
Definition: api2d.h:35
static void project_global(SpaceSharedPtr< Scalar > space, MatrixFormVol< Scalar > *custom_projection_jacobian, VectorFormVol< Scalar > *custom_projection_residual, Scalar *target_vec)
This method allows to specify your own OG-projection form.
Abstract, base class for vector Volumetric form - i.e. VectorForm, where the integration is with resp...
Definition: weakform.h:46