6 #ifndef INVERSE_MAPPING_HPP_INCLUDED
7 #define INVERSE_MAPPING_HPP_INCLUDED
29 template <
class LSet,
class Scalar>
36 static unsigned const xi_dim = domain_t::dimension;
37 static unsigned const N = xi_dim + 1;
38 typedef Eigen::Matrix<Scalar, N, 1> result_t;
46 , m_constrained_in_elem(constrained_in_elem)
55 bool eval(x_t
const &x0,
double tol,
unsigned max_iter)
59 double xi_tol = tol / std::sqrt(m_elem.get_normal(domain_t::get_center()).norm());
65 Eigen::Matrix<double, N, N> df;
67 xi_t xi_prev = xi_t::Zero();
70 for (m_iter = 0; m_iter < max_iter; ++m_iter)
73 auto xi = m_res.topRows(xi_dim);
74 double zeta = m_res(xi_dim);
77 auto y = m_elem.get_x(xi);
78 x_t n = m_elem.get_normal(xi);
80 double jac = n.norm();
82 throw std::runtime_error(
"Element " + std::to_string(m_elem.get_id()(0)) +
" is overdistorted, and inverse mapping cannot be performed for nearly singular integration.");
83 double sqrtjac = std::sqrt(n.norm());
87 auto x_guess = y + n * zeta;
90 auto f = x_guess - x0;
96 auto dy = m_elem.get_dx(xi);
97 auto ddy = m_elem.get_ddx(xi);
109 x_t dnxi = (ddyxixi.cross(dyeta) + dyxi.cross(ddyxieta)) / sqrtjac;
110 x_t dneta = (ddyxieta.cross(dyeta) + dyxi.cross(ddyetaeta)) / sqrtjac;
112 df.col(0) = dyxi + dnxi * zeta;
113 df.col(1) = dyeta + dneta * zeta;
117 throw std::logic_error(
"Inverse mapping is unimplemented for this element type");
119 m_res = m_res - df.colPivHouseholderQr().solve(f);
121 if (m_constrained_in_elem)
123 m_res.topRows(xi_dim) = domain_t::constrain_inside(m_res.topRows(xi_dim));
124 xi_t delta = m_res.topRows(xi_dim) - xi_prev;
125 if (delta.norm() < xi_tol)
127 xi_prev = m_res.topRows(xi_dim);
154 bool m_constrained_in_elem;
162 #endif // INVERSE_MAPPING_HPP_INCLUDED