コード例 #1
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;
}
コード例 #2
0
bool CompareMetric::evaluate_with_indices( PatchData& pd,
                 size_t handle,
                 double& value,
                 std::vector<size_t>& indices,
                 MsqError& err )
{
  double m2val;
  bool r1, r2;
  m2Handles.clear();
  r1 = metric1->evaluate_with_indices( pd, handle, value, indices, err ); MSQ_ERRZERO(err);
  r2 = metric2->evaluate_with_indices( pd, handle, m2val, m2Handles, err ); MSQ_ERRZERO(err);
  if (r1 != r2 || (r1 && fabs(value - m2val) > epsilon)) {
    MSQ_SETERR(err)(MsqError::INVALID_STATE,
                    "Metrics returned different values for handle %lu "
                    "in evaluate_with_indices:\n"
                    "\t%s %f vs. %s %f\n", (unsigned long)handle,
                    r1?"true":"false",value,r2?"true":"false",m2val);
  }
  else {
    bool same = (indices.size() == m2Handles.size());
    std::sort( m2Handles.begin(), m2Handles.end() );
    for (std::vector<size_t>::iterator i = indices.begin(); i != indices.end(); ++i) 
      if (!std::binary_search( m2Handles.begin(), m2Handles.end(), *i ))
        same = false;
    if (!same) {
      MSQ_SETERR(err)(MsqError::INVALID_STATE,
                      "Metrics returned incompatible lists of vertex indices"
                      " for handle %lu in evaluate_with_indices\n.", 
                      (unsigned long)handle );
    }
  }
  
  return r1 && !err;
}
コード例 #3
0
std::string CompareMetric::get_name() const
{
  std::string n = metric1->get_name();
  n += " =? ";
  n += metric2->get_name();
  return n;
}
コード例 #4
0
ファイル: LInfTemplate.cpp プロジェクト: haripandey/trilinos
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;
}
コード例 #5
0
ファイル: LPtoPTemplate.cpp プロジェクト: 00liujj/trilinos
bool LPtoPTemplate::evaluate_with_gradient( EvalType type, 
                                            PatchData& pd,
                                            double& OF_val,
                                            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) );
  bool qm_bool=true;
  double QM_val;
  OF_val = 0.;
  int p1;
  
    // calculate OF value and gradient for just the patch
  std::vector<size_t>::const_iterator i;
  for (i = qmHandles.begin(); i != qmHandles.end(); ++i)
  {
    qm_bool = qm->evaluate_with_gradient( pd, *i, QM_val, mIndices, mGradient, err );
    if (MSQ_CHKERR(err) || !qm_bool)
      return false;
    
    QM_val = fabs(QM_val);
    double QM_pow = 1.0;
    double factor = qm->get_negate_flag();
    if (pVal == 1) 
      QM_pow = 1.0;
    else {
      QM_pow = QM_val;
      for (p1 = 2; p1 < pVal; ++p1)
        QM_pow *= QM_val;
      factor *= QM_pow * pVal;
    }
    
    OF_val += QM_pow * QM_val;
    for (size_t j = 0; j < mIndices.size(); ++j) {
      mGradient[j] *= factor;
      grad_out[mIndices[j]] += mGradient[j];
    }
  }
  
    // get overall OF value, update member data, etc.
  size_t global_count;
  OF_val = qm->get_negate_flag() * get_value( OF_val, qmHandles.size(), type, global_count, err );
