void CircleDomainTest::test_snap_to() { Vector3D origin(0,0,0); Vector3D z(0,0,1); double rad1 = 4.0/3.0; CircleDomain dom1( origin, z, rad1 ); Vector3D pt( 1, 0, 0 ); dom1.snap_to( 0, pt ); CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D(rad1,0,0), pt, 1e-6 ); Vector3D a = Vector3D( 1, 2, 3 ); pt = a; dom1.snap_to( 0, pt ); a = Vector3D( 1, 2, 0 ); a *= rad1 / a.length(); CPPUNIT_ASSERT_VECTORS_EQUAL( a, pt, 1e-6 ); Vector3D some_pt(5,-1,6); Vector3D some_dir(-5,-4,1); double rad2 = 1.0; CircleDomain dom2( some_pt, some_dir, rad2 ); a = Vector3D( 0, 0, 0); pt = a; dom2.snap_to( 0, pt ); CPPUNIT_ASSERT_DOUBLES_EQUAL( rad2, (pt - some_pt).length(), 1e-6 ); // rad from center CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, (pt - some_pt) % some_dir, 1e-6 );// in plane CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ((pt - some_pt) * (a - some_pt)) % some_dir, 1e-6 ); // correct direction from center a = Vector3D( 0, -1, -2 ); pt = a; dom2.snap_to( 0, pt ); CPPUNIT_ASSERT_DOUBLES_EQUAL( rad2, (pt - some_pt).length(), 1e-6 ); // rad from center CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, (pt - some_pt) % some_dir, 1e-6 );// in plane CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ((pt - some_pt) * (a - some_pt)) % some_dir, 1e-6 ); // correct direction from center }
void ObjectiveFunctionTests::compare_hessian_diagonal( ObjectiveFunction* of ) { MsqPrintError err(std::cout); PatchData pd; create_twelve_hex_patch( pd, err ); ASSERT_NO_ERROR( err ); std::vector<Vector3D> diag_grad, hess_grad; std::vector<SymMatrix3D> diag; MsqHessian hess; double diag_val, hess_val; bool valid; valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, diag_val, diag_grad, diag, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag_grad.size() ); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag.size() ); hess.initialize( pd, err ); ASSERT_NO_ERROR( err ); valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() ); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess.size() ); CPPUNIT_ASSERT_DOUBLES_EQUAL( hess_val, diag_val, 1e-6 ); for (size_t i = 0; i < pd.num_free_vertices(); ++i) { CPPUNIT_ASSERT_VECTORS_EQUAL( hess_grad[i], diag_grad[i], 1e-6 ); CPPUNIT_ASSERT_MATRICES_EQUAL( *hess.get_block(i,i), diag[i], 1e-6 ); } }
void ObjectiveFunctionTests::compare_diagonal_gradient( ObjectiveFunction* of ) { MsqPrintError err(std::cout); PatchData pd; create_twelve_hex_patch( pd, err ); ASSERT_NO_ERROR( err ); std::vector<Vector3D> grad, hess_grad; std::vector<SymMatrix3D> hess; double grad_val, hess_val; bool valid; valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, grad_val, grad, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), grad.size() ); valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() ); CPPUNIT_ASSERT_DOUBLES_EQUAL( grad_val, hess_val, 1e-6 ); for (size_t i = 0; i < pd.num_free_vertices(); ++i) { CPPUNIT_ASSERT_VECTORS_EQUAL( grad[i], hess_grad[i], 1e-6 ); } }
void ObjectiveFunctionTests::compare_numerical_gradient( ObjectiveFunction* of ) { MsqPrintError err(std::cout); PatchData pd; create_twelve_hex_patch( pd, err ); ASSERT_NO_ERROR( err ); std::vector<Vector3D> num_grad, ana_grad; double num_val, ana_val; bool valid; valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, ana_val, ana_grad, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), ana_grad.size() ); valid = of->ObjectiveFunction::evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, num_val, num_grad, err ); ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(valid); CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), num_grad.size() ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ana_val, num_val, 1e-6 ); for (size_t i = 0; i < pd.num_free_vertices(); ++i) { CPPUNIT_ASSERT_VECTORS_EQUAL( num_grad[i], ana_grad[i], 1e-3 ); } }
void CircleDomainTest::test_position_from_length() { MsqPrintError err(std::cerr); Vector3D origin(0,0,0); Vector3D z(0,0,1); double rad1 = 4.0/3.0; CircleDomain dom1( origin, z, rad1 ); Vector3D xp = Vector3D(1,0,0); Vector3D xn = Vector3D(-1,0,0); Vector3D yp = Vector3D(0,1,0); const double qc = 0.5 * rad1 * M_PI; Vector3D result; dom1.position_from_length( xp.to_array(), qc, result.to_array(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( yp*rad1, result, 1e-6 ); dom1.position_from_length( xp.to_array(), 2*qc, result.to_array(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( xn*rad1, result, 1e-6 ); dom1.position_from_length( yp.to_array(), -qc, result.to_array(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( xp*rad1, result, 1e-6 ); dom1.position_from_length( (xp+z).to_array(), qc, result.to_array(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( yp*rad1, result, 1e-6 ); Vector3D center(-1,-2,-1); Vector3D normal(-2,-1,-2); double rad2 = 1.5; CircleDomain dom2( center, normal, rad2 ); Vector3D v(1,0,0); v = v * normal; v *= rad2 / v.length(); v += center; dom2.position_from_length( v.to_array(), 0.0, result.to_array(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( v, result, 1e-6 ); }
/** Test correct handling of QM negate flag */ void ObjectiveFunctionTests::test_negate_flag( OFTestMode test_mode, 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); MsqPrintError err(cout); bool rval = false; double value[2]; vector<Vector3D> grad[2]; vector<SymMatrix3D> diag[2]; MsqHessian hess[2]; // Do twice, once w/out negate flag set and then once // with negate flag == -1. ObjectiveFunction::EvalType type = ObjectiveFunction::CALCULATE; for (unsigned i = 0; i < 2; ++i ) { switch (test_mode) { case EVAL: rval = of->evaluate( type, patch(), value[i], false, err ); break; case GRAD: rval = of->evaluate_with_gradient( type, patch(), value[i], grad[i], err ); break; case DIAG: rval = of->evaluate_with_Hessian_diagonal( type, patch(), value[i], grad[i], diag[i], err ); break; case HESS: hess[i].initialize(patch(),err); ASSERT_NO_ERROR( err ); rval = of->evaluate_with_Hessian( type, patch(), value[i], grad[i], hess[i], err ); break; default: CPPUNIT_ASSERT_MESSAGE("Invalid enum value in test code",false); break; } ASSERT_NO_ERROR( err ); CPPUNIT_ASSERT(rval); metric.set_negate_flag(-1); } switch (test_mode) { case HESS: CPPUNIT_ASSERT_EQUAL( hess[0].size(), hess[1].size() ); for (size_t r = 0; r < hess[0].size(); ++r) for (size_t c = r; c < hess[0].size(); ++c) if (hess[0].get_block(r,c)) CPPUNIT_ASSERT_MATRICES_EQUAL( -*hess[0].get_block(r,c), *hess[1].get_block(r,c), 1e-6 ); case DIAG: // NOTE: When case HESS: falls through to here, diag[0] and diag[1] // will be empty, making this a no-op. CPPUNIT_ASSERT_EQUAL( diag[0].size(), diag[1].size() ); for (size_t j = 0; j < diag[0].size(); ++j) CPPUNIT_ASSERT_MATRICES_EQUAL( -diag[0][j], diag[1][j], 1e-6 ); case GRAD: CPPUNIT_ASSERT_EQUAL( grad[0].size(), grad[1].size() ); for (size_t j = 0; j < grad[0].size(); ++j) CPPUNIT_ASSERT_VECTORS_EQUAL( -grad[0][j], grad[1][j], 1e-6 ); default: CPPUNIT_ASSERT_DOUBLES_EQUAL( -value[0], value[1], 1e-6 ); } }