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;
}
Ejemplo n.º 3
0
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;
}