//  if (!global_count)
//    return false;  // invalid mesh

  if (dividingByN && 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;
}
コード例 #6
0
bool CompareMetric::evaluate_with_gradient( PatchData& pd,
                 size_t handle,
                 double& value,
                 std::vector<size_t>& indices,
                 std::vector<Vector3D>& gradient,
                 MsqError& err )
{
  double m2val;
  bool r1, r2;
  m2Handles.clear();
  m2Grad.clear();
  r1 = metric1->evaluate_with_gradient( pd, handle, value, indices, gradient, err ); MSQ_ERRZERO(err);
  r2 = metric2->evaluate_with_gradient( pd, handle, m2val, m2Handles, m2Grad, err ); MSQ_ERRZERO(err);
  if (r1 != r2 || (r1 && fabs(value - m2val) > epsilon)) {
    MSQ_SETERR(err)(MsqError::INVALID_STATE,
                    "Metrics returned different values for handle %lu in "
                    "evaluate_with_gradient:\n"
                    "\t%s %f vs. %s %f\n", (unsigned long)handle,
                    r1?"true":"false",value,r2?"true":"false",m2val);
  }
  else {
    std::vector<size_t>::const_iterator i, j;
    std::vector<Vector3D>::const_iterator r, s;
    int grad_diff = 0;
    bool same = (indices.size() == m2Handles.size());
    std::sort( m2Handles.begin(), m2Handles.end() );
    for (i = indices.begin(); i != indices.end(); ++i) {
      j = std::lower_bound( m2Handles.begin(), m2Handles.end(), *i );
      if (j == m2Handles.end() || *j != *i) {
        same = false;
        continue;
      }
      
      r = gradient.begin() + (i - indices.begin());
      s = m2Grad.begin() + (j - m2Handles.begin());
      if (!equal(*r,*s))
        ++grad_diff;
    }
      
    if (!same) {
      MSQ_SETERR(err)(MsqError::INVALID_STATE,
                      "Metrics returned incompatible lists of vertex indices"
                      " for handle %lu in evaluate_with_gradient\n.", 
                      (unsigned long)handle );
    }
    else if (grad_diff) {
      MSQ_SETERR(err)(MsqError::INVALID_STATE,
                      "Metrics returned different gradient vectors for "
                      " %d of %u vertices for handle %lu in "
                      "evaluate_with_gradient\n.", 
                      grad_diff, (unsigned)gradient.size(), 
                      (unsigned long)handle );
    }
  }
  
  return r1 && !err;
}
コード例 #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 CompareMetric::evaluate( PatchData& pd, 
                 size_t handle, 
                 double& value, 
                 MsqError& err )
{
  double m2val;
  bool r1, r2;
  r1 = metric1->evaluate( pd, handle, value, err ); MSQ_ERRZERO(err);
  r2 = metric2->evaluate( pd, handle, m2val, err ); MSQ_ERRZERO(err);
  if (r1 != r2 || (r1 && fabs(value - m2val) > epsilon)) {
    MSQ_SETERR(err)(MsqError::INVALID_STATE,
                    "Metrics returned different values for handle %lu "
                    "in evaluate:\n"
                    "\t%s %f vs. %s %f\n", (unsigned long)handle,
                    r1?"true":"false",value,r2?"true":"false",m2val);
  }
  
  return r1 && !err;
}
コード例 #9
0
void CompareMetric::get_evaluations( PatchData& pd, 
                                     std::vector<size_t>& handles, 
                                     bool free_vertices_only,
                                     MsqError& err )
{
  if (maskPlane)
    get_mask_axis(pd);

  m2Handles.clear();
  metric1->get_evaluations( pd, handles, free_vertices_only, err ); MSQ_ERRRTN(err);
  metric2->get_evaluations( pd, m2Handles, free_vertices_only, err ); MSQ_ERRRTN(err);
  bool same = (handles.size() == m2Handles.size());
  std::sort( m2Handles.begin(), m2Handles.end() );
  for (std::vector<size_t>::iterator i = handles.begin(); i != handles.end(); ++i) 
    if (!std::binary_search( m2Handles.begin(), m2Handles.end(), *i ))
      same = false;
  if (!same) {
    MSQ_SETERR(err)("Metrics have incompatible lists of evaluation handles.\n",
                    MsqError::INVALID_STATE);
  }
}
コード例 #10
0
bool LPtoPTemplate::concrete_evaluate(PatchData &pd, double &fval,
                                      MsqError &err){
  size_t index=0;
  MsqMeshEntity* elems=pd.get_element_array(err);
  bool obj_bool=true;
    //double check for pVal=0;
  if(pVal==0){
    MSQ_SETERR(err)("pVal equal zero not allowed.  L_0 is not a valid norm.",
                    MsqError::INVALID_STATE);
    return false;
  }
  
    //Michael:  this may not do what we want
    //Set currentQM to be the first quality metric* in the list
  QualityMetric* currentQM = get_quality_metric();
  if(currentQM==NULL)
    currentQM=get_quality_metric_list().front();
  if(currentQM==NULL) {
    MSQ_SETERR(err)("NULL QualityMetric pointer in LPtoPTemplate",
                    MsqError::INVALID_STATE);
    return false;
  }
  size_t num_elements=pd.num_elements();
  size_t num_vertices=pd.num_vertices();
  size_t total_num=0;
  if(currentQM->get_metric_type()==QualityMetric::ELEMENT_BASED)   
    total_num=num_elements;
  else if (currentQM->get_metric_type()==QualityMetric::VERTEX_BASED)
    total_num=num_vertices;
  else {
    MSQ_SETERR(err)("Make sure MetricType is initialised in concrete "
                    "QualityMetric constructor.", MsqError::INVALID_STATE);
    return false;
  }
  
  msq_std::vector<double> metric_values(total_num);
  if(currentQM->get_metric_type()==QualityMetric::ELEMENT_BASED)
  {
    for (index=0; index<num_elements;index++)
    {
        //if invalid return false after clean-up
      obj_bool=currentQM->evaluate_element(pd, (&elems[index]),
                                           metric_values[index], err);
      if(MSQ_CHKERR(err) || !obj_bool){
        fval=0.0;
        return false;
      }
      
      metric_values[index]=fabs(metric_values[index]);
      MSQ_DBGOUT(3) << "      o  Quality metric value for element "
                    << index << "\t: " << metric_values[index] << "\n";
    }
  }
  else if(currentQM->get_metric_type()==QualityMetric::VERTEX_BASED)
  {
    MsqVertex* vertices=pd.get_vertex_array(err); MSQ_ERRZERO(err);
    for (index=0; index<num_vertices;index++)
    {
        //evaluate metric for this vertex
      obj_bool=currentQM->evaluate_vertex(pd, (&vertices[index]),
                                          metric_values[index], err);
        //if invalid return false after clean-up
      if(MSQ_CHKERR(err) || !obj_bool){
        fval=0.0;
        return false;
      }
      
      metric_values[index]=fabs(metric_values[index]);
    }
  }
  fval=compute_function(&metric_values[0], total_num, err);
  return !MSQ_CHKERR(err);
}
コード例 #11
0
/* virtual function reimplemented from QualityMetric. No doxygen doc needed. */
bool LPtoPTemplate::compute_analytical_gradient(PatchData &pd,
                                              Vector3D *const &grad,
                                              double &OF_val,
                                              MsqError &err, size_t array_size)
{
  MSQ_FUNCTION_TIMER( "LPtoPTemplate::compute_analytical_gradient" );
  
    //initialize the scaling value
  double scaling_value=1.0;
 
  size_t num_elements=pd.num_elements();
  size_t num_vertices=pd.num_vertices();
  if( num_vertices!=array_size && array_size>0)
  {
    MSQ_SETERR(err)("Incorrect array size.", MsqError::INVALID_ARG);
    return false;
  }
  
  MsqMeshEntity* elems=pd.get_element_array(err); MSQ_ERRZERO(err);
  MsqVertex* vertices=pd.get_vertex_array(err); MSQ_ERRZERO(err);
  bool qm_bool=true;
  double QM_val;
  OF_val = 0.;
  size_t i;
  int p1;
  
  //Set currentQM to be quality metric (possibly composite) associated with the objective function
  QualityMetric* currentQM = get_quality_metric();
  if(currentQM==NULL) {
    MSQ_SETERR(err)("LPtoPTemplate has NULL QualityMetric pointer.",MsqError::INVALID_STATE);
    return false;
  }
  enum QualityMetric::MetricType qm_type=currentQM->get_metric_type();
  
  if (qm_type!=QualityMetric::ELEMENT_BASED &&
      qm_type!=QualityMetric::VERTEX_BASED) {
    MSQ_SETERR(err)("Make sure MetricType is initialised"
                    "in concrete QualityMetric constructor.",
                    MsqError::INVALID_STATE);
    return false;
  }


  // zeros out objective function gradient
  for (i=0; i<num_vertices; ++i)
    grad[i] =0;
  
  // Computes objective function gradient for an element based metric
  if(qm_type==QualityMetric::ELEMENT_BASED){
      //if scaling, divid by num_elements
    if(dividingByN){
      if(num_elements<=0) {
        MSQ_SETERR(err)("The number of elements should not be zero.",MsqError::INVALID_MESH);
        return false;
      }
      
      scaling_value/=num_elements;
    }
    size_t e, ve;
    size_t nfve; // num free vtx in element
    size_t nve; // num vtx in element
    MsqVertex* ele_free_vtces[MSQ_MAX_NUM_VERT_PER_ENT];
    const size_t *ele_vtces_ind;

    // loops over all elements.
    for (e=0; e<num_elements; ++e) {
      // stores the pointers to the free vertices within the element
      // (using pointer arithmetic).
      nfve = 0;
      nve = elems[e].vertex_count();
      ele_vtces_ind = elems[e].get_vertex_index_array();
      for (ve=0; ve<nve; ++ve) {
        if (vertices[ele_vtces_ind[ve]].is_free_vertex()) {
          ele_free_vtces[nfve] = vertices + ele_vtces_ind[ve];
          ++nfve;
        }
      }

      // Computes q and grad(q)
      Vector3D grad_vec[MSQ_MAX_NUM_VERT_PER_ENT];
      qm_bool = currentQM->compute_element_gradient(
                                     pd, &elems[e],
                                     ele_free_vtces,
                                     grad_vec, nfve, QM_val, err);
      if(MSQ_CHKERR(err) || !qm_bool) return false;

      // computes p*|Q(e)|^{p-1}
      QM_val = fabs(QM_val);
      double QM_pow=1.0;
      double factor;
      if (pVal==1) factor=1;
      else {
        QM_pow=QM_val;
        for (p1=1; p1<pVal-1; ++p1)
          QM_pow*=QM_val;
        factor = QM_pow * pVal;
      }
        //this scales the gradient
      factor *= (scaling_value * get_negate_flag());

        // computes Objective Function value \sum_{i=1}^{N_e} |q_i|^P
        // possibly scaled by 1/num.
      OF_val += (scaling_value * QM_pow * QM_val);
      
      // For each free vertex in the element ... 
      for (i=0; i<nfve; ++i) {
        // ... computes p*q^{p-1}*grad(q) ...
        grad_vec[i] *= factor;
        // ... and accumulates it in the objective function gradient.
        grad[pd.get_vertex_index(ele_free_vtces[i])] += grad_vec[i];
      }
    }
  }
  
  // Computes objective function gradient for a vertex based metric  
  else if (qm_type==QualityMetric::VERTEX_BASED){
      //if scaling, divide by the number of vertices
    if(dividingByN){
      if(num_elements<=0) {
        MSQ_SETERR(err)("The number of vertices should not be zero.",MsqError::INVALID_MESH);
        return false;
      }
      
      scaling_value/=num_vertices;
    }
    //vector for storing indices of vertex's connected elems
    msq_std::vector<size_t> vert_on_vert_ind;
    //position in pd's vertex array
    size_t vert_count=0;
    //position in vertex array
    size_t vert_pos=0;
    //loop over the free vertex indices to find the gradient...
    size_t vfv_array_length=10;//holds the current legth of vert_free_vtces
    msq_std::vector<MsqVertex*> vert_free_vtces(vfv_array_length);
    msq_std::vector<Vector3D> grad_vec(vfv_array_length); 
    for(vert_count=0; vert_count<num_vertices; ++vert_count){
      //For now we compute the metric for attached vertices and this
      //vertex, the above line gives us the attached vertices.  Now,
      //we must add this vertex.
      pd.get_adjacent_vertex_indices(vert_count,
                                     vert_on_vert_ind,err);
      vert_on_vert_ind.push_back(vert_count);
      size_t vert_num_vtces = vert_on_vert_ind.size();
      
      // dynamic memory management if arrays are too small.
      if(vert_num_vtces > vfv_array_length){
        vfv_array_length=vert_num_vtces+5;
        vert_free_vtces.resize(vfv_array_length);
        grad_vec.resize(vfv_array_length);
      }
      
      size_t vert_num_free_vtces=0;
      //loop over the vertices connected to this one (vert_count)
      //and put the free ones into vert_free_vtces
      while(!vert_on_vert_ind.empty()){
        vert_pos=(vert_on_vert_ind.back());
        //clear the vector as we go
        vert_on_vert_ind.pop_back();
        //if the vertex is free, add it to ver_free_vtces
        if(vertices[vert_pos].is_free_vertex()){
          vert_free_vtces[vert_num_free_vtces]=&vertices[vert_pos];
          ++vert_num_free_vtces ;
        }
      }
      
      qm_bool=currentQM->compute_vertex_gradient(pd,
                                                 vertices[vert_count],
                                                 &vert_free_vtces[0],
                                                 &grad_vec[0],
                                                 vert_num_free_vtces,
                                                 QM_val, err);
      if(MSQ_CHKERR(err) || !qm_bool){
        return false;
      }
       // computes p*|Q(e)|^{p-1}
      QM_val = fabs(QM_val);
      double QM_pow = 1.0;
      double factor;
      if (pVal==1) factor=1;
      else {
        QM_pow=QM_val;
        for (p1=1; p1<pVal-1; ++p1)
          QM_pow*=QM_val;
        factor = QM_pow * pVal;
      }
        //this scales the gradient
      factor *= (scaling_value * get_negate_flag());

      // computes Objective Function value \sum_{i=1}^{N_v} |q_i|^P
        // possibly scaled by 1/num
      OF_val += (scaling_value * QM_pow * QM_val);
      // For each free vertex around the vertex (and the vertex itself if free) ... 
      for (i=0; i < vert_num_free_vtces ; ++i) {
        // ... computes p*q^{p-1}*grad(q) ...
        grad_vec[i] *= factor;
        // ... and accumulates it in the objective function gradient.
        grad[pd.get_vertex_index(vert_free_vtces[i])] += grad_vec[i];
      }
    }
  }

  OF_val *= get_negate_flag();
  
  return true;  

}
コード例 #12
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;
}
コード例 #13
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;
}
コード例 #14
0
ファイル: LPtoPTemplate.cpp プロジェクト: 00liujj/trilinos
/*\ For each element, each entry to be accumulated in the Hessian for
    this objective function (\f$ \sum_{e \in E} Q(e)^p \f$ where \f$ E \f$
    is the set of all elements in the patch) has the form:
    \f$ pQ(e)^{p-1} \nabla^2 Q(e) + p(p-1)Q(e)^{p-2} \nabla Q(e) [\nabla Q(e)]^T \f$.

    For \f$ p=2 \f$, this simplifies to
    \f$ 2Q(e) \nabla^2 Q(e) + 2 \nabla Q(e) [\nabla Q(e)]^T \f$.

    For \f$ p=1 \f$, this simplifies to \f$ \nabla^2 Q(e) \f$.

    The \f$ p=1 \f$ simplified version is implemented directly
    to speed up computation. 

    This function does not support vertex-based metrics.
    
    \param pd The PatchData object for which the objective function
           hessian is computed.
    \param hessian this object must have been previously initialized.
*/
bool LPtoPTemplate::evaluate_with_Hessian( EvalType type, 
                                           PatchData& pd,
                                           double& OF_val,
                                           std::vector<Vector3D>& grad,
                                           MsqHessian& hessian,
                                           MsqError& err )
{
  QualityMetric* qm = get_quality_metric();
  qm->get_evaluations( pd, qmHandles, OF_FREE_EVALS_ONLY, err );  MSQ_ERRFALSE(err);
  double negate_flag = qm->get_negate_flag();
  
    // zero gradient and hessian
  grad.clear();
  grad.resize( pd.num_free_vertices(), 0.0 );
  hessian.zero_out();
  
  double QM_val, QM_pow = 1.0;
  double fac1, fac2;
  Matrix3D elem_outer_product;
  bool qm_bool;
  size_t i, j, n;
  short p;
   
  // Loops over all elements in the patch.
  OF_val = 0.0;
  std::vector<size_t>::const_iterator k;
  for (k = qmHandles.begin(); k != qmHandles.end(); ++k)
  {
    // Computes \nabla^2 Q(e). Only the free vertices will have non-zero entries. 
    qm_bool = qm->evaluate_with_Hessian( pd, *k, QM_val, mIndices, mGradient, mHessian, err );
    if (MSQ_CHKERR(err) || !qm_bool) 
      return false;
    QM_val = fabs(QM_val);

    // **** Computes Hessian ****
    const size_t nve = mIndices.size();
    if (pVal == 1) {
      QM_pow = 1.0;
      n=0;
      for (i=0; i<nve; ++i) {
        for (j=i; j<nve; ++j) {
            //negate if necessary
          mHessian[n] *= negate_flag;
          hessian.add( mIndices[i], mIndices[j], mHessian[n], err ); MSQ_ERRFALSE(err);
          ++n;
        }
      }
      fac1 = 1;
    }
    else if (pVal >= 2) {
       // Computes the coefficients:
      QM_pow = 1.0;
      for (p=0; p<pVal-2; ++p)
        QM_pow *= QM_val;
      // 1 - computes p(p-1)Q(e)^{p-2}
      fac2 = pVal* (pVal-1) * QM_pow;
      // 2 - computes  pQ(e)^{p-1}
      QM_pow *= QM_val;
      fac1 = pVal * QM_pow;

        //fac1 *= qm->get_negate_flag();
        //fac2 *= qm->get_negate_flag();

      n=0;
      for (i=0; i<nve; ++i) {
        for (j=i; j<nve; ++j) {
          elem_outer_product.outer_product(mGradient[i], mGradient[j]);
          elem_outer_product *= fac2;
          mHessian[n] *= fac1;
          mHessian[n] += elem_outer_product;
          mHessian[n] *= negate_flag;
          hessian.add( mIndices[i], mIndices[j], mHessian[n], err ); MSQ_ERRFALSE(err);
          ++n;
        }
      }
    } else {
      MSQ_SETERR(err)(" invalid P value.", MsqError::INVALID_STATE);
      return false;
    }


    // **** Computes Gradient ****

    // For each vertex in the element ... 
    for (i=0; i<nve; ++i) {
      // ... computes p*q^{p-1}*grad(q) ...
      mGradient[i] *= fac1*negate_flag;
      // ... and accumulates it in the objective function gradient.
        //also scale the gradient by the scaling factor
      assert (mIndices[i] < pd.num_free_vertices());
      grad[mIndices[i]] += mGradient[i];
    }

    // **** computes Objective Function value \sum_{i=1}^{N_e} |q_i|^P ****
    OF_val += QM_pow * QM_val;
  }

  size_t global_count;
  OF_val = negate_flag
         * get_value( OF_val, qmHandles.size(), type, global_count, err );
//  if (!global_count)
//    return false;  // invalid mesh

  if (dividingByN && global_count) {
    const double inv_n = 1.0 / global_count;
    std::vector<Vector3D>::iterator g;
    for (g = grad.begin(); g != grad.end(); ++g)
      *g *= inv_n;
    hessian.scale( inv_n );
  }
  
  return true;
}
コード例 #15
0
QualityMetric::MetricType NumericQM::get_metric_type() const
  { return realMetric->get_metric_type(); }
