Exemplo n.º 1
0
bool TMPQualityMetric::evaluate_with_indices( PatchData& pd,
        size_t handle,
        double& value,
        std::vector<size_t>& indices,
        MsqError& err )
{
    indices.resize( MAX_ELEM_NODES );
    size_t num_idx = 0;
    bool result = evaluate_internal( pd, handle, value, arrptr(indices), num_idx, err );
    if (MSQ_CHKERR(err) || !result)
        return false;

    indices.resize( num_idx );

    // apply target weight to value
    if (weightCalc) {
        const Sample s = ElemSampleQM::sample( handle );
        const size_t e = ElemSampleQM::  elem( handle );
        double ck = weightCalc->get_weight( pd, e, s, err );
        MSQ_ERRZERO(err);
        value *= ck;
    }

    return true;
}
void ObjectiveFunctionTests::test_value( 
                        const double* input_values,
                        unsigned num_input_values,
                        double expected_value,
                        OFTestMode test_mode,
                        ObjectiveFunctionTemplate* of )
{
  OFTestQM metric( input_values, num_input_values );
  of->set_quality_metric( &metric );
  
  double val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
  CPPUNIT_ASSERT_DOUBLES_EQUAL( expected_value, val, 1e-6 );
}
bool TMPQualityMetric::evaluate( PatchData& pd, size_t handle, double& value, MsqError& err )
{
  size_t num_idx;
  bool valid = evaluate_internal( pd, handle, value, mIndices, num_idx, err );
  if (MSQ_CHKERR(err) || !valid)
    return false;
  
    // apply target weight to value
  if (weightCalc) {
    const Sample s = ElemSampleQM::sample( handle );
    const size_t e = ElemSampleQM::  elem( handle );
    double ck = weightCalc->get_weight( pd, e, s, err ); MSQ_ERRZERO(err);
    value *= ck;
  }
  return true;
}
void ObjectiveFunctionTests::test_clone( ObjectiveFunctionTemplate* of )
{
  const double some_vals[] = { 1, 2, 3, 4, 5, 6, 0.5 };
  const unsigned num_vals = sizeof(some_vals)/sizeof(some_vals[0]);
  OFTestQM metric( some_vals, num_vals );
  of->set_quality_metric(&metric);
  
    // test that we get the same value from both
  auto_ptr<ObjectiveFunction> of2( of->clone() );
  double exp_val, val;
  exp_val = evaluate_internal( ObjectiveFunction::CALCULATE, EVAL, of );
  val = evaluate_internal( ObjectiveFunction::CALCULATE, EVAL, of2.get() );
  CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_val, val, 1e-12 );
  
    // check if OF supports BCD -- if not then done
  MsqError err;
  of->evaluate( ObjectiveFunction::UPDATE, patch(), val, false, err );
  if (err) {
    err.clear();
    return;
  }
  
    // build up some saved state in the objective function
  of->clear();
  const double vals1[] = { 1.0, 3.0, 4.0, 8.0 };
  const size_t vals1_len = sizeof(vals1)/sizeof(vals1[0]);
  const double vals2[] = { 21.5, 11.1, 30.0, 0.5 };
  const size_t vals2_len = sizeof(vals2)/sizeof(vals2[0]);
  metric.set_values( vals1, vals1_len );
  evaluate_internal( ObjectiveFunction::SAVE, EVAL, of );
  metric.append_values( vals2, vals2_len );
  evaluate_internal( ObjectiveFunction::ACCUMULATE, EVAL, of );
  
    // check that clone has same accumulated data
  of2 = auto_ptr<ObjectiveFunction>(of->clone());
  metric.set_values( some_vals, num_vals );
  exp_val = evaluate_internal( ObjectiveFunction::UPDATE, EVAL, of );
  val = evaluate_internal( ObjectiveFunction::UPDATE, EVAL, of2.get() );
  CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_val, val, 1e-12 );
}
void ObjectiveFunctionTests::test_eval_type( 
                            ObjectiveFunction::EvalType type,
                            OFTestMode test_mode,
                            ObjectiveFunctionTemplate* of )
{
    // define two sets of quality metric values
  const double vals1[] = { 1.0, 3.0, 4.0, 8.0 };
  const size_t vals1_len = sizeof(vals1)/sizeof(vals1[0]);
  const double vals2[] = { 21.5, 11.1, 30.0, 0.5 };
  const size_t vals2_len = sizeof(vals2)/sizeof(vals2[0]);
  
    // create a quality metric to use
  OFTestQM metric;
  of->set_quality_metric( &metric );
  
    // get some initial values to compare to
  of->clear();
  metric.set_values( vals1, vals1_len );
  const double init1 = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
  of->clear();
  metric.set_values( vals2, vals2_len );
  const double init2 = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
  of->clear();
  metric.append_values( vals1, vals1_len );
  const double inits = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
  of->clear();

  double val, expected;  
  switch (type) {
    case ObjectiveFunction::CALCULATE:
    
        // first make sure we get back the same values
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );
      
        // now do something that should modify the accumulated value of the OF
      evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      
        // check that the values are unchanged
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );
      
      break;
      
    case ObjectiveFunction::ACCUMULATE:
      
        // begin with first set
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
        
        // add in second set
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );
      
        // clear 
      of->clear();
      
        // begin with second set
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );
      
        // add in first set
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );
      
      break;
      
    case ObjectiveFunction::SAVE:
      
        // calculate value for first set twice
      metric.set_values( vals1, vals1_len );
      metric.append_values( vals1, vals1_len );
      expected = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
      
        // begin with the first set
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
      
        // add the second set
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );
      
        // now save the second set of values - OF value should not change
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::SAVE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );
      
        // now replace the second set with the first
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, val, 1e-6 );
      
        // check that saved values are cleared
      of->clear();
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );
      
      break;
 
    case ObjectiveFunction::UPDATE:
      
        // With no saved data, an update should produce the same
        // result as CALCULATE
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );

        // Doing an update with a second patch should change
        // the global value to that of the second set
      metric.set_values( vals2, vals2_len );
      val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );
      
        // Now add in the second set again
      metric.set_values( vals2, vals2_len );
      evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      
        // Now replace one accumulation of the second set with the first
        // Should result in the first set + the second set
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );
     
      break;

    case ObjectiveFunction::TEMPORARY:
      
        // With no saved data, an TEMPORARY should produce the same
        // result as CALCULATE
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::TEMPORARY, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
      
        // Begin with two instances of the second set in the 
        // accumulated value, with one instance saved so it 
        // can be removed later
      metric.set_values( vals2, vals2_len );
      evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
      evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      
        // Now do a temporary eval, replacing one instance of the
        // second set wiht the first set
      metric.set_values( vals1, vals1_len );
      val = evaluate_internal( ObjectiveFunction::TEMPORARY, test_mode, of );
      
        // TEMPORARY should produce the same value as UPDATE, but without
        // modifying any internal state.  
      expected = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, val, 1e-6 );
      
      break;
      
    default:
      CPPUNIT_ASSERT_MESSAGE("No test for specified evaluation type", false);
      break;
  }
}