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; }
bool TShapeSizeOrientB1::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 d = det(T); if (TMetric::invalid_determinant(d)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } deriv_wrt_T = T; pluseq_scaled_I( deriv_wrt_T, -1.0 ); double inv_d = 1.0/d; result = 0.5 * sqr_Frobenius(deriv_wrt_T) * inv_d; MsqMatrix<2,2> adjt = transpose_adj(T); set_scaled_outer_product( second_wrt_T, 2*result*inv_d*inv_d, adjt ); pluseq_scaled_sum_outer_product( second_wrt_T, -inv_d*inv_d, deriv_wrt_T, adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -result * inv_d, T ); pluseq_scaled_I( second_wrt_T, inv_d ); deriv_wrt_T -= result * adjt; deriv_wrt_T *= inv_d; return true; }
bool Target2DUntangle::evaluate_with_hess( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqMatrix<2,2>& deriv_wrt_A, MsqMatrix<2,2> second_wrt_A[3], MsqError& err ) { const MsqMatrix<2,2> Winv = inverse(W); const MsqMatrix<2,2> T = A * Winv; double tau = det(T); if (tau < mGamma) { double d = tau - mGamma; result = 16 * d*d*d*d; const MsqMatrix<2,2> adjt = transpose_adj(T); deriv_wrt_A = 64 * d*d*d * adjt; deriv_wrt_A = deriv_wrt_A * transpose(Winv); set_scaled_outer_product( second_wrt_A, 192*d*d, adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_A, 64*d*d*d ); second_deriv_wrt_product_factor( second_wrt_A, Winv ); } else { result = 0.0; second_wrt_A[0] = second_wrt_A[1] = second_wrt_A[2] = deriv_wrt_A = MsqMatrix<2,2>(0.0); } return true; }
/** \f$ \frac{\partial^2 \mu}{\partial T^2} = \frac{1}{\tau} I_4 - \frac{1}{\tau^2} \left( T \otimes \frac{\partial \tau}{\partial T} + \frac{\partial \tau}{\partial T} \otimes T \right) + \frac{|T|^2}{\tau^3} \left( \frac{\partial \tau}{\partial T} \otimes \frac{\partial \tau}{\partial T} \right) - \frac{|T|^2}{2 \tau^3} \frac{\partial^2 \tau}{\partial T^2} \f$ */ bool Target2DShapeBarrier::evaluate_with_hess( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqMatrix<2,2>& deriv_wrt_A, MsqMatrix<2,2> second_wrt_A[3], MsqError& err ) { const MsqMatrix<2,2> Winv = inverse(W); const MsqMatrix<2,2> T = A * Winv; const double d = det(T); if (invalid_determinant(d)) { // barrier result = 0.0; return false; } double inv_d = 1.0/d; double f1 = sqr_Frobenius(T) * inv_d; result = 0.5 * f1; const MsqMatrix<2,2> adjt = transpose_adj(T); deriv_wrt_A = T; deriv_wrt_A -= result * adjt; deriv_wrt_A *= inv_d; deriv_wrt_A = deriv_wrt_A * transpose(Winv); set_scaled_outer_product( second_wrt_A, f1 * inv_d * inv_d, adjt ); pluseq_scaled_sum_outer_product( second_wrt_A, -inv_d*inv_d, T, adjt ); pluseq_scaled_I( second_wrt_A, inv_d ); pluseq_scaled_2nd_deriv_of_det( second_wrt_A, -result * inv_d ); second_deriv_wrt_product_factor( second_wrt_A, Winv ); result -= 1.0; return true; }
bool TShapeB1::evaluate_with_hess( const MsqMatrix<3,3>& T, double& result, MsqMatrix<3,3>& deriv_wrt_T, MsqMatrix<3,3> second_wrt_T[6], MsqError& err ) { double d = det(T); if (invalid_determinant(d)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } double id = 1.0/d; double norm = Frobenius(T); double den = 1.0/(3 * MSQ_SQRT_THREE * d); double norm_cube = norm*norm*norm; result = norm_cube * den - 1.0; MsqMatrix<3,3> adjt = transpose_adj(T); deriv_wrt_T = T; deriv_wrt_T *= 3 * norm * den; deriv_wrt_T -= norm_cube * den * id * transpose_adj(T); set_scaled_outer_product( second_wrt_T, 3 * den / norm, T ); pluseq_scaled_I( second_wrt_T, 3 * norm * den ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -den * norm_cube * id, T ); pluseq_scaled_outer_product( second_wrt_T, 2 * den * norm_cube * id * id , adjt ); pluseq_scaled_sum_outer_product( second_wrt_T, -3 * norm * den * id, T, adjt ); return true; }
bool TShapeSizeB3::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 tau = det(T); if (invalid_determinant(tau)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } result = sqr_Frobenius(T) - 2.0 * std::log(tau) - 2; const MsqMatrix<2,2> adjt = transpose_adj(T); const double it = 1/tau; deriv_wrt_T = T; deriv_wrt_T -= it * adjt; deriv_wrt_T *= 2; set_scaled_outer_product( second_wrt_T, 2*it*it, adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -2*it ); pluseq_scaled_I( second_wrt_T, 2.0 ); 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; }
template <unsigned DIM> static inline bool hess( const MsqMatrix<DIM,DIM>& T, double& result, MsqMatrix<DIM,DIM>& deriv, MsqMatrix<DIM,DIM>* second ) { double d1 = det(T) - 1; result = d1*d1; const MsqMatrix<DIM,DIM> adjt = transpose_adj(T); deriv = 2 * d1 * adjt; set_scaled_outer_product( second, 2, adjt ); pluseq_scaled_2nd_deriv_of_det( second, 2 * d1, T ); return true; }
bool TSizeB1::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 ) { double d = det(T); if (TMetric::invalid_determinant(d)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } result = d + 1.0/d - 2.0; MsqMatrix<2,2> adjt = transpose_adj(T); const double f = 1 - 1/(d*d); deriv_wrt_T = f * adjt; set_scaled_outer_product( second_wrt_T, 2/(d*d*d), adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, f, T ); 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; }
bool TShapeSize3DB4::evaluate_with_hess( const MsqMatrix<3,3>& T, double& result, MsqMatrix<3,3>& deriv, MsqMatrix<3,3> second[6], MsqError& err ) { const double tau = det(T); if (invalid_determinant(tau)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } const double norm = Frobenius(T); const double f = norm*norm/3.0; const double h = 1/(MSQ_SQRT_THREE * tau); const double g = norm * h; const double inv_tau = 1.0/tau; result = f * g - 1 + mGamma * (tau + inv_tau - 2); const double g1 = mGamma * (1 - inv_tau*inv_tau); const MsqMatrix<3,3> adjt = transpose_adj(T); deriv = g*T; deriv += (g1 - f*g*inv_tau) * adjt; if (norm > 1e-50) { const double inv_norm = 1/norm; set_scaled_outer_product( second, h*inv_norm, T ); pluseq_scaled_I( second, norm * h ); pluseq_scaled_2nd_deriv_of_det( second, g1 - f*g*inv_tau, T ); pluseq_scaled_outer_product( second, (f*g + mGamma*inv_tau)*2*inv_tau*inv_tau, adjt ); pluseq_scaled_sum_outer_product( second, -g*inv_tau, T, adjt ); } else { std::cout << "Warning: Division by zero avoided in TShapeSize3DB4::evaluate_with_hess()" << std::endl; } return true; }
bool TShapeSizeB3::evaluate_with_hess( const MsqMatrix<3,3>& T, double& result, MsqMatrix<3,3>& deriv_wrt_T, MsqMatrix<3,3> second_wrt_T[6], MsqError& err ) { const double tau = det(T); if (invalid_determinant(tau)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } double n = Frobenius(T); result = n*n*n - 3*MSQ_SQRT_THREE*( log(tau) + 1 ); const MsqMatrix<3,3> adjt = transpose_adj(T); const double it = 1/tau; deriv_wrt_T = T; deriv_wrt_T *= 3*n; deriv_wrt_T -= 3*MSQ_SQRT_THREE*it * adjt; if (n > 1e-50) { set_scaled_outer_product( second_wrt_T, 3/n, T ); pluseq_scaled_I( second_wrt_T, 3*n ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -3*MSQ_SQRT_THREE*it, T ); pluseq_scaled_outer_product( second_wrt_T, 3*MSQ_SQRT_THREE*it*it, adjt ); } else { std::cout << "Warning: Division by zero avoided in TShapeSizeB3::evaluate_with_hess()" << std::endl; } return true; }