Hermes2D  2.0
localprojection.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/localprojection.h"
17 #include "space.h"
18 #include "discrete_problem.h"
19 
20 namespace Hermes
21 {
22  namespace Hermes2D
23  {
24  template<typename Scalar>
25  int LocalProjection<Scalar>::ndof = 0;
26 
27  template<typename Scalar>
28  LocalProjection<Scalar>::LocalProjection()
29  {
30  }
31 
32  template<typename Scalar>
33  void LocalProjection<Scalar>::project_local(const Space<Scalar>* space, MeshFunction<Scalar>* meshfn,
34  Scalar* target_vec, ProjNormType proj_norm)
35  {
36  if(proj_norm == HERMES_UNSET_NORM)
37  {
38  SpaceType space_type = space->get_type();
39  switch (space_type)
40  {
41  case HERMES_H1_SPACE: proj_norm = HERMES_H1_NORM; break;
42  case HERMES_HCURL_SPACE: proj_norm = HERMES_HCURL_NORM; break;
43  case HERMES_HDIV_SPACE: proj_norm = HERMES_HDIV_NORM; break;
44  case HERMES_L2_SPACE: proj_norm = HERMES_L2_NORM; break;
45  default: throw Hermes::Exceptions::Exception("Unknown space type in OGProjection<Scalar>::project_global().");
46  }
47  }
48 
49  // Get dimension of the space.
50  int ndof = space->get_num_dofs();
51 
52  // Erase the target vector.
53  memset(target_vec, 0, ndof*sizeof(Scalar));
54 
55  // Dump into the first part of target_vec the values of active vertex dofs, then add values
56  // of active edge dofs, and finally also values of active bubble dofs.
57  // Start with active vertex dofs.
58  Mesh* mesh = space->get_mesh();
59  Element* e;
60  // Go through all active elements in mesh to collect active vertex DOF.
61  for_all_active_elements(e, mesh)
62  {
63  int order = space->get_element_order(e->id);
64  if(order > 0)
65  {
66  for (unsigned int j = 0; j < e->get_nvert(); j++)
67  {
68  // FIXME - the same vertex is visited several times since it
69  // belongs to multiple elements!
70  Node* vn = e->vn[j];
71  double x = e->vn[j]->x;
72  double y = e->vn[j]->y;
73  //this->info("Probing vertex %g %g\n", x, y);
74  typename Space<Scalar>::NodeData* nd = space->ndata + vn->id;
75  if(!vn->is_constrained_vertex() && nd->dof >= 0)
76  {
77  int dof_num = nd->dof;
78  // FIXME: If this is a Solution, the it would be MUCH faster to just
79  // retrieve the value from the coefficient vector stored in the Solution.
80 
81  // FIXME: Retrieving the value through get_pt_value() is slow and this
82  // should be only done if we are dealing with MeshFunction (not a Solution).
83  Scalar val = meshfn->get_pt_value(x, y)->val[0];
84  //printf("Found active vertex %g %g, val = %g, dof_num = %d\n", x, y, std::abs(val), dof_num);
85  target_vec[dof_num] = val;
86  }
87  }
88  }
89 
90  // TODO: Calculate coefficients of edge functions and copy into target_vec_space[i] as well
91 
92  // TODO: Calculate coefficients of bubble functions and copy into target_vec_space[i] as well.
93  }
94  }
95 
96  template<typename Scalar>
97  void LocalProjection<Scalar>::project_local(const Space<Scalar>* space,
98  Solution<Scalar>* source_sln, Solution<Scalar>* target_sln,
99  ProjNormType proj_norm)
100  {
101  int ndof = space->get_num_dofs();
102  Scalar* coeff_vec = new Scalar[ndof];
103  project_local(space, source_sln, coeff_vec, proj_norm);
104  Solution<Scalar>::vector_to_solution(coeff_vec, space, target_sln, proj_norm);
105  delete [] coeff_vec;
106  }
107 
108  template<typename Scalar>
109  void LocalProjection<Scalar>::project_local(Hermes::vector<const Space<Scalar>*> spaces,
110  Hermes::vector<MeshFunction<Scalar>*> meshfns, Scalar* target_vec,
111  Hermes::vector<ProjNormType> proj_norms)
112  {
113  int n = spaces.size();
114 
115  if(n != meshfns.size()) throw Exceptions::LengthException(1, 2, n, meshfns.size());
116  if(target_vec == NULL) throw Exceptions::NullException(3);
117  if(!proj_norms.empty() && n!=proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
118 
119  int start_index = 0;
120  for (int i = 0; i < n; i++)
121  {
122  if(proj_norms.empty())
123  project_local(spaces[i], meshfns[i], target_vec + start_index);
124  else
125  project_local(spaces[i], meshfns[i], target_vec + start_index, proj_norms[i]);
126  start_index += spaces[i]->get_num_dofs();
127  }
128  }
129 
130  template<typename Scalar>
131  void LocalProjection<Scalar>::project_local(Hermes::vector<const Space<Scalar>*> spaces,
132  Hermes::vector<Solution<Scalar>*> slns, Scalar* target_vec,
133  Hermes::vector<ProjNormType> proj_norms)
134  {
135  int n = spaces.size();
136 
137  // Sanity checks.
138  if(n != slns.size()) throw Exceptions::LengthException(1, 2, n, slns.size());
139  if(target_vec == NULL) throw Exceptions::NullException(3);
140  if(!proj_norms.empty() && n!=proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
141 
142  int start_index = 0;
143  for (int i = 0; i < n; i++)
144  {
145  if(proj_norms.empty())
146  project_local(spaces[i], slns[i], target_vec + start_index);
147  else
148  project_local(spaces[i], slns[i], target_vec + start_index, proj_norms[i]);
149  start_index += spaces[i]->get_num_dofs();
150  }
151  }
152 
153  template<typename Scalar>
154  void LocalProjection<Scalar>::project_local(Hermes::vector<const Space<Scalar>*> spaces, Hermes::vector<Solution<Scalar>*> source_slns,
155  Hermes::vector<Solution<Scalar>*> target_slns, Hermes::vector<ProjNormType> proj_norms, bool delete_old_meshes)
156  {
157  int n = spaces.size();
158 
159  // Sanity checks.
160  if(n != source_slns.size()) throw Exceptions::LengthException(1, 2, n, source_slns.size());
161  if(n != target_slns.size()) throw Exceptions::LengthException(1, 2, n, target_slns.size());
162  if(!proj_norms.empty() && n != proj_norms.size()) throw Exceptions::LengthException(1, 5, n, proj_norms.size());
163 
164  for (int i = 0; i < n; i++)
165  {
166  if(proj_norms.empty())
167  project_local(spaces[i], source_slns[i], target_slns[i]);
168  else
169  project_local(spaces[i], source_slns[i], target_slns[i], proj_norms[i]);
170  }
171  }
172 
173  template class HERMES_API LocalProjection<double>;
174  template class HERMES_API LocalProjection<std::complex<double> >;
175  }
176 }