bool Target3DShapeOrientBarrierAlt1::evaluate_with_Hess( const MsqMatrix<3,3>& A, const MsqMatrix<3,3>& W, double& result, MsqMatrix<3,3>& deriv_wrt_A, MsqMatrix<3,3> second_wrt_A[6], MsqError& err ) { MsqMatrix<3,3> Winv = inverse(W); MsqMatrix<3,3> T = A * Winv; double tau = det(T); if (invalid_determinant(tau)) { result = 0.0; return false; } const double b = 0.5/tau; // calculate non-barrier value (ShapeOrientAlt1) const double tr = trace(T); const double f = MSQ_ONE_THIRD * fabs(tr); result = sqr_Frobenius( T ) - f * tr; // calculate non-barrier first derivatives deriv_wrt_A = T; deriv_wrt_A(0,0) -= f; deriv_wrt_A(1,1) -= f; deriv_wrt_A(2,2) -= f; deriv_wrt_A *= 2; // calculate barrier second derivs const MsqMatrix<3,3> adjt = transpose_adj(T); set_scaled_sum_outer_product( second_wrt_A, -b/tau, deriv_wrt_A, adjt ); pluseq_scaled_outer_product( second_wrt_A, result/(tau*tau*tau), adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_A, -result * b / tau, T ); // calculate non-barrier barrier portion of second derivs pluseq_scaled_I( second_wrt_A, 1/tau ); pluseq_scaled_outer_product_I_I( second_wrt_A, MSQ_ONE_THIRD/tau * (tr < 0 ? 1 : -1) ); // calculate barrier derivs from non-barrier deriv_wrt_A *= tau; deriv_wrt_A -= result * adjt; deriv_wrt_A *= b/tau; // barrier value from non-barrier result *= b; // convert from derivs wrt T to derivs wrt A deriv_wrt_A = deriv_wrt_A * transpose(Winv); second_deriv_wrt_product_factor( second_wrt_A, Winv ); return true; }
template <unsigned DIM> static inline bool hess( const MsqMatrix<DIM,DIM>& T, double& result, MsqMatrix<DIM,DIM>& deriv_wrt_T, MsqMatrix<DIM,DIM>* second_wrt_T ) { const double tr = trace(T); const double f = DimConst<DIM>::inv() * fabs(tr); result = sqr_Frobenius( T ) - f * tr; deriv_wrt_T = T; pluseq_scaled_I( deriv_wrt_T, -f ); deriv_wrt_T *= 2; set_scaled_I( second_wrt_T, 2.0 ); pluseq_scaled_outer_product_I_I( second_wrt_T, DimConst<DIM>::inv() * (tr < 0 ? 2 : -2) ); return true; }
bool TShapeOrientB2::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 tau = det(T); if (TMetric::invalid_determinant(tau)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); result = 0.0; return false; } const double b = 0.5/tau; // calculate non-barrier value (ShapeOrientAlt1) const double tr = trace(T); const double f = MSQ_ONE_THIRD * fabs(tr); result = sqr_Frobenius( T ) - f * tr; // calculate non-barrier first derivatives deriv_wrt_T = T; pluseq_scaled_I( deriv_wrt_T, -f ); deriv_wrt_T *= 2; // calculate barrier second derivs const MsqMatrix<3,3> adjt = transpose_adj(T); set_scaled_sum_outer_product( second_wrt_T, -b/tau, deriv_wrt_T, adjt ); pluseq_scaled_outer_product( second_wrt_T, result/(tau*tau*tau), adjt ); pluseq_scaled_2nd_deriv_of_det( second_wrt_T, -result * b / tau, T ); // calculate non-barrier barrier portion of second derivs pluseq_scaled_I( second_wrt_T, 1/tau ); pluseq_scaled_outer_product_I_I( second_wrt_T, MSQ_ONE_THIRD/tau * (tr < 0 ? 1 : -1) ); // calculate barrier derivs from non-barrier deriv_wrt_T *= tau; deriv_wrt_T -= result * adjt; deriv_wrt_T *= b/tau; // barrier value from non-barrier result *= b; return true; }