19 #include "shapeset/shapeset_h1_all.h"
20 #include "shapeset/shapeset_common.h"
21 #include "shapeset/precalc.h"
25 #include "algebra/dense_matrix_operations.h"
33 HERMES_API Quad1DStd g_quad_1d_std;
34 HERMES_API Quad2DStd g_quad_2d_std;
36 H1ShapesetJacobi ref_map_shapeset;
37 PrecalcShapesetAssembling ref_map_pss_static(&ref_map_shapeset);
39 CurvMapStatic::CurvMapStatic()
41 int order = ref_map_shapeset.get_max_order();
43 this->edge_proj_matrix_size = order - 1;
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);
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);
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);
60 this->precalculate_cholesky_projection_matrices_bubble();
61 this->precalculate_cholesky_projection_matrix_edge();
64 CurvMapStatic::~CurvMapStatic()
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);
74 double** CurvMapStatic::calculate_bubble_projection_matrix(
short* indices,
ElementMode2D mode)
79 if (mode == HERMES_MODE_TRIANGLE)
81 mat = this->bubble_proj_matrix_tri;
82 nb = this->tri_bubble_np;
86 mat = this->bubble_proj_matrix_quad;
87 nb = this->quad_bubble_np;
92 for (
unsigned short i = 0; i < nb; i++)
94 for (
unsigned short j = i; j < nb; j++)
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);
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();
108 double3* pt = g_quad_2d_std.get_points(o, mode);
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]);
113 mat[i][j] = mat[j][i] = val;
120 void CurvMapStatic::precalculate_cholesky_projection_matrices_bubble()
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);
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);
153 void CurvMapStatic::precalculate_cholesky_projection_matrix_edge()
156 for (
int i = 0; i < this->edge_proj_matrix_size; i++)
158 for (
int j = i; j < this->edge_proj_matrix_size; j++)
161 double2* pt = g_quad_1d_std.get_points(o);
163 for (
int k = 0; k < g_quad_1d_std.get_num_points(o); k++)
246 val += pt[k][1] * (fi * fj);
248 this->edge_proj_matrix[i][j] = this->edge_proj_matrix[j][i] = val;
253 choldc(this->edge_proj_matrix, this->edge_proj_matrix_size, this->edge_p);
258 Curve::Curve(CurvType
type) : type(type)
266 Arc::Arc() : Curve(ArcType)
268 kv[0] = kv[1] = kv[2] = 0;
269 kv[3] = kv[4] = kv[5] = 1;
272 Arc::Arc(
double angle) : Curve(ArcType), angle(angle)
274 kv[0] = kv[1] = kv[2] = 0;
275 kv[3] = kv[4] = kv[5] = 1;
278 Arc::Arc(
const Arc* other) : Curve(ArcType)
280 this->angle = other->angle;
282 memcpy(this->kv, other->kv, 6 *
sizeof(
double));
283 memcpy(this->pt, other->pt, 3 *
sizeof(double3));
286 Nurbs::Nurbs() : Curve(NurbsType)
298 Nurbs::Nurbs(
const Nurbs* other) : Curve(NurbsType)
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);
307 static double lambda_0(
double x,
double y)
309 return -0.5 * (x + y);
311 static double lambda_1(
double x,
double y)
313 return 0.5 * (x + 1);
315 static double lambda_2(
double x,
double y)
317 return 0.5 * (y + 1);
320 CurvMap::CurvMap() : ref_map_pss(&ref_map_shapeset)
325 this->parent =
nullptr;
329 CurvMap::CurvMap(
const CurvMap* cm) : ref_map_pss(&ref_map_shapeset)
332 this->order = cm->
order;
335 this->coeffs = malloc_with_check<double2>(nc,
true);
336 memcpy(coeffs, cm->coeffs,
sizeof(double2)* nc);
341 for (
int i = 0; i < 4; i++)
345 if (cm->curves[i]->type == NurbsType)
346 this->curves[i] =
new Nurbs((
Nurbs*)cm->curves[i]);
348 this->curves[i] =
new Arc((
Arc*)cm->curves[i]);
351 this->curves[i] =
nullptr;
353 this->parent =
nullptr;
359 this->parent = cm->parent;
360 this->sub_idx = cm->sub_idx;
371 free_with_check(this->coeffs,
true);
375 for (
int i = 0; i < 4; i++)
384 double CurvMap::nurbs_basis_fn(
unsigned short i,
unsigned short k,
double t,
double* knot)
388 return (t >= knot[i] && t <= knot[i + 1] && knot[i] < knot[i + 1]) ? 1.0 : 0.0;
392 double N1 = nurbs_basis_fn(i, k - 1, t, knot);
393 double N2 = nurbs_basis_fn(i + 1, k - 1, t, knot);
395 if ((N1 > HermesEpsilon) || (N2 > HermesEpsilon))
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;
409 void CurvMap::nurbs_edge(Element* e, Curve* curve,
int edge,
double t,
double& x,
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 };
420 double2 v = { B[0] - A[0], B[1] - A[1] };
433 if (curve->type == ArcType)
435 cp = ((Arc*)curve)->pt;
436 np = ((Arc*)curve)->np;
437 degree = ((Arc*)curve)->degree;
438 kv = ((Arc*)curve)->kv;
442 cp = ((Nurbs*)curve)->pt;
443 np = ((Nurbs*)curve)->np;
444 degree = ((Nurbs*)curve)->degree;
445 kv = ((Nurbs*)curve)->kv;
451 for (
int i = 0; i < np; i++)
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;
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 } }
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)
474 unsigned short va = edge;
475 unsigned short vb = e->next_vert(edge);
476 nurbs_edge(e, curve, edge, t, x, y);
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));
481 double k = 4.0 / ((1 - t) * (1 + t));
486 void CurvMap::calc_ref_map_tri(Element* e, Curve** curve,
double xi_1,
double xi_2,
double& x,
double& y)
491 double l[3] = { lambda_0(xi_1, xi_2), lambda_1(xi_1, xi_2), lambda_2(xi_1, xi_2) };
493 for (
unsigned char j = 0; j < e->get_nvert(); j++)
496 int vb = e->next_vert(j);
501 x += e->vn[j]->x * la;
502 y += e->vn[j]->y * la;
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))))
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);
516 void CurvMap::calc_ref_map_quad(Element* e, Curve** curve,
double xi_1,
double xi_2,
517 double& x,
double& y)
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]);
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;
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;
537 void CurvMap::calc_ref_map(Element* e, Curve** curve,
double xi_1,
double xi_2, double2& f)
539 if (e->get_mode() == HERMES_MODE_QUAD)
540 calc_ref_map_quad(e, curve, xi_1, xi_2, f[0], f[1]);
542 calc_ref_map_tri(e, curve, xi_1, xi_2, f[0], f[1]);
545 void CurvMap::edge_coord(Element* e,
unsigned short edge,
double t, double2& x)
const
547 unsigned short mode = e->get_mode();
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];
554 for (
int i = 0; i < 2; i++)
556 x[i] = a[i] + (t + 1.0) / 2.0 * (b[i] - a[i]);
560 void CurvMap::calc_edge_projection(Element* e,
unsigned short edge, Curve** nurbs,
unsigned short order, double2* proj)
const
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();
568 assert(np <= 15 && ne <= 10);
570 double rhside[2][10];
571 memset(rhside[0], 0,
sizeof(
double)* ne);
572 memset(rhside[1], 0,
sizeof(
double)* ne);
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];
582 calc_ref_map(e, nurbs, a_1, a_2, fa);
583 calc_ref_map(e, nurbs, b_1, b_2, fb);
585 double2* pt = g_quad_1d_std.get_points(mo1);
587 for (j = 0; j < np; j++)
591 edge_coord(e, edge, t, x);
592 calc_ref_map(e, nurbs, x[0], x[1], fn[j]);
594 for (k = 0; k < 2; k++)
595 fn[j][k] = fn[j][k] - (fa[k] + (t + 1) / 2.0 * (fb[k] - fa[k]));
598 double2* result = proj + e->get_nvert() + edge * (order - 1);
599 for (k = 0; k < 2; k++)
601 for (i = 0; i < ne; i++)
603 for (j = 0; j < np; j++)
646 rhside[k][i] += pt[j][1] * (fi * fn[j][k]);
651 for (i = 0; i < ne; i++)
652 result[i][k] = rhside[k][i];
656 void CurvMap::old_projection(Element* e,
unsigned short order, double2* proj,
double* old[2])
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();
662 for (
unsigned int k = 0; k < nvert; k++)
665 int index_v = ref_map_shapeset.get_vertex_index(k, e->get_mode());
670 for (
int m = 0; m < 2; m++)
671 for (
int j = 0; j < np; j++)
672 old[m][j] += proj[k][m] * vd[j];
674 for (
int ii = 0; ii < order - 1; ii++)
677 int index_e = ref_map_shapeset.get_edge_index(k, 0, ii + 2, e->get_mode());
682 for (
int m = 0; m < 2; m++)
683 for (
int j = 0; j < np; j++)
684 old[m][j] += proj[nvert + k * (order - 1) + ii][m] * ed[j];
689 void CurvMap::calc_bubble_projection(Element* e, Curve** curve,
unsigned short order, double2* proj)
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());
699 double2* fn =
new double2[np];
700 memset(fn, 0, np *
sizeof(double2));
704 for (i = 0; i < 2; i++)
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);
713 old_projection(e, order, proj, old);
716 double3* pt = g_quad_2d_std.get_points(mo2, e->get_mode());
717 for (j = 0; j < np; j++)
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]);
725 double2* result = proj + e->get_nvert() + e->get_nvert() * (order - 1);
726 for (k = 0; k < 2; k++)
728 for (i = 0; i < nb; i++)
731 int index_i = ref_map_shapeset.get_bubble_indices(qo, e->get_mode())[i];
736 for (j = 0; j < np; j++)
737 rhside[k][i] += pt[j][2] * (bfn[j] * (fn[j][k] - old[k][j]));
741 if (e->get_mode() == HERMES_MODE_TRIANGLE)
746 for (i = 0; i < nb; i++)
747 result[i][k] = rhside[k][i];
750 for (i = 0; i < 2; i++)
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);
778 curves = parent->
cm->curves;
783 curves = e->
cm->curves;
789 for (
unsigned char i = 0; i < nvert; i++)
791 coeffs[i][0] = e->
vn[i]->
x;
792 coeffs[i][1] = e->
vn[i]->y;
799 for (
unsigned char edge = 0; edge < nvert; edge++)
800 calc_edge_projection(e, edge, curves, order, coeffs);
803 calc_bubble_projection(e, curves, order, coeffs);
806 void CurvMap::get_mid_edge_points(
Element* e, double2* pt,
unsigned short n)
808 Curve** curves = this->curves;
816 curves = e->
cm->curves;
821 for (
unsigned short i = 0; i < n; i++)
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]);
829 CurvMap* CurvMap::create_son_curv_map(Element* e,
int son)
833 if (e->cm->sub_idx & 0xe000000000000000ULL)
838 if (e->iro_cache == 0)
841 CurvMap* cm =
new CurvMap;
842 if (e->cm->toplevel ==
false)
844 cm->parent = e->cm->parent;
845 cm->sub_idx = (e->cm->sub_idx << 3) + son + 1;
850 cm->sub_idx = (son + 1);
853 cm->toplevel =
false;
double x
vertex node coordinates
PrecalcShapeset variant for fast assembling.
virtual void set_active_element(Element *e)
Sets the active element.
Stores one element of a mesh.
const double * get_fn_values(int component=0) const
Returns function values.
double ** edge_proj_matrix
projection matrix for each edge is the same
CurvMap * cm
curved mapping, nullptr if not curvilinear
unsigned short order
current polynomial degree of the refmap approximation
Represents one NURBS curve.
void set_quad_order(unsigned short order, unsigned short mask=H2D_FN_DEFAULT)
Common definitions for Hermes2D.
double ** bubble_proj_matrix_tri
projection matrix for triangle bubbles
unsigned char nvert
number of vertices (3 or 4)
::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
#define H2D_MAX_NUMBER_EDGES
A maximum number of edges of an element.
virtual void set_transform(uint64_t idx)
#define H2D_GET_H_ORDER(encoded_order)
Macros for combining quad horizontal and vertical encoded_orders.
double2 t
The 2x2 diagonal transformation matrix.
#define H2D_MAX_NUMBER_VERTICES
A maximum number of vertices of an element.
double ** bubble_proj_matrix_quad
projection matrix for quad bubbles
double * bubble_quad_p
diagonal vector in cholesky factorization
const int H2D_FN_VAL
Both components are usually requested together...
void update_refmap_coeffs(Element *e)
CurvMapStatic curvMapStatic
Global instance used inside Hermes which is also accessible to users.
virtual void set_quad_2d(Quad2D *quad_2d)
Selects the quadrature points in which the function will be evaluated.
double * edge_p
diagonal vector in cholesky factorization
virtual void reset_transform()
Empties the stack, loads identity transform.
Node * vn[H2D_MAX_NUMBER_VERTICES]
vertex node pointers
virtual void set_active_shape(int index)