template <unsigned DIM> static inline bool grad( const MsqMatrix<DIM,DIM>& T, double& result, MsqMatrix<DIM,DIM>& deriv_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; return true; }
bool TShape3DB2::evaluate_with_grad( const MsqMatrix<3,3>& T, double& result, MsqMatrix<3,3>& wrt_T, MsqError& err ) { double f = sqr_Frobenius(T); double g = sqr_Frobenius(adj(T)); double d = det(T); if (invalid_determinant(d)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } result = (f*g) / (9*d*d) - 1; wrt_T = T; wrt_T *= (g + f*f); wrt_T -= f * (T * transpose(T) * T); wrt_T -= f * g / d * transpose_adj(T); wrt_T *= 2 / (9*d*d); return true; }
bool TShapeOrientB2::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& err ) { double tau = det(T); if (TMetric::invalid_determinant(tau)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } const double tr = trace(T); result = (0.5/tau) * (sqr_Frobenius( T ) - 0.5 * tr * fabs(tr)); return true; }
bool TShapeB1::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& err) { const double d = det(T); if (invalid_determinant(d)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } result = 0.5 * sqr_Frobenius(T) / d - 1; return true; }
bool TShapeSize2DNB2::evaluate_with_hess( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, MsqMatrix<2,2> second[3], MsqError& err ) { double frob_sqr = sqr_Frobenius(T); double psi = sqrt( frob_sqr + 2.0*det(T) ); double a = 1e-12; while (!Mesquite::divide(frob_sqr+2,2*psi,result)) { MsqMatrix<2,2> Tdelta(T); Tdelta(0,0) += a; Tdelta(1,1) += a; a *= 2.0; frob_sqr = sqr_Frobenius(Tdelta); psi = sqrt( frob_sqr + 2.0*det(Tdelta) ); if (psi > 1e-50) result = (frob_sqr+2) / 2*psi; } const double inv_psi = 1.0/psi; MsqMatrix<2,2> d_psi = T + transpose_adj(T); d_psi *= inv_psi; deriv_wrt_T = d_psi; deriv_wrt_T *= -result; deriv_wrt_T += T; deriv_wrt_T *= inv_psi; set_scaled_2nd_deriv_wrt_psi( second, -result*inv_psi, psi, T ); pluseq_scaled_outer_product( second, 2*result*inv_psi*inv_psi, d_psi ); pluseq_scaled_sum_outer_product( second, -inv_psi*inv_psi, d_psi, T ); pluseq_scaled_I( second, inv_psi ); result -= 1.0; return true; }
/** \f$ \mu(T) = \frac{|T|^2+2}{2\psi(T)} - 1 \f$ * \f$ \psi(T) = \sqrt{|T|^2 + 2 \tau}\f$ * \f$ \tau = det(T) \f$ */ bool TShapeSize2DNB2::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& ) { double frob_sqr = sqr_Frobenius(T); double psi = sqrt( frob_sqr + 2.0*det(T) ); double a = 1e-12; while (!Mesquite::divide(frob_sqr+2,2*psi,result)) { MsqMatrix<2,2> Tdelta(T); Tdelta(0,0) += a; Tdelta(1,1) += a; a *= 2.0; frob_sqr = sqr_Frobenius(Tdelta); psi = sqrt( frob_sqr + 2.0*det(Tdelta) ); if (psi > 1e-50) result = (frob_sqr+2) / 2*psi; } result -= 1.0; return true; }
bool TShapeSizeB3::evaluate( const MsqMatrix<2,2>& T, double& result, 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; return true; }
template <unsigned DIM> static inline bool hess( const MsqMatrix<DIM,DIM>& A, const MsqMatrix<DIM,DIM>& W, double& result, MsqMatrix<DIM,DIM>& deriv, MsqMatrix<DIM,DIM>* second ) { deriv = A - W; result = sqr_Frobenius( deriv ); deriv *= 2.0; set_scaled_I( second, 2.0 ); return true; }
bool TShapeSize2DB2::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& err ) { const double two_det = 2.0 * det(T); if (invalid_determinant(two_det)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } const double frob_sqr = sqr_Frobenius(T); result = (frob_sqr - 2.0 * sqrt( frob_sqr + two_det ) + 2.0)/two_det; return true; }
bool AWShape2DNB1::evaluate_with_grad( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqMatrix<2,2>& deriv_wrt_A, MsqError& ) { const double alpha = det(A); const double omega = det(W); const MsqMatrix<2,2> AtA = transpose(A) * A; const MsqMatrix<2,2> WtW = transpose(W) * W; const MsqMatrix<2,2> AWt = A * transpose(W); const double alphaWtW = alpha * sqr_Frobenius(WtW); const double omegaAtA = omega * sqr_Frobenius(AtA); const double omegaAWt = omega * sqr_Frobenius(AWt); result = omega*omegaAtA; result += alpha*alphaWtW; result -= 2*alpha*omegaAWt; deriv_wrt_A = 4*omega*omega * A * transpose(A) * A; deriv_wrt_A -= 4*alpha*omega * AWt * W; deriv_wrt_A += 2*(alphaWtW - omegaAWt) * transpose_adj(A); return true; }
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; }
bool Target2DShapeBarrier::evaluate( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqError& ) { const MsqMatrix<2,2> T = A * inverse(W); const double d = det(T); if (invalid_determinant(d)) { // barrier result = 0.0; return false; } result = 0.5 * sqr_Frobenius(T) / d - 1; return true; }
bool Target3DShapeOrientBarrierAlt1::evaluate( const MsqMatrix<3,3>& A, const MsqMatrix<3,3>& W, double& result, MsqError& ) { const MsqMatrix<3,3> T = A * inverse(W); double tau = det(T); if (invalid_determinant(tau)) { result = 0.0; return false; } const double tr = trace(T); result = (0.5/tau) * (sqr_Frobenius( T ) - MSQ_ONE_THIRD * tr * fabs(tr)); return true; }
bool TShapeSizeB1::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& ) { const double tau = det(T); if (invalid_determinant(tau)) { // barrier result = 0.0; return false; } const double nT = sqr_Frobenius(T); const double f = 1/(tau*tau); result = (1 + f) * nT - 4; return true; }
bool TShapeSizeOrientB1::evaluate( const MsqMatrix<2,2>& T, double& result, MsqError& err ) { double tau = det(T); if (TMetric::invalid_determinant(tau)) { MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } MsqMatrix<2,2> T_I(T); pluseq_scaled_I( T_I, -1 ); result = sqr_Frobenius( T_I ) / (2*tau); 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 InverseMeanRatio2D::evaluate( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqError& err ) { const MsqMatrix<2,2> T = A * inverse(W); const double d = det( T ); if (invalid_determinant(d)) { result = 0.0; return false; } else { result = sqr_Frobenius(T) / (2 * d) - 1; return true; } }
bool TShapeSizeB3::evaluate_with_grad( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, 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; deriv_wrt_T = T; deriv_wrt_T -= 1/tau * transpose_adj(T); deriv_wrt_T *= 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; }
bool TShapeB1::evaluate_with_grad( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, MsqError& err ) { const double d = det(T); if (invalid_determinant(d)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } double inv_d = 1.0/d; result = 0.5 * sqr_Frobenius(T) * inv_d; deriv_wrt_T = T; deriv_wrt_T -= result * transpose_adj(T); deriv_wrt_T *= inv_d; result -= 1.0; return true; }
bool TShapeSizeOrientB1::evaluate_with_grad( const MsqMatrix<3,3>& T, double& result, MsqMatrix<3,3>& deriv_wrt_T, 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 ); double inv_d = 1.0/d; result = 0.5 * sqr_Frobenius(deriv_wrt_T) * inv_d; deriv_wrt_T -= result * transpose_adj(T); deriv_wrt_T *= inv_d; return true; }
bool TShapeSizeB1::evaluate_with_grad( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, MsqError& ) { const double tau = det(T); if (invalid_determinant(tau)) { // barrier result = 0.0; return false; } const MsqMatrix<2,2> adjt = transpose_adj(T); const double nT = sqr_Frobenius(T); const double f = 1/(tau*tau); result = (1 + f) * nT - 4; deriv_wrt_T = T; deriv_wrt_T *= 2 + 2*f; deriv_wrt_T -= 2 * f/tau * nT * adjt; return true; }
bool Target2DShapeBarrier::evaluate_with_grad( const MsqMatrix<2,2>& A, const MsqMatrix<2,2>& W, double& result, MsqMatrix<2,2>& deriv_wrt_A, 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; result = 0.5 * sqr_Frobenius(T) * inv_d; deriv_wrt_A = T; deriv_wrt_A -= result * transpose_adj(T); deriv_wrt_A *= inv_d; deriv_wrt_A = deriv_wrt_A * transpose(Winv); result -= 1.0; return true; }
bool TShapeSize2DB2::evaluate_with_grad( const MsqMatrix<2,2>& T, double& result, MsqMatrix<2,2>& deriv_wrt_T, MsqError& err ) { const double d = det(T); if (invalid_determinant(d)) { // barrier MSQ_SETERR(err)( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); return false; } const double frob_sqr = sqr_Frobenius(T); const double psi = sqrt( frob_sqr + 2.0*det(T) ); const double v = frob_sqr - 2.0 * psi + 2.0; result = v / (2*d); // deriv of V wrt T MsqMatrix<2,2> adjt = transpose_adj(T); MsqMatrix<2,2> v_wrt_T(T); if (psi > 1e-50) { v_wrt_T *= (1.0 - 1.0/psi); v_wrt_T -= 1.0/psi * adjt; v_wrt_T *= 2; } else { std::cout << "Warning: Division by zero avoided in TShapeSize2DB2::evaluate_with_grad()" << std::endl; } // deriv of mu wrt T deriv_wrt_T = v_wrt_T; deriv_wrt_T *= 0.5/d; deriv_wrt_T -= v / (2*d*d) * adjt; return true; }
template <unsigned DIM> static inline bool eval( const MsqMatrix<DIM,DIM>& T, double& result) { result = sqr_Frobenius( T ); return true; }