2023-05-10 19:33:29 -04:00
/*
2024-10-15 11:47:13 -04:00
Copyright 2017 - 2024 Ian Jauslin
2023-05-10 19:33:29 -04:00
Licensed under the Apache License , Version 2.0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
*/
2022-05-18 09:57:06 +02:00
# define VERSION "0.1"
2018-01-11 22:48:14 +00:00
2024-12-11 15:48:11 -05:00
# include <math.h>
2023-04-12 15:23:35 -04:00
# include <signal.h>
2018-01-11 22:48:14 +00:00
# include <string.h>
# include <stdlib.h>
2022-05-27 16:09:17 -04:00
# include <errno.h>
2023-11-03 12:08:25 -04:00
# include <wordexp.h>
2023-04-26 11:27:03 -04:00
# include "constants.cpp"
2022-05-18 09:57:06 +02:00
# include "driving.h"
2023-11-03 16:04:53 -04:00
# include "dstring.h"
2022-05-26 15:05:30 -04:00
# include "init.h"
2022-05-26 20:54:30 -04:00
# include "int_tools.h"
2024-02-19 19:05:35 -05:00
# include "lyapunov.h"
2023-04-26 11:27:03 -04:00
# include "navier-stokes.h"
2023-04-12 19:05:01 -04:00
2022-05-26 14:25:45 -04:00
// structure to store parameters, to make it easier to pass parameters to CLI functions
typedef struct nstrophy_parameters {
2024-12-11 15:48:11 -05:00
double init_energy ;
double init_enstrophy ;
unsigned int init_enstrophy_or_energy ; //whether to fix the initial enstrophy or energy
2023-04-05 20:33:38 -04:00
bool irreversible ;
2022-05-26 14:25:45 -04:00
int K1 ;
int K2 ;
int N1 ;
int N2 ;
2023-05-16 00:00:18 -04:00
double final_time ;
2022-05-26 14:25:45 -04:00
double nu ;
double delta ;
double L ;
2023-05-15 20:29:06 -04:00
double adaptive_tolerance ;
double adaptive_factor ;
2023-06-13 18:45:19 -04:00
double max_delta ;
2024-11-18 17:09:17 -05:00
unsigned int adaptive_cost ;
2023-05-16 00:00:18 -04:00
double print_freq ;
2022-05-26 15:05:30 -04:00
int seed ;
2023-05-15 20:29:06 -04:00
double starting_time ;
2023-04-12 18:22:40 -04:00
unsigned int driving ;
unsigned int init ;
2023-04-26 11:27:03 -04:00
unsigned int algorithm ;
2025-01-31 10:52:40 -05:00
unsigned int algorithm_lyapunov ;
2023-06-29 16:58:33 -04:00
bool keep_en_cst ;
2023-04-12 18:22:40 -04:00
FILE * initfile ;
2023-04-24 12:22:29 -04:00
FILE * drivingfile ;
2024-02-19 19:05:35 -05:00
double lyapunov_reset ;
2025-01-31 10:52:40 -05:00
unsigned int lyapunov_trigger ;
2024-02-19 19:05:35 -05:00
double D_epsilon ;
2024-11-07 14:39:03 -05:00
bool print_alpha ;
2022-05-26 14:25:45 -04:00
} nstrophy_parameters ;
2018-01-11 22:48:14 +00:00
// usage message
int print_usage ( ) ;
2022-05-26 20:54:30 -04:00
// print parameters
2023-04-24 12:22:29 -04:00
int print_params ( nstrophy_parameters parameters , char * initfile_str , char * drivingfile_str , FILE * file ) ;
2022-05-18 09:57:06 +02:00
2018-01-11 22:48:14 +00:00
// read command line arguments
2023-11-03 16:04:53 -04:00
int read_args ( int argc , const char * argv [ ] , dstring * params , unsigned int * command , unsigned int * nthreads , dstring * savefile_str , dstring * utfile_str , dstring * resumefile_str ) ;
2023-11-03 12:08:25 -04:00
int set_default_params ( nstrophy_parameters * parameters ) ;
2023-11-03 16:42:27 -04:00
int read_params ( dstring param_str , nstrophy_parameters * parameters , dstring * initfile_str , dstring * drivingfile_str ) ;
2023-11-03 16:04:53 -04:00
int set_parameter ( char * lhs , char * rhs , nstrophy_parameters * parameters , bool * setN1 , bool * setN2 , dstring * initfile_str , dstring * drivingfile_str ) ;
2023-11-03 12:08:25 -04:00
// read args from file
2023-11-03 16:04:53 -04:00
int args_from_file ( dstring * params , unsigned int * command , unsigned int * nthreads , dstring * savefile_str , dstring * utfile_str , char * file_str ) ;
2022-05-18 09:57:06 +02:00
2022-05-26 15:16:44 -04:00
// set driving force
2023-04-12 18:22:40 -04:00
_Complex double * set_driving ( nstrophy_parameters parameters ) ;
2022-05-26 15:05:30 -04:00
// set initial condition
2023-05-15 20:29:06 -04:00
_Complex double * set_init ( nstrophy_parameters * parameters ) ;
2022-05-26 15:05:30 -04:00
2023-04-12 15:23:35 -04:00
// signal handler
void sig_handler ( int signo ) ;
// global variable to handle interrupts
volatile bool g_abort = false ;
// signal handler
void sig_handler ( int signo ) {
2023-11-03 12:08:25 -04:00
if ( signo = = SIGINT ) {
fprintf ( stderr , " received signal SIGINT, interrupting computation \n " ) ;
2023-04-12 15:23:35 -04:00
g_abort = true ;
}
2023-11-03 12:08:25 -04:00
else if ( signo = = SIGTERM ) {
fprintf ( stderr , " received signal SIGTERM, interrupting computation \n " ) ;
g_abort = true ;
}
else {
fprintf ( stderr , " received signal %d \n " , signo ) ;
}
2023-04-12 15:23:35 -04:00
}
2022-05-18 09:57:06 +02:00
int main (
int argc ,
const char * argv [ ]
) {
2023-11-03 16:04:53 -04:00
dstring param_str ;
2022-05-26 14:25:45 -04:00
nstrophy_parameters parameters ;
2018-01-11 22:48:14 +00:00
int ret ;
2023-04-12 18:22:40 -04:00
unsigned int command ;
2022-05-18 23:52:01 +02:00
unsigned int nthreads = 1 ;
2022-05-26 15:05:30 -04:00
_Complex double * u0 ;
2022-05-26 15:16:44 -04:00
_Complex double * g ;
2023-11-03 16:04:53 -04:00
dstring savefile_str ;
dstring utfile_str ;
dstring initfile_str ;
dstring drivingfile_str ;
dstring resumefile_str ;
2022-05-27 16:09:17 -04:00
FILE * savefile = NULL ;
2023-06-14 14:19:27 -04:00
FILE * utfile = NULL ;
2018-01-11 22:48:14 +00:00
2022-05-18 09:57:06 +02:00
command = 0 ;
2018-01-11 22:48:14 +00:00
2023-11-03 16:04:53 -04:00
// init strings
dstring_init ( & param_str , 64 ) ;
dstring_init ( & savefile_str , 64 ) ;
dstring_init ( & utfile_str , 64 ) ;
dstring_init ( & initfile_str , 64 ) ;
dstring_init ( & drivingfile_str , 64 ) ;
dstring_init ( & resumefile_str , 64 ) ;
2018-01-11 22:48:14 +00:00
// read command line arguments
2023-11-03 12:08:25 -04:00
ret = read_args ( argc , argv , & param_str , & command , & nthreads , & savefile_str , & utfile_str , & resumefile_str ) ;
2022-05-18 09:57:06 +02:00
if ( ret < 0 ) {
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
dstring_free ( resumefile_str ) ;
return ( ret ) ;
2022-05-18 09:57:06 +02:00
}
2022-05-26 15:05:30 -04:00
2023-11-03 12:08:25 -04:00
// set default params
set_default_params ( & parameters ) ;
2022-05-18 09:57:06 +02:00
// read params
2023-11-03 16:42:27 -04:00
ret = read_params ( param_str , & parameters , & initfile_str , & drivingfile_str ) ;
2018-01-11 22:48:14 +00:00
if ( ret < 0 ) {
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
dstring_free ( resumefile_str ) ;
return ( ret ) ;
2018-01-11 22:48:14 +00:00
}
2022-05-26 15:05:30 -04:00
2023-11-03 12:08:25 -04:00
// if command is 'resume', then read args from file
if ( command = = COMMAND_RESUME ) {
2023-11-03 16:04:53 -04:00
ret = args_from_file ( & param_str , & command , & nthreads , & savefile_str , & utfile_str , dstring_to_str_noinit ( & resumefile_str ) ) ;
2023-11-03 12:08:25 -04:00
if ( ret < 0 ) {
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
dstring_free ( resumefile_str ) ;
return ( ret ) ;
2023-11-03 12:08:25 -04:00
}
// read params
2023-11-03 16:42:27 -04:00
ret = read_params ( param_str , & parameters , & initfile_str , & drivingfile_str ) ;
2023-11-03 12:08:25 -04:00
if ( ret < 0 ) {
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
dstring_free ( resumefile_str ) ;
return ( ret ) ;
2023-11-03 12:08:25 -04:00
}
2023-11-03 18:02:12 -04:00
// reread arguments (to allow overrides from the command line, but do not override the command)
unsigned int dummy_command ;
read_args ( argc , argv , & param_str , & dummy_command , & nthreads , & savefile_str , & utfile_str , & resumefile_str ) ;
2023-11-03 12:08:25 -04:00
// reread params
2023-11-03 17:41:30 -04:00
read_params ( param_str , & parameters , & initfile_str , & drivingfile_str ) ;
2023-11-03 12:08:25 -04:00
}
2023-11-03 17:41:30 -04:00
// free strings
dstring_free ( resumefile_str ) ;
2022-05-27 16:09:17 -04:00
// open initfile
2023-11-03 16:04:53 -04:00
if ( initfile_str . length ! = 0 ) {
parameters . initfile = fopen ( dstring_to_str_noinit ( & initfile_str ) , " r " ) ;
2023-04-12 18:22:40 -04:00
if ( parameters . initfile = = NULL ) {
2023-11-03 16:04:53 -04:00
fprintf ( stderr , " Error opening file '%s' for reading: %s \n " , dstring_to_str_noinit ( & initfile_str ) , strerror ( errno ) ) ;
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
2022-05-27 16:09:17 -04:00
return ( - 1 ) ;
}
}
2023-04-24 12:22:29 -04:00
// open drivingfile
2023-11-03 16:04:53 -04:00
if ( drivingfile_str . length ! = 0 ) {
parameters . drivingfile = fopen ( dstring_to_str_noinit ( & drivingfile_str ) , " r " ) ;
2023-04-24 12:22:29 -04:00
if ( parameters . drivingfile = = NULL ) {
2023-11-03 16:04:53 -04:00
fprintf ( stderr , " Error opening file '%s' for reading: %s \n " , dstring_to_str_noinit ( & drivingfile_str ) , strerror ( errno ) ) ;
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
2023-04-24 12:22:29 -04:00
return ( - 1 ) ;
}
}
2022-05-27 16:09:17 -04:00
2022-05-18 09:57:06 +02:00
// set driving force
2023-04-12 18:22:40 -04:00
g = set_driving ( parameters ) ;
2022-05-26 15:05:30 -04:00
// set initial condition
2023-05-15 20:29:06 -04:00
u0 = set_init ( & parameters ) ;
2022-05-27 16:09:17 -04:00
2024-12-11 15:48:11 -05:00
// if init_enstrophy is not set in the parameters, then compute it from the initial condition
if ( parameters . init_enstrophy_or_energy ! = FIX_ENSTROPHY ) {
parameters . init_enstrophy = compute_enstrophy ( u0 , parameters . K1 , parameters . K2 , parameters . L ) ;
}
// same with init_energy
if ( parameters . init_enstrophy_or_energy ! = FIX_ENERGY ) {
parameters . init_energy = compute_energy ( u0 , parameters . K1 , parameters . K2 ) ;
}
2022-05-27 16:09:17 -04:00
// close initfile (do this early, so that it is possible to use the same file for init and save)
2023-04-12 18:22:40 -04:00
if ( parameters . initfile ! = NULL ) {
fclose ( parameters . initfile ) ;
2022-05-27 16:09:17 -04:00
}
2023-04-24 12:22:29 -04:00
// close drivingfile
if ( parameters . drivingfile ! = NULL ) {
fclose ( parameters . drivingfile ) ;
}
2022-05-27 16:09:17 -04:00
// open savefile (do this after closing init file)
2023-11-03 16:04:53 -04:00
if ( savefile_str . length ! = 0 ) {
savefile = fopen ( dstring_to_str_noinit ( & savefile_str ) , " w " ) ;
2022-05-27 16:09:17 -04:00
if ( savefile = = NULL ) {
2023-11-03 16:04:53 -04:00
fprintf ( stderr , " Error opening file '%s' for writing: %s \n " , dstring_to_str_noinit ( & savefile_str ) , strerror ( errno ) ) ;
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
free ( g ) ;
free ( u0 ) ;
2022-05-27 16:09:17 -04:00
return ( - 1 ) ;
}
}
2022-05-26 15:05:30 -04:00
2023-06-14 14:19:27 -04:00
// open utfile (do this after closing init file)
2023-11-03 16:04:53 -04:00
if ( utfile_str . length ! = 0 ) {
utfile = fopen ( dstring_to_str_noinit ( & utfile_str ) , " w " ) ;
2023-06-14 14:19:27 -04:00
if ( utfile = = NULL ) {
2023-11-03 16:04:53 -04:00
fprintf ( stderr , " Error opening file '%s' for writing: %s \n " , dstring_to_str_noinit ( & utfile_str ) , strerror ( errno ) ) ;
2023-11-03 17:41:30 -04:00
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
free ( g ) ;
free ( u0 ) ;
2023-06-14 14:19:27 -04:00
return ( - 1 ) ;
}
}
2022-05-26 20:54:30 -04:00
// print parameters
2023-11-03 16:04:53 -04:00
print_params ( parameters , dstring_to_str_noinit ( & initfile_str ) , dstring_to_str_noinit ( & drivingfile_str ) , stderr ) ;
print_params ( parameters , dstring_to_str_noinit ( & initfile_str ) , dstring_to_str_noinit ( & drivingfile_str ) , stdout ) ;
2022-05-26 20:54:30 -04:00
2023-11-03 16:04:53 -04:00
// free strings
dstring_free ( initfile_str ) ;
dstring_free ( drivingfile_str ) ;
2023-04-12 19:05:01 -04:00
2022-05-18 09:57:06 +02:00
// run command
if ( command = = COMMAND_UK ) {
2024-12-11 15:48:11 -05:00
uk ( parameters . K1 , parameters . K2 , parameters . N1 , parameters . N2 , parameters . final_time , parameters . nu , parameters . delta , parameters . L , parameters . adaptive_tolerance , parameters . adaptive_factor , parameters . max_delta , parameters . adaptive_cost , u0 , g , parameters . irreversible , parameters . keep_en_cst , parameters . init_enstrophy , parameters . algorithm , parameters . print_freq , parameters . starting_time , nthreads , savefile ) ;
2022-05-18 09:57:06 +02:00
}
2023-05-10 19:29:31 -04:00
else if ( command = = COMMAND_ENSTROPHY ) {
2023-04-12 15:23:35 -04:00
// register signal handler to handle aborts
signal ( SIGINT , sig_handler ) ;
2023-05-26 17:37:51 -04:00
signal ( SIGTERM , sig_handler ) ;
2024-12-11 15:48:11 -05:00
enstrophy ( parameters . K1 , parameters . K2 , parameters . N1 , parameters . N2 , parameters . final_time , parameters . nu , parameters . delta , parameters . L , parameters . adaptive_tolerance , parameters . adaptive_factor , parameters . max_delta , parameters . adaptive_cost , u0 , g , parameters . irreversible , parameters . keep_en_cst , parameters . init_enstrophy , parameters . algorithm , parameters . print_freq , parameters . starting_time , parameters . print_alpha , nthreads , savefile , utfile , ( char * ) argv [ 0 ] , dstring_to_str_noinit ( & param_str ) , dstring_to_str_noinit ( & savefile_str ) , dstring_to_str_noinit ( & utfile_str ) ) ;
2022-05-18 09:57:06 +02:00
}
2022-05-18 22:22:42 +02:00
else if ( command = = COMMAND_QUIET ) {
2024-12-11 15:48:11 -05:00
quiet ( parameters . K1 , parameters . K2 , parameters . N1 , parameters . N2 , parameters . final_time , parameters . nu , parameters . delta , parameters . L , parameters . adaptive_tolerance , parameters . adaptive_factor , parameters . max_delta , parameters . adaptive_cost , parameters . starting_time , u0 , g , parameters . irreversible , parameters . keep_en_cst , parameters . init_enstrophy , parameters . algorithm , nthreads , savefile ) ;
2022-05-18 22:22:42 +02:00
}
2024-02-19 19:05:35 -05:00
else if ( command = = COMMAND_LYAPUNOV ) {
2025-01-31 10:52:40 -05:00
lyapunov ( parameters . K1 , parameters . K2 , parameters . N1 , parameters . N2 , parameters . final_time , parameters . lyapunov_reset , parameters . lyapunov_trigger , parameters . nu , parameters . delta , parameters . L , parameters . adaptive_tolerance , parameters . adaptive_factor , parameters . max_delta , parameters . adaptive_cost , u0 , g , parameters . irreversible , parameters . keep_en_cst , parameters . init_enstrophy , parameters . algorithm , parameters . algorithm_lyapunov , parameters . starting_time , nthreads ) ;
2024-02-19 19:05:35 -05:00
}
2022-05-18 09:57:06 +02:00
else if ( command = = 0 ) {
fprintf ( stderr , " error: no command specified \n " ) ;
print_usage ( ) ;
2018-01-11 22:48:14 +00:00
}
2022-05-26 15:16:44 -04:00
free ( g ) ;
2022-05-26 15:05:30 -04:00
free ( u0 ) ;
2023-11-03 16:04:53 -04:00
// free strings
dstring_free ( param_str ) ;
dstring_free ( savefile_str ) ;
dstring_free ( utfile_str ) ;
2022-05-27 16:09:17 -04:00
// close savefile
if ( savefile ! = NULL ) {
fclose ( savefile ) ;
}
2023-06-14 14:19:27 -04:00
// close utfile
if ( utfile ! = NULL ) {
fclose ( utfile ) ;
}
2018-01-11 22:48:14 +00:00
return ( 0 ) ;
}
// usage message
int print_usage ( ) {
2023-11-03 12:08:25 -04:00
fprintf ( stderr , " usage: \n nstrophy [-t nthreads] [-p parameters] [-s savefile] [-u u_outfile] <command> \n where <command> is one of \n enstrophy \n uk \n quiet \n resume <resume_file> \n \n " ) ;
2018-01-11 22:48:14 +00:00
return ( 0 ) ;
}
2022-05-26 20:54:30 -04:00
// print parameters
int print_params (
nstrophy_parameters parameters ,
2022-05-27 16:09:17 -04:00
char * initfile_str ,
2023-04-24 12:22:29 -04:00
char * drivingfile_str ,
2022-05-26 20:54:30 -04:00
FILE * file
) {
2023-04-05 22:41:19 -04:00
fprintf ( file , " # " ) ;
if ( parameters . irreversible ) {
fprintf ( file , " equation=irreversible " ) ;
} else {
fprintf ( file , " equation=reversible " ) ;
}
2024-12-11 15:48:11 -05:00
fprintf ( file , " , K1=%d, K2=%d, N1=%d, N2=%d, nu=%.15e, delta=%.15e, L=%.15e " , parameters . K1 , parameters . K2 , parameters . N1 , parameters . N2 , parameters . nu , parameters . delta , parameters . L ) ;
if ( parameters . init_enstrophy_or_energy = = FIX_ENSTROPHY ) {
fprintf ( file , " , init_enstrophy=%.15e " , parameters . init_enstrophy ) ;
} else if ( parameters . init_enstrophy_or_energy = = FIX_ENERGY ) {
fprintf ( file , " , init_energy=%.15e " , parameters . init_energy ) ;
}
2022-05-26 20:54:30 -04:00
2023-04-12 18:22:40 -04:00
switch ( parameters . driving ) {
2022-05-26 20:54:30 -04:00
case DRIVING_TEST :
fprintf ( file , " , driving=test " ) ;
break ;
case DRIVING_ZERO :
fprintf ( file , " , driving=zero " ) ;
break ;
2023-04-24 12:22:29 -04:00
case DRIVING_FILE :
fprintf ( file , " , driving=file:%s " , drivingfile_str ) ;
break ;
case DRIVING_FILE_TXT :
fprintf ( file , " , driving=file_txt:%s " , drivingfile_str ) ;
break ;
2022-05-26 20:54:30 -04:00
default :
fprintf ( file , " , driving=test " ) ;
break ;
}
2023-04-12 18:22:40 -04:00
switch ( parameters . init ) {
2022-05-26 20:54:30 -04:00
case INIT_RANDOM :
fprintf ( file , " , init=random " ) ;
break ;
case INIT_GAUSSIAN :
fprintf ( file , " , init=gaussian " ) ;
break ;
2022-05-27 16:09:17 -04:00
case INIT_FILE :
fprintf ( file , " , init=file:%s " , initfile_str ) ;
break ;
2023-04-24 12:06:35 -04:00
case INIT_FILE_TXT :
fprintf ( file , " , init=file_txt:%s " , initfile_str ) ;
break ;
2022-05-26 20:54:30 -04:00
default :
fprintf ( file , " , init=gaussian " ) ;
break ;
}
2023-04-26 11:27:03 -04:00
switch ( parameters . algorithm ) {
case ALGORITHM_RK4 :
fprintf ( file , " , algorithm=RK4 " ) ;
break ;
case ALGORITHM_RK2 :
fprintf ( file , " , algorithm=RK2 " ) ;
break ;
2023-05-15 20:29:06 -04:00
case ALGORITHM_RKF45 :
2023-06-13 18:45:19 -04:00
fprintf ( file , " , algorithm=RKF45, tolerance=%.15e " , parameters . adaptive_tolerance ) ;
2023-05-15 20:29:06 -04:00
break ;
2023-05-17 17:41:00 -04:00
case ALGORITHM_RKDP54 :
2023-06-13 18:45:19 -04:00
fprintf ( file , " , algorithm=RKDP54, tolerance=%.15e " , parameters . adaptive_tolerance ) ;
2023-05-17 17:41:00 -04:00
break ;
2023-05-17 16:59:15 -04:00
case ALGORITHM_RKBS32 :
2023-06-13 18:45:19 -04:00
fprintf ( file , " , algorithm=RKBS32, tolerance=%.15e " , parameters . adaptive_tolerance ) ;
2023-05-17 16:47:15 -04:00
break ;
2023-04-26 11:27:03 -04:00
default :
fprintf ( file , " , algorithm=RK4 " ) ;
break ;
}
2023-06-13 23:56:35 -04:00
if ( parameters . algorithm > ALGORITHM_ADAPTIVE_THRESHOLD ) {
2024-11-18 17:09:17 -05:00
switch ( parameters . adaptive_cost ) {
case COST_L1 :
fprintf ( file , " , cost=L1 " ) ;
2023-06-13 23:56:35 -04:00
break ;
2024-11-18 17:09:17 -05:00
case COST_k3 :
fprintf ( file , " , cost=k3 " ) ;
2023-06-13 23:56:35 -04:00
break ;
2024-11-18 17:09:17 -05:00
case COST_k32 :
fprintf ( file , " , cost=k32 " ) ;
2023-06-13 23:56:35 -04:00
break ;
2024-11-18 17:09:17 -05:00
case COST_ENSTROPHY :
fprintf ( file , " , cost=enstrophy " ) ;
break ;
case COST_ALPHA :
fprintf ( file , " , cost=alpha " ) ;
2023-06-13 23:56:35 -04:00
break ;
}
}
2022-05-26 20:54:30 -04:00
fprintf ( file , " \n " ) ;
return 0 ;
}
2023-04-12 19:05:01 -04:00
2018-01-11 22:48:14 +00:00
// read command line arguments
2022-05-18 09:57:06 +02:00
# define CP_FLAG_PARAMS 1
2023-04-12 18:22:40 -04:00
# define CP_FLAG_NTHREADS 2
# define CP_FLAG_SAVEFILE 3
2023-06-14 14:19:27 -04:00
# define CP_FLAG_UTFILE 4
2023-11-03 12:08:25 -04:00
# define CP_FLAG_RESUME 5
2022-05-18 09:57:06 +02:00
int read_args (
int argc ,
const char * argv [ ] ,
2023-11-03 16:04:53 -04:00
dstring * params ,
2022-05-18 23:52:01 +02:00
unsigned int * command ,
2022-05-27 16:09:17 -04:00
unsigned int * nthreads ,
2023-11-03 16:04:53 -04:00
dstring * savefile_str ,
dstring * utfile_str ,
dstring * resumefile_str
2022-05-18 09:57:06 +02:00
) {
2018-01-11 22:48:14 +00:00
int i ;
2022-05-18 23:52:01 +02:00
int ret ;
2018-01-11 22:48:14 +00:00
// pointers
char * ptr ;
// flag that indicates what argument is being read
int flag = 0 ;
// loop over arguments
for ( i = 1 ; i < argc ; i + + ) {
// flag
if ( argv [ i ] [ 0 ] = = ' - ' ) {
for ( ptr = ( ( char * ) argv [ i ] ) + 1 ; * ptr ! = ' \0 ' ; ptr + + ) {
switch ( * ptr ) {
2022-05-18 09:57:06 +02:00
case ' p ' :
flag = CP_FLAG_PARAMS ;
2018-01-11 22:48:14 +00:00
break ;
2022-05-18 23:52:01 +02:00
case ' t ' :
flag = CP_FLAG_NTHREADS ;
break ;
2022-05-27 16:09:17 -04:00
case ' s ' :
flag = CP_FLAG_SAVEFILE ;
break ;
2023-06-14 14:19:27 -04:00
case ' u ' :
flag = CP_FLAG_UTFILE ;
break ;
2018-01-11 22:48:14 +00:00
default :
fprintf ( stderr , " unrecognized option '-%c' \n " , * ptr ) ;
print_usage ( ) ;
return ( - 1 ) ;
break ;
}
}
}
2022-05-18 09:57:06 +02:00
// params
else if ( flag = = CP_FLAG_PARAMS ) {
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( ( char * ) argv [ i ] , params ) ;
2018-01-11 22:48:14 +00:00
flag = 0 ;
}
2022-05-18 23:52:01 +02:00
// nthreads
else if ( flag = = CP_FLAG_NTHREADS ) {
ret = sscanf ( argv [ i ] , " %u " , nthreads ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: '-t' should be followed by an unsigned integer \n got '%s' \n " , argv [ i ] ) ;
return ( - 1 ) ;
}
flag = 0 ;
}
2022-05-27 16:09:17 -04:00
// savefile
else if ( flag = = CP_FLAG_SAVEFILE ) {
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( ( char * ) argv [ i ] , savefile_str ) ;
2022-05-27 16:09:17 -04:00
flag = 0 ;
}
2023-06-14 14:19:27 -04:00
// savefile
else if ( flag = = CP_FLAG_UTFILE ) {
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( ( char * ) argv [ i ] , utfile_str ) ;
2023-06-14 14:19:27 -04:00
flag = 0 ;
}
2023-11-03 12:08:25 -04:00
// resume file
else if ( flag = = CP_FLAG_RESUME ) {
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( ( char * ) argv [ i ] , resumefile_str ) ;
2023-11-03 12:08:25 -04:00
flag = 0 ;
}
2018-01-11 22:48:14 +00:00
// computation to run
else {
2022-05-18 09:57:06 +02:00
if ( strcmp ( argv [ i ] , " uk " ) = = 0 ) {
* command = COMMAND_UK ;
}
2023-05-10 19:29:31 -04:00
else if ( strcmp ( argv [ i ] , " enstrophy " ) = = 0 ) {
* command = COMMAND_ENSTROPHY ;
2018-01-11 22:48:14 +00:00
}
2022-05-18 22:22:42 +02:00
else if ( strcmp ( argv [ i ] , " quiet " ) = = 0 ) {
* command = COMMAND_QUIET ;
}
2023-11-03 12:08:25 -04:00
else if ( strcmp ( argv [ i ] , " resume " ) = = 0 ) {
* command = COMMAND_RESUME ;
flag = CP_FLAG_RESUME ;
}
2024-02-19 19:05:35 -05:00
else if ( strcmp ( argv [ i ] , " lyapunov " ) = = 0 ) {
* command = COMMAND_LYAPUNOV ;
}
2018-01-11 22:48:14 +00:00
else {
2022-05-18 09:57:06 +02:00
fprintf ( stderr , " error: unrecognized command: '%s' \n " , argv [ i ] ) ;
2018-01-11 22:48:14 +00:00
return ( - 1 ) ;
}
}
}
2023-11-03 12:08:25 -04:00
// check that if the command is 'resume', then resumefile has been set
2023-11-03 16:04:53 -04:00
if ( * command = = COMMAND_RESUME & & resumefile_str - > length = = 0 ) {
2023-11-03 12:08:25 -04:00
fprintf ( stderr , " error: 'resume' command used, but no resume file \n " ) ;
print_usage ( ) ;
return ( - 1 ) ;
}
2018-01-11 22:48:14 +00:00
return ( 0 ) ;
}
2023-11-03 12:08:25 -04:00
// set default parameters
int set_default_params (
nstrophy_parameters * parameters
2022-05-18 09:57:06 +02:00
) {
2024-12-11 15:48:11 -05:00
// no choice
parameters - > init_enstrophy_or_energy = 0 ; // do not set init_enstrophy or init_energy here: do that after reading init
2023-04-05 20:33:38 -04:00
parameters - > irreversible = true ;
2022-05-26 14:25:45 -04:00
parameters - > K1 = 16 ;
parameters - > K2 = parameters - > K1 ;
2022-05-18 09:57:06 +02:00
//delta=2^-13
2022-05-26 14:25:45 -04:00
parameters - > delta = 0.0001220703125 ;
2022-05-18 09:57:06 +02:00
//nu=2^-11
2022-05-26 14:25:45 -04:00
parameters - > nu = 0.00048828125 ;
parameters - > L = 2 * M_PI ;
2023-05-15 20:29:06 -04:00
parameters - > adaptive_tolerance = 1e-11 ;
parameters - > adaptive_factor = 0.9 ;
2023-06-13 18:45:19 -04:00
parameters - > max_delta = 1e-2 ;
2024-11-18 17:09:17 -05:00
parameters - > adaptive_cost = COST_L1 ;
2023-05-16 00:00:18 -04:00
parameters - > final_time = 100000 ;
parameters - > print_freq = 1 ;
2022-05-27 17:06:38 -04:00
parameters - > starting_time = 0 ;
2022-05-26 15:05:30 -04:00
parameters - > seed = 17 ;
2023-04-12 18:22:40 -04:00
parameters - > driving = DRIVING_TEST ;
2023-04-24 12:22:29 -04:00
parameters - > drivingfile = NULL ;
2023-04-12 18:22:40 -04:00
parameters - > init = INIT_GAUSSIAN ;
parameters - > initfile = NULL ;
2023-04-26 11:27:03 -04:00
parameters - > algorithm = ALGORITHM_RK4 ;
2023-06-29 16:58:33 -04:00
parameters - > keep_en_cst = false ;
2025-01-31 10:52:40 -05:00
parameters - > algorithm_lyapunov = ALGORITHM_RK4 ;
// default lyapunov_reset will be print_time (set later) for now set target to 0 to indicate it hasn't been set explicitly
parameters - > lyapunov_trigger = 0 ;
2024-11-07 14:39:03 -05:00
parameters - > print_alpha = false ;
2023-11-03 12:08:25 -04:00
return ( 0 ) ;
}
// read parameters string
int read_params (
2023-11-03 16:42:27 -04:00
dstring param_str ,
2023-11-03 12:08:25 -04:00
nstrophy_parameters * parameters ,
2023-11-03 16:04:53 -04:00
dstring * initfile_str ,
dstring * drivingfile_str
2023-11-03 12:08:25 -04:00
) {
int ret ;
2023-11-03 16:42:27 -04:00
unsigned int i ;
2023-11-03 12:08:25 -04:00
// buffer and associated pointer
2023-11-03 16:42:27 -04:00
dstring buffer_lhs ;
dstring buffer_rhs ;
2023-11-03 12:08:25 -04:00
// whether N was set explicitly
bool setN1 = false ;
bool setN2 = false ;
2023-11-03 16:42:27 -04:00
// which buffer to add to
dstring * buffer = & buffer_lhs ;
2022-05-18 09:57:06 +02:00
2023-11-03 16:04:53 -04:00
// init
2023-11-03 16:42:27 -04:00
dstring_init ( & buffer_lhs , param_str . length ) ;
dstring_init ( & buffer_rhs , param_str . length ) ;
for ( i = 0 ; i < param_str . length ; i + + ) {
switch ( param_str . string [ i ] ) {
2023-11-03 16:04:53 -04:00
case ' = ' :
// reset buffer
2023-11-03 16:42:27 -04:00
buffer_rhs . length = 0 ;
buffer = & buffer_rhs ;
2023-11-03 16:04:53 -04:00
break ;
case ' ; ' :
//set parameter
2023-11-03 16:42:27 -04:00
ret = set_parameter ( dstring_to_str_noinit ( & buffer_lhs ) , dstring_to_str_noinit ( & buffer_rhs ) , parameters , & setN1 , & setN2 , initfile_str , drivingfile_str ) ;
2022-05-18 09:57:06 +02:00
if ( ret < 0 ) {
return ret ;
}
2023-11-03 16:04:53 -04:00
// reset buffer
2023-11-03 16:42:27 -04:00
buffer_lhs . length = 0 ;
buffer = & buffer_lhs ;
2023-11-03 16:04:53 -04:00
break ;
default :
// add to buffer
2023-11-03 16:42:27 -04:00
dstring_append ( param_str . string [ i ] , buffer ) ;
2023-11-03 16:04:53 -04:00
break ;
2022-05-18 09:57:06 +02:00
}
2023-11-03 16:04:53 -04:00
}
2018-01-11 22:48:14 +00:00
2023-11-03 16:04:53 -04:00
// set last param
2023-11-03 16:42:27 -04:00
if ( param_str . length ! = 0 ) {
ret = set_parameter ( dstring_to_str_noinit ( & buffer_lhs ) , dstring_to_str_noinit ( & buffer_rhs ) , parameters , & setN1 , & setN2 , initfile_str , drivingfile_str ) ;
2023-11-03 16:04:53 -04:00
if ( ret < 0 ) {
return ret ;
}
2022-05-18 09:57:06 +02:00
}
2018-02-19 16:00:07 +00:00
2023-11-03 16:04:53 -04:00
// free vects
2023-11-03 16:42:27 -04:00
dstring_free ( buffer_lhs ) ;
dstring_free ( buffer_rhs ) ;
2023-11-03 16:04:53 -04:00
2022-05-26 20:54:30 -04:00
// if N not set explicitly, set it to the smallest power of 2 that is >3*K+1 (the fft is faster on vectors whose length is a power of 2)
2022-05-18 09:57:06 +02:00
if ( ! setN1 ) {
2022-05-26 20:54:30 -04:00
parameters - > N1 = smallest_pow2 ( 3 * ( parameters - > K1 ) ) ;
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
if ( ! setN2 ) {
2022-05-26 20:54:30 -04:00
parameters - > N2 = smallest_pow2 ( 3 * ( parameters - > K2 ) ) ;
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
2025-01-31 10:52:40 -05:00
// if lyapunov_reset or lyapunov_maxu are not set explicitly
if ( parameters - > lyapunov_trigger = = 0 ) {
parameters - > lyapunov_trigger = LYAPUNOV_TRIGGER_TIME ;
parameters - > lyapunov_reset = parameters - > print_freq ;
}
2022-05-18 09:57:06 +02:00
return ( 0 ) ;
}
// set a parameter from the parameter string
int set_parameter (
char * lhs ,
char * rhs ,
2022-05-26 14:25:45 -04:00
nstrophy_parameters * parameters ,
2022-05-18 09:57:06 +02:00
bool * setN1 ,
2023-04-12 14:37:02 -04:00
bool * setN2 ,
2023-11-03 16:04:53 -04:00
dstring * initfile_str ,
dstring * drivingfile_str
2022-05-18 09:57:06 +02:00
) {
int ret ;
2023-04-05 20:33:38 -04:00
if ( strcmp ( lhs , " equation " ) = = 0 ) {
if ( strcmp ( rhs , " irreversible " ) = = 0 ) {
parameters - > irreversible = true ;
}
else if ( strcmp ( rhs , " reversible " ) = = 0 ) {
parameters - > irreversible = false ;
}
else {
fprintf ( stderr , " error: 'equation' should be 'irreversible' or 'reversible' \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2024-12-11 15:48:11 -05:00
else if ( strcmp ( lhs , " init_enstrophy " ) = = 0 ) {
// check that the energy was not also set
if ( parameters - > init_enstrophy_or_energy = = FIX_ENERGY ) {
fprintf ( stderr , " error: cannot use init_enstrophy if init_energy has been used \n " ) ;
return ( - 1 ) ;
}
parameters - > init_enstrophy_or_energy = FIX_ENSTROPHY ;
ret = sscanf ( rhs , " %lf " , & ( parameters - > init_enstrophy ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'init_enstrophy' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
else if ( strcmp ( lhs , " init_energy " ) = = 0 ) {
// check that the enstrophy was not also set
if ( parameters - > init_enstrophy_or_energy = = FIX_ENSTROPHY ) {
fprintf ( stderr , " error: cannot use init_energy if init_enstrophy has been used \n " ) ;
return ( - 1 ) ;
}
parameters - > init_enstrophy_or_energy = FIX_ENERGY ;
ret = sscanf ( rhs , " %lf " , & ( parameters - > init_energy ) ) ;
2023-04-05 22:41:19 -04:00
if ( ret ! = 1 ) {
2024-12-11 15:48:11 -05:00
fprintf ( stderr , " error: parameter 'init_energy' should be a double \n got '%s' \n " , rhs ) ;
2023-04-05 22:41:19 -04:00
return ( - 1 ) ;
}
}
2023-04-05 20:33:38 -04:00
else if ( strcmp ( lhs , " K1 " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > K1 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'K1' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " K2 " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > K2 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'K2' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-02-19 16:00:07 +00:00
}
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " K " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > K1 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'K' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-02-19 16:00:07 +00:00
}
2022-05-26 14:25:45 -04:00
parameters - > K2 = parameters - > K1 ;
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " N1 " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > N1 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'N1' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
* setN1 = true ;
2018-02-19 16:00:07 +00:00
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " N2 " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > N2 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'N2' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-01-11 22:48:14 +00:00
}
2022-05-18 09:57:06 +02:00
* setN2 = true ;
2018-01-11 22:48:14 +00:00
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " N " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %d " , & ( parameters - > N1 ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'N' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2022-05-17 14:31:22 +02:00
}
2022-05-26 14:25:45 -04:00
parameters - > N2 = parameters - > N1 ;
2022-05-18 09:57:06 +02:00
* setN1 = true ;
* setN2 = true ;
2022-05-17 14:31:22 +02:00
}
2023-05-16 00:00:18 -04:00
else if ( strcmp ( lhs , " final_time " ) = = 0 ) {
ret = sscanf ( rhs , " %lf " , & ( parameters - > final_time ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
2023-05-16 00:00:18 -04:00
fprintf ( stderr , " error: parameter 'final_time' should be a double \n got '%s' \n " , rhs ) ;
2022-05-18 09:57:06 +02:00
return ( - 1 ) ;
2018-01-11 22:48:14 +00:00
}
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " nu " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %lf " , & ( parameters - > nu ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'nu' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-01-11 22:48:14 +00:00
}
2022-05-18 09:57:06 +02:00
}
else if ( strcmp ( lhs , " delta " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %lf " , & ( parameters - > delta ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'delta' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
2018-01-11 22:48:14 +00:00
}
2022-05-18 09:57:06 +02:00
}
2022-05-25 11:12:02 -04:00
else if ( strcmp ( lhs , " L " ) = = 0 ) {
2022-05-26 14:25:45 -04:00
ret = sscanf ( rhs , " %lf " , & ( parameters - > L ) ) ;
2022-05-25 11:12:02 -04:00
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'L' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2023-05-15 20:29:06 -04:00
else if ( strcmp ( lhs , " adaptive_tolerance " ) = = 0 ) {
ret = sscanf ( rhs , " %lf " , & ( parameters - > adaptive_tolerance ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'adaptive_tolerance' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
else if ( strcmp ( lhs , " adaptive_factor " ) = = 0 ) {
ret = sscanf ( rhs , " %lf " , & ( parameters - > adaptive_factor ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'adaptive_factor' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2023-06-13 18:45:19 -04:00
else if ( strcmp ( lhs , " max_delta " ) = = 0 ) {
ret = sscanf ( rhs , " %lf " , & ( parameters - > max_delta ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'max_delta' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2024-11-18 17:09:17 -05:00
else if ( strcmp ( lhs , " adaptive_cost " ) = = 0 ) {
2023-06-13 23:56:35 -04:00
if ( strcmp ( rhs , " L1 " ) = = 0 ) {
2024-11-18 17:09:17 -05:00
parameters - > adaptive_cost = COST_L1 ;
2023-06-13 23:56:35 -04:00
}
else if ( strcmp ( rhs , " k3 " ) = = 0 ) {
2024-11-18 17:09:17 -05:00
parameters - > adaptive_cost = COST_k3 ;
2023-06-13 23:56:35 -04:00
}
else if ( strcmp ( rhs , " k32 " ) = = 0 ) {
2024-11-18 17:09:17 -05:00
parameters - > adaptive_cost = COST_k32 ;
2023-06-13 23:56:35 -04:00
}
else if ( strcmp ( rhs , " enstrophy " ) = = 0 ) {
2024-11-18 17:09:17 -05:00
parameters - > adaptive_cost = COST_ENSTROPHY ;
}
else if ( strcmp ( rhs , " alpha " ) = = 0 ) {
parameters - > adaptive_cost = COST_ALPHA ;
2023-06-13 23:56:35 -04:00
}
else {
2024-11-18 17:09:17 -05:00
fprintf ( stderr , " error: unrecognized adaptive_cost '%s' \n " , rhs ) ;
2023-06-13 23:56:35 -04:00
return ( - 1 ) ;
}
}
2022-05-18 09:57:06 +02:00
else if ( strcmp ( lhs , " print_freq " ) = = 0 ) {
2023-05-16 00:00:18 -04:00
ret = sscanf ( rhs , " %lf " , & ( parameters - > print_freq ) ) ;
2022-05-18 09:57:06 +02:00
if ( ret ! = 1 ) {
2023-05-16 00:00:18 -04:00
fprintf ( stderr , " error: parameter 'print_freq' should be a double \n got '%s' \n " , rhs ) ;
2022-05-18 09:57:06 +02:00
return ( - 1 ) ;
2018-01-11 22:48:14 +00:00
}
}
2022-05-26 15:05:30 -04:00
else if ( strcmp ( lhs , " random_seed " ) = = 0 ) {
ret = sscanf ( rhs , " %d " , & ( parameters - > seed ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'random_seed' should be an integer \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2022-05-27 17:06:38 -04:00
else if ( strcmp ( lhs , " starting_time " ) = = 0 ) {
2023-05-15 20:29:06 -04:00
ret = sscanf ( rhs , " %lf " , & ( parameters - > starting_time ) ) ;
2022-05-27 17:06:38 -04:00
if ( ret ! = 1 ) {
2023-05-15 20:29:06 -04:00
fprintf ( stderr , " error: parameter 'starting_time' should be a double \n got '%s' \n " , rhs ) ;
2022-05-27 17:06:38 -04:00
return ( - 1 ) ;
}
}
2024-02-19 21:39:48 -05:00
else if ( strcmp ( lhs , " D_epsilon " ) = = 0 ) {
ret = sscanf ( rhs , " %lf " , & ( parameters - > D_epsilon ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'D_epsilon' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2023-04-12 18:22:40 -04:00
else if ( strcmp ( lhs , " driving " ) = = 0 ) {
if ( strcmp ( rhs , " zero " ) = = 0 ) {
parameters - > driving = DRIVING_ZERO ;
}
else if ( strcmp ( rhs , " test " ) = = 0 ) {
parameters - > driving = DRIVING_TEST ;
}
2023-04-24 12:22:29 -04:00
// matches any argument that starts with 'file:'
else if ( strncmp ( rhs , " file: " , 5 ) = = 0 ) {
parameters - > driving = DRIVING_FILE ;
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( rhs + 5 , drivingfile_str ) ;
2023-04-24 12:22:29 -04:00
}
// matches any argument that starts with 'file_txt:'
else if ( strncmp ( rhs , " file_txt: " , 9 ) = = 0 ) {
parameters - > driving = DRIVING_FILE_TXT ;
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( rhs + 9 , drivingfile_str ) ;
2023-04-24 12:22:29 -04:00
}
2023-04-12 18:22:40 -04:00
else {
fprintf ( stderr , " error: unrecognized driving force '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
// initial condition
else if ( strcmp ( lhs , " init " ) = = 0 ) {
if ( strcmp ( rhs , " random " ) = = 0 ) {
parameters - > init = INIT_RANDOM ;
}
else if ( strcmp ( rhs , " gaussian " ) = = 0 ) {
parameters - > init = INIT_GAUSSIAN ;
}
// matches any argument that starts with 'file:'
else if ( strncmp ( rhs , " file: " , 5 ) = = 0 ) {
parameters - > init = INIT_FILE ;
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( rhs + 5 , initfile_str ) ;
2023-04-12 18:22:40 -04:00
}
2023-04-24 12:06:35 -04:00
// matches any argument that starts with 'file_txt:'
else if ( strncmp ( rhs , " file_txt: " , 9 ) = = 0 ) {
parameters - > init = INIT_FILE_TXT ;
2023-11-03 16:04:53 -04:00
str_to_dstring_noinit ( rhs + 9 , initfile_str ) ;
2023-04-24 12:06:35 -04:00
}
2023-04-12 18:22:40 -04:00
else {
fprintf ( stderr , " error: unrecognized initial condition '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2023-04-26 11:27:03 -04:00
// algorithm
else if ( strcmp ( lhs , " algorithm " ) = = 0 ) {
if ( strcmp ( rhs , " RK4 " ) = = 0 ) {
parameters - > algorithm = ALGORITHM_RK4 ;
}
else if ( strcmp ( rhs , " RK2 " ) = = 0 ) {
parameters - > algorithm = ALGORITHM_RK2 ;
}
2023-05-15 20:29:06 -04:00
else if ( strcmp ( rhs , " RKF45 " ) = = 0 ) {
parameters - > algorithm = ALGORITHM_RKF45 ;
}
2023-05-17 17:41:00 -04:00
else if ( strcmp ( rhs , " RKDP54 " ) = = 0 ) {
parameters - > algorithm = ALGORITHM_RKDP54 ;
}
2023-05-17 16:59:15 -04:00
else if ( strcmp ( rhs , " RKBS32 " ) = = 0 ) {
parameters - > algorithm = ALGORITHM_RKBS32 ;
2023-05-17 16:47:15 -04:00
}
2023-04-26 11:27:03 -04:00
else {
fprintf ( stderr , " error: unrecognized algorithm '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2023-06-29 16:58:33 -04:00
else if ( strcmp ( lhs , " keep_en_cst " ) = = 0 ) {
int tmp ;
ret = sscanf ( rhs , " %d " , & tmp ) ;
if ( ret ! = 1 | | ( tmp ! = 0 & & tmp ! = 1 ) ) {
fprintf ( stderr , " error: parameter 'keep_en_cst' should be 0 or 1 \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
parameters - > keep_en_cst = ( tmp = = 1 ) ;
}
2024-11-07 14:39:03 -05:00
else if ( strcmp ( lhs , " print_alpha " ) = = 0 ) {
int tmp ;
ret = sscanf ( rhs , " %d " , & tmp ) ;
if ( ret ! = 1 | | ( tmp ! = 0 & & tmp ! = 1 ) ) {
fprintf ( stderr , " error: parameter 'print_alpha' should be 0 or 1 \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
parameters - > print_alpha = ( tmp = = 1 ) ;
}
2025-01-31 10:52:40 -05:00
else if ( strcmp ( lhs , " lyapunov_reset " ) = = 0 ) {
if ( parameters - > lyapunov_trigger = = LYAPUNOV_TRIGGER_SIZE ) {
fprintf ( stderr , " error: cannot use 'lyapunov_reset' and 'lyapunov_maxu' in the same run: \n 'lyapunov_reset' is to be used to renormalize the tangent flow at fixed times, 'lyapunov_maxu' is to be used to renormalize the tangent flow when the matrix exceeds a certain size. " ) ;
return ( - 1 ) ;
}
parameters - > lyapunov_trigger = LYAPUNOV_TRIGGER_TIME ;
ret = sscanf ( rhs , " %lf " , & ( parameters - > lyapunov_reset ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'lyapunov_reset' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
else if ( strcmp ( lhs , " lyapunov_maxu " ) = = 0 ) {
if ( parameters - > lyapunov_trigger = = LYAPUNOV_TRIGGER_TIME ) {
fprintf ( stderr , " error: cannot use 'lyapunov_maxu' and 'lyapunov_reset' in the same run: \n 'lyapunov_reset' is to be used to renormalize the tangent flow at fixed times, 'lyapunov_maxu' is to be used to renormalize the tangent flow when the matrix exceeds a certain size. " ) ;
return ( - 1 ) ;
}
parameters - > lyapunov_trigger = LYAPUNOV_TRIGGER_SIZE ;
ret = sscanf ( rhs , " %lf " , & ( parameters - > lyapunov_reset ) ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " error: parameter 'lyapunov_maxu' should be a double \n got '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
// algorithm for tangent flow (for lyapunov)
else if ( strcmp ( lhs , " algorithm_lyapunov " ) = = 0 ) {
if ( strcmp ( rhs , " RK4 " ) = = 0 ) {
parameters - > algorithm_lyapunov = ALGORITHM_RK4 ;
}
else if ( strcmp ( rhs , " RK2 " ) = = 0 ) {
parameters - > algorithm_lyapunov = ALGORITHM_RK2 ;
}
else if ( strcmp ( rhs , " RKF45 " ) = = 0 | | strcmp ( rhs , " RKDP45 " ) = = 0 | | strcmp ( rhs , " RKBS32 " ) = = 0 ) {
fprintf ( stderr , " error: cannot use an adaptove step algorithm for the tangent flow (Lyapunov exponents); must be one of 'RK4' or 'RK2', got:'%s' \n " , rhs ) ;
return ( - 1 ) ;
}
else {
fprintf ( stderr , " error: unrecognized algorithm '%s' \n " , rhs ) ;
return ( - 1 ) ;
}
}
2022-05-18 09:57:06 +02:00
else {
fprintf ( stderr , " error: unrecognized parameter '%s' \n " , lhs ) ;
return ( - 1 ) ;
}
2018-01-11 22:48:14 +00:00
return ( 0 ) ;
}
2022-05-26 15:05:30 -04:00
2023-11-03 12:08:25 -04:00
// read args from file
int args_from_file (
2023-11-03 16:04:53 -04:00
dstring * params ,
2023-11-03 12:08:25 -04:00
unsigned int * command ,
unsigned int * nthreads ,
2023-11-03 16:04:53 -04:00
dstring * savefile_str ,
dstring * utfile_str ,
2023-11-03 12:08:25 -04:00
char * file_str
) {
2023-11-03 16:45:51 -04:00
dstring line ;
2023-11-03 12:08:25 -04:00
char c ;
// open file
FILE * file = fopen ( file_str , " r " ) ;
if ( file = = NULL ) {
fprintf ( stderr , " Error opening file '%s' for reading: %s \n " , file_str , strerror ( errno ) ) ;
return ( - 1 ) ;
}
// allocate line buffer
2023-11-03 16:45:51 -04:00
dstring_init ( & line , 64 ) ;
2023-11-03 12:08:25 -04:00
while ( 1 ) {
c = fgetc ( file ) ;
// end of file
if ( feof ( file ) ) {
break ;
}
// newline: read line and reset buffer
if ( c = = ' \n ' | | c = = ' \r ' ) {
// read entry
// ignore lines with fewer than three characters
2023-11-03 16:45:51 -04:00
if ( line . length > = 3 ) {
2023-11-03 12:08:25 -04:00
// find line starting with "#!"
2023-11-03 16:45:51 -04:00
if ( line . string [ 0 ] = = ' # ' & & line . string [ 1 ] = = ' ! ' ) {
2023-11-03 12:08:25 -04:00
wordexp_t pwordexp ;
2023-11-03 16:45:51 -04:00
wordexp ( line . string + 2 , & pwordexp , 0 ) ;
2023-11-03 12:08:25 -04:00
// read arguments
read_args ( pwordexp . we_wordc , ( const char * * ) pwordexp . we_wordv , params , command , nthreads , savefile_str , utfile_str , NULL ) ;
wordfree ( & pwordexp ) ;
// exit
break ;
}
}
// reset buffer
2023-11-03 16:45:51 -04:00
line . length = 0 ;
2023-11-03 12:08:25 -04:00
}
// add to buffer
else {
2023-11-03 16:45:51 -04:00
dstring_append ( c , & line ) ;
2023-11-03 12:08:25 -04:00
}
}
2023-11-03 16:45:51 -04:00
dstring_free ( line ) ;
2023-11-03 12:08:25 -04:00
// close file
fclose ( file ) ;
return ( 0 ) ;
}
2022-05-26 15:16:44 -04:00
// set driving force
_Complex double * set_driving (
nstrophy_parameters parameters
) {
2024-10-15 11:31:53 -04:00
_Complex double * g = calloc ( parameters . K1 * ( 2 * parameters . K2 + 1 ) + parameters . K2 , sizeof ( _Complex double ) ) ;
2022-05-26 15:16:44 -04:00
2023-04-12 18:22:40 -04:00
switch ( parameters . driving ) {
2022-05-26 15:16:44 -04:00
case DRIVING_ZERO :
g_zero ( g , parameters . K1 , parameters . K2 ) ;
break ;
case DRIVING_TEST :
g_test ( g , parameters . K1 , parameters . K2 ) ;
break ;
2023-04-24 12:22:29 -04:00
case DRIVING_FILE :
init_file_bin ( g , parameters . K1 , parameters . K2 , parameters . drivingfile ) ;
break ;
case DRIVING_FILE_TXT :
init_file_txt ( g , parameters . K1 , parameters . K2 , parameters . drivingfile ) ;
break ;
2022-05-26 15:16:44 -04:00
default :
g_test ( g , parameters . K1 , parameters . K2 ) ;
break ;
}
return g ;
}
2022-05-26 15:05:30 -04:00
// set initial condition
_Complex double * set_init (
2023-05-15 20:29:06 -04:00
nstrophy_parameters * parameters
2022-05-26 15:05:30 -04:00
) {
2024-10-15 11:31:53 -04:00
_Complex double * u0 = calloc ( parameters - > K1 * ( 2 * parameters - > K2 + 1 ) + parameters - > K2 , sizeof ( _Complex double ) ) ;
2022-05-26 15:05:30 -04:00
2023-05-15 20:29:06 -04:00
switch ( parameters - > init ) {
2022-05-26 15:05:30 -04:00
case INIT_RANDOM :
2024-12-11 15:48:11 -05:00
init_random ( u0 , parameters - > K1 , parameters - > K2 , parameters - > seed ) ;
2022-05-26 15:05:30 -04:00
break ;
case INIT_GAUSSIAN :
2024-12-11 15:48:11 -05:00
init_gaussian ( u0 , parameters - > K1 , parameters - > K2 ) ;
2022-05-26 15:05:30 -04:00
break ;
2022-05-27 16:09:17 -04:00
case INIT_FILE :
2023-05-15 20:29:06 -04:00
init_file_bin ( u0 , parameters - > K1 , parameters - > K2 , parameters - > initfile ) ;
2023-05-16 00:00:18 -04:00
// read start time
fread ( & ( parameters - > starting_time ) , sizeof ( double ) , 1 , parameters - > initfile ) ;
2023-05-15 20:29:06 -04:00
if ( parameters - > algorithm > ALGORITHM_ADAPTIVE_THRESHOLD ) {
// read delta
fread ( & ( parameters - > delta ) , sizeof ( double ) , 1 , parameters - > initfile ) ;
}
2023-04-24 12:06:35 -04:00
break ;
case INIT_FILE_TXT :
2023-05-15 20:29:06 -04:00
init_file_txt ( u0 , parameters - > K1 , parameters - > K2 , parameters - > initfile ) ;
2022-05-27 16:09:17 -04:00
break ;
2022-05-26 15:05:30 -04:00
default :
2024-12-11 15:48:11 -05:00
init_gaussian ( u0 , parameters - > K1 , parameters - > K2 ) ;
2022-05-26 15:05:30 -04:00
break ;
}
2024-12-11 15:48:11 -05:00
// rescale energy or enstrophy
if ( parameters - > init_enstrophy_or_energy = = FIX_ENERGY ) {
// fix the energy
double rescale = compute_energy ( u0 , parameters - > K1 , parameters - > K2 ) ;
int kx , ky ;
for ( kx = 0 ; kx < = parameters - > K1 ; kx + + ) {
for ( ky = ( kx > 0 ? - parameters - > K2 : 1 ) ; ky < = parameters - > K2 ; ky + + ) {
u0 [ klookup_sym ( kx , ky , parameters - > K2 ) ] = u0 [ klookup_sym ( kx , ky , parameters - > K2 ) ] * sqrt ( parameters - > init_energy / rescale ) ;
}
}
} else if ( parameters - > init_enstrophy_or_energy = = FIX_ENSTROPHY ) {
// fix the enstrophy
double rescale = compute_enstrophy ( u0 , parameters - > K1 , parameters - > K2 , parameters - > L ) ;
int kx , ky ;
for ( kx = 0 ; kx < = parameters - > K1 ; kx + + ) {
for ( ky = ( kx > 0 ? - parameters - > K2 : 1 ) ; ky < = parameters - > K2 ; ky + + ) {
u0 [ klookup_sym ( kx , ky , parameters - > K2 ) ] = u0 [ klookup_sym ( kx , ky , parameters - > K2 ) ] * sqrt ( parameters - > init_enstrophy / rescale ) ;
}
}
}
2022-05-26 15:05:30 -04:00
return u0 ;
}