bool TShapeOrientB1::evaluate_with_hess( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, MsqMatrix<2,2> second_wrt_T[3], MsqError& err ) { const double norm = Frobenius(T); const double invroot = 1.0/MSQ_SQRT_TWO; const double tau = det(T); if (TMetric::invalid_determinant(tau)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } const double inv_tau = 1.0/tau; const double invnorm = 1.0/norm; const double f = norm - invroot * trace(T); result = 0.5 * inv_tau * f; const MsqMatrix<2,2> adjt = transpose_adj(T); deriv_wrt_T = invnorm * T; pluseq_scaled_I( deriv_wrt_T, -invroot ); deriv_wrt_T *= 0.5; deriv_wrt_T -= result * adjt; deriv_wrt_T *= inv_tau; const double a = 0.5 * inv_tau * invnorm; set_scaled_outer_product( second_wrt_T, -a*invnorm*invnorm, T ); pluseq_scaled_I( second_wrt_T, a ); pluseq_scaled_outer_product( second_wrt_T, f*inv_tau*inv_tau*inv_tau, adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -0.5*f*inv_tau*inv_tau, T ); pluseq_scaled_sum_outer_product( second_wrt_T, -0.5*inv_tau*inv_tau*invnorm, T, adjt ); pluseq_scaled_sum_outer_product_I( second_wrt_T, 0.5*inv_tau*inv_tau*invroot, adjt ); return true; }
template <unsigned DIM> static inline bool hess( const MsqMatrix<DIM,DIM>& T, double& result, MsqMatrix<DIM,DIM>& deriv, MsqMatrix<DIM,DIM>* second ) { const double norm = Frobenius(T); const double invroot = 1.0/DimConst<DIM>::sqrt(); const double tau = det(T); if (TMetric::invalid_determinant(tau)) { // barrier result = 0.0; return false; } const double inv_tau = 1.0/tau; const double invnorm = 1.0/norm; const double f = norm - invroot * trace(T); result = 0.5 * inv_tau * f; const MsqMatrix<DIM,DIM> adjt = transpose_adj(T); deriv = invnorm * T; pluseq_scaled_I( deriv, -invroot ); deriv *= 0.5; deriv -= result * adjt; deriv *= inv_tau; const double a = 0.5 * inv_tau * invnorm; set_scaled_outer_product( second, -a*invnorm*invnorm, T ); pluseq_scaled_I( second, a ); pluseq_scaled_outer_product( second, f*inv_tau*inv_tau*inv_tau, adjt ); pluseq_scaled_2nd_deriv_of_det( second, -0.5*f*inv_tau*inv_tau, T ); pluseq_scaled_sum_outer_product( second, -0.5*inv_tau*inv_tau*invnorm, T, adjt ); pluseq_scaled_sum_outer_product_I( second, 0.5*inv_tau*inv_tau*invroot, adjt ); return true; }
bool Target2DShapeOrientBarrier::evaluate_with_hess( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqMatrix<2,2>& deriv, MsqMatrix<2,2> second[3], MsqError& err ) { const MsqMatrix<2,2> Winv = inverse(W); const MsqMatrix<2,2> T = A * Winv; const double norm = Frobenius(T); const double invroot = 1.0/MSQ_SQRT_TWO; const double tau = det(T); if (invalid_determinant(tau)) { // barrier result = 0.0; return false; } const double inv_tau = 1.0/tau; const double invnorm = 1.0/norm; const double f = norm - invroot * trace(T); result = 0.5 * inv_tau * f; const MsqMatrix<2,2> adjt = transpose_adj(T); deriv = invnorm * T; deriv(0,0) -= invroot; deriv(1,1) -= invroot; deriv *= 0.5; deriv -= result * adjt; deriv *= inv_tau; deriv = deriv * transpose(Winv); const double a = 0.5 * inv_tau * invnorm; set_scaled_outer_product( second, -a*invnorm*invnorm, T ); pluseq_scaled_I( second, a ); pluseq_scaled_outer_product( second, f*inv_tau*inv_tau*inv_tau, adjt ); pluseq_scaled_2nd_deriv_of_det( second, -0.5*f*inv_tau*inv_tau ); pluseq_scaled_sum_outer_product( second, -0.5*inv_tau*inv_tau*invnorm, T, adjt ); pluseq_scaled_sum_outer_product_I( second, 0.5*inv_tau*inv_tau*invroot, adjt ); second_deriv_wrt_product_factor( second, Winv ); return true; }