コード例 #16
0
bool CompareMetric::evaluate_with_Hessian( PatchData& pd,
                 size_t handle,
                 double& value,
                 std::vector<size_t>& indices,
                 std::vector<Vector3D>& gradient,
                 std::vector<Matrix3D>& Hessian,
                 MsqError& err )
{
  double m2val;
  bool r1, r2;
  m2Handles.clear();
  m2Grad.clear();
  m2Hess.clear();
  r1 = metric1->evaluate_with_Hessian( pd, handle, value, indices, gradient, Hessian, err ); MSQ_ERRZERO(err);
  r2 = metric2->evaluate_with_Hessian( pd, handle, m2val, m2Handles, m2Grad, m2Hess, err ); MSQ_ERRZERO(err);
  if (r1 != r2 || fabs(value - m2val) > epsilon) {
    MSQ_SETERR(err)(MsqError::INVALID_STATE,
                    "Metrics returned different values for handle %lu in "
                    "evaluate_with_Hessian:\n"
                    "\t%s %f vs. %s %f\n", (unsigned long)handle,
                    r1?"true":"false",value,r2?"true":"false",m2val);
  }
  else {
    std::vector<size_t>::const_iterator i, j;
    std::vector<Vector3D>::const_iterator r, s;
    int grad_diff = 0, hess_diff = 0;
    bool same = (indices.size() == m2Handles.size());
    std::sort( m2Handles.begin(), m2Handles.end() );
    for (i = indices.begin(); i != indices.end(); ++i) {
      j = std::lower_bound( m2Handles.begin(), m2Handles.end(), *i );
      if (j == m2Handles.end() || *j != *i) {
        same = false;
        continue;
      }
      
      r = gradient.begin() + (i - indices.begin());
      s = m2Grad.begin() + (j - m2Handles.begin());
      if (!equal(*r,*s)) {
        ++grad_diff;
          // call again for so debugger can step into it after failure is found
        std::vector<size_t> i2;
        std::vector<Vector3D> g2;
        std::vector<Matrix3D> h2;
        metric2->evaluate_with_Hessian(pd, handle, m2val, i2, g2, h2, err );
      }
    }  
     
    if (!same) {
      MSQ_SETERR(err)(MsqError::INVALID_STATE,
                      "Metrics returned incompatible lists of vertex indices"
                      " for handle %lu in evaluate_with_Hessian\n.", 
                      (unsigned long)handle );
    }
    else if (grad_diff) {
      MSQ_SETERR(err)(MsqError::INVALID_STATE,
                      "Metrics returned different gradient vectors for "
                      " %d of %u vertices for handle %lu in "
                      "evaluate_with_Hessian\n.", 
                      grad_diff, (unsigned)gradient.size(), 
                      (unsigned long)handle );
    }
    else {
      size_t row, col, row2, col2, idx, idx2;
      for (row = idx = 0; row < indices.size(); ++row) {
        row2 = std::lower_bound( m2Handles.begin(), m2Handles.end(), indices[row] ) - m2Handles.begin();
        for (col = row; col < indices.size(); ++col, ++idx) {
          col2 = std::lower_bound( m2Handles.begin(), m2Handles.end(), indices[col] ) - m2Handles.begin();
          if (row2 <= col2) {
            idx2 = indices.size()*row2 - row2*(row2+1)/2 + col2;
            if (!equal(Hessian[idx], m2Hess[idx2]))
              ++hess_diff;
          }
          else {
            idx2 = indices.size()*col2 - col2*(col2+1)/2 + row2;
            if (!equal(Hessian[idx], transpose(m2Hess[idx2])))
              ++hess_diff;
          }
        }
      }

      if (hess_diff) {
        MSQ_SETERR(err)(MsqError::INVALID_STATE,
                        "Metrics returned different Hessian blocks for "
                        " %d of %u vertices for handle %lu in "
                        "evaluate_with_Hessian\n.", 
                        hess_diff, (unsigned)Hessian.size(), 
                        (unsigned long)handle );
      }
    }
  }
  
  return r1 && !err;
}
コード例 #17
0
std::string NumericQM::get_name() const{
  std::string r = realMetric->get_name();
  r += " (FD)";
  return r;
}
コード例 #18
0
void NumericQM::get_evaluations( PatchData& pd,
                      std::vector<size_t>& handles, 
                      bool free_vertices_only,
                      MsqError& err )
{ realMetric->get_evaluations( pd, handles, free_vertices_only, err ); }
コード例 #19
0
int NumericQM::get_negate_flag() const
{ return realMetric->get_negate_flag(); }
コード例 #20
0
bool NumericQM::evaluate( PatchData& pd, 
                size_t handle, 
                double& value, 
                MsqError& err )
{ return realMetric->evaluate( pd, handle, value, err ); }
コード例 #21
0
/*! \fn LPtoPTemplate::compute_analytical_hessian(PatchData &pd, MsqHessian &hessian, MsqError &err)

    For each element, each entry to be accumulated in the Hessian for
    this objective function (\f$ \sum_{e \in E} Q(e)^p \f$ where \f$ E \f$
    is the set of all elements in the patch) has the form:
    \f$ pQ(e)^{p-1} \nabla^2 Q(e) + p(p-1)Q(e)^{p-2} \nabla Q(e) [\nabla Q(e)]^T \f$.

    For \f$ p=2 \f$, this simplifies to
    \f$ 2Q(e) \nabla^2 Q(e) + 2 \nabla Q(e) [\nabla Q(e)]^T \f$.

    For \f$ p=1 \f$, this simplifies to \f$ \nabla^2 Q(e) \f$.

    The \f$ p=1 \f$ simplified version is implemented directly
    to speed up computation. 

    This function does not support vertex-based metrics.
    
    \param pd The PatchData object for which the objective function
           hessian is computed.
    \param hessian: this object must have been previously initialized.
*/
bool LPtoPTemplate::compute_analytical_hessian(PatchData &pd,
                                               MsqHessian &hessian,
                                               Vector3D *const &grad,
                                               double &OF_val,
                                               MsqError &err)
{
  double scaling_value=1.0;
  
  MSQ_FUNCTION_TIMER( "LPtoPTemplate::compute_analytical_hessian" );

  MsqMeshEntity* elements = pd.get_element_array(err); MSQ_ERRZERO(err);
  MsqVertex* vertices = pd.get_vertex_array(err); MSQ_ERRZERO(err);
  size_t num_elems = pd.num_elements();
    //if scaling divide by the number of elements.
  if(dividingByN){
    if(num_elems<=0) {
      MSQ_SETERR(err)("LPtoP is attempting to divide by zero in analytical Hessian.",
                      MsqError::INVALID_MESH);
      return false;
    }
    scaling_value/=num_elems;
  }
  
  size_t num_vertices = pd.num_vertices();
  Matrix3D elem_hessian[MSQ_MAX_NUM_VERT_PER_ENT*(MSQ_MAX_NUM_VERT_PER_ENT+1)/2];
  Matrix3D elem_outer_product;
  Vector3D grad_vec[MSQ_MAX_NUM_VERT_PER_ENT];
  double QM_val;
  double fac1, fac2;
  Matrix3D grad_outprod;
  bool qm_bool;
  QualityMetric* currentQM = get_quality_metric();
  
  MsqVertex* ele_free_vtces[MSQ_MAX_NUM_VERT_PER_ENT];
  short i;
  for (i=0; i<MSQ_MAX_NUM_VERT_PER_ENT; ++i) ele_free_vtces[i]=NULL;
  
  const size_t* vtx_indices;
    
  size_t e, v;
  size_t nfve; // number of free vertices in element
  short j,n;

  hessian.zero_out();
  for (v=0; v<num_vertices; ++v) grad[v] = 0.;
  OF_val = 0.;
  
  // Loops over all elements in the patch.
  for (e=0; e<num_elems; ++e) {
    short nve = elements[e].vertex_count();
    
    // Gets a list of free vertices in the element.
    vtx_indices = elements[e].get_vertex_index_array();
    nfve=0;
    for (i=0; i<nve; ++i) {
      if ( vertices[vtx_indices[i]].is_free_vertex() ) {
        ele_free_vtces[nfve] = vertices + vtx_indices[i];
        ++nfve;
      }
    }
    
    // Computes \nabla^2 Q(e). Only the free vertices will have non-zero entries. 
    qm_bool = currentQM->compute_element_hessian(pd,
                                    elements+e, ele_free_vtces,
                                    grad_vec, elem_hessian,
                                    nfve, QM_val, err);
    if (MSQ_CHKERR(err) || !qm_bool) return false;


    // **** Computes Hessian ****
    double QM_pow=1.;
    if (pVal == 1) {
      n=0;
      for (i=0; i<nve; ++i) {
        for (j=i; j<nve; ++j) {
            //negate if necessary
          elem_hessian[n] *= (scaling_value * get_negate_flag());
          ++n;
        }
      }
      hessian.accumulate_entries(pd, e, elem_hessian, err);
      fac1 = 1;
    }
    else if (pVal >= 2) {
      // Computes the coefficients:
      QM_val = fabs(QM_val);
      QM_pow = 1;
      for (i=0; i<pVal-2; ++i)
        QM_pow *= QM_val;
      // 1 - computes p(p-1)Q(e)^{p-2}
      fac2 = pVal* (pVal-1) * QM_pow;
      // 2 - computes  pQ(e)^{p-1}
      QM_pow *= QM_val;
      fac1 = pVal * QM_pow;

        //fac1 *= get_negate_flag();
        //fac2 *= get_negate_flag();

      n=0;
      for (i=0; i<nve; ++i) {
        for (j=i; j<nve; ++j) {
          if ( vertices[vtx_indices[i]].is_free_vertex() &&
               vertices[vtx_indices[j]].is_free_vertex() ) {
            // Computes \nabla Q(e) [\nabla Q(e)]^T 
            elem_outer_product.outer_product(grad_vec[i], grad_vec[j]);

	    elem_outer_product *= fac2;
	    elem_hessian[n] *= fac1;
	    elem_hessian[n] += elem_outer_product;
          } else {
            // elem_outer_product is nul 
            elem_hessian[n] *= fac1;
          }
            //scale the hessian by the scaling factor
          elem_hessian[n] *= (scaling_value * get_negate_flag());
          ++n;
        }
      }

      hessian.accumulate_entries(pd, e, elem_hessian, err); MSQ_ERRZERO(err);

    } else {
      MSQ_SETERR(err)(" invalid P value.", MsqError::INVALID_STATE);
      return false;
    }


    // **** Computes Gradient ****

    // For each vertex in the element ... 
    for (i=0; i<nve; ++i) {
      if ( vertices[vtx_indices[i]].is_free_vertex() ) {
        // ... computes p*q^{p-1}*grad(q) ...
        grad_vec[i] *= fac1*get_negate_flag();
        // ... and accumulates it in the objective function gradient.
          //also scale the gradient by the scaling factor
        grad[vtx_indices[i]] += (scaling_value * grad_vec[i]);
      }
    }
    
    // **** computes Objective Function value \sum_{i=1}^{N_e} |q_i|^P ****
      //and scale by 1/num if necessary
    OF_val += (scaling_value * QM_pow * QM_val);
    
  }

  OF_val *= get_negate_flag();
  
  return true;
}
コード例 #22
0
int CompareMetric::get_negate_flag() const
{
  assert(metric1->get_negate_flag() == metric2->get_negate_flag());
  return metric1->get_negate_flag();
}
コード例 #23
0
bool NumericQM::evaluate_with_indices( PatchData& pd,
               size_t handle,
               double& value,
               std::vector<size_t>& indices,
               MsqError& err )
{ return realMetric->evaluate_with_indices( pd, handle, value, indices, err ); }
コード例 #24
0
QualityMetric::MetricType CompareMetric::get_metric_type() const
{
  MetricType t1 = metric1->get_metric_type();
  assert(metric2->get_metric_type() == t1);
  return t1;
}