Hermes2D  2.0
space_l2.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 "global.h"
17 #include "space_l2.h"
18 #include "matrix.h"
19 #include "quad_all.h"
20 #include "shapeset/shapeset_l2_all.h"
21 #include "boundary_conditions/essential_boundary_conditions.h"
22 
23 namespace Hermes
24 {
25  namespace Hermes2D
26  {
27  template<typename Scalar>
28  L2Space<Scalar>::L2Space() : Space<Scalar>()
29  {
30  }
31 
32  template<typename Scalar>
33  void L2Space<Scalar>::init(Shapeset* shapeset, int p_init)
34  {
35  if(shapeset == NULL)
36  {
37  this->shapeset = new L2Shapeset;
38  this->own_shapeset = true;
39  }
40  ldata = NULL;
41  lsize = 0;
42 
43  // set uniform poly order in elements
44  if(p_init < 0) throw Hermes::Exceptions::Exception("P_INIT must be >= 0 in an L2 space.");
45  else this->set_uniform_order_internal(p_init, HERMES_ANY_INT);
46 
47  // enumerate basis functions
48  this->assign_dofs();
49  }
50 
51  template<typename Scalar>
52  L2Space<Scalar>::L2Space(const Mesh* mesh, int p_init, Shapeset* shapeset)
53  : Space<Scalar>(mesh, shapeset, NULL)
54  {
55  init(shapeset, p_init);
56  }
57 
58  template<typename Scalar>
59  L2Space<Scalar>::~L2Space()
60  {
61  ::free(ldata);
62  if(this->own_shapeset)
63  delete this->shapeset;
64  }
65 
66  template<typename Scalar>
67  void L2Space<Scalar>::copy(const Space<Scalar>* space, Mesh* new_mesh)
68  {
69  Space<Scalar>::copy(space, new_mesh);
70 
71  ldata = NULL;
72  lsize = 0;
73  }
74 
75  template<typename Scalar>
77  {
78  if(shapeset->get_id() < 40 && shapeset->get_id() > 29)
79  {
80  this->shapeset = shapeset;
81  this->own_shapeset = false;
82  }
83  else
84  throw Hermes::Exceptions::Exception("Wrong shapeset type in L2Space<Scalar>::set_shapeset()");
85  }
86 
87  template<typename Scalar>
89  {
90  if(lsize < this->mesh->get_max_element_id())
91  {
92  if(!lsize) lsize = 1000;
93  while (lsize < this->mesh->get_max_element_id()) lsize = lsize * 3 / 2;
94  ldata = (L2Data*) realloc(ldata, sizeof(L2Data) * lsize);
95  }
97  }
98 
99  template<typename Scalar>
101  {
102  Element* e;
103  this->bubble_functions_count = 0;
104  for_all_active_elements(e, this->mesh)
105  {
106  typename Space<Scalar>::ElementData* ed = &this->edata[e->id];
107  ed->bdof = this->next_dof;
108  ed->n = this->shapeset->get_num_bubbles(ed->order, e->get_mode()); //FIXME: this function might return invalid value because retrieved bubble functions for non-uniform orders might be invalid for the given order.
109  this->next_dof += ed->n * this->stride;
110  this->bubble_functions_count += ed->n;
111  }
112  }
113 
114  template<typename Scalar>
115  void L2Space<Scalar>::get_vertex_assembly_list(Element* e, int iv, AsmList<Scalar>* al) const
116  {}
117 
118  template<typename Scalar>
119  void L2Space<Scalar>::get_element_assembly_list(Element* e, AsmList<Scalar>* al, unsigned int first_dof) const
120  {
121  if(e->id >= this->esize || this->edata[e->id].order < 0)
122  throw Hermes::Exceptions::Exception("Uninitialized element order (id = #%d).", e->id);
123  if(!this->is_up_to_date())
124  throw Hermes::Exceptions::Exception("The space is out of date. You need to update it with assign_dofs()"
125  " any time the mesh changes.");
126 
127  // add bubble functions to the assembly list
128  al->cnt = 0;
129  get_bubble_assembly_list(e, al);
130 
131  for(unsigned int i = 0; i < al->cnt; i++)
132  if(al->dof[i] >= 0)
133  al->dof[i] += first_dof;
134  }
135 
136  template<typename Scalar>
138  {
139  typename Space<Scalar>::ElementData* ed = &this->edata[e->id];
140  if(!ed->n) return;
141 
142  int* indices = this->shapeset->get_bubble_indices(ed->order, e->get_mode());
143  for (int i = 0, dof = ed->bdof; i < ed->n; i++, dof += this->stride)
144  {
145  //printf("triplet: %d, %d, %f\n", *indices, dof, 1.0);
146  al->add_triplet(*indices++, dof, 1.0);
147  }
148  }
149 
150  template<typename Scalar>
151  void L2Space<Scalar>::get_boundary_assembly_list_internal(Element* e, int surf_num, AsmList<Scalar>* al) const
152  {
153  this->get_bubble_assembly_list(e, al);
154  }
155 
156  template<typename Scalar>
157  Scalar* L2Space<Scalar>::get_bc_projection(SurfPos* surf_pos, int order, EssentialBoundaryCondition<Scalar> *bc)
158  {
159  throw Hermes::Exceptions::Exception("Method get_bc_projection() called from an L2Space.");
160  return NULL;
161  }
162 
163  template HERMES_API class L2Space<double>;
164  template HERMES_API class L2Space<std::complex<double> >;
165  }
166 }