Hermes2D  3.0
curved.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 "curved.h"
17 #include <algorithm>
18 #include "global.h"
19 #include "shapeset/shapeset_h1_all.h"
20 #include "shapeset/shapeset_common.h"
21 #include "shapeset/precalc.h"
22 #include "mesh.h"
23 #include "quad_all.h"
24 #include "matrix.h"
25 #include "algebra/dense_matrix_operations.h"
26 
28 
29 namespace Hermes
30 {
31  namespace Hermes2D
32  {
33  HERMES_API Quad1DStd g_quad_1d_std;
34  HERMES_API Quad2DStd g_quad_2d_std;
35 
36  H1ShapesetJacobi ref_map_shapeset;
37  PrecalcShapesetAssembling ref_map_pss_static(&ref_map_shapeset);
38 
39  CurvMapStatic::CurvMapStatic()
40  {
41  int order = ref_map_shapeset.get_max_order();
42 
43  this->edge_proj_matrix_size = order - 1;
44 
45  // Edges.
46  this->edge_proj_matrix = new_matrix<double>(edge_proj_matrix_size, edge_proj_matrix_size);
47  edge_p = malloc_with_check<double>(edge_proj_matrix_size);
48 
49  // Bubbles - triangles.
50  this->tri_bubble_np = ref_map_shapeset.get_num_bubbles(order, HERMES_MODE_TRIANGLE);
51  bubble_proj_matrix_tri = new_matrix<double>(tri_bubble_np, tri_bubble_np);
52  bubble_tri_p = malloc_with_check<double>(tri_bubble_np);
53 
54  // Bubbles - quads.
55  order = H2D_MAKE_QUAD_ORDER(order, order);
56  this->quad_bubble_np = ref_map_shapeset.get_num_bubbles(order, HERMES_MODE_QUAD);
57  bubble_proj_matrix_quad = new_matrix<double>(quad_bubble_np, quad_bubble_np);
58  bubble_quad_p = malloc_with_check<double>(quad_bubble_np);
59 
60  this->precalculate_cholesky_projection_matrices_bubble();
61  this->precalculate_cholesky_projection_matrix_edge();
62  }
63 
64  CurvMapStatic::~CurvMapStatic()
65  {
66  free_with_check(edge_proj_matrix, true);
67  free_with_check(bubble_proj_matrix_tri, true);
68  free_with_check(bubble_proj_matrix_quad, true);
69  free_with_check(edge_p);
70  free_with_check(bubble_tri_p);
71  free_with_check(bubble_quad_p);
72  }
73 
74  double** CurvMapStatic::calculate_bubble_projection_matrix(short* indices, ElementMode2D mode)
75  {
76  unsigned short nb;
77  double** mat;
78 
79  if (mode == HERMES_MODE_TRIANGLE)
80  {
81  mat = this->bubble_proj_matrix_tri;
82  nb = this->tri_bubble_np;
83  }
84  else
85  {
86  mat = this->bubble_proj_matrix_quad;
87  nb = this->quad_bubble_np;
88  }
89 
90  PrecalcShapesetAssembling ref_map_pss_static_temp(&ref_map_shapeset);
91  ref_map_pss_static_temp.set_active_element(ref_map_pss_static.get_active_element());
92  for (unsigned short i = 0; i < nb; i++)
93  {
94  for (unsigned short j = i; j < nb; j++)
95  {
96  short ii = indices[i], ij = indices[j];
97  unsigned short o = ref_map_shapeset.get_order(ii, mode) + ref_map_shapeset.get_order(ij, mode);
98  o = std::max(H2D_GET_V_ORDER(o), H2D_GET_H_ORDER(o));
99 
100  ref_map_pss_static.set_active_shape(ii);
101  ref_map_pss_static.set_quad_order(o, H2D_FN_VAL);
102  const double* fni = ref_map_pss_static.get_fn_values();
103 
104  ref_map_pss_static_temp.set_active_shape(ij);
105  ref_map_pss_static_temp.set_quad_order(o, H2D_FN_VAL);
106  const double* fnj = ref_map_pss_static_temp.get_fn_values();
107 
108  double3* pt = g_quad_2d_std.get_points(o, mode);
109  double val = 0.0;
110  for (unsigned short k = 0; k < g_quad_2d_std.get_num_points(o, mode); k++)
111  val += pt[k][2] * (fni[k] * fnj[k]);
112 
113  mat[i][j] = mat[j][i] = val;
114  }
115  }
116 
117  return mat;
118  }
119 
120  void CurvMapStatic::precalculate_cholesky_projection_matrices_bubble()
121  {
122  // *** triangles ***
123  // calculate projection matrix of maximum order
124  {
125  Element e;
126  e.nvert = 3;
127  e.cm = nullptr;
128  e.id = -1;
129  ref_map_pss_static.set_active_element(&e);
130  short* indices = ref_map_shapeset.get_bubble_indices(ref_map_shapeset.get_max_order(), HERMES_MODE_TRIANGLE);
131  curvMapStatic.bubble_proj_matrix_tri = calculate_bubble_projection_matrix(indices, HERMES_MODE_TRIANGLE);
132 
133  // cholesky factorization of the matrix
134  choldc(curvMapStatic.bubble_proj_matrix_tri, this->tri_bubble_np, curvMapStatic.bubble_tri_p);
135  }
136 
137  // *** quads ***
138  // calculate projection matrix of maximum order
139  {
140  Element e;
141  e.nvert = 4;
142  e.cm = nullptr;
143  e.id = -1;
144  ref_map_pss_static.set_active_element(&e);
145  short *indices = ref_map_shapeset.get_bubble_indices(H2D_MAKE_QUAD_ORDER(ref_map_shapeset.get_max_order(), ref_map_shapeset.get_max_order()), HERMES_MODE_QUAD);
146  curvMapStatic.bubble_proj_matrix_quad = calculate_bubble_projection_matrix(indices, HERMES_MODE_QUAD);
147 
148  // cholesky factorization of the matrix
149  choldc(curvMapStatic.bubble_proj_matrix_quad, this->quad_bubble_np, curvMapStatic.bubble_quad_p);
150  }
151  }
152 
153  void CurvMapStatic::precalculate_cholesky_projection_matrix_edge()
154  {
155  // calculate projection matrix of maximum order
156  for (int i = 0; i < this->edge_proj_matrix_size; i++)
157  {
158  for (int j = i; j < this->edge_proj_matrix_size; j++)
159  {
160  int o = i + j + 4;
161  double2* pt = g_quad_1d_std.get_points(o);
162  double val = 0.0;
163  for (int k = 0; k < g_quad_1d_std.get_num_points(o); k++)
164  {
165  double fi = 0;
166  double fj = 0;
167  double x = pt[k][0];
168  switch (i + 2)
169  {
170  case 0:
171  fi = l0(x);
172  break;
173  case 1:
174  fi = l1(x);
175  break;
176  case 2:
177  fi = l2(x);
178  break;
179  case 3:
180  fi = l3(x);
181  break;
182  case 4:
183  fi = l4(x);
184  break;
185  case 5:
186  fi = l5(x);
187  break;
188  case 6:
189  fi = l6(x);
190  break;
191  case 7:
192  fi = l7(x);
193  break;
194  case 8:
195  fi = l8(x);
196  break;
197  case 9:
198  fi = l9(x);
199  break;
200  case 10:
201  fi = l10(x);
202  break;
203  case 11:
204  fi = l11(x);
205  break;
206  }
207  switch (j + 2)
208  {
209  case 0:
210  fj = l0(x);
211  break;
212  case 1:
213  fj = l1(x);
214  break;
215  case 2:
216  fj = l2(x);
217  break;
218  case 3:
219  fj = l3(x);
220  break;
221  case 4:
222  fj = l4(x);
223  break;
224  case 5:
225  fj = l5(x);
226  break;
227  case 6:
228  fj = l6(x);
229  break;
230  case 7:
231  fj = l7(x);
232  break;
233  case 8:
234  fj = l8(x);
235  break;
236  case 9:
237  fj = l9(x);
238  break;
239  case 10:
240  fj = l10(x);
241  break;
242  case 11:
243  fj = l11(x);
244  break;
245  }
246  val += pt[k][1] * (fi * fj);
247  }
248  this->edge_proj_matrix[i][j] = this->edge_proj_matrix[j][i] = val;
249  }
250  }
251 
252  // Cholesky factorization of the matrix
253  choldc(this->edge_proj_matrix, this->edge_proj_matrix_size, this->edge_p);
254  }
255 
257 
258  Curve::Curve(CurvType type) : type(type)
259  {
260  }
261 
262  Curve::~Curve()
263  {
264  }
265 
266  Arc::Arc() : Curve(ArcType)
267  {
268  kv[0] = kv[1] = kv[2] = 0;
269  kv[3] = kv[4] = kv[5] = 1;
270  }
271 
272  Arc::Arc(double angle) : Curve(ArcType), angle(angle)
273  {
274  kv[0] = kv[1] = kv[2] = 0;
275  kv[3] = kv[4] = kv[5] = 1;
276  }
277 
278  Arc::Arc(const Arc* other) : Curve(ArcType)
279  {
280  this->angle = other->angle;
281 
282  memcpy(this->kv, other->kv, 6 * sizeof(double));
283  memcpy(this->pt, other->pt, 3 * sizeof(double3));
284  }
285 
286  Nurbs::Nurbs() : Curve(NurbsType)
287  {
288  pt = nullptr;
289  kv = nullptr;
290  };
291 
292  Nurbs::~Nurbs()
293  {
294  free_with_check(pt);
295  free_with_check(kv);
296  };
297 
298  Nurbs::Nurbs(const Nurbs* other) : Curve(NurbsType)
299  {
300  this->degree = other->degree;
301  this->nk = other->nk;
302  this->np = other->np;
303  this->kv = malloc_with_check<double>(nk);
304  this->pt = malloc_with_check<double3>(np);
305  }
306 
307  static double lambda_0(double x, double y)
308  {
309  return -0.5 * (x + y);
310  }
311  static double lambda_1(double x, double y)
312  {
313  return 0.5 * (x + 1);
314  }
315  static double lambda_2(double x, double y)
316  {
317  return 0.5 * (y + 1);
318  }
319 
320  CurvMap::CurvMap() : ref_map_pss(&ref_map_shapeset)
321  {
322  coeffs = nullptr;
323  ctm = nullptr;
324  memset(curves, 0, sizeof(Curve*)* H2D_MAX_NUMBER_EDGES);
325  this->parent = nullptr;
326  this->sub_idx = 0;
327  }
328 
329  CurvMap::CurvMap(const CurvMap* cm) : ref_map_pss(&ref_map_shapeset)
330  {
331  this->nc = cm->nc;
332  this->order = cm->order;
334  this->ctm = cm->ctm;
335  this->coeffs = malloc_with_check<double2>(nc, true);
336  memcpy(coeffs, cm->coeffs, sizeof(double2)* nc);
337 
338  this->toplevel = cm->toplevel;
339  if (this->toplevel)
340  {
341  for (int i = 0; i < 4; i++)
342  {
343  if (cm->curves[i])
344  {
345  if (cm->curves[i]->type == NurbsType)
346  this->curves[i] = new Nurbs((Nurbs*)cm->curves[i]);
347  else
348  this->curves[i] = new Arc((Arc*)cm->curves[i]);
349  }
350  else
351  this->curves[i] = nullptr;
352  }
353  this->parent = nullptr;
354  this->sub_idx = 0;
355  }
356  else
357  {
358  memset(curves, 0, sizeof(Curve*)* H2D_MAX_NUMBER_EDGES);
359  this->parent = cm->parent;
360  this->sub_idx = cm->sub_idx;
361  }
362  }
363 
364  CurvMap::~CurvMap()
365  {
366  this->free();
367  }
368 
369  void CurvMap::free()
370  {
371  free_with_check(this->coeffs, true);
372 
373  if (toplevel)
374  {
375  for (int i = 0; i < 4; i++)
376  if (curves[i])
377  {
378  delete curves[i];
379  curves[i] = nullptr;
380  }
381  }
382  }
383 
384  double CurvMap::nurbs_basis_fn(unsigned short i, unsigned short k, double t, double* knot)
385  {
386  if (k == 0)
387  {
388  return (t >= knot[i] && t <= knot[i + 1] && knot[i] < knot[i + 1]) ? 1.0 : 0.0;
389  }
390  else
391  {
392  double N1 = nurbs_basis_fn(i, k - 1, t, knot);
393  double N2 = nurbs_basis_fn(i + 1, k - 1, t, knot);
394 
395  if ((N1 > HermesEpsilon) || (N2 > HermesEpsilon))
396  {
397  double result = 0.0;
398  if ((N1 > HermesEpsilon) && knot[i + k] != knot[i])
399  result += ((t - knot[i]) / (knot[i + k] - knot[i])) * N1;
400  if ((N2 > HermesEpsilon) && knot[i + k + 1] != knot[i + 1])
401  result += ((knot[i + k + 1] - t) / (knot[i + k + 1] - knot[i + 1])) * N2;
402  return result;
403  }
404  else
405  return 0.0;
406  }
407  }
408 
409  void CurvMap::nurbs_edge(Element* e, Curve* curve, int edge, double t, double& x,
410  double& y)
411  {
412  // Nurbs curves are parametrized from 0 to 1.
413  t = (t + 1.0) / 2.0;
414 
415  // Start point A, end point B.
416  double2 A = { e->vn[edge]->x, e->vn[edge]->y };
417  double2 B = { e->vn[e->next_vert(edge)]->x, e->vn[e->next_vert(edge)]->y };
418 
419  // Vector pointing from A to B.
420  double2 v = { B[0] - A[0], B[1] - A[1] };
421 
422  // Straight line.
423  if (!curve)
424  {
425  x = A[0] + t * v[0];
426  y = A[1] + t * v[1];
427  }
428  else
429  {
430  double3* cp;
431  int degree, np;
432  double* kv;
433  if (curve->type == ArcType)
434  {
435  cp = ((Arc*)curve)->pt;
436  np = ((Arc*)curve)->np;
437  degree = ((Arc*)curve)->degree;
438  kv = ((Arc*)curve)->kv;
439  }
440  else
441  {
442  cp = ((Nurbs*)curve)->pt;
443  np = ((Nurbs*)curve)->np;
444  degree = ((Nurbs*)curve)->degree;
445  kv = ((Nurbs*)curve)->kv;
446  }
447 
448  // sum of basis fns and weights
449  double sum = 0.0;
450  x = y = 0.0;
451  for (int i = 0; i < np; i++)
452  {
453  double basis = nurbs_basis_fn(i, degree, t, kv);
454  sum += cp[i][2] * basis;
455  double x_i = cp[i][0];
456  double y_i = cp[i][1];
457  double w_i = cp[i][2];
458  x += w_i * basis * x_i;
459  y += w_i * basis * y_i;
460  }
461  x /= sum;
462  y /= sum;
463  }
464  }
465 
466  const double2 CurvMap::ref_vert[2][H2D_MAX_NUMBER_VERTICES] =
467  {
468  { { -1.0, -1.0 }, { 1.0, -1.0 }, { -1.0, 1.0 }, { 0.0, 0.0 } },
469  { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 } }
470  };
471 
472  void CurvMap::nurbs_edge_0(Element* e, Curve* curve, unsigned short edge, double t, double& x, double& y, double& n_x, double& n_y, double& t_x, double& t_y)
473  {
474  unsigned short va = edge;
475  unsigned short vb = e->next_vert(edge);
476  nurbs_edge(e, curve, edge, t, x, y);
477 
478  x -= 0.5 * ((1 - t) * (e->vn[va]->x) + (1 + t) * (e->vn[vb]->x));
479  y -= 0.5 * ((1 - t) * (e->vn[va]->y) + (1 + t) * (e->vn[vb]->y));
480 
481  double k = 4.0 / ((1 - t) * (1 + t));
482  x *= k;
483  y *= k;
484  }
485 
486  void CurvMap::calc_ref_map_tri(Element* e, Curve** curve, double xi_1, double xi_2, double& x, double& y)
487  {
488  double fx, fy;
489  x = y = 0.0;
490 
491  double l[3] = { lambda_0(xi_1, xi_2), lambda_1(xi_1, xi_2), lambda_2(xi_1, xi_2) };
492 
493  for (unsigned char j = 0; j < e->get_nvert(); j++)
494  {
495  int va = j;
496  int vb = e->next_vert(j);
497  double la = l[va];
498  double lb = l[vb];
499 
500  // vertex part
501  x += e->vn[j]->x * la;
502  y += e->vn[j]->y * la;
503 
504  if (!(((ref_vert[0][va][0] == xi_1) && (ref_vert[0][va][1] == xi_2)) || ((ref_vert[0][vb][0] == xi_1) && (ref_vert[0][vb][1] == xi_2))))
505  {
506  // edge part
507  double t = lb - la;
508  double n_x, n_y, t_x, t_y;
509  nurbs_edge_0(e, curve[j], j, t, fx, fy, n_x, n_y, t_x, t_y);
510  x += fx * lb * la;
511  y += fy * lb * la;
512  }
513  }
514  }
515 
516  void CurvMap::calc_ref_map_quad(Element* e, Curve** curve, double xi_1, double xi_2,
517  double& x, double& y)
518  {
520 
521  nurbs_edge(e, curve[0], 0, xi_1, ex[0], ey[0]);
522  nurbs_edge(e, curve[1], 1, xi_2, ex[1], ey[1]);
523  nurbs_edge(e, curve[2], 2, -xi_1, ex[2], ey[2]);
524  nurbs_edge(e, curve[3], 3, -xi_2, ex[3], ey[3]);
525 
526  x = (1 - xi_2) / 2.0 * ex[0] + (1 + xi_1) / 2.0 * ex[1] +
527  (1 + xi_2) / 2.0 * ex[2] + (1 - xi_1) / 2.0 * ex[3] -
528  (1 - xi_1)*(1 - xi_2) / 4.0 * e->vn[0]->x - (1 + xi_1)*(1 - xi_2) / 4.0 * e->vn[1]->x -
529  (1 + xi_1)*(1 + xi_2) / 4.0 * e->vn[2]->x - (1 - xi_1)*(1 + xi_2) / 4.0 * e->vn[3]->x;
530 
531  y = (1 - xi_2) / 2.0 * ey[0] + (1 + xi_1) / 2.0 * ey[1] +
532  (1 + xi_2) / 2.0 * ey[2] + (1 - xi_1) / 2.0 * ey[3] -
533  (1 - xi_1)*(1 - xi_2) / 4.0 * e->vn[0]->y - (1 + xi_1)*(1 - xi_2) / 4.0 * e->vn[1]->y -
534  (1 + xi_1)*(1 + xi_2) / 4.0 * e->vn[2]->y - (1 - xi_1)*(1 + xi_2) / 4.0 * e->vn[3]->y;
535  }
536 
537  void CurvMap::calc_ref_map(Element* e, Curve** curve, double xi_1, double xi_2, double2& f)
538  {
539  if (e->get_mode() == HERMES_MODE_QUAD)
540  calc_ref_map_quad(e, curve, xi_1, xi_2, f[0], f[1]);
541  else
542  calc_ref_map_tri(e, curve, xi_1, xi_2, f[0], f[1]);
543  }
544 
545  void CurvMap::edge_coord(Element* e, unsigned short edge, double t, double2& x) const
546  {
547  unsigned short mode = e->get_mode();
548  double2 a, b;
549  a[0] = ctm->m[0] * ref_vert[mode][edge][0] + ctm->t[0];
550  a[1] = ctm->m[1] * ref_vert[mode][edge][1] + ctm->t[1];
551  b[0] = ctm->m[0] * ref_vert[mode][e->next_vert(edge)][0] + ctm->t[0];
552  b[1] = ctm->m[1] * ref_vert[mode][e->next_vert(edge)][1] + ctm->t[1];
553 
554  for (int i = 0; i < 2; i++)
555  {
556  x[i] = a[i] + (t + 1.0) / 2.0 * (b[i] - a[i]);
557  }
558  }
559 
560  void CurvMap::calc_edge_projection(Element* e, unsigned short edge, Curve** nurbs, unsigned short order, double2* proj) const
561  {
562  unsigned short i, j, k;
563  unsigned short mo1 = g_quad_1d_std.get_max_order();
564  unsigned char np = g_quad_1d_std.get_num_points(mo1);
565  unsigned short ne = order - 1;
566  unsigned short mode = e->get_mode();
567 
568  assert(np <= 15 && ne <= 10);
569  double2 fn[15];
570  double rhside[2][10];
571  memset(rhside[0], 0, sizeof(double)* ne);
572  memset(rhside[1], 0, sizeof(double)* ne);
573 
574  double a_1, a_2, b_1, b_2;
575  a_1 = ctm->m[0] * ref_vert[mode][edge][0] + ctm->t[0];
576  a_2 = ctm->m[1] * ref_vert[mode][edge][1] + ctm->t[1];
577  b_1 = ctm->m[0] * ref_vert[mode][e->next_vert(edge)][0] + ctm->t[0];
578  b_2 = ctm->m[1] * ref_vert[mode][e->next_vert(edge)][1] + ctm->t[1];
579 
580  // values of nonpolynomial function in two vertices
581  double2 fa, fb;
582  calc_ref_map(e, nurbs, a_1, a_2, fa);
583  calc_ref_map(e, nurbs, b_1, b_2, fb);
584 
585  double2* pt = g_quad_1d_std.get_points(mo1);
586  // over all integration points
587  for (j = 0; j < np; j++)
588  {
589  double2 x;
590  double t = pt[j][0];
591  edge_coord(e, edge, t, x);
592  calc_ref_map(e, nurbs, x[0], x[1], fn[j]);
593 
594  for (k = 0; k < 2; k++)
595  fn[j][k] = fn[j][k] - (fa[k] + (t + 1) / 2.0 * (fb[k] - fa[k]));
596  }
597 
598  double2* result = proj + e->get_nvert() + edge * (order - 1);
599  for (k = 0; k < 2; k++)
600  {
601  for (i = 0; i < ne; i++)
602  {
603  for (j = 0; j < np; j++)
604  {
605  double t = pt[j][0];
606  double fi = 0;
607  switch (i + 2)
608  {
609  case 0:
610  fi = l0(t);
611  break;
612  case 1:
613  fi = l1(t);
614  break;
615  case 2:
616  fi = l2(t);
617  break;
618  case 3:
619  fi = l3(t);
620  break;
621  case 4:
622  fi = l4(t);
623  break;
624  case 5:
625  fi = l5(t);
626  break;
627  case 6:
628  fi = l6(t);
629  break;
630  case 7:
631  fi = l7(t);
632  break;
633  case 8:
634  fi = l8(t);
635  break;
636  case 9:
637  fi = l9(t);
638  break;
639  case 10:
640  fi = l10(t);
641  break;
642  case 11:
643  fi = l11(t);
644  break;
645  }
646  rhside[k][i] += pt[j][1] * (fi * fn[j][k]);
647  }
648  }
649  // solve
650  cholsl(curvMapStatic.edge_proj_matrix, ne, curvMapStatic.edge_p, rhside[k], rhside[k]);
651  for (i = 0; i < ne; i++)
652  result[i][k] = rhside[k][i];
653  }
654  }
655 
656  void CurvMap::old_projection(Element* e, unsigned short order, double2* proj, double* old[2])
657  {
658  unsigned short mo2 = g_quad_2d_std.get_max_order(e->get_mode());
659  unsigned char np = g_quad_2d_std.get_num_points(mo2, e->get_mode());
660  unsigned short nvert = e->get_nvert();
661 
662  for (unsigned int k = 0; k < nvert; k++) // loop over vertices
663  {
664  // vertex basis functions in all integration points
665  int index_v = ref_map_shapeset.get_vertex_index(k, e->get_mode());
666  ref_map_pss.set_active_shape(index_v);
667  ref_map_pss.set_quad_order(mo2, H2D_FN_VAL_0);
668  const double* vd = ref_map_pss.get_fn_values();
669 
670  for (int m = 0; m < 2; m++) // part 0 or 1
671  for (int j = 0; j < np; j++)
672  old[m][j] += proj[k][m] * vd[j];
673 
674  for (int ii = 0; ii < order - 1; ii++)
675  {
676  // edge basis functions in all integration points
677  int index_e = ref_map_shapeset.get_edge_index(k, 0, ii + 2, e->get_mode());
678  ref_map_pss.set_active_shape(index_e);
679  ref_map_pss.set_quad_order(mo2, H2D_FN_VAL_0);
680  const double* ed = ref_map_pss.get_fn_values();
681 
682  for (int m = 0; m < 2; m++) //part 0 or 1
683  for (int j = 0; j < np; j++)
684  old[m][j] += proj[nvert + k * (order - 1) + ii][m] * ed[j];
685  }
686  }
687  }
688 
689  void CurvMap::calc_bubble_projection(Element* e, Curve** curve, unsigned short order, double2* proj)
690  {
691  ref_map_pss.set_active_element(e);
692 
693  unsigned short i, j, k;
694  unsigned short mo2 = g_quad_2d_std.get_max_order(e->get_mode());
695  unsigned char np = g_quad_2d_std.get_num_points(mo2, e->get_mode());
696  unsigned short qo = e->is_quad() ? H2D_MAKE_QUAD_ORDER(order, order) : order;
697  unsigned short nb = ref_map_shapeset.get_num_bubbles(qo, e->get_mode());
698 
699  double2* fn = new double2[np];
700  memset(fn, 0, np * sizeof(double2));
701 
702  double* rhside[2];
703  double* old[2];
704  for (i = 0; i < 2; i++)
705  {
706  rhside[i] = new double[nb];
707  old[i] = new double[np];
708  memset(rhside[i], 0, sizeof(double)* nb);
709  memset(old[i], 0, sizeof(double)* np);
710  }
711 
712  // compute known part of projection (vertex and edge part)
713  old_projection(e, order, proj, old);
714 
715  // fn values of both components of nonpolynomial function
716  double3* pt = g_quad_2d_std.get_points(mo2, e->get_mode());
717  for (j = 0; j < np; j++) // over all integration points
718  {
719  double2 a;
720  a[0] = ctm->m[0] * pt[j][0] + ctm->t[0];
721  a[1] = ctm->m[1] * pt[j][1] + ctm->t[1];
722  calc_ref_map(e, curve, a[0], a[1], fn[j]);
723  }
724 
725  double2* result = proj + e->get_nvert() + e->get_nvert() * (order - 1);
726  for (k = 0; k < 2; k++)
727  {
728  for (i = 0; i < nb; i++) // loop over bubble basis functions
729  {
730  // bubble basis functions in all integration points
731  int index_i = ref_map_shapeset.get_bubble_indices(qo, e->get_mode())[i];
732  ref_map_pss.set_active_shape(index_i);
733  ref_map_pss.set_quad_order(mo2, H2D_FN_VAL_0);
734  const double *bfn = ref_map_pss.get_fn_values();
735 
736  for (j = 0; j < np; j++) // over all integration points
737  rhside[k][i] += pt[j][2] * (bfn[j] * (fn[j][k] - old[k][j]));
738  }
739 
740  // solve
741  if (e->get_mode() == HERMES_MODE_TRIANGLE)
742  cholsl(curvMapStatic.bubble_proj_matrix_tri, nb, curvMapStatic.bubble_tri_p, rhside[k], rhside[k]);
743  else
744  cholsl(curvMapStatic.bubble_proj_matrix_quad, nb, curvMapStatic.bubble_quad_p, rhside[k], rhside[k]);
745 
746  for (i = 0; i < nb; i++)
747  result[i][k] = rhside[k][i];
748  }
749 
750  for (i = 0; i < 2; i++)
751  {
752  delete[] rhside[i];
753  delete[] old[i];
754  }
755  delete[] fn;
756  }
757 
759  {
760  ref_map_pss.set_quad_2d(&g_quad_2d_std);
761  ref_map_pss.set_active_element(e);
762 
763  // allocate projection coefficients
764  unsigned char nvert = e->get_nvert();
765  unsigned char ne = order - 1;
766  unsigned short qo = e->is_quad() ? H2D_MAKE_QUAD_ORDER(order, order) : order;
767  unsigned short nb = ref_map_shapeset.get_num_bubbles(qo, e->get_mode());
768  this->nc = nvert + nvert*ne + nb;
769  this->coeffs = realloc_with_check<double2>(this->coeffs, nc);
770 
771  // WARNING: do not change the format of the array 'coeffs'. If it changes,
772  // RefMap::set_active_element() has to be changed too.
773  Curve** curves;
774  if (toplevel == false)
775  {
776  ref_map_pss.set_active_element(e);
777  ref_map_pss.set_transform(this->sub_idx);
778  curves = parent->cm->curves;
779  }
780  else
781  {
782  ref_map_pss.reset_transform();
783  curves = e->cm->curves;
784  }
785  ctm = ref_map_pss.get_ctm();
786 
787  // calculation of new_ projection coefficients
788  // vertex part
789  for (unsigned char i = 0; i < nvert; i++)
790  {
791  coeffs[i][0] = e->vn[i]->x;
792  coeffs[i][1] = e->vn[i]->y;
793  }
794 
795  if (!e->cm->toplevel)
796  e = e->cm->parent;
797 
798  // edge part
799  for (unsigned char edge = 0; edge < nvert; edge++)
800  calc_edge_projection(e, edge, curves, order, coeffs);
801 
802  //bubble part
803  calc_bubble_projection(e, curves, order, coeffs);
804  }
805 
806  void CurvMap::get_mid_edge_points(Element* e, double2* pt, unsigned short n)
807  {
808  Curve** curves = this->curves;
809  Transformable tran;
810  tran.set_active_element(e);
811 
812  if (toplevel == false)
813  {
814  tran.set_transform(this->sub_idx);
815  e = e->cm->parent;
816  curves = e->cm->curves;
817  }
818 
819  ctm = tran.get_ctm();
820  double xi_1, xi_2;
821  for (unsigned short i = 0; i < n; i++)
822  {
823  xi_1 = ctm->m[0] * pt[i][0] + ctm->t[0];
824  xi_2 = ctm->m[1] * pt[i][1] + ctm->t[1];
825  calc_ref_map(e, curves, xi_1, xi_2, pt[i]);
826  }
827  }
828 
829  CurvMap* CurvMap::create_son_curv_map(Element* e, int son)
830  {
831  // if the top three bits of part are nonzero, we would overflow
832  // -- make the element non-curvilinear
833  if (e->cm->sub_idx & 0xe000000000000000ULL)
834  return nullptr;
835 
836  // if the parent element is already almost straight-edged,
837  // the son will be even more straight-edged
838  if (e->iro_cache == 0)
839  return nullptr;
840 
841  CurvMap* cm = new CurvMap;
842  if (e->cm->toplevel == false)
843  {
844  cm->parent = e->cm->parent;
845  cm->sub_idx = (e->cm->sub_idx << 3) + son + 1;
846  }
847  else
848  {
849  cm->parent = e;
850  cm->sub_idx = (son + 1);
851  }
852 
853  cm->toplevel = false;
854  cm->order = 4;
855 
856  return cm;
857  }
858  }
859 }
virtual void set_active_element(Element *e)
double x
vertex node coordinates
Definition: element.h:63
PrecalcShapeset variant for fast assembling.
Definition: precalc.h:109
Definition: adapt.h:24
virtual void set_active_element(Element *e)
Sets the active element.
Definition: function.cpp:66
int id
element id number
Definition: element.h:112
Stores one element of a mesh.
Definition: element.h:107
const double * get_fn_values(int component=0) const
Returns function values.
Definition: precalc.cpp:203
double ** edge_proj_matrix
projection matrix for each edge is the same
Definition: curved.h:209
CurvMap * cm
curved mapping, nullptr if not curvilinear
Definition: element.h:188
unsigned short order
current polynomial degree of the refmap approximation
Definition: curved.h:122
Represents one NURBS curve.
Definition: curved.h:77
void set_quad_order(unsigned short order, unsigned short mask=H2D_FN_DEFAULT)
Definition: function.cpp:59
Common definitions for Hermes2D.
double ** bubble_proj_matrix_tri
projection matrix for triangle bubbles
Definition: curved.h:212
unsigned char nvert
number of vertices (3 or 4)
Definition: element.h:222
::xsd::cxx::tree::type type
C++ type corresponding to the anyType XML Schema built-in type.
double * bubble_tri_p
diagonal vector in cholesky factorization
Definition: curved.h:219
#define H2D_MAX_NUMBER_EDGES
A maximum number of edges of an element.
Definition: global.h:31
virtual void set_transform(uint64_t idx)
virtual void set_transform(uint64_t idx)
Definition: function.cpp:155
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
Definition: global.h:98
double2 t
The 2x2 diagonal transformation matrix.
Definition: transformable.h:32
#define H2D_MAX_NUMBER_VERTICES
A maximum number of vertices of an element.
Definition: global.h:32
double ** bubble_proj_matrix_quad
projection matrix for quad bubbles
Definition: curved.h:214
double * bubble_quad_p
diagonal vector in cholesky factorization
Definition: curved.h:222
const int H2D_FN_VAL
Both components are usually requested together...
Definition: function.h:53
void update_refmap_coeffs(Element *e)
Definition: curved.cpp:758
CurvMapStatic curvMapStatic
Global instance used inside Hermes which is also accessible to users.
Definition: curved.cpp:256
virtual void set_quad_2d(Quad2D *quad_2d)
Selects the quadrature points in which the function will be evaluated.
Definition: precalc.cpp:45
double * edge_p
diagonal vector in cholesky factorization
Definition: curved.h:217
virtual void reset_transform()
Empties the stack, loads identity transform.
Definition: function.cpp:148
Node * vn[H2D_MAX_NUMBER_VERTICES]
vertex node pointers
Definition: element.h:134
virtual void set_active_shape(int index)
Definition: precalc.cpp:50