From d8f8827a038d021b8942ce10be5162b7df94f08f Mon Sep 17 00:00:00 2001 From: henrysky Date: Sat, 24 Nov 2018 13:21:04 -0500 Subject: [PATCH 1/3] handle ctrl-c event on windows too --- galpy/util/bovy_rk.c | 47 ++++++++++++++++++++++++-------- galpy/util/bovy_symplecticode.c | 48 ++++++++++++++++++++++++++++++--- galpy/util/bovy_symplecticode.h | 9 +++---- 3 files changed, 84 insertions(+), 20 deletions(-) diff --git a/galpy/util/bovy_rk.c b/galpy/util/bovy_rk.c index 0f3fc7095..390c15dfe 100644 --- a/galpy/util/bovy_rk.c +++ b/galpy/util/bovy_rk.c @@ -34,9 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#ifndef _WIN32 #include "signal.h" -#endif #define _MAX_STEPCHANGE_POWERTWO 3. #define _MIN_STEPCHANGE_POWERTWO -3. #define _MAX_STEPREDUCE 10000. @@ -99,6 +97,15 @@ void bovy_rk4(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -201,6 +208,15 @@ void bovy_rk6(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -277,14 +293,14 @@ void bovy_rk6_onestep(void (*func)(double t, double *q, double *a, func(tn+2.*dt/3.,ynk,a,nargs,potentialArgs); for (ii=0; ii < dim; ii++) *(yn1+ii) += 81. * dt * *(a+ii) / 120.; for (ii=0; ii < dim; ii++) *(k3+ii)= dt * *(a+ii); - for (ii=0; ii < dim; ii++) *(ynk+ii)= *(yn+ii) + ( *(k1+ii) + for (ii=0; ii < dim; ii++) *(ynk+ii)= *(yn+ii) + ( *(k1+ii) + 4. * *(k2+ii) - *(k3+ii))/12.; //calculate k4 func(tn+dt/3.,ynk,a,nargs,potentialArgs); for (ii=0; ii < dim; ii++) *(yn1+ii) += 81.* dt * *(a+ii) / 120.; for (ii=0; ii < dim; ii++) *(k4+ii)= dt * *(a+ii); - for (ii=0; ii < dim; ii++) *(ynk+ii)= *(yn+ii) + ( -*(k1+ii) + for (ii=0; ii < dim; ii++) *(ynk+ii)= *(yn+ii) + ( -*(k1+ii) + 18. * *(k2+ii) - 3. * *(k3+ii) -6.* *(k4+ii))/16.; @@ -307,7 +323,7 @@ void bovy_rk6_onestep(void (*func)(double t, double *q, double *a, -64. * *(k5+ii))/44.; //calculate k7 func(tn+dt,ynk,a,nargs,potentialArgs); - for (ii=0; ii < dim; ii++) *(yn1+ii) += 11.* dt * *(a+ii) / 120.; + for (ii=0; ii < dim; ii++) *(yn1+ii) += 11.* dt * *(a+ii) / 120.; //yn1 is new value } @@ -360,10 +376,10 @@ double rk4_estimate_step(void (*func)(double t, double *y, double *a,int nargs, err+= exp(2.*log(fabs(*(y1+ii)-*(y2+ii)))-2.* *(scale+ii)); } err= sqrt(err/dim); - if ( ceil(pow(err,1./5.)) > 1. + if ( ceil(pow(err,1./5.)) > 1. && init_dt / dt * ceil(pow(err,1./5.)) < _MAX_DT_REDUCE) dt/= ceil(pow(err,1./5.)); - else + else break; } //free what we allocated @@ -378,7 +394,7 @@ double rk4_estimate_step(void (*func)(double t, double *y, double *a,int nargs, //printf("%f\n",dt); //fflush(stdout); return dt; -} +} double rk6_estimate_step(void (*func)(double t, double *y, double *a,int nargs, struct potentialArg *), int dim, double *yo, double dt, double *t, @@ -436,10 +452,10 @@ double rk6_estimate_step(void (*func)(double t, double *y, double *a,int nargs, err+= exp(2.*log(fabs(*(y1+ii)-*(y2+ii)))-2.* *(scale+ii)); } err= sqrt(err/dim); - if ( ceil(pow(err,1./7.)) > 1. + if ( ceil(pow(err,1./7.)) > 1. && init_dt / dt * ceil(pow(err,1./7.)) < _MAX_DT_REDUCE) dt/= ceil(pow(err,1./7.)); - else + else break; } //free what we allocated @@ -459,7 +475,7 @@ double rk6_estimate_step(void (*func)(double t, double *y, double *a,int nargs, //printf("%f\n",dt); //fflush(stdout); return dt; -} +} /* Runge-Kutta Dormand-Prince 5/4 integrator Usage: @@ -525,6 +541,15 @@ void bovy_dopr54(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { diff --git a/galpy/util/bovy_symplecticode.c b/galpy/util/bovy_symplecticode.c index 1a06ed387..b69773cd1 100644 --- a/galpy/util/bovy_symplecticode.c +++ b/galpy/util/bovy_symplecticode.c @@ -34,16 +34,31 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #define _MAX_DT_REDUCE 10000. -//CTRL-C only works on UNIX systems with signal library -#ifndef _WIN32 #include "signal.h" volatile sig_atomic_t interrupted= 0; + +// handle CTRL-C differently on UNIX systems and Windows +#ifndef _WIN32 void handle_sigint(int signum) { interrupted= 1; } #else -int interrupted= 0; +#include +BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) +{ + switch (fdwCtrlType) + { + // Handle the CTRL-C signal. + case CTRL_C_EVENT: + interrupted= 1; + // needed to avoid other control handlers like python from being called before us + return TRUE; + default: + return FALSE; + } +} + #endif static inline void leapfrog_leapq(int dim, double *q,double *p,double dt, double *qn){ @@ -124,6 +139,15 @@ void leapfrog(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -242,6 +266,15 @@ void symplec4(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -395,6 +428,15 @@ void symplec6(void (*func)(double t, double *q, double *a, memset(&action, 0, sizeof(struct sigaction)); action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); +#else + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) + {} + else + { + // for whatever reason cant install handler, print to warn + printf("\nERROR: Could not set control handler"); + return 1; + } #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { diff --git a/galpy/util/bovy_symplecticode.h b/galpy/util/bovy_symplecticode.h index d41bea3e3..875a6ef62 100644 --- a/galpy/util/bovy_symplecticode.h +++ b/galpy/util/bovy_symplecticode.h @@ -34,23 +34,20 @@ POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus extern "C" { #endif -#ifndef _WIN32 #include "signal.h" -#endif #include /* Global variables */ -#ifndef _WIN32 extern volatile sig_atomic_t interrupted; -#else -extern int interrupted; -#endif /* Function declarations */ #ifndef _WIN32 void handle_sigint(int); +#else +#include "windows.h" +BOOL WINAPI CtrlHandler(DWORD fdwCtrlType); #endif void leapfrog(void (*func)(double, double *, double *, int, struct potentialArg *), From b92f909455c16ba1c9b24409b038ea53a89225a3 Mon Sep 17 00:00:00 2001 From: henrysky Date: Mon, 26 Nov 2018 21:00:41 -0500 Subject: [PATCH 2/3] remove handler print msg [ci skip] --- galpy/util/bovy_rk.c | 27 +++------------------------ galpy/util/bovy_symplecticode.c | 27 +++------------------------ 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/galpy/util/bovy_rk.c b/galpy/util/bovy_rk.c index 390c15dfe..d635286d1 100644 --- a/galpy/util/bovy_rk.c +++ b/galpy/util/bovy_rk.c @@ -98,14 +98,7 @@ void bovy_rk4(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) {} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -209,14 +202,7 @@ void bovy_rk6(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) {} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -542,14 +528,7 @@ void bovy_dopr54(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) {} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { diff --git a/galpy/util/bovy_symplecticode.c b/galpy/util/bovy_symplecticode.c index b69773cd1..e781c2c9a 100644 --- a/galpy/util/bovy_symplecticode.c +++ b/galpy/util/bovy_symplecticode.c @@ -140,14 +140,7 @@ void leapfrog(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)){} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -267,14 +260,7 @@ void symplec4(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) {} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { @@ -429,14 +415,7 @@ void symplec6(void (*func)(double t, double *q, double *a, action.sa_handler= handle_sigint; sigaction(SIGINT,&action,NULL); #else - if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) - {} - else - { - // for whatever reason cant install handler, print to warn - printf("\nERROR: Could not set control handler"); - return 1; - } + if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) {} #endif for (ii=0; ii < (nt-1); ii++){ if ( interrupted ) { From f3b6dccb0bd4581e6206b4f1c4a5d92639aeb115 Mon Sep 17 00:00:00 2001 From: Jo Bovy Date: Tue, 27 Nov 2018 10:33:29 -0500 Subject: [PATCH 3/3] Added new KeyboardInterrupt Windows functionality to HISTORY [ci skip] --- HISTORY.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.txt b/HISTORY.txt index 010dae604..71272c306 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -20,6 +20,9 @@ v1.5 (????-??-??) - DehnenSmoothWrapperPotential can now decay rather than grow a potential by setting ``decay=True``. + +- Allow orbit integrations to be KeyboardInterrupted on Windows as well + (#362 by Henry Leung) v1.4 (2018-09-09) =================