@@ -295,7 +295,7 @@ void calcu0(int ndata,
295295 u_lo = gsl_min_fminimizer_x_lower (s );
296296 u_hi = gsl_min_fminimizer_x_upper (s );
297297 status = gsl_min_test_interval (u_lo , u_hi ,
298- 9.9999999999999998e-13 ,
298+ 4.4408920985006262e-16 ,
299299 4.4408920985006262e-16 );
300300 }
301301 while (status == GSL_CONTINUE && iter < max_iter );
@@ -1333,8 +1333,8 @@ void calcAnglesStaeckel(int ndata,
13331333 midpoint = * (umin + ii )+ 0.5 * ( * (umax + ii ) - * (umin + ii ) );
13341334 if ( * (pux + ii ) > 0. ) {
13351335 if ( * (ux + ii ) > midpoint ) {
1336- mid = 2. * asin ( sqrt ( ( * (umax + ii ) - * (ux + ii ) )
1337- / ( * (umax + ii ) - * (umin + ii ) ) ) );
1336+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( * (umax + ii ) - * (ux + ii ) )
1337+ / ( * (umax + ii ) - * (umin + ii ) ), 0. ), 1. ) ) );
13381338 (AngleuInt + tid )-> function = & dJRdEHighStaeckelIntegrand ;
13391339 Or1 = gsl_integration_glfixed (AngleuInt + tid ,0. ,mid ,T );
13401340 (AngleuInt + tid )-> function = & dJRdI3HighStaeckelIntegrand ;
@@ -1347,8 +1347,8 @@ void calcAnglesStaeckel(int ndata,
13471347 I3r1 = M_PI * * (dJRdI3 + ii ) - I3r1 ;
13481348 }
13491349 else {
1350- mid = 2. * asin ( sqrt ( ( * (ux + ii ) - * (umin + ii ) )
1351- / ( * (umax + ii ) - * (umin + ii ) ) ) );
1350+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( * (ux + ii ) - * (umin + ii ) )
1351+ / ( * (umax + ii ) - * (umin + ii ) ), 0. ), 1. ) ) );
13521352 (AngleuInt + tid )-> function = & dJRdELowStaeckelIntegrand ;
13531353 Or1 = gsl_integration_glfixed (AngleuInt + tid ,0. ,mid ,T );
13541354 (AngleuInt + tid )-> function = & dJRdI3LowStaeckelIntegrand ;
@@ -1361,8 +1361,8 @@ void calcAnglesStaeckel(int ndata,
13611361 }
13621362 else {
13631363 if ( * (ux + ii ) > midpoint ) {
1364- mid = 2. * asin ( sqrt ( ( * (umax + ii ) - * (ux + ii ) )
1365- / ( * (umax + ii ) - * (umin + ii ) ) ) );
1364+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( * (umax + ii ) - * (ux + ii ) )
1365+ / ( * (umax + ii ) - * (umin + ii ) ), 0. ), 1. ) ) );
13661366 (AngleuInt + tid )-> function = & dJRdEHighStaeckelIntegrand ;
13671367 Or1 = gsl_integration_glfixed (AngleuInt + tid ,0. ,mid ,T );
13681368 Or1 *= * (delta + ii * delta_stride ) / sqrt (2. );
@@ -1375,8 +1375,8 @@ void calcAnglesStaeckel(int ndata,
13751375 * (Anglephi + ii )= M_PI * * (dJRdLz + ii ) - * (Lz + ii ) * gsl_integration_glfixed (AngleuInt + tid ,0. ,mid ,T ) / * (delta + ii * delta_stride ) / sqrt (2. );
13761376 }
13771377 else {
1378- mid = 2. * asin ( sqrt ( ( * (ux + ii ) - * (umin + ii ) )
1379- / ( * (umax + ii ) - * (umin + ii ) ) ) );
1378+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( * (ux + ii ) - * (umin + ii ) )
1379+ / ( * (umax + ii ) - * (umin + ii ) ), 0. ), 1. ) ) );
13801380 (AngleuInt + tid )-> function = & dJRdELowStaeckelIntegrand ;
13811381 Or1 = gsl_integration_glfixed (AngleuInt + tid ,0. ,mid ,T );
13821382 Or1 *= * (delta + ii * delta_stride ) / sqrt (2. );
@@ -1405,10 +1405,10 @@ void calcAnglesStaeckel(int ndata,
14051405 if ( * (vx + ii ) < midpoint || * (vx + ii ) > (M_PI - midpoint ) ) {
14061406 // chi of the current v, measured from the vmin turning point along
14071407 // the full loop [vmin, pi - vmin]; v beyond the midplane mirrors
1408- mid = 2. * asin ( sqrt ( ( ( * (vx + ii ) > 0.5 * M_PI )
1408+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( ( * (vx + ii ) > 0.5 * M_PI )
14091409 ? ( M_PI - * (vx + ii ) - * (vmin + ii ) )
14101410 : ( * (vx + ii ) - * (vmin + ii ) ) )
1411- / ( M_PI - 2. * * (vmin + ii ) ) ) );
1411+ / ( M_PI - 2. * * (vmin + ii ) ), 0. ), 1. ) ) );
14121412 (AnglevInt + tid )-> function = & dJzdELowStaeckelIntegrand ;
14131413 Or2 = gsl_integration_glfixed (AnglevInt + tid ,0. ,mid ,T );
14141414 Or2 *= * (delta + ii * delta_stride ) / sqrt (2. );
@@ -1451,10 +1451,10 @@ void calcAnglesStaeckel(int ndata,
14511451 if ( * (vx + ii ) < midpoint || * (vx + ii ) > (M_PI - midpoint )) {
14521452 // chi of the current v, measured from the vmin turning point along
14531453 // the full loop [vmin, pi - vmin]; v beyond the midplane mirrors
1454- mid = 2. * asin ( sqrt ( ( ( * (vx + ii ) > 0.5 * M_PI )
1454+ mid = 2. * asin ( sqrt ( fmin ( fmax ( ( ( * (vx + ii ) > 0.5 * M_PI )
14551455 ? ( M_PI - * (vx + ii ) - * (vmin + ii ) )
14561456 : ( * (vx + ii ) - * (vmin + ii ) ) )
1457- / ( M_PI - 2. * * (vmin + ii ) ) ) );
1457+ / ( M_PI - 2. * * (vmin + ii ) ), 0. ), 1. ) ) );
14581458 (AnglevInt + tid )-> function = & dJzdELowStaeckelIntegrand ;
14591459 Or2 = gsl_integration_glfixed (AnglevInt + tid ,0. ,mid ,T );
14601460 Or2 *= * (delta + ii * delta_stride ) / sqrt (2. );
@@ -1591,7 +1591,35 @@ void calcUminUmax(int ndata,
15911591 meps = GSL_FN_EVAL (JRRoot + tid ,* (ux + ii )- 0.000001 );
15921592 if ( fabs (GSL_FN_EVAL (JRRoot + tid ,* (ux + ii ))) < 0.0000001 && peps * meps < 0. ){ //we are at umin or umax
15931593 if ( peps < 0. && meps > 0. ) {//umax
1594- * (umax + ii )= * (ux + ii );
1594+ //The point lies within 1e-6 of umax. Adopting the point itself as
1595+ //the turning point is fine for the actions (an O(eps) endpoint
1596+ //error only enters them at O(eps^1.5)), but the frequency and
1597+ //angle integrands diverge as 1/sqrt(W) at the endpoint, so there
1598+ //it enters at O(sqrt(eps)); solve for the true root instead (the
1599+ //+-1e-6 bracket has the sign change by the branch condition),
1600+ //keeping the point itself only as the degenerate fallback
1601+ status = gsl_root_fsolver_set ((s + tid )-> s , JRRoot + tid ,
1602+ * (ux + ii ) - 0.000001 ,
1603+ * (ux + ii ) + 0.000001 );
1604+ if (status == GSL_EINVAL )
1605+ // LCOV_EXCL_START
1606+ * (umax + ii )= * (ux + ii );//can't happen: the branch condition peps*meps<0 is the bracket
1607+ // LCOV_EXCL_STOP
1608+ else {
1609+ iter = 0 ;
1610+ do
1611+ {
1612+ iter ++ ;
1613+ status = gsl_root_fsolver_iterate ((s + tid )-> s );
1614+ u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
1615+ u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
1616+ status = gsl_root_test_interval (u_lo , u_hi ,
1617+ 4.4408920985006262e-16 ,
1618+ 4.4408920985006262e-16 );
1619+ }
1620+ while (status == GSL_CONTINUE && iter < max_iter );
1621+ * (umax + ii )= gsl_root_fsolver_root ((s + tid )-> s );
1622+ }
15951623 u_lo = 0.9 * (* (ux + ii ) - 0.000001 );
15961624 u_hi = * (ux + ii ) - 0.0000001 ;
15971625 while ( GSL_FN_EVAL (JRRoot + tid ,u_lo ) >= 0. && u_lo > 0.000000001 ){
@@ -1611,7 +1639,7 @@ void calcUminUmax(int ndata,
16111639 u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
16121640 u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
16131641 status = gsl_root_test_interval (u_lo , u_hi ,
1614- 9.9999999999999998e-13 ,
1642+ 4.4408920985006262e-16 ,
16151643 4.4408920985006262e-16 );
16161644 }
16171645 while (status == GSL_CONTINUE && iter < max_iter );
@@ -1626,7 +1654,30 @@ void calcUminUmax(int ndata,
16261654 }
16271655 }
16281656 else {// JB: Should catch all: if ( peps > 0. && meps < 0. ){//umin
1629- * (umin + ii )= * (ux + ii );
1657+ //Same as the umax case above: solve for the true root, with the
1658+ //point itself only as the degenerate fallback
1659+ status = gsl_root_fsolver_set ((s + tid )-> s , JRRoot + tid ,
1660+ * (ux + ii ) - 0.000001 ,
1661+ * (ux + ii ) + 0.000001 );
1662+ if (status == GSL_EINVAL )
1663+ // LCOV_EXCL_START
1664+ * (umin + ii )= * (ux + ii );//can't happen: the branch condition peps*meps<0 is the bracket
1665+ // LCOV_EXCL_STOP
1666+ else {
1667+ iter = 0 ;
1668+ do
1669+ {
1670+ iter ++ ;
1671+ status = gsl_root_fsolver_iterate ((s + tid )-> s );
1672+ u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
1673+ u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
1674+ status = gsl_root_test_interval (u_lo , u_hi ,
1675+ 4.4408920985006262e-16 ,
1676+ 4.4408920985006262e-16 );
1677+ }
1678+ while (status == GSL_CONTINUE && iter < max_iter );
1679+ * (umin + ii )= gsl_root_fsolver_root ((s + tid )-> s );
1680+ }
16301681 u_lo = * (ux + ii ) + 0.000001 ;
16311682 u_hi = 1.1 * (* (ux + ii ) + 0.000001 );
16321683 while ( GSL_FN_EVAL (JRRoot + tid ,u_hi ) >= 0. && u_hi < asinh (37.5 / * (delta + ii * delta_stride ))) {
@@ -1648,7 +1699,7 @@ void calcUminUmax(int ndata,
16481699 u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
16491700 u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
16501701 status = gsl_root_test_interval (u_lo , u_hi ,
1651- 9.9999999999999998e-13 ,
1702+ 4.4408920985006262e-16 ,
16521703 4.4408920985006262e-16 );
16531704 }
16541705 while (status == GSL_CONTINUE && iter < max_iter );
@@ -1687,7 +1738,7 @@ void calcUminUmax(int ndata,
16871738 u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
16881739 u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
16891740 status = gsl_root_test_interval (u_lo , u_hi ,
1690- 9.9999999999999998e-13 ,
1741+ 4.4408920985006262e-16 ,
16911742 4.4408920985006262e-16 );
16921743 }
16931744 while (status == GSL_CONTINUE && iter < max_iter );
@@ -1723,7 +1774,7 @@ void calcUminUmax(int ndata,
17231774 u_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
17241775 u_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
17251776 status = gsl_root_test_interval (u_lo , u_hi ,
1726- 9.9999999999999998e-13 ,
1777+ 4.4408920985006262e-16 ,
17271778 4.4408920985006262e-16 );
17281779 }
17291780 while (status == GSL_CONTINUE && iter < max_iter );
@@ -1803,8 +1854,41 @@ void calcVmin(int ndata,
18031854 (JzRoot + tid )-> function = & JzStaeckelIntegrandSquared ;
18041855 (JzRoot + tid )-> params = params + tid ;
18051856 //Find starting points for minimum
1806- if ( fabs (GSL_FN_EVAL (JzRoot + tid ,* (vx + ii ))) < 0.0000001 ) //we are at vmin
1807- * (vmin + ii )= ( * (vx + ii ) > 0.5 * M_PI ) ? M_PI - * (vx + ii ): * (vx + ii );
1857+ if ( fabs (GSL_FN_EVAL (JzRoot + tid ,* (vx + ii ))) < 0.0000001 ) {//we are at vmin
1858+ //The point lies within 1e-6 of vmin. Adopting the point itself as
1859+ //the turning point is fine for the actions (an O(eps) endpoint
1860+ //error only enters them at O(eps^1.5)), but the frequency and
1861+ //angle integrands diverge as 1/sqrt(W) at the endpoint, so there
1862+ //it enters at O(sqrt(eps)); solve for the true root instead: W is
1863+ //negative below vmin and positive above, so the +-1e-6 bracket
1864+ //around the (mirrored) point holds unless the point is degenerate
1865+ //at roundoff level, where the point IS the turning point and the
1866+ //old assignment remains as the fallback
1867+ v_lo = ( ( * (vx + ii ) > 0.5 * M_PI ) ? M_PI - * (vx + ii ): * (vx + ii ) )
1868+ - 0.000001 ;
1869+ if ( v_lo < 0.000000001 ) v_lo = 0.000000001 ;
1870+ v_hi = ( ( * (vx + ii ) > 0.5 * M_PI ) ? M_PI - * (vx + ii ): * (vx + ii ) )
1871+ + 0.000001 ;
1872+ if ( v_hi > 0.5 * M_PI ) v_hi = 0.5 * M_PI ;
1873+ status = gsl_root_fsolver_set ((s + tid )-> s , JzRoot + tid , v_lo , v_hi );
1874+ if (status == GSL_EINVAL )
1875+ * (vmin + ii )= ( * (vx + ii ) > 0.5 * M_PI ) ? M_PI - * (vx + ii ): * (vx + ii );
1876+ else {
1877+ iter = 0 ;
1878+ do
1879+ {
1880+ iter ++ ;
1881+ status = gsl_root_fsolver_iterate ((s + tid )-> s );
1882+ v_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
1883+ v_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
1884+ status = gsl_root_test_interval (v_lo , v_hi ,
1885+ 4.4408920985006262e-16 ,
1886+ 4.4408920985006262e-16 );
1887+ }
1888+ while (status == GSL_CONTINUE && iter < max_iter );
1889+ * (vmin + ii )= gsl_root_fsolver_root ((s + tid )-> s );
1890+ }
1891+ }
18081892 else {
18091893 if ( * (vx + ii ) > 0.5 * M_PI ){
18101894 v_lo = 0.9 * ( M_PI - * (vx + ii ) );
@@ -1832,7 +1916,7 @@ void calcVmin(int ndata,
18321916 v_lo = gsl_root_fsolver_x_lower ((s + tid )-> s );
18331917 v_hi = gsl_root_fsolver_x_upper ((s + tid )-> s );
18341918 status = gsl_root_test_interval (v_lo , v_hi ,
1835- 9.9999999999999998e-13 ,
1919+ 4.4408920985006262e-16 ,
18361920 4.4408920985006262e-16 );
18371921 }
18381922 while (status == GSL_CONTINUE && iter < max_iter );
0 commit comments