19 #include "shapeset/shapeset_h1_all.h"
20 #include "shapeset/shapeset_common.h"
21 #include "shapeset/precalc.h"
26 using namespace Hermes::Algebra::DenseMatrixOperations;
31 double** CurvMap::edge_proj_matrix = NULL;
32 double** CurvMap::bubble_proj_matrix_tri = NULL;
33 double** CurvMap::bubble_proj_matrix_quad = NULL;
35 double* CurvMap::edge_p = NULL;
36 double* CurvMap::bubble_tri_p = NULL;
37 double* CurvMap::bubble_quad_p = NULL;
39 Quad1DStd CurvMap::quad1d;
40 Quad2DStd CurvMap::quad2d;
44 static double lambda_0(
double x,
double y)
46 return -0.5 * (x + y);
48 static double lambda_1(
double x,
double y)
52 static double lambda_2(
double x,
double y)
57 bool CurvMap::warning_issued =
false;
59 double CurvMap::nurbs_basis_fn(
int i,
int k,
double t,
double* knot)
63 return (t >= knot[i] && t <= knot[i + 1] && knot[i] < knot[i + 1]) ? 1.0 : 0.0;
67 double N1 = nurbs_basis_fn(i, k-1, t, knot);
68 double N2 = nurbs_basis_fn(i + 1, k-1, t, knot);
71 if(knot[i + k] != knot[i])
73 result += ((t - knot[i]) / (knot[i + k] - knot[i])) * N1;
75 if(knot[i + k+1] != knot[i + 1])
77 result += ((knot[i + k+1] - t) / (knot[i + k+1] - knot[i + 1])) * N2;
83 void CurvMap::nurbs_edge(Element* e, Nurbs* nurbs,
int edge,
double t,
double& x,
84 double& y,
double& n_x,
double& n_y,
double& t_x,
double& t_y)
91 A[0] = e->vn[edge]->x;
92 A[1] = e->vn[edge]->y;
93 B[0] = e->vn[e->next_vert(edge)]->x;
94 B[1] = e->vn[e->next_vert(edge)]->y;
100 double abs_v = sqrt(sqr(v[0]) + sqr(v[1]));
117 double3* cp = nurbs->pt;
121 for (
int i = 0; i < nurbs->np; i++)
123 double basis = nurbs_basis_fn(i, nurbs->degree, t, nurbs->kv);
124 sum += cp[i][2] * basis;
125 double x_i = cp[i][0];
126 double y_i = cp[i][1];
127 double w_i = cp[i][2];
128 x += w_i * basis * x_i;
129 y += w_i * basis * y_i;
142 M[0] = (A[0] + B[0]) / 2.;
143 M[1] = (A[1] + B[1]) / 2.;
150 w[0] = -v[1] / abs_v;
156 double alpha_rad = nurbs->angle * M_PI / 180.;
157 double L = 0.5 * abs_v / tan(0.5 * alpha_rad);
162 S[0] = M[0] + w[0] * L;
163 S[1] = M[1] + w[1] * L;
172 double R = sqrt(sqr(SA[0]) + sqr(SA[1]));
173 double R2 = sqrt(sqr(SB[0]) + sqr(SB[1]));
174 if(std::abs(R - R2) > 1e-6)
175 throw Hermes::Exceptions::Exception(
"Internal error in nurbs_edge() - bad radius R.");
178 double2 normal_A, normal_B;
179 normal_A[0] = SA[0] / R;
180 normal_A[1] = SA[1] / R;
181 normal_B[0] = SB[0] / R;
182 normal_B[1] = SB[1] / R;
189 SB_ref[0] = R * cos(alpha_rad);
190 SB_ref[1] = R * sin(alpha_rad);
192 double m_11, m_12, m_21, m_22;
197 double m_det = m_11 * m_22 - m_12 * m_21;
198 double inv_11, inv_12, inv_21, inv_22;
199 inv_11 = m_22 / m_det;
200 inv_12 = -m_12 / m_det;
201 inv_21 = -m_21 / m_det;
202 inv_22 = m_11 / m_det;
203 double s_11, s_12, s_21, s_22;
209 double r_11, r_12, r_21, r_22;
210 r_11 = s_11 * inv_11 + s_12 * inv_21;
211 r_12 = s_11 * inv_12 + s_12 * inv_22;
212 r_21 = s_21 * inv_11 + s_22 * inv_21;
213 r_22 = s_21 * inv_12 + s_22 * inv_22;
215 double n_x_ref = cos(alpha_rad * t);
216 double n_y_ref = sin(alpha_rad * t);
218 n_x = r_11 * n_x_ref + r_12 * n_y_ref;
219 n_y = r_21 * n_x_ref + r_22 * n_y_ref;
249 double3* cp = nurbs->pt;
253 for (
int i = 0; i < nurbs->np; i++)
255 double basis = nurbs_basis_fn(i, nurbs->degree, t, nurbs->kv);
256 sum += cp[i][2] * basis;
257 double x_i = cp[i][0];
258 double y_i = cp[i][1];
259 double w_i = cp[i][2];
260 x += w_i * basis * x_i;
261 y += w_i * basis * y_i;
269 printf(
"FIXME: IMPLEMENT CALCULATION OF n_x, n_y, t_x, t_y in nurbs_edge() !!!\n");
270 warning_issued =
true;
283 { { -1.0, -1.0 }, { 1.0, -1.0 }, { -1.0, 1.0 }, { 0.0, 0.0 } },
284 { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 } }
288 void CurvMap::nurbs_edge_0(Element* e, Nurbs* nurbs,
int edge,
double t,
double& x,
double& y,
double& n_x,
double& n_y,
double& t_x,
double& t_y)
291 int vb = e->next_vert(edge);
292 nurbs_edge(e, nurbs, edge, t, x, y, n_x, n_y, t_x, t_y);
294 x -= 0.5 * ((1-t) * (e->vn[va]->x) + (1 + t) * (e->vn[vb]->x));
295 y -= 0.5 * ((1-t) * (e->vn[va]->y) + (1 + t) * (e->vn[vb]->y));
297 double k = 4.0 / ((1-t) * (1 + t));
303 void CurvMap::calc_ref_map_tri(Element* e, Nurbs** nurbs,
double xi_1,
double xi_2,
double& x,
double& y)
308 for (
unsigned int j = 0; j < e->get_nvert(); j++)
311 int vb = e->next_vert(j);
317 l_a = lambda_0(xi_1, xi_2);
320 l_a = lambda_1(xi_1, xi_2);
323 l_a = lambda_2(xi_1, xi_2);
330 l_b = lambda_0(xi_1, xi_2);
333 l_b = lambda_1(xi_1, xi_2);
336 l_b = lambda_2(xi_1, xi_2);
341 x += e->vn[j]->x * l_a;
342 y += e->vn[j]->y * l_a;
344 if(!(((ref_vert[0][va][0] == xi_1) && (ref_vert[0][va][1] == xi_2)) ||
345 ((ref_vert[0][vb][0] == xi_1) && (ref_vert[0][vb][1] == xi_2))))
348 double t = l_b - l_a;
349 double n_x, n_y, t_x, t_y;
350 nurbs_edge_0(e, nurbs[j], j, t, fx, fy, n_x, n_y, t_x, t_y);
357 void CurvMap::calc_ref_map_quad(Element* e, Nurbs** nurbs,
double xi_1,
double xi_2,
358 double& x,
double& y)
362 double n_x, n_y, t_x, t_y;
363 nurbs_edge(e, nurbs[0], 0, xi_1, ex[0], ey[0], n_x, n_y, t_x, t_y);
364 nurbs_edge(e, nurbs[1], 1, xi_2, ex[1], ey[1], n_x, n_y, t_x, t_y);
365 nurbs_edge(e, nurbs[2], 2, -xi_1, ex[2], ey[2], n_x, n_y, t_x, t_y);
366 nurbs_edge(e, nurbs[3], 3, -xi_2, ex[3], ey[3], n_x, n_y, t_x, t_y);
368 x = (1-xi_2)/2.0 * ex[0] + (1 + xi_1)/2.0 * ex[1] +
369 (1 + xi_2)/2.0 * ex[2] + (1-xi_1)/2.0 * ex[3] -
370 (1-xi_1)*(1-xi_2)/4.0 * e->vn[0]->x - (1 + xi_1)*(1-xi_2)/4.0 * e->vn[1]->x -
371 (1 + xi_1)*(1 + xi_2)/4.0 * e->vn[2]->x - (1-xi_1)*(1 + xi_2)/4.0 * e->vn[3]->x;
373 y = (1-xi_2)/2.0 * ey[0] + (1 + xi_1)/2.0 * ey[1] +
374 (1 + xi_2)/2.0 * ey[2] + (1-xi_1)/2.0 * ey[3] -
375 (1-xi_1)*(1-xi_2)/4.0 * e->vn[0]->y - (1 + xi_1)*(1-xi_2)/4.0 * e->vn[1]->y -
376 (1 + xi_1)*(1 + xi_2)/4.0 * e->vn[2]->y - (1-xi_1)*(1 + xi_2)/4.0 * e->vn[3]->y;
379 void CurvMap::calc_ref_map(Element* e, Nurbs** nurbs,
double xi_1,
double xi_2, double2& f)
381 if(e->get_mode() == HERMES_MODE_QUAD)
382 calc_ref_map_quad(e, nurbs, xi_1, xi_2, f[0], f[1]);
384 calc_ref_map_tri(e, nurbs, xi_1, xi_2, f[0], f[1]);
390 void CurvMap::precalculate_cholesky_projection_matrix_edge(H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
392 int order = ref_map_shapeset->get_max_order();
395 if(!edge_proj_matrix)
396 edge_proj_matrix = new_matrix<double>(n, n);
399 for (
int i = 0; i < n; i++)
401 for (
int j = i; j < n; j++)
404 double2* pt = quad1d.get_points(o);
406 for (
int k = 0; k < quad1d.get_num_points(o); k++)
489 val += pt[k][1] * (fi * fj);
491 edge_proj_matrix[i][j] = edge_proj_matrix[j][i] = val;
497 edge_p =
new double[n];
498 choldc(edge_proj_matrix, n, edge_p);
502 double** CurvMap::calculate_bubble_projection_matrix(
int nb,
int* indices, H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss, ElementMode2D mode)
504 double** mat = new_matrix<double>(nb, nb);
506 for (
int i = 0; i < nb; i++)
508 for (
int j = i; j < nb; j++)
510 int ii = indices[i], ij = indices[j];
511 int o = ref_map_shapeset->get_order(ii, mode) + ref_map_shapeset->get_order(ij, mode);
514 ref_map_pss->set_active_shape(ii);
515 ref_map_pss->set_quad_order(o, H2D_FN_VAL);
516 double* fni = ref_map_pss->get_fn_values();
518 ref_map_pss->set_active_shape(ij);
519 ref_map_pss->set_quad_order(o, H2D_FN_VAL);
520 double* fnj = ref_map_pss->get_fn_values();
522 double3* pt = quad2d.get_points(o, mode);
524 for (
int k = 0; k < quad2d.get_num_points(o, mode); k++)
525 val += pt[k][2] * (fni[k] * fnj[k]);
527 mat[i][j] = mat[j][i] = val;
534 void CurvMap::precalculate_cholesky_projection_matrices_bubble(H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
537 int order = ref_map_shapeset->get_max_order();
540 if(ref_map_pss->get_active_element()->get_mode() == HERMES_MODE_TRIANGLE)
542 int nb = ref_map_shapeset->get_num_bubbles(order, HERMES_MODE_TRIANGLE);
543 int* indices = ref_map_shapeset->get_bubble_indices(order, HERMES_MODE_TRIANGLE);
544 bubble_proj_matrix_tri = calculate_bubble_projection_matrix(nb, indices, ref_map_shapeset, ref_map_pss, HERMES_MODE_TRIANGLE);
547 bubble_tri_p =
new double[nb];
548 choldc(bubble_proj_matrix_tri, nb, bubble_tri_p);
554 if(ref_map_pss->get_active_element()->get_mode() == HERMES_MODE_QUAD)
556 order = H2D_MAKE_QUAD_ORDER(order, order);
557 int nb = ref_map_shapeset->get_num_bubbles(order, HERMES_MODE_QUAD);
558 int *indices = ref_map_shapeset->get_bubble_indices(order, HERMES_MODE_QUAD);
560 bubble_proj_matrix_quad = calculate_bubble_projection_matrix(nb, indices, ref_map_shapeset, ref_map_pss, HERMES_MODE_QUAD);
563 bubble_quad_p =
new double[nb];
564 choldc(bubble_proj_matrix_quad, nb, bubble_quad_p);
571 void CurvMap::edge_coord(Element* e,
int edge,
double t, double2& x, double2& v)
573 int mode = e->get_mode();
575 a[0] = ctm.m[0] * ref_vert[mode][edge][0] + ctm.t[0];
576 a[1] = ctm.m[1] * ref_vert[mode][edge][1] + ctm.t[1];
577 b[0] = ctm.m[0] * ref_vert[mode][e->next_vert(edge)][0] + ctm.t[0];
578 b[1] = ctm.m[1] * ref_vert[mode][e->next_vert(edge)][1] + ctm.t[1];
580 for (
int i = 0; i < 2; i++)
583 x[i] = a[i] + (t + 1.0)/2.0 * v[i];
585 double lenght = sqrt(v[0] * v[0] + v[1] * v[1]);
586 v[0] /= lenght; v[1] /= lenght;
589 void CurvMap::calc_edge_projection(Element* e,
int edge, Nurbs** nurbs,
int order, double2* proj, H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
591 ref_map_pss->set_active_element(e);
594 int mo1 = quad1d.get_max_order();
595 int np = quad1d.get_num_points(mo1);
597 int mode = e->get_mode();
599 assert(np <= 15 && ne <= 10);
601 double rhside[2][10];
602 memset(fn, 0,
sizeof(double2) * np);
603 memset(rhside[0], 0,
sizeof(
double) * ne);
604 memset(rhside[1], 0,
sizeof(
double) * ne);
606 double a_1, a_2, b_1, b_2;
607 a_1 = ctm.m[0] * ref_vert[mode][edge][0] + ctm.t[0];
608 a_2 = ctm.m[1] * ref_vert[mode][edge][1] + ctm.t[1];
609 b_1 = ctm.m[0] * ref_vert[mode][e->next_vert(edge)][0] + ctm.t[0];
610 b_2 = ctm.m[1] * ref_vert[mode][e->next_vert(edge)][1] + ctm.t[1];
614 calc_ref_map(e, nurbs, a_1, a_2, fa);
615 calc_ref_map(e, nurbs, b_1, b_2, fb);
617 double2* pt = quad1d.get_points(mo1);
618 for (j = 0; j < np; j++)
622 edge_coord(e, edge, t, x, v);
623 calc_ref_map(e, nurbs, x[0], x[1], fn[j]);
625 for (k = 0; k < 2; k++)
626 fn[j][k] = fn[j][k] - (fa[k] + (t + 1)/2.0 * (fb[k] - fa[k]));
629 double2* result = proj + e->get_nvert() + edge * (order - 1);
630 for (k = 0; k < 2; k++)
632 for (i = 0; i < ne; i++)
634 for (j = 0; j < np; j++)
677 rhside[k][i] += pt[j][1] * (fi * fn[j][k]);
681 cholsl(edge_proj_matrix, ne, edge_p, rhside[k], rhside[k]);
682 for (i = 0; i < ne; i++)
683 result[i][k] = rhside[k][i];
689 void CurvMap::old_projection(Element* e,
int order, double2* proj,
double* old[2], H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
691 int mo2 = quad2d.get_max_order(e->get_mode());
692 int np = quad2d.get_num_points(mo2, e->get_mode());
694 for (
unsigned int k = 0; k < e->get_nvert(); k++)
698 int index_v = ref_map_shapeset->get_vertex_index(k, e->get_mode());
699 ref_map_pss->set_active_shape(index_v);
700 ref_map_pss->set_quad_order(mo2);
701 vd = ref_map_pss->get_fn_values();
703 for (
int m = 0; m < 2; m++)
704 for (
int j = 0; j < np; j++)
705 old[m][j] += proj[k][m] * vd[j];
707 for (
int ii = 0; ii < order - 1; ii++)
711 int index_e = ref_map_shapeset->get_edge_index(k, 0, ii + 2, e->get_mode());
712 ref_map_pss->set_active_shape(index_e);
713 ref_map_pss->set_quad_order(mo2);
714 ed = ref_map_pss->get_fn_values();
716 for (
int m = 0; m < 2; m++)
717 for (
int j = 0; j < np; j++)
718 old[m][j] += proj[e->get_nvert() + k * (order-1) + ii][m] * ed[j];
723 void CurvMap::calc_bubble_projection(Element* e, Nurbs** nurbs,
int order, double2* proj, H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
725 ref_map_pss->set_active_element(e);
728 int mo2 = quad2d.get_max_order(e->get_mode());
729 int np = quad2d.get_num_points(mo2, e->get_mode());
730 int qo = e->is_quad() ? H2D_MAKE_QUAD_ORDER(order, order) : order;
731 int nb = ref_map_shapeset->get_num_bubbles(qo, e->get_mode());
733 double2* fn =
new double2[np];
734 memset(fn, 0, np *
sizeof(double2));
738 for (i = 0; i < 2; i++)
740 rhside[i] =
new double[nb];
741 old[i] =
new double[np];
742 memset(rhside[i], 0,
sizeof(
double) * nb);
743 memset(old[i], 0,
sizeof(
double) * np);
747 old_projection(e, order, proj, old, ref_map_shapeset, ref_map_pss);
750 double3* pt = quad2d.get_points(mo2, e->get_mode());
751 for (j = 0; j < np; j++)
754 a[0] = ctm.m[0] * pt[j][0] + ctm.t[0];
755 a[1] = ctm.m[1] * pt[j][1] + ctm.t[1];
756 calc_ref_map(e, nurbs, a[0], a[1], fn[j]);
759 double2* result = proj + e->get_nvert() + e->get_nvert() * (order - 1);
760 for (k = 0; k < 2; k++)
762 for (i = 0; i < nb; i++)
766 int index_i = ref_map_shapeset->get_bubble_indices(qo, e->get_mode())[i];
767 ref_map_pss->set_active_shape(index_i);
768 ref_map_pss->set_quad_order(mo2);
769 bfn = ref_map_pss->get_fn_values();
771 for (j = 0; j < np; j++)
772 rhside[k][i] += pt[j][2] * (bfn[j] * (fn[j][k] - old[k][j]));
776 if(e->get_mode() == HERMES_MODE_TRIANGLE)
777 cholsl(bubble_proj_matrix_tri, nb, bubble_tri_p, rhside[k], rhside[k]);
779 cholsl(bubble_proj_matrix_quad, nb, bubble_quad_p, rhside[k], rhside[k]);
781 for (i = 0; i < nb; i++)
782 result[i][k] = rhside[k][i];
785 for (i = 0; i < 2; i++)
795 void CurvMap::ref_map_projection(Element* e, Nurbs** nurbs,
int order, double2* proj, H1ShapesetJacobi* ref_map_shapeset, PrecalcShapeset* ref_map_pss)
798 for (
unsigned int i = 0; i < e->get_nvert(); i++)
800 proj[i][0] = e->vn[i]->x;
801 proj[i][1] = e->vn[i]->y;
804 if(e->cm->toplevel ==
false)
808 for (
int edge = 0; edge < (int)e->get_nvert(); edge++)
809 calc_edge_projection(e, edge, nurbs, order, proj, ref_map_shapeset, ref_map_pss);
812 calc_bubble_projection(e, nurbs, order, proj, ref_map_shapeset, ref_map_pss);
815 void CurvMap::update_refmap_coeffs(Element* e)
817 H1ShapesetJacobi ref_map_shapeset;
818 PrecalcShapeset ref_map_pss(&ref_map_shapeset);
820 ref_map_pss.set_quad_2d(&quad2d);
821 ref_map_pss.set_active_element(e);
824 if(edge_proj_matrix == NULL)
825 precalculate_cholesky_projection_matrix_edge(&ref_map_shapeset, &ref_map_pss);
826 if(bubble_proj_matrix_tri == NULL && e->get_mode() == HERMES_MODE_TRIANGLE)
827 precalculate_cholesky_projection_matrices_bubble(&ref_map_shapeset, &ref_map_pss);
828 if(bubble_proj_matrix_quad == NULL && e->get_mode() == HERMES_MODE_QUAD)
829 precalculate_cholesky_projection_matrices_bubble(&ref_map_shapeset, &ref_map_pss);
832 int nv = e->get_nvert();
834 int qo = e->is_quad() ? H2D_MAKE_QUAD_ORDER(order, order) : order;
835 int nb = ref_map_shapeset.get_num_bubbles(qo, e->get_mode());
836 nc = nv + nv*ne + nb;
842 coeffs =
new double2[nc];
848 if(toplevel ==
false)
850 ref_map_pss.set_active_element(e);
851 ref_map_pss.set_transform(part);
852 nurbs = parent->cm->nurbs;
856 ref_map_pss.reset_transform();
857 nurbs = e->cm->nurbs;
859 ctm = *(ref_map_pss.get_ctm());
860 ref_map_pss.reset_transform();
863 ref_map_projection(e, nurbs, order, coeffs, &ref_map_shapeset, &ref_map_pss);
866 void CurvMap::get_mid_edge_points(Element* e, double2* pt,
int n)
868 Nurbs** nurbs = this->nurbs;
870 tran.set_active_element(e);
872 if(toplevel ==
false)
874 tran.set_transform(part);
876 nurbs = e->cm->nurbs;
879 ctm = *(tran.get_ctm());
881 for (
int i = 0; i < n; i++)
883 xi_1 = ctm.m[0] * pt[i][0] + ctm.t[0];
884 xi_2 = ctm.m[1] * pt[i][1] + ctm.t[1];
885 calc_ref_map(e, nurbs, xi_1, xi_2, pt[i]);
899 CurvMap::CurvMap(CurvMap* cm)
901 memcpy(
this, cm,
sizeof(CurvMap));
902 coeffs =
new double2[nc];
903 memcpy(coeffs, cm->coeffs,
sizeof(double2) * nc);
906 for (
int i = 0; i < 4; i++)
920 for (
int i = 0; i < 4; i++)