double *RefMap::get_jacobian(const int np, const QuadPt3D *pt, bool trans) { _F_ double *jac = new double[np]; MEM_CHECK(jac); if (is_const_jacobian) { if (trans) for (int i = 0; i < np; i++) jac[i] = const_jacobian * pt[i].w; else for (int i = 0; i < np; i++) jac[i] = const_jacobian; } else { double3x3 *m = get_ref_map(np, pt); double trj = get_transform_jacobian(); if (trans) for (int i = 0; i < np; i++) jac[i] = det(m[i]) * trj * pt[i].w; else for (int i = 0; i < np; i++) jac[i] = det(m[i]) * trj; delete [] m; } return jac; }
void RefMap::calc_inv_ref_map(int order) { assert(quad_2d != NULL); int i, j, np = quad_2d->get_num_points(order); // construct jacobi matrices of the direct reference map for all integration points AUTOLA_OR(double2x2, m, np); memset(m, 0, m.size); ref_map_pss.force_transform(sub_idx, ctm); for (i = 0; i < nc; i++) { double *dx, *dy; ref_map_pss.set_active_shape(indices[i]); ref_map_pss.set_quad_order(order); ref_map_pss.get_dx_dy_values(dx, dy); for (j = 0; j < np; j++) { m[j][0][0] += coeffs[i][0] * dx[j]; m[j][0][1] += coeffs[i][0] * dy[j]; m[j][1][0] += coeffs[i][1] * dx[j]; m[j][1][1] += coeffs[i][1] * dy[j]; } } // calculate the jacobian and inverted matrix double trj = get_transform_jacobian(); double2x2* irm = cur_node->inv_ref_map[order] = new double2x2[np]; double* jac = cur_node->jacobian[order] = new double[np]; for (i = 0; i < np; i++) { jac[i] = (m[i][0][0] * m[i][1][1] - m[i][0][1] * m[i][1][0]); double ij = 1.0 / jac[i]; error_if(!finite(ij), "1/jac[%d] is infinity when calculating inv. ref. map for order %d (jac=%g)", i, order); assert_msg(ij == ij, "1/jac[%d] is NaN when calculating inv. ref. map for order %d (jac=%g)", i, order); // invert and transpose the matrix irm[i][0][0] = m[i][1][1] * ij; irm[i][0][1] = -m[i][1][0] * ij; irm[i][1][0] = -m[i][0][1] * ij; irm[i][1][1] = m[i][0][0] * ij; jac[i] *= trj; } }
/// Quickly calculates the (hard-coded) reference mapping for elements with constant jacobians /// (ie., linear triangles and linear parallelogram quads). How it works for parallelograms /// can be found <a href="../data/parallelogram.pdf">here</a>. /// void RefMap::calc_const_inv_ref_map() { if (element == NULL) error("The element variable must not be NULL."); int k = element->is_triangle() ? 2 : 3; double m[2][2] = { { element->vn[1]->x - element->vn[0]->x, element->vn[k]->x - element->vn[0]->x }, { element->vn[1]->y - element->vn[0]->y, element->vn[k]->y - element->vn[0]->y } }; const_jacobian = 0.25 * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); if (const_jacobian <= 0.0) error("Element #%d is concave or badly oriented.", element->id); double ij = 0.5 / const_jacobian; const_inv_ref_map[0][0] = m[1][1] * ij; const_inv_ref_map[1][0] = -m[0][1] * ij; const_inv_ref_map[0][1] = -m[1][0] * ij; const_inv_ref_map[1][1] = m[0][0] * ij; const_jacobian *= get_transform_jacobian(); }
double3x3 *RefMap::get_inv_ref_map(const int np, const QuadPt3D *pt) { _F_ double3x3 *irm = new double3x3[np]; MEM_CHECK(irm); if (is_const_jacobian) { for (int i = 0; i < np; i++) memcpy(irm + i, const_inv_ref_map, sizeof(double3x3)); } else { double3x3 *m = get_ref_map(np, pt); double trj = get_transform_jacobian(); double *jac = new double[np]; MEM_CHECK(jac); for (int i = 0; i < np; i++) { jac[i] = det(m[i]); double ij = 1.0 / jac[i]; irm[i][0][0] = (m[i][1][1] * m[i][2][2] - m[i][1][2] * m[i][2][1]) * ij; irm[i][1][0] = (m[i][0][2] * m[i][2][1] - m[i][0][1] * m[i][2][2]) * ij; irm[i][2][0] = (m[i][0][1] * m[i][1][2] - m[i][0][2] * m[i][1][1]) * ij; irm[i][0][1] = (m[i][1][2] * m[i][2][0] - m[i][1][0] * m[i][2][2]) * ij; irm[i][1][1] = (m[i][0][0] * m[i][2][2] - m[i][0][2] * m[i][2][0]) * ij; irm[i][2][1] = (m[i][0][2] * m[i][1][0] - m[i][0][0] * m[i][1][2]) * ij; irm[i][0][2] = (m[i][1][0] * m[i][2][1] - m[i][1][1] * m[i][2][0]) * ij; irm[i][1][2] = (m[i][0][1] * m[i][2][0] - m[i][0][0] * m[i][2][1]) * ij; irm[i][2][2] = (m[i][0][0] * m[i][1][1] - m[i][0][1] * m[i][1][0]) * ij; jac[i] *= trj; } delete [] m; delete [] jac; } return irm; }