TEST(FunctionalExpansionsTest, zernikeSeriesEvaluationYZ) { const unsigned int order = 4; const Point location(-0.90922108754014, 0.262698547343, 0.156796889218); expansion_type = "standard"; generation_type = "orthonormal"; Zernike zernike({FunctionalBasisInterface::_domain_options = "y", FunctionalBasisInterface::_domain_options = "z"}, {order}, expansion_type, generation_type); zernike.setLocation(location); const std::array<Real, 15> truth = {{0.318309886183791, 0.052230505695590, 0.330374978445085, 0.040657672622662, -0.823129261009826, 0.125372638358686, 0.020923587239414, -0.187295294511344, -1.184703806003468, 0.041151106306071, 0.008896570968308, -0.184582980412102, 0.978025517529447, -0.569182979683797, 0.012274247968574}}; auto & answer = zernike.getAllGeneration(); for (std::size_t i = 0; i < zernike.getNumberOfTerms(); ++i) EXPECT_NEAR(answer[i], truth[i], tol); }
TEST(FunctionalExpansionsTest, zernikeSeriesEvaluationXZ) { const unsigned int order = 4; const Point location(-0.90922108754014, 0.262698547343, 0.156796889218); expansion_type = "standard"; generation_type = "orthonormal"; Zernike zernike({FunctionalBasisInterface::_domain_options = "x", FunctionalBasisInterface::_domain_options = "z"}, {order}, expansion_type, generation_type); zernike.setLocation(location); const std::array<Real, 15> truth = {{0.318309886183791, -0.180774038043348, -1.143454732567233, 0.487041727962393, 0.623918544603900, 1.501849527692451, -0.867504286868072, -0.173560777222340, -1.097828505968007, -1.706149176114187, 1.276644449771070, 0.248985426801565, 0.223343150486739, 0.767775375651402, 1.761335979897610}}; auto & answer = zernike.getAllGeneration(); for (std::size_t i = 0; i < zernike.getNumberOfTerms(); ++i) EXPECT_NEAR(answer[i], truth[i], tol); }
TEST(FunctionalExpansionsTest, zernikeSeriesEvaluationXY) { const unsigned int order = 4; const Point location(-0.90922108754014, 0.262698547343, 0.156796889218); expansion_type = "standard"; generation_type = "orthonormal"; Zernike zernike({FunctionalBasisInterface::_domain_options = "x", FunctionalBasisInterface::_domain_options = "y"}, {order}, expansion_type, generation_type); zernike.setLocation(location); const std::array<Real, 15> truth = {{0.318309886183791, -0.300628811510287, -1.117940202314423, 0.791881706198328, 0.623918544603900, 1.365900806059890, -1.357069098439213, -0.288633095470502, -1.073332058640328, -1.349767446988918, 1.887803726543957, 0.404825692079851, 0.223343150486739, 0.698275682841869, 1.080889714660983}}; auto & answer = zernike.getAllGeneration(); for (std::size_t i = 0; i < zernike.getNumberOfTerms(); ++i) EXPECT_NEAR(answer[i], truth[i], tol); }
void setup_zernike(void) { int i, j; float rho, theta; /* Make the mutex so this will be thread safe */ if (pthread_mutex_init(&zernike_mutex, NULL) != 0) error(FATAL, "Unable to create Zernike mutex."); /* Normalize the x and y */ for (i=1; i<= NUM_ACTUATORS; i++) { actuator_x[i] /= 3.0; actuator_y[i] *= (sqrt(0.75)/3.0); } /* Setup the zernike stuff */ set_up_zernike_calcs(maxJ); /* Allocate memory iand fill things in */ actuator_zernike_values[0] = NULL; zernike_max = -1e32; zernike_min = 1e32; for (i=1; i<= NUM_ACTUATORS; i++) { actuator_zernike_values[i]=malloc(sizeof(float)*(maxJ+1)); if (actuator_zernike_values[i] == NULL) error(FATAL, "Not enough memory."); rho = sqrt(actuator_x[i]*actuator_x[i] + actuator_y[i]*actuator_y[i]); if (rho > 1.0) rho = 1.0; theta = atan2(actuator_y[i], actuator_x[i]); if (theta < 0.0) theta += (2.0*M_PI); for(j=1; j<= maxJ; j++) { actuator_zernike_values[i][j] = zernike(j,rho,theta); if (actuator_zernike_values[i][j] > zernike_max) zernike_max = actuator_zernike_values[i][j]; else if (actuator_zernike_values[i][j] < zernike_min) zernike_min = actuator_zernike_values[i][j]; } } /* Now we allocate the first version of the zernike values */ zernike_values = malloc(sizeof(float)*(maxJ+1)); if (zernike_values == NULL) error(FATAL, "Not enough memory."); zernike_values[0] = 1.0; zernike_values[1] = 0.0; for(j = 2; j <= maxJ; j++) zernike_values[j] = 0.0; } /* setup_zernike() */
TEST(FunctionalExpansionsTest, zernikeConstructor) { const unsigned int order = 5; expansion_type = "orthonormal"; generation_type = "standard"; Zernike zernike({FunctionalBasisInterface::_domain_options = "x", FunctionalBasisInterface::_domain_options = "y"}, {order}, expansion_type, generation_type); EXPECT_EQ(zernike.getOrder(0), order); }
TEST(FunctionalExpansionsTest, zernikeSeriesStandardEvaluation) { const unsigned int order = 4; const Point location(-0.90922108754014, 0.262698547343, 0.156796889218); expansion_type = "standard"; generation_type = "standard"; Zernike zernike({FunctionalBasisInterface::_domain_options = "y", FunctionalBasisInterface::_domain_options = "z"}, {order}, expansion_type, generation_type); zernike.setLocation(location); const std::array<Real, 15> truth = {{0.318309886183791, 0.052230505695590, 0.330374978445085, 0.040657672622662, -0.823129261009826, 0.125372638358686, 0.020923587239414, -0.187295294511344, -1.184703806003468, 0.041151106306071, 0.008896570968308, -0.184582980412102, 0.978025517529447, -0.569182979683797, 0.012274247968574}}; auto & answer = zernike.getAllGeneration(); EXPECT_NEAR(answer[0], truth[0] * M_PI, tol); size_t i = 1; for (size_t n = 1; n < order + 1; ++n) { for (size_t m = 0; m < n + 1; ++m) { if (m != 0 && n / m == 2 && n % m == 0) EXPECT_NEAR(answer[i], truth[i] * M_PI / (n + 1), tol); else EXPECT_NEAR(answer[i], truth[i] * M_PI / (2 * n + 2), tol); ++i; } } }
/* * zernike_grid() * * Add zernike polynomial values to pre-defined grid. * * grid - pre-allocated & initialized double storage (square). * gsize - size of the grid in x / y. * gcenter - center point of the grid. * radius - radius on which to calculate the polynomial. * scale - scaling factor. * m - zernike m value. * n - zernike n value. */ void zernike_grid(double *grid, int gsize, double gcenter, double radius, double scale, int m, int n) { int i, j; double dd, dx, dy, phi, rr; rr = radius * radius; for(i=0;i<gsize;i++){ dx = i - gcenter; for(j=0;j<gsize;j++){ dy = j - gcenter; dd = dx * dx + dy * dy; if(dd <= rr){ dd = sqrt(dd)/radius; phi = atan2(dy, dx); grid[i*gsize+j] += scale * zernike(m, n, dd, phi); } } } }