コード例 #1
0
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;
}
コード例 #2
0
ファイル: Target3DShape.cpp プロジェクト: haripandey/trilinos
bool Target3DShape::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 f = Frobenius(T);
  double d = det(T);
  result = f*f*f - 3*MSQ_SQRT_THREE*d;

  deriv_wrt_A = T;
  deriv_wrt_A *= f;
  deriv_wrt_A -= MSQ_SQRT_THREE*transpose_adj(T);
  deriv_wrt_A *= 3;
  deriv_wrt_A = deriv_wrt_A * transpose(Winv);
  
  set_scaled_2nd_deriv_of_det( second_wrt_A, -3 * MSQ_SQRT_THREE, T );
  pluseq_scaled_outer_product( second_wrt_A, 3.0/f, T );
  pluseq_scaled_I( second_wrt_A, 3.0*f );
  second_deriv_wrt_product_factor( second_wrt_A, Winv );
  return true;
}
コード例 #3
0
/** \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;
}
コード例 #4
0
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;
}
コード例 #5
0
bool Target3DShapeSizeBarrierAlt1::evaluate_with_hess( const MsqMatrix<3,3>& A,
                                                       const MsqMatrix<3,3>& W,
                                                       double& result,
                                                       MsqMatrix<3,3>& wrt_A,
                                                       MsqMatrix<3,3> second[6],
                                                       MsqError& err )
{
  const MsqMatrix<3,3> Winv = inverse(W);
  const MsqMatrix<3,3> T = A * Winv;
  const double tau = det(T);
  if (invalid_determinant(tau)) { // barrier
    result = 0.0;
    return false;
  }
  
  const double f = sqr_Frobenius(T);
  const double g = sqr_Frobenius(adj(T));
  result = (f + g)/(6 * tau);
  
  MsqMatrix<3,3> dtau = transpose_adj(T);
  MsqMatrix<3,3> dg = -transpose(T) * T;
  dg(0,0) += f;
  dg(1,1) += f;
  dg(2,2) += f;
  dg = T * dg;
  dg *= 2;
  
  wrt_A = T;
  wrt_A += 0.5*dg;
  wrt_A *= 1.0/3.0;
  wrt_A -= result * dtau;
  wrt_A *= 1.0/tau;
  wrt_A = wrt_A * transpose(Winv);
  
  set_scaled_2nd_deriv_norm_sqr_adj( second, 1.0/6.0, T );
  pluseq_scaled_I( second, 1.0/3.0 );
  pluseq_scaled_sum_outer_product( second, -1./3./tau, T, dtau );
  pluseq_scaled_sum_outer_product( second, -1./6./tau, dg, dtau );
  pluseq_scaled_outer_product( second, 2*result/tau, dtau );
  pluseq_scaled_2nd_deriv_of_det( second, -result, T );
  hess_scale( second, 1.0/tau );
  second_deriv_wrt_product_factor( second, Winv );
  
  result -= 1.0;
  return true;
}
コード例 #6
0
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;
}
コード例 #7
0
bool TQualityMetric::evaluate_with_Hessian_diagonal( 
                                           PatchData& pd,
                                           size_t handle,
                                           double& value,
                                           std::vector<size_t>& indices,
                                           std::vector<Vector3D>& grad,
                                           std::vector<SymMatrix3D>& diagonal,
                                           MsqError& err )
{
  const Sample s = ElemSampleQM::sample( handle );
  const size_t e = ElemSampleQM::  elem( handle );
  MsqMeshEntity& elem = pd.element_by_index( e );
  EntityTopology type = elem.get_element_type();
  unsigned edim = TopologyInfo::dimension( type );
  size_t num_idx = 0;
  const NodeSet bits = pd.non_slave_node_set( e );
  
  bool rval;
  if (edim == 3) { // 3x3 or 3x2 targets ?
    const MappingFunction3D* mf = pd.get_mapping_function_3D( type );
    if (!mf) {
      MSQ_SETERR(err)( "No mapping function for element type", MsqError::UNSUPPORTED_ELEMENT );
      return false;
    }

    MsqMatrix<3,3> A, W, dmdT, d2mdT2[6];
    mf->jacobian( pd, e, bits, s, mIndices, mDerivs3D, num_idx, A, err );
    MSQ_ERRZERO(err);
    targetCalc->get_3D_target( pd, e, s, W, err ); MSQ_ERRZERO(err);
    const MsqMatrix<3,3> Winv = inverse(W);
    const MsqMatrix<3,3> T = A*Winv;
    rval = targetMetric->evaluate_with_hess( T, value, dmdT, d2mdT2, err );
    MSQ_ERRZERO(err);
    gradient<3>( num_idx, mDerivs3D, dmdT * transpose(Winv), grad );
    second_deriv_wrt_product_factor( d2mdT2, Winv );
    
    diagonal.resize( num_idx );
    hessian_diagonal<3>(num_idx, mDerivs3D, d2mdT2, arrptr(diagonal) );
#ifdef PRINT_INFO
    print_info<3>( e, s, A, W, A * inverse(W) );
#endif
  }
  else if (edim == 2) {
#ifdef NUMERICAL_2D_HESSIAN
    // use finite diference approximation for now
    return QualityMetric::evaluate_with_Hessian_diagonal( pd, handle,
                                           value, indices, grad, diagonal,
                                           err );
#else
    MsqMatrix<2,2> W, A, dmdT, d2mdT2[3];
    MsqMatrix<3,2> M;
    rval = evaluate_surface_common( pd, s, e, bits, mIndices, num_idx,
                             mDerivs2D, W, A, M, err ); 
    if (MSQ_CHKERR(err) || !rval)
      return false;
    const MsqMatrix<2,2> Winv = inverse(W);
    const MsqMatrix<2,2> T = A*Winv;
    rval = targetMetric->evaluate_with_hess( T, value, dmdT, d2mdT2, err );
    MSQ_ERRZERO(err);
    gradient<2>( num_idx, mDerivs2D, M * dmdT * transpose(Winv), grad );
    second_deriv_wrt_product_factor( d2mdT2, Winv );

    diagonal.resize( num_idx );
    for (size_t i = 0; i < num_idx; ++i) {
      MsqMatrix<2,2> block2d;
      block2d(0,0) = transpose(mDerivs2D[i]) * d2mdT2[0] * mDerivs2D[i];
      block2d(0,1) = transpose(mDerivs2D[i]) * d2mdT2[1] * mDerivs2D[i];
      block2d(1,0) = block2d(0,1);
      block2d(1,1) = transpose(mDerivs2D[i]) * d2mdT2[2] * mDerivs2D[i];
      MsqMatrix<3,2> p = M * block2d;
      
      SymMatrix3D& H = diagonal[i];
      H[0] = p.row(0) * transpose(M.row(0));
      H[1] = p.row(0) * transpose(M.row(1));
      H[2] = p.row(0) * transpose(M.row(2));
      H[3] = p.row(1) * transpose(M.row(1));
      H[4] = p.row(1) * transpose(M.row(2));
      H[5] = p.row(2) * transpose(M.row(2));
    }
#ifdef PRINT_INFO
    print_info<2>( e, s, J, Wp, A * inverse(W) );
#endif
#endif
  }
  else {
    assert(0);
    return false;
  }
  
    // pass back index list
  indices.resize( num_idx );
  std::copy( mIndices, mIndices+num_idx, indices.begin() );
  
    // apply target weight to value
  if (!num_idx) 
    weight( pd, s, e, num_idx, value, 0, 0, 0, err );
  else
    weight( pd, s, e, num_idx, value, arrptr(grad), arrptr(diagonal), 0, err ); 
  MSQ_ERRZERO(err);
  return rval;
}
コード例 #8
0
bool TQualityMetric::evaluate_with_Hessian( PatchData& pd,
                                            size_t handle,
                                            double& value,
                                            std::vector<size_t>& indices,
                                            std::vector<Vector3D>& grad,
                                            std::vector<Matrix3D>& Hessian,
                                            MsqError& err )
{
  const Sample s = ElemSampleQM::sample( handle );
  const size_t e = ElemSampleQM::  elem( handle );
  MsqMeshEntity& elem = pd.element_by_index( e );
  EntityTopology type = elem.get_element_type();
  unsigned edim = TopologyInfo::dimension( type );
  size_t num_idx = 0;
  const NodeSet bits = pd.non_slave_node_set( e );
  
  bool rval;
  if (edim == 3) { // 3x3 or 3x2 targets ?
    const MappingFunction3D* mf = pd.get_mapping_function_3D( type );
    if (!mf) {
      MSQ_SETERR(err)( "No mapping function for element type", MsqError::UNSUPPORTED_ELEMENT );
      return false;
    }

    MsqMatrix<3,3> A, W, dmdT, d2mdT2[6];
    mf->jacobian( pd, e, bits, s, mIndices, mDerivs3D, num_idx, A, err );
    MSQ_ERRZERO(err);
    targetCalc->get_3D_target( pd, e, s, W, err ); MSQ_ERRZERO(err);
    const MsqMatrix<3,3> Winv = inverse(W);
    const MsqMatrix<3,3> T = A*Winv;
    rval = targetMetric->evaluate_with_hess( T, value, dmdT, d2mdT2, err );
    MSQ_ERRZERO(err);
    gradient<3>( num_idx, mDerivs3D, dmdT*transpose(Winv), grad );
    second_deriv_wrt_product_factor( d2mdT2, Winv );
    Hessian.resize( num_idx*(num_idx+1)/2 );
    if (num_idx)
      hessian<3>( num_idx, mDerivs3D, d2mdT2, arrptr(Hessian) );
    
#ifdef PRINT_INFO
    print_info<3>( e, s, A, W, A * inverse(W) );
#endif
  }
  else if (edim == 2) {
#ifdef NUMERICAL_2D_HESSIAN
    // return finite difference approximation for now

    return QualityMetric::evaluate_with_Hessian( pd, handle,
                                           value, indices, grad, Hessian,
                                           err );
#else
    MsqMatrix<2,2> W, A, dmdT, d2mdT2[3];
    MsqMatrix<3,2> M;
    rval = evaluate_surface_common( pd, s, e, bits, mIndices, num_idx,
                             mDerivs2D, W, A, M, err ); 
    if (MSQ_CHKERR(err) || !rval)
      return false;
    const MsqMatrix<2,2> Winv = inverse(W);
    const MsqMatrix<2,2> T = A*Winv;
    rval = targetMetric->evaluate_with_hess( T, value, dmdT, d2mdT2, err );
    MSQ_ERRZERO(err);
    gradient<2>( num_idx, mDerivs2D, M * dmdT * transpose(Winv), grad );
      // calculate 2D hessian
    second_deriv_wrt_product_factor( d2mdT2, Winv );
    const size_t n = num_idx*(num_idx+1)/2;
    hess2d.resize(n);
    if (n)
      hessian<2>( num_idx, mDerivs2D, d2mdT2, arrptr(hess2d) );
      // calculate surface hessian as transform of 2D hessian
    Hessian.resize(n);
    for (size_t i = 0; i < n; ++i)
      Hessian[i] = Matrix3D( (M * hess2d[i] * transpose(M)).data() );
#ifdef PRINT_INFO
    print_info<2>( e, s, J, Wp, A * inverse(W) );
#endif
#endif
  }
  else {
    assert(0);
    return false;
  }
  
    // pass back index list
  indices.resize( num_idx );
  std::copy( mIndices, mIndices+num_idx, indices.begin() );
  
    // apply target weight to value
  if (!num_idx) 
    weight( pd, s, e, num_idx, value, 0, 0, 0, err );
  else
    weight( pd, s, e, num_idx, value, arrptr(grad), 0, arrptr(Hessian), err ); 
  MSQ_ERRZERO(err);
  return rval;
}