Hermes2D  3.0
h1_proj_based_selector.cpp
1 #include "matrix.h"
2 #include "h1_proj_based_selector.h"
3 
4 namespace Hermes
5 {
6  namespace Hermes2D
7  {
8  namespace RefinementSelectors
9  {
10  template<typename Scalar>
11  H1ProjBasedSelector<Scalar>::H1ProjBasedSelector(CandList cand_list, int max_order, H1Shapeset* user_shapeset)
12  : ProjBasedSelector<Scalar>(cand_list, max_order, user_shapeset == nullptr ? new H1Shapeset() : user_shapeset, Range(1, 1), Range(2, H2DRS_MAX_ORDER)), user_shapeset(user_shapeset == nullptr ? false : true)
13  {
14  if (user_shapeset != nullptr)
15  {
16  this->warn("Warn: The user shapeset provided for the selector has to have a correct copy constructor implemented.");
17  this->warn("Warning: The functionality for cloning user shapeset is to be implemented yet.");
18  }
19  }
20 
21  template<typename Scalar>
23  {
24  if (!this->user_shapeset)
25  delete this->shapeset;
26  }
27 
28  template<typename Scalar>
29  void H1ProjBasedSelector<Scalar>::get_current_order_range(Element* element, int& min_order_, int& max_order_)
30  {
31  int max_element_order = (20 - element->iro_cache) / 2 - 1;
32  if (this->max_order == H2DRS_DEFAULT_ORDER)
33  max_order_ = max_element_order;
34  else
35  max_order_ = std::min(this->max_order, max_element_order);
36  min_order_ = 1;
37  }
38 
39  template<typename Scalar>
40  void H1ProjBasedSelector<Scalar>::precalc_shapes(const double3* gip_points, const int num_gip_points, const Trf* trfs, const int num_noni_trfs, const std::vector<typename OptimumSelector<Scalar>::ShapeInx>& shapes, const int max_shape_inx, typename ProjBasedSelector<Scalar>::TrfShape& svals, ElementMode2D mode)
41  {
42  //for all transformations
43  bool done = false;
44  int inx_trf = 0;
45  while (!done && inx_trf < H2D_TRF_NUM)
46  {
47  //prepare data for processing
48  const Trf& trf = trfs[inx_trf];
49  std::vector<typename ProjBasedSelector<Scalar>::TrfShapeExp>& trf_svals = svals[inx_trf];
50 
51  //allocate
52  trf_svals.resize(max_shape_inx + 1);
53 
54  //for all shapes
55  const int num_shapes = (int)shapes.size();
56  for (int i = 0; i < num_shapes; i++)
57  {
58  int inx_shape = shapes[i].inx;
59  typename ProjBasedSelector<Scalar>::TrfShapeExp& shape_exp = trf_svals[inx_shape];
60 
61  //allocate
62  shape_exp.allocate(H2D_H1FE_NUM, num_gip_points);
63 
64  //for all GIP points
65  for (int k = 0; k < num_gip_points; k++)
66  {
67  //transform coordinates
68  double ref_x = gip_points[k][H2D_GIP2D_X] * trf.m[0] + trf.t[0];
69  double ref_y = gip_points[k][H2D_GIP2D_Y] * trf.m[1] + trf.t[1];
70 
71  //for all expansions: retrieve values
72  shape_exp[H2D_H1FE_VALUE][k] = this->shapeset->get_fn_value(inx_shape, ref_x, ref_y, 0, mode);
73  shape_exp[H2D_H1FE_DX][k] = this->shapeset->get_dx_value(inx_shape, ref_x, ref_y, 0, mode);
74  shape_exp[H2D_H1FE_DY][k] = this->shapeset->get_dy_value(inx_shape, ref_x, ref_y, 0, mode);
75  }
76  }
77 
78  //move to the next transformation
79  if (inx_trf == H2D_TRF_IDENTITY)
80  done = true;
81  else
82  {
83  inx_trf++;
84  if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
85  inx_trf = H2D_TRF_IDENTITY;
86  }
87  }
88  if (!done)
89  //identity transformation has to be the last transformation
90  throw Exceptions::Exception("All transformation processed but identity transformation not found.");
91  }
92 
93  template<typename Scalar>
94  void H1ProjBasedSelector<Scalar>::precalc_ortho_shapes(const double3* gip_points, const int num_gip_points, const Trf* trfs, const int num_noni_trfs, const std::vector<typename OptimumSelector<Scalar>::ShapeInx>& shapes, const int max_shape_inx, typename ProjBasedSelector<Scalar>::TrfShape& svals, ElementMode2D mode)
95  {
96  //calculate values
97  precalc_shapes(gip_points, num_gip_points, trfs, num_noni_trfs, shapes, max_shape_inx, svals, mode);
98 
99  //calculate orthonormal basis
100  const int num_shapes = (int)shapes.size();
101  for (int i = 0; i < num_shapes; i++)
102  {
103  const int inx_shape_i = shapes[i].inx;
104 
105  //orthogonalize
106  for (int j = 0; j < i; j++)
107  {
108  const int inx_shape_j = shapes[j].inx;
109 
110  //calculate product of non-transformed functions
111  double product = 0.0;
112  for (int k = 0; k < num_gip_points; k++)
113  {
114  double sum = 0.0;
115  sum += svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_VALUE][k] * svals[H2D_TRF_IDENTITY][inx_shape_j][H2D_H1FE_VALUE][k];
116  sum += svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_DX][k] * svals[H2D_TRF_IDENTITY][inx_shape_j][H2D_H1FE_DX][k];
117  sum += svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_DY][k] * svals[H2D_TRF_IDENTITY][inx_shape_j][H2D_H1FE_DY][k];
118  product += gip_points[k][H2D_GIP2D_W] * sum;
119  }
120 
121  //for all transformations
122  int inx_trf = 0;
123  bool done = false;
124  while (!done && inx_trf < H2D_TRF_NUM)
125  {
126  //for all integration points
127  for (int k = 0; k < num_gip_points; k++)
128  {
129  svals[inx_trf][inx_shape_i][H2D_H1FE_VALUE][k] -= product * svals[inx_trf][inx_shape_j][H2D_H1FE_VALUE][k];
130  svals[inx_trf][inx_shape_i][H2D_H1FE_DX][k] -= product * svals[inx_trf][inx_shape_j][H2D_H1FE_DX][k];
131  svals[inx_trf][inx_shape_i][H2D_H1FE_DY][k] -= product * svals[inx_trf][inx_shape_j][H2D_H1FE_DY][k];
132  }
133 
134  //move to the next transformation
135  if (inx_trf == H2D_TRF_IDENTITY)
136  done = true;
137  else
138  {
139  inx_trf++;
140  if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
141  inx_trf = H2D_TRF_IDENTITY;
142  }
143  }
144  if (!done)
145  //identity transformation has to be the last transformation
146  throw Exceptions::Exception("All transformation processed but identity transformation not found.");
147  }
148 
149  //normalize
150  //calculate norm
151  double norm_squared = 0.0;
152  for (int k = 0; k < num_gip_points; k++)
153  {
154  double sum = 0.0;
155  sum += sqr(svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_VALUE][k]);
156  sum += sqr(svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_DX][k]);
157  sum += sqr(svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_H1FE_DY][k]);
158  norm_squared += gip_points[k][H2D_GIP2D_W] * sum;
159  }
160  double norm = sqrt(norm_squared);
161  if (!finite(1 / norm))
162  throw Exceptions::Exception("Norm (%g) is almost zero.", norm);
163 
164  //for all transformations: normalize
165  int inx_trf = 0;
166  bool done = false;
167  while (!done && inx_trf < H2D_TRF_NUM)
168  {
169  //for all integration points
170  for (int k = 0; k < num_gip_points; k++)
171  {
172  svals[inx_trf][inx_shape_i][H2D_H1FE_VALUE][k] /= norm;
173  svals[inx_trf][inx_shape_i][H2D_H1FE_DX][k] /= norm;
174  svals[inx_trf][inx_shape_i][H2D_H1FE_DY][k] /= norm;
175  }
176 
177  //move to the next transformation
178  if (inx_trf == H2D_TRF_IDENTITY)
179  done = true;
180  else
181  {
182  inx_trf++;
183  if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
184  inx_trf = H2D_TRF_IDENTITY;
185  }
186  }
187  if (!done)
188  //identity transformation has to be the last transformation
189  throw Exceptions::Exception("All transformation processed but identity transformation not found.");
190  }
191  }
192 
193  template<typename Scalar>
194  void H1ProjBasedSelector<Scalar>::precalc_ref_solution(int inx_son, MeshFunction<Scalar>* rsln, Element* element, int intr_gip_order, Scalar* rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
195  {
196  const int num_gip = rsln->get_quad_2d()->get_num_points(intr_gip_order, rsln->get_active_element()->get_mode());
197 
198  rval[inx_son][H2D_H1FE_VALUE] = malloc_with_check<Scalar>(num_gip);
199  rval[inx_son][H2D_H1FE_DX] = malloc_with_check<Scalar>(num_gip);
200  rval[inx_son][H2D_H1FE_DY] = malloc_with_check<Scalar>(num_gip);
201 
202  memcpy(rval[inx_son][H2D_H1FE_VALUE], rsln->get_fn_values(0), num_gip * sizeof(Scalar));
203  memcpy(rval[inx_son][H2D_H1FE_DX], rsln->get_dx_values(0), num_gip * sizeof(Scalar));
204  memcpy(rval[inx_son][H2D_H1FE_DY], rsln->get_dy_values(0), num_gip * sizeof(Scalar));
205  }
206 
207  template<typename Scalar>
208  void H1ProjBasedSelector<Scalar>::free_ref_solution_data(int inx_son, Scalar* rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
209  {
210  free_with_check(rval[inx_son][H2D_H1FE_VALUE]);
211  free_with_check(rval[inx_son][H2D_H1FE_DX]);
212  free_with_check(rval[inx_son][H2D_H1FE_DY]);
213  }
214 
215  template<typename Scalar>
216  double** H1ProjBasedSelector<Scalar>::build_projection_matrix(double3* gip_points, int num_gip_points,
217  const int* shape_inx, const int num_shapes, ElementMode2D mode)
218  {
219  //allocate
220  double** matrix = new_matrix<double>(num_shapes, num_shapes);
221 
222  //calculate products
223  int inx_row = 0;
224  for (int i = 0; i < num_shapes; i++, inx_row += num_shapes)
225  {
226  double* matrix_row = matrix[i];
227  int shape0_inx = shape_inx[i];
228  for (int k = 0; k < num_shapes; k++)
229  {
230  int shape1_inx = shape_inx[k];
231 
232  double value = 0.0;
233  for (int j = 0; j < num_gip_points; j++)
234  {
235  double gip_x = gip_points[j][H2D_GIP2D_X], gip_y = gip_points[j][H2D_GIP2D_Y];
236  double value0 = this->shapeset->get_value(H2D_FEI_VALUE, shape0_inx, gip_x, gip_y, 0, mode);
237  double value1 = this->shapeset->get_value(H2D_FEI_VALUE, shape1_inx, gip_x, gip_y, 0, mode);
238  double dx0 = this->shapeset->get_value(H2D_FEI_DX, shape0_inx, gip_x, gip_y, 0, mode);
239  double dx1 = this->shapeset->get_value(H2D_FEI_DX, shape1_inx, gip_x, gip_y, 0, mode);
240  double dy0 = this->shapeset->get_value(H2D_FEI_DY, shape0_inx, gip_x, gip_y, 0, mode);
241  double dy1 = this->shapeset->get_value(H2D_FEI_DY, shape1_inx, gip_x, gip_y, 0, mode);
242 
243  value += gip_points[j][H2D_GIP2D_W] * (value0*value1 + dx0*dx1 + dy0*dy1);
244  }
245  matrix_row[k] = value;
246  }
247  }
248 
249  return matrix;
250  }
251 
252  template<typename Scalar>
253  Scalar H1ProjBasedSelector<Scalar>::evaluate_rhs_subdomain(Element* sub_elem, const typename ProjBasedSelector<Scalar>::ElemGIP& sub_gip, int son, const typename ProjBasedSelector<Scalar>::ElemSubTrf& sub_trf, const typename ProjBasedSelector<Scalar>::ElemSubShapeFunc& sub_shape, Scalar* rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
254  {
255  Scalar total_value = 0;
256  for (int gip_inx = 0; gip_inx < sub_gip.num_gip_points; gip_inx++)
257  {
258  double3 &gip_pt = sub_gip.gip_points[gip_inx];
259 
260  //get value of a shape function
261  double shape_value[H2D_H1FE_NUM] = { 0, 0, 0 };
262  shape_value[H2D_H1FE_VALUE] = sub_shape.svals[H2D_H1FE_VALUE][gip_inx];
263  shape_value[H2D_H1FE_DX] = sub_shape.svals[H2D_H1FE_DX][gip_inx];
264  shape_value[H2D_H1FE_DY] = sub_shape.svals[H2D_H1FE_DY][gip_inx];
265 
266  //get value of ref. solution
267  Scalar ref_value[H2D_H1FE_NUM];
268  ref_value[H2D_H1FE_VALUE] = rval[son][H2D_H1FE_VALUE][gip_inx];
269  ref_value[H2D_H1FE_DX] = sub_trf.coef_mx * rval[son][H2D_H1FE_DX][gip_inx];
270  ref_value[H2D_H1FE_DY] = sub_trf.coef_my * rval[son][H2D_H1FE_DY][gip_inx];
271 
272  //evaluate a right-hand value
273  Scalar value = (shape_value[H2D_H1FE_VALUE] * ref_value[H2D_H1FE_VALUE])
274  + (shape_value[H2D_H1FE_DX] * ref_value[H2D_H1FE_DX])
275  + (shape_value[H2D_H1FE_DY] * ref_value[H2D_H1FE_DY]);
276 
277  total_value += gip_pt[H2D_GIP2D_W] * value;
278  }
279  return total_value;
280  }
281 
282  template<typename Scalar>
283  double H1ProjBasedSelector<Scalar>::evaluate_error_squared_subdomain(Element* sub_elem, const typename ProjBasedSelector<Scalar>::ElemGIP& sub_gip, int son, const typename ProjBasedSelector<Scalar>::ElemSubTrf& sub_trf, const typename ProjBasedSelector<Scalar>::ElemProj& elem_proj, Scalar* rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
284  {
285  double total_error_squared = 0;
286  for (int gip_inx = 0; gip_inx < sub_gip.num_gip_points; gip_inx++)
287  {
288  double3 &gip_pt = sub_gip.gip_points[gip_inx];
289 
290  //calculate value of projected solution
291  Scalar proj_value[H2D_H1FE_NUM] = { 0, 0, 0 };
292  for (int i = 0; i < elem_proj.num_shapes; i++)
293  {
294  int shape_inx = elem_proj.shape_inxs[i];
295  proj_value[H2D_H1FE_VALUE] += elem_proj.shape_coeffs[i] * elem_proj.svals[shape_inx][H2D_H1FE_VALUE][gip_inx];
296  proj_value[H2D_H1FE_DX] += elem_proj.shape_coeffs[i] * elem_proj.svals[shape_inx][H2D_H1FE_DX][gip_inx];
297  proj_value[H2D_H1FE_DY] += elem_proj.shape_coeffs[i] * elem_proj.svals[shape_inx][H2D_H1FE_DY][gip_inx];
298  }
299 
300  {
301  //get value of ref. solution
302  Scalar ref_value[3];
303  ref_value[H2D_H1FE_VALUE] = rval[son][H2D_H1FE_VALUE][gip_inx];
304  ref_value[H2D_H1FE_DX] = sub_trf.coef_mx * rval[son][H2D_H1FE_DX][gip_inx];
305  ref_value[H2D_H1FE_DY] = sub_trf.coef_my * rval[son][H2D_H1FE_DY][gip_inx];
306 
307  //evaluate error
308  double error_squared = sqr(proj_value[H2D_H1FE_VALUE] - ref_value[H2D_H1FE_VALUE])
309  + sqr(proj_value[H2D_H1FE_DX] - ref_value[H2D_H1FE_DX])
310  + sqr(proj_value[H2D_H1FE_DY] - ref_value[H2D_H1FE_DY]);
311 
312  total_error_squared += gip_pt[H2D_GIP2D_W] * error_squared;
313  }
314  }
315 
316  return total_error_squared;
317  }
318  template class HERMES_API H1ProjBasedSelector < double > ;
319  template class HERMES_API H1ProjBasedSelector < std::complex<double> > ;
320  }
321  }
322 }
double coef_my
A coefficient that scales df/dy for each subdomain. A coefficient represents effects of a transformat...
Element * get_active_element() const
Definition: transformable.h:48
Definition: adapt.h:24
virtual void precalc_ortho_shapes(const double3 *gip_points, const int num_gip_points, const Trf *trfs, const int num_noni_trfs, const std::vector< typename OptimumSelector< Scalar >::ShapeInx > &shapes, const int max_shape_inx, typename ProjBasedSelector< Scalar >::TrfShape &svals, ElementMode2D mode)
Calculates values of orthogonalized shape function at GIP for all transformations.
Stores one element of a mesh.
Definition: element.h:107
virtual Scalar evaluate_rhs_subdomain(Element *sub_elem, const typename ProjBasedSelector< Scalar >::ElemGIP &sub_gip, int son, const typename ProjBasedSelector< Scalar >::ElemSubTrf &sub_trf, const typename ProjBasedSelector< Scalar >::ElemSubShapeFunc &sub_shape, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
Evaluates a value of the right-hande side in a subdomain.
#define H2DRS_MAX_ORDER
A maximum order suported by refinement selectors.
Definition: global.h:104
Shape functions based on integrated Jacobi polynomials.
Represents a function defined on a mesh.
Definition: mesh_function.h:56
Quad2D * get_quad_2d() const
Returns the current quadrature points.
Definition: function.cpp:129
virtual void precalc_shapes(const double3 *gip_points, const int num_gip_points, const Trf *trfs, const int num_noni_trfs, const std::vector< typename OptimumSelector< Scalar >::ShapeInx > &shapes, const int max_shape_inx, typename ProjBasedSelector< Scalar >::TrfShape &svals, ElementMode2D mode)
Calculates values of shape function at GIP for all transformations.
Integration points in the reference domain of an element of a candidate.
A projection-based selector for H1 space.
Definition: function.h:35
double coef_mx
A coefficient that scales df/dx for each subdomain. A coefficient represents effects of a transformat...
virtual void free_ref_solution_data(int inx_son, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
Frees the data allocated in precalc_ref_solution.
virtual void precalc_ref_solution(int inx_son, MeshFunction< Scalar > *rsln, Element *element, int intr_gip_order, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
Returns an array of values of the reference solution at integration points.
Index of df/dx.
Definition: shapeset.h:27
virtual const Scalar * get_dx_values(int component=0) const
Returns the x partial derivative.
Definition: function.cpp:175
virtual const Scalar * get_dy_values(int component=0) const
Returns the y partial derivative.
Definition: function.cpp:182
Index of df/dy.
Definition: shapeset.h:28
double3 * gip_points
Integration points and weights. The first index is an index of an integration point, the second index is defined through the enum GIP2DIndices.
A general projection-based selector.
Definition: function.h:33
CandList
Predefined list of candidates.
Definition: candidates.h:46
Index of a function value f.
Definition: shapeset.h:26
unsigned short iro_cache
Increase in integration order, see RefMap::calc_inv_ref_order()
Definition: element.h:199
Y-axis coordinate.
Definition: quad.h:29
Scalar * shape_coeffs
Coefficients of shape indices of a projection.
double2 t
The 2x2 diagonal transformation matrix.
Definition: transformable.h:32
2D transformation.
Definition: transformable.h:29
std::vector< TrfShapeExp > & svals
A precalculated shape-function values. Empty is not defined.
TrfShapeExp & svals
Evaluate values of a shape function. If TrfShapeExp::empty(), no precalculated values are available...
A transformation from a reference domain of a subdomain to a reference domain of an element of a cand...
H1ProjBasedSelector(CandList cand_list=H2D_HP_ANISO, int max_order=H2DRS_DEFAULT_ORDER, H1Shapeset *user_shapeset=nullptr)
Constructor.
virtual void get_current_order_range(Element *element, int &min_order, int &max_order)
Sets OptimumSelector::current_max_order and OptimumSelector::current_min_order.
#define H2D_MAX_ELEMENT_SONS
Macros.
Definition: global.h:30
virtual const Scalar * get_fn_values(int component=0) const
Returns function values.
Definition: function.cpp:168
virtual double evaluate_error_squared_subdomain(Element *sub_elem, const typename ProjBasedSelector< Scalar >::ElemGIP &sub_gip, int son, const typename ProjBasedSelector< Scalar >::ElemSubTrf &sub_trf, const typename ProjBasedSelector< Scalar >::ElemProj &elem_proj, Scalar *rval[H2D_MAX_ELEMENT_SONS][MAX_NUMBER_FUNCTION_VALUES_FOR_SELECTORS])
Evaluates an squared error of a projection of an element of a candidate onto subdomains.
#define H2DRS_DEFAULT_ORDER
A default order. Used to indicate an unkonwn order or a maximum support order.
Definition: global.h:103
virtual double ** build_projection_matrix(double3 *gip_points, int num_gip_points, const int *shape_inx, const int num_shapes, ElementMode2D mode)
Builds projection matrix using a given set of shapes.
X-axis coordinate.
Definition: quad.h:27