示例#1
0
bool LInfTemplate::evaluate( EvalType type, 
                             PatchData& pd,
                             double& value_out,
                             bool free,
                             MsqError& err )
{
  if (type != ObjectiveFunction::CALCULATE) {
    MSQ_SETERR(err)(
      "LInfTemplate does not support block coodinate descent algoritms",
      MsqError::INVALID_STATE );
    return false;
  }

  QualityMetric* qm = get_quality_metric();
  qm->get_evaluations( pd, qmHandles, free, err );  MSQ_ERRFALSE(err);
  const double negate = qm->get_negate_flag();
  
    // calculate OF value for just the patch
  std::vector<size_t>::const_iterator i;
  double value;
  value_out = -HUGE_VAL;
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    bool result = qm->evaluate( pd, *i, value, err );
    if (MSQ_CHKERR(err) || !result)
      return false;

    value = negate * fabs(value);
    if (value > value_out)
      value_out = value;
  }
  
  return true;
}
示例#2
0
bool PMeanPTemplate::evaluate( EvalType type, 
                           PatchData& pd,
                           double& value_out,
                           bool free,
                           MsqError& err )
{
  QualityMetric* qm = get_quality_metric();
  if (type == ObjectiveFunction::ACCUMULATE)
    qm->get_single_pass( pd, qmHandles, free, err );
  else
    qm->get_evaluations( pd, qmHandles, free, err );  
  MSQ_ERRFALSE(err);
  
    // calculate OF value for just the patch
  std::vector<size_t>::const_iterator i;
  double value, working_sum = 0.0;
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    bool result = qm->evaluate( pd, *i, value, err );
    if (MSQ_CHKERR(err) || !result)
      return false;
    
    working_sum += mPower.raise( value );
  }
  
    // get overall OF value, update member data, etc.
  size_t global_count;
  value_out = qm->get_negate_flag() 
            * get_value( working_sum, qmHandles.size(), type, global_count );
  return true;
}
示例#3
0
bool ElementMaxQM::evaluate( PatchData& pd, 
                              size_t handle, 
                              double& value, 
                              MsqError& err )
{
  ElemSampleQM* qm = get_quality_metric();
  mHandles.clear();
  qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err);

  bool valid = true;
  double tmpval;
  bool tmpvalid;

  value = -1.e+100; // initialize max computation
  for (std::vector<size_t>::iterator h = mHandles.begin(); h != mHandles.end(); ++h) { 
    tmpvalid = qm->evaluate( pd, *h, tmpval, err );  // MSQ_ERRZERO(err);
    if (!tmpvalid)
    {
      value = +1.e+100;
      return false;   // if any handle within the element makes tmpvalid false, then valid is false, no matter what the other handles say
    }
    else if (tmpval > value)
      value = tmpval;
  }

  return valid;
}
示例#4
0
bool ElementAvgQM::evaluate( PatchData& pd, 
                              size_t handle, 
                              double& value, 
                              MsqError& err )
{
  ElemSampleQM* qm = get_quality_metric();
  mHandles.clear();
  qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err);

  bool valid = true;
  double tmpval;
  double accumulate = 0.0;
  int num_values = 0;
  bool tmpvalid;

  value = -std::numeric_limits<double>::infinity();
  for (std::vector<size_t>::iterator h = mHandles.begin(); h != mHandles.end(); ++h) 
  {
    tmpvalid = qm->evaluate( pd, *h, tmpval, err ); MSQ_ERRZERO(err);
    if (!tmpvalid) 
    {
      valid = false;
      break;
    }
    else
    { 
      accumulate += tmpval;    
      num_values++;
    }
  }
  if (valid)
    value = accumulate/num_values;
    
  return valid;
}
示例#5
0
bool ElementPMeanP::evaluate( PatchData& pd, 
                              size_t handle, 
                              double& value, 
                              MsqError& err )
{
  ElemSampleQM* qm = get_quality_metric();
  mHandles.clear();
  qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err);
  bool result = average( pd, qm, mHandles, value, err );
  return !MSQ_CHKERR(err) && result;
}
示例#6
0
bool ElementPMeanP::evaluate_with_gradient( PatchData& pd, 
                                            size_t handle, 
                                            double& value, 
                                            std::vector<size_t>& indices,
                                            std::vector<Vector3D>& gradient,
                                            MsqError& err )
{
  ElemSampleQM* qm = get_quality_metric();
  mHandles.clear();
  qm->get_element_evaluations( pd, handle, mHandles, err ); MSQ_ERRFALSE(err);
  bool result = average_with_gradient( pd, qm, mHandles, value, indices, gradient, err );
  return !MSQ_CHKERR(err) && result;
}
示例#7
0
bool PMeanPTemplate::evaluate_with_gradient( EvalType type, 
                                         PatchData& pd,
                                         double& value_out,
                                         std::vector<Vector3D>& grad_out,
                                         MsqError& err )
{
  QualityMetric* qm = get_quality_metric();
  qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err );  MSQ_ERRFALSE(err);
  
    // zero gradient
  grad_out.clear();
  grad_out.resize( pd.num_free_vertices(), Vector3D(0.0,0.0,0.0) );
  
    // calculate OF value and gradient for just the patch
  std::vector<size_t>::const_iterator i;
  double value, working_sum = 0.0;
  const double f = qm->get_negate_flag() * mPower.value();
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    bool result = qm->evaluate_with_gradient( pd, *i, value, mIndices, mGradient, err );
    if (MSQ_CHKERR(err) || !result)
      return false;
    if (fabs(value) < DBL_EPSILON)
      continue;
    
    const double r1 = mPowerMinus1.raise( value );
    const double qmp = r1 * value;
    working_sum += qmp;
    value = f * r1;

    for (size_t j = 0; j < mIndices.size(); ++j) {
      mGradient[j] *= value;
      grad_out[mIndices[j]] += mGradient[j];
    }
  }
  
    // get overall OF value, update member data, etc.
  size_t global_count;
  value_out = qm->get_negate_flag() 
            * get_value( working_sum, qmHandles.size(), type, global_count );
  const double inv_n = 1.0 / global_count;
  std::vector<Vector3D>::iterator g;
  for (g = grad_out.begin(); g != grad_out.end(); ++g)
    *g *= inv_n;
  return true;
}
示例#8
0
bool PMeanPTemplate::evaluate_with_Hessian( EvalType type, 
                                        PatchData& pd,
                                        double& value_out,
                                        std::vector<Vector3D>& grad_out,
                                        MsqHessian& Hessian_out,
                                        MsqError& err )
{
  QualityMetric* qm = get_quality_metric();
  qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err );  MSQ_ERRFALSE(err);
  
    // zero gradient and hessian
  grad_out.clear();
  grad_out.resize( pd.num_free_vertices(), 0.0 );
  Hessian_out.zero_out();
  
    // calculate OF value and gradient for just the patch
  std::vector<size_t>::const_iterator i;
  size_t j, k, n;
  double value, working_sum = 0.0;
  const double f1 = qm->get_negate_flag() * mPower.value();
  const double f2 = f1 * (mPower.value() - 1);
  Matrix3D m;
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    bool result = qm->evaluate_with_Hessian( pd, *i, value, mIndices, mGradient, mHessian, err );
    if (MSQ_CHKERR(err) || !result)
      return false;
    if (fabs(value) < DBL_EPSILON)
      continue;
    
    const size_t nfree = mIndices.size();
    n = 0;
    if (mPower.value() == 1.0) {
      working_sum += mPower.raise( value );
      for (j = 0; j < nfree; ++j) {
        mGradient[j] *= f1;
        grad_out[mIndices[j]] += mGradient[j];
        for (k = j; k < nfree; ++k) {
          mHessian[n] *= f1;
          Hessian_out.add( mIndices[j], mIndices[k], mHessian[n], err );  MSQ_ERRFALSE(err);
          ++n;
        }
     }
    }
    else {
      const double r2 = mPowerMinus2.raise( value );
      const double r1 = r2 * value;
      working_sum += r1 * value;
      const double hf = f2 * r2;
      const double gf = f1 * r1;
      for (j = 0; j < nfree; ++j) {
        for (k = j; k < nfree; ++k) {
          m.outer_product( mGradient[j], mGradient[k] );
          m *= hf;
          mHessian[n] *= gf;
          m += mHessian[n];
          Hessian_out.add( mIndices[j], mIndices[k], m, err );  MSQ_ERRFALSE(err);
          ++n;
        }
      }
      for (j = 0; j < nfree; ++j) {
        mGradient[j] *= gf;
        grad_out[mIndices[j]] += mGradient[j];
      }
    }
  }
  
    // get overall OF value, update member data, etc.
  size_t global_count;
  value_out = qm->get_negate_flag() 
            * get_value( working_sum, qmHandles.size(), type, global_count );
  const double inv_n = 1.0 / global_count;
  std::vector<Vector3D>::iterator g;
  for (g = grad_out.begin(); g != grad_out.end(); ++g)
    *g *= inv_n;
  Hessian_out.scale( inv_n );
  return true;
}
示例#9
0
bool PMeanPTemplate::evaluate_with_Hessian_diagonal( EvalType type, 
                                        PatchData& pd,
                                        double& value_out,
                                        std::vector<Vector3D>& grad_out,
                                        std::vector<SymMatrix3D>& hess_diag_out,
                                        MsqError& err )
{
  QualityMetric* qm = get_quality_metric();
  qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err );  MSQ_ERRFALSE(err);
  
    // zero gradient and hessian
  const size_t s = pd.num_free_vertices();
  grad_out.clear();
  grad_out.resize( s, 0.0 );
  hess_diag_out.clear();
  hess_diag_out.resize( s, 0.0 );
  
    // calculate OF value and gradient for just the patch
  std::vector<size_t>::const_iterator i;
  size_t j;
  double value, working_sum = 0.0;
  const double f1 = qm->get_negate_flag() * mPower.value();
  const double f2 = f1 * (mPower.value() - 1);
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    bool result = qm->evaluate_with_Hessian_diagonal( pd, *i, value, mIndices, mGradient, mDiag, err );
    if (MSQ_CHKERR(err) || !result)
      return false;
    if (fabs(value) < DBL_EPSILON)
      continue;
    
    const size_t nfree = mIndices.size();
    if (mPower.value() == 1.0) {
      working_sum += mPower.raise( value );
      for (j = 0; j < nfree; ++j) {
        const size_t idx = mIndices[j];
        hess_diag_out[idx] += f1 * mDiag[j];
        mGradient[j] *= f1;
        grad_out[idx] += mGradient[j];
      }
    }
    else {
      const double r2 = mPowerMinus2.raise( value );
      const double r1 = r2 * value;
      working_sum += r1 * value;
      const double hf = f2 * r2;
      const double gf = f1 * r1;
      for (j = 0; j < nfree; ++j) {
        const size_t idx = mIndices[j];

        hess_diag_out[idx] += hf * outer( mGradient[j] );
        hess_diag_out[idx] += gf * mDiag[j];

        mGradient[j] *= gf;
        grad_out[idx] += mGradient[j];
      }
    }
  }
  
    // get overall OF value, update member data, etc.
  size_t global_count;
  value_out = qm->get_negate_flag() 
            * get_value( working_sum, qmHandles.size(), type, global_count );
  const double inv_n = 1.0 / global_count;
  for (j = 0; j < s; ++j) {
    grad_out[j] *= inv_n;
    hess_diag_out[j] *= inv_n;
  }
  return true;
}
  bool I_DFT_NoBarrierSmoother::i_dft_no_barrier_smooth_mesh(
    PatchData &pd, size_t free_index, MsqError &err)
  {
      //get vertex and element arrays
    MsqVertex* verts=pd.get_vertex_array(err); MSQ_ERRFALSE(err);
    MsqMeshEntity* elems=pd.get_element_array(err);MSQ_ERRFALSE(err);
    size_t num_elements = pd.num_elements();
      //matrix to store a map for the given corner
      // (element/vertex combination) that maps the
      //vertex to 0 and the other vertices to 1,2,3
    int local_matrix_map[MSQ_MAX_NUM_VERT_PER_ENT];
    size_t local_matrix_map_length=MSQ_MAX_NUM_VERT_PER_ENT;
    size_t local_matrix_map_used=0;
    Vector3D new_position;
      //will be used as the denominator
    double scale_value = 0.0;
    size_t i, j, k;
      //Z and Z^(t)
    Matrix3D z_mat_transpose;
    Matrix3D z_mat[4];
      //array of Y's... one for each vertex in this corner.
    Matrix3D y_mat[4];
      //c_(j,k) for the vertices
    double c_scalars[4];
      //zeta for this corner
    Vector3D zeta_vector;
    vector<size_t> elems_verts;
      //loop over the two or three dimensions
    for(i=0;i<num_elements;++i) {
        //actually get the map for this corner...
      local_matrix_map_used = elems[i].get_local_matrix_map_about_vertex(
        pd, &verts[free_index],local_matrix_map_length, local_matrix_map,err);
      MSQ_ERRFALSE(err);
      
        //get a vector of the vertex indices for this element
      elems[i].get_vertex_indices(elems_verts);
        //get the W array for this elements
      int elem_idx = pd.get_element_index(&elems[i]);
      const TargetMatrix* W = pd.targetMatrices.get_element_corner_tags(
        &pd, elem_idx, err );      MSQ_ERRFALSE(err);

        //initial c_scalars and zeta_vector to 0.0 and calculate Y for
        //each vertex in the this corner.
      zeta_vector.set( 0.0, 0.0, 0.0);
      for(j=0;j<local_matrix_map_used;++j){
        c_scalars[j]=0.0;
        if(local_matrix_map[j] < 0){
          MSQ_SETERR(err)("Invalid index returned from MsqMeshEntity.\n",
                          MsqError::INVALID_STATE);
          return false;
        }
        inv(z_mat[j],W[local_matrix_map[j]]);
          //inv(z_mat[j], I);
        z_mat_transpose=transpose(z_mat[j]);
        matmult( y_mat[j], z_mat[j], z_mat_transpose);
          //std::cout<<"\n j "<<j<<"\n";
          //std::cout<<"\n"<<y_mat[j]<<"\n";
      }
        //0 case (c_scalars[0])
      for(j=0;j<3;++j){
        for(k=0;k<3;++k){
          c_scalars[0] += ((y_mat[0])[j][k]);
        }
        c_scalars[0] += ((y_mat[j+1])[j][j]);
      }
        //1, 2, and if need 3
      for(j=0;j<3;++j){
        for(k=0;k<3;++k){
          c_scalars[j+1] -= (((y_mat[0])[j][k]) + ((y_mat[j+1])[k][j]));
        }
        c_scalars[j+1] += ((y_mat[((j+2)%3)+1])[((j+1)%3)][((j+2)%3)]);
        c_scalars[j+1] += ((y_mat[((j+1)%3)+1])[((j+2)%3)][((j+1)%3)]);
      }
        //now do zeta_vector
      for(j=0;j<3;++j){
        for(k=0;k<3;++k){
          zeta_vector[j] += ((z_mat[0])[k][j] - (z_mat[k+1])[k][j]);
        }
      }
    
        // accumulate this corner's contribution to the numerator
        // and the denominator...
      for(j=1;j<local_matrix_map_used;++j){
          //std::cout<<"c_k ("<<j<<") ="<<c_scalars[j]<<"\n";
          //std::cout<<"x_k ("<<j<<") ="<<verts[elems_verts[ (size_t) local_matrix_map[j]]]<<"\n";
        new_position+=verts[elems_verts[ (size_t) local_matrix_map[j]]]
          *c_scalars[j];
      }
      new_position+=zeta_vector;
    
        //std::cout<<"c_k (0) ="<<c_scalars[0]<<"\n";
        //std::cout<<"zeta ="<<zeta_vector<<"\n";
      scale_value+=c_scalars[0];
    
    }
    if(scale_value==0.0){
      MSQ_SETERR(err)("Invalid accummulation.\n",
                      MsqError::INVALID_STATE);
      return false;
    }
      //divide the new position by the denominator and get the
      // negative sign into the equation.
    new_position/=(-1.0*scale_value);
      //debug
      //MSQ_DBGOUT(1) << "Original position "<<verts[free_index]<<"\n";
      //MSQ_DBGOUT(1) << "New position "<<new_position<<"\n";
      //actually set the new position
    verts[free_index].set(new_position);
  
    return true;
  }