Nstrophy/src/main.c

986 lines
26 KiB
C
Raw Normal View History

2023-05-10 19:33:29 -04:00
/*
Copyright 2017-2023 Ian Jauslin
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
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>
#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"
2022-05-26 15:05:30 -04:00
#include "init.h"
#include "int_tools.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 {
2023-04-05 22:41:19 -04:00
double init_en; // initial value for the energy for ins and enstrophy for rns
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;
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;
2023-06-13 23:56:35 -04:00
unsigned int adaptive_norm;
double print_freq;
2022-05-26 15:05:30 -04:00
int seed;
2023-05-15 20:29:06 -04:00
double starting_time;
unsigned int driving;
unsigned int init;
2023-04-26 11:27:03 -04:00
unsigned int algorithm;
2023-06-29 16:58:33 -04:00
bool keep_en_cst;
FILE* initfile;
2023-04-24 12:22:29 -04:00
FILE* drivingfile;
2022-05-26 14:25:45 -04:00
} nstrophy_parameters;
2018-01-11 22:48:14 +00:00
// usage message
int print_usage();
// 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
int read_args(int argc, const char* argv[], char** params, unsigned int* command, unsigned int* nthreads, char** savefile_str, char** utfile_str, char** resumefile_str);
int set_default_params(nstrophy_parameters* parameters);
2023-04-24 12:22:29 -04:00
int read_params(char* param_str, nstrophy_parameters* parameters, char** initfile_str, char** drivingfile_str);
int set_parameter(char* lhs, char* rhs, nstrophy_parameters* parameters, bool* setN1, bool* setN2, char** initfile_str, char** drivingfile_str);
// read args from file
int args_from_file(char** params, unsigned int* command, unsigned int* nthreads, char** savefile_str, char** utfile_str, char* file_str);
2022-05-18 09:57:06 +02:00
// set driving force
_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){
if (signo == SIGINT){
fprintf(stderr,"received signal SIGINT, interrupting computation\n");
2023-04-12 15:23:35 -04:00
g_abort = true;
}
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[]
){
2022-05-26 14:25:45 -04:00
char* param_str=NULL;
nstrophy_parameters parameters;
2018-01-11 22:48:14 +00:00
int ret;
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;
_Complex double *g;
2022-05-27 16:09:17 -04:00
char* savefile_str=NULL;
2023-06-14 14:19:27 -04:00
char* utfile_str=NULL;
2022-05-27 16:09:17 -04:00
char* initfile_str=NULL;
2023-04-24 12:22:29 -04:00
char* drivingfile_str=NULL;
char* resumefile_str=NULL;
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
// read command line arguments
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){
return(-1);
}
2022-05-26 15:05:30 -04:00
// set default params
set_default_params(&parameters);
2022-05-18 09:57:06 +02:00
// read params
2023-04-24 12:22:29 -04:00
ret=read_params(param_str, &parameters, &initfile_str, &drivingfile_str);
2018-01-11 22:48:14 +00:00
if(ret<0){
return(-1);
}
2022-05-26 15:05:30 -04:00
// if command is 'resume', then read args from file
if(command==COMMAND_RESUME){
ret=args_from_file(&param_str, &command, &nthreads, &savefile_str, &utfile_str, resumefile_str);
if(ret<0){
return(-1);
}
// read params
ret=read_params(param_str, &parameters, &initfile_str, &drivingfile_str);
if(ret<0){
return(-1);
}
// reread arguments (to allow overrides from the command line)
ret=read_args(argc, argv, &param_str, &command, &nthreads, &savefile_str, &utfile_str, &resumefile_str);
if(ret<0){
return(-1);
}
// reread params
ret=read_params(param_str, &parameters, &initfile_str, &drivingfile_str);
if(ret<0){
return(-1);
}
}
2022-05-27 16:09:17 -04:00
// open initfile
if(initfile_str!=NULL){
parameters.initfile=fopen(initfile_str,"r");
if(parameters.initfile==NULL){
2022-05-27 16:09:17 -04:00
fprintf(stderr,"Error opening file '%s' for reading: %s\n", initfile_str, strerror(errno));
return(-1);
}
}
2023-04-24 12:22:29 -04:00
// open drivingfile
if(drivingfile_str!=NULL){
parameters.drivingfile=fopen(drivingfile_str,"r");
if(parameters.drivingfile==NULL){
fprintf(stderr,"Error opening file '%s' for reading: %s\n", drivingfile_str, strerror(errno));
return(-1);
}
}
2022-05-27 16:09:17 -04:00
2022-05-18 09:57:06 +02:00
// set driving force
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
// close initfile (do this early, so that it is possible to use the same file for init and save)
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)
if(savefile_str!=NULL){
savefile=fopen(savefile_str,"w");
if(savefile==NULL){
fprintf(stderr,"Error opening file '%s' for writing: %s\n", savefile_str, strerror(errno));
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)
if(utfile_str!=NULL){
utfile=fopen(utfile_str,"w");
if(utfile==NULL){
fprintf(stderr,"Error opening file '%s' for writing: %s\n", utfile_str, strerror(errno));
return(-1);
}
}
// print parameters
2023-04-24 12:22:29 -04:00
print_params(parameters, initfile_str, drivingfile_str, stderr);
print_params(parameters, initfile_str, drivingfile_str, stdout);
2023-04-12 19:05:01 -04:00
// free initfile_str
if(initfile_str!=NULL){
free(initfile_str);
}
2023-04-24 12:22:29 -04:00
// free drivingfile_str
if(drivingfile_str!=NULL){
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){
2023-06-29 16:58:33 -04: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_norm, u0, g, parameters.irreversible, parameters.keep_en_cst, parameters.init_en, parameters.algorithm, parameters.print_freq, parameters.starting_time, nthreads, savefile);
2022-05-18 09:57:06 +02: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);
2023-06-29 16:58:33 -04: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_norm, u0, g, parameters.irreversible, parameters.keep_en_cst, parameters.init_en, parameters.algorithm, parameters.print_freq, parameters.starting_time, nthreads, savefile, utfile, (char*)argv[0], param_str, savefile_str, utfile_str);
2022-05-18 09:57:06 +02:00
}
2022-05-18 22:22:42 +02:00
else if(command==COMMAND_QUIET){
2023-06-29 16:58:33 -04: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_norm, parameters.starting_time, u0, g, parameters.irreversible, parameters.keep_en_cst, parameters.init_en, parameters.algorithm, nthreads, savefile);
2022-05-18 22:22:42 +02: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
}
free(g);
2022-05-26 15:05:30 -04:00
free(u0);
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(){
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);
}
// 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,
FILE* file
){
2023-04-05 22:41:19 -04:00
fprintf(file,"# ");
if (parameters.irreversible){
fprintf(file,"equation=irreversible");
} else {
fprintf(file,"equation=reversible");
}
fprintf(file,", K1=%d, K2=%d, N1=%d, N2=%d, nu=%.15e, delta=%.15e, L=%.15e, init_en=%.15e", parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nu, parameters.delta, parameters.L, parameters.init_en);
switch(parameters.driving){
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;
default:
fprintf(file,", driving=test");
break;
}
switch(parameters.init){
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;
case INIT_FILE_TXT:
fprintf(file,", init=file_txt:%s", initfile_str);
break;
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){
switch(parameters.adaptive_norm){
case NORM_L1:
fprintf(file,", norm=L1");
break;
case NORM_k3:
fprintf(file,", norm=k3");
break;
case NORM_k32:
fprintf(file,", norm=k32");
break;
case NORM_ENSTROPHY:
fprintf(file,", norm=enstrophy");
break;
}
}
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
#define CP_FLAG_NTHREADS 2
#define CP_FLAG_SAVEFILE 3
2023-06-14 14:19:27 -04:00
#define CP_FLAG_UTFILE 4
#define CP_FLAG_RESUME 5
2022-05-18 09:57:06 +02:00
int read_args(
int argc,
const char* argv[],
char** params,
2022-05-18 23:52:01 +02:00
unsigned int* command,
2022-05-27 16:09:17 -04:00
unsigned int* nthreads,
2023-06-14 14:19:27 -04:00
char** savefile_str,
char** utfile_str,
char** 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){
*params=(char*)argv[i];
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){
*savefile_str=(char*)argv[i];
flag=0;
}
2023-06-14 14:19:27 -04:00
// savefile
else if(flag==CP_FLAG_UTFILE){
*utfile_str=(char*)argv[i];
flag=0;
}
// resume file
else if(flag==CP_FLAG_RESUME){
*resumefile_str=(char*)argv[i];
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;
}
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;
}
else if(strcmp(argv[i], "resume")==0){
*command=COMMAND_RESUME;
flag=CP_FLAG_RESUME;
}
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);
}
}
}
// check that if the command is 'resume', then resumefile has been set
if(*command==COMMAND_RESUME && *resumefile_str==NULL){
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);
}
// set default parameters
int set_default_params(
nstrophy_parameters* parameters
2022-05-18 09:57:06 +02:00
){
2023-04-05 22:41:19 -04:00
parameters->init_en=1.54511597324389e+02;
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;
2023-06-13 23:56:35 -04:00
parameters->adaptive_norm=NORM_L1;
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;
parameters->driving=DRIVING_TEST;
2023-04-24 12:22:29 -04:00
parameters->drivingfile=NULL;
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;
return(0);
}
// read parameters string
int read_params(
char* param_str,
nstrophy_parameters* parameters,
char** initfile_str,
char** drivingfile_str
){
int ret;
// pointer in params
char* ptr;
// buffer and associated pointer
char *buffer_lhs, *lhs_ptr;
char *buffer_rhs, *rhs_ptr;
// whether N was set explicitly
bool setN1=false;
bool setN2=false;
// whether lhs (false is rhs)
bool lhs=true;
2022-05-18 09:57:06 +02:00
2022-05-26 14:25:45 -04:00
if (param_str!=NULL){
2022-05-18 09:57:06 +02:00
// init
2022-05-26 14:25:45 -04:00
buffer_lhs=calloc(sizeof(char),strlen(param_str));
2022-05-18 09:57:06 +02:00
lhs_ptr=buffer_lhs;
*lhs_ptr='\0';
2022-05-26 14:25:45 -04:00
buffer_rhs=calloc(sizeof(char),strlen(param_str));
2022-05-18 09:57:06 +02:00
rhs_ptr=buffer_rhs;
*rhs_ptr='\0';
2018-01-11 22:48:14 +00:00
2022-05-26 14:25:45 -04:00
for(ptr=param_str;*ptr!='\0';ptr++){
2022-05-18 09:57:06 +02:00
switch(*ptr){
case '=':
// reset buffer
rhs_ptr=buffer_rhs;
*rhs_ptr='\0';
lhs=false;
break;
case ';':
//set parameter
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, initfile_str, drivingfile_str);
2022-05-18 09:57:06 +02:00
if(ret<0){
return ret;
}
// reset buffer
lhs_ptr=buffer_lhs;
*lhs_ptr='\0';
lhs=true;
break;
default:
// add to buffer
if (lhs){
*lhs_ptr=*ptr;
lhs_ptr++;
*lhs_ptr='\0';
}
else{
*rhs_ptr=*ptr;
rhs_ptr++;
*rhs_ptr='\0';
}
break;
}
}
2018-01-11 22:48:14 +00:00
2022-05-18 09:57:06 +02:00
// set last param
2022-05-26 14:25:45 -04:00
if (*param_str!='\0'){
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, initfile_str, drivingfile_str);
2022-05-18 09:57:06 +02:00
if(ret<0){
return ret;
}
}
2018-01-11 22:48:14 +00:00
2022-05-18 09:57:06 +02:00
// free vects
free(buffer_lhs);
free(buffer_rhs);
}
2018-02-19 16:00:07 +00: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){
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){
parameters->N2=smallest_pow2(3*(parameters->K2));
2018-02-19 16:00:07 +00:00
}
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-04-24 12:22:29 -04:00
char** initfile_str,
char** 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);
}
}
2023-04-05 22:41:19 -04:00
else if (strcmp(lhs,"init_en")==0){
ret=sscanf(rhs,"%lf",&(parameters->init_en));
if(ret!=1){
fprintf(stderr, "error: parameter 'init_en' should be a double\n got '%s'\n",rhs);
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
}
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){
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);
}
}
2023-06-13 23:56:35 -04:00
else if (strcmp(lhs,"adaptive_norm")==0){
if (strcmp(rhs,"L1")==0){
parameters->adaptive_norm=NORM_L1;
}
else if (strcmp(rhs,"k3")==0){
parameters->adaptive_norm=NORM_k3;
}
else if (strcmp(rhs,"k32")==0){
parameters->adaptive_norm=NORM_k32;
}
else if (strcmp(rhs,"enstrophy")==0){
parameters->adaptive_norm=NORM_ENSTROPHY;
}
else{
fprintf(stderr, "error: unrecognized adaptive_norm '%s'\n",rhs);
return(-1);
}
}
2022-05-18 09:57:06 +02:00
else if (strcmp(lhs,"print_freq")==0){
ret=sscanf(rhs,"%lf",&(parameters->print_freq));
2022-05-18 09:57:06 +02:00
if(ret!=1){
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);
}
}
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;
*drivingfile_str=calloc(sizeof(char), strlen(rhs)-5+1);
strcpy(*drivingfile_str, rhs+5);
}
// matches any argument that starts with 'file_txt:'
else if (strncmp(rhs,"file_txt:",9)==0){
parameters->driving=DRIVING_FILE_TXT;
*drivingfile_str=calloc(sizeof(char), strlen(rhs)-9+1);
strcpy(*drivingfile_str, rhs+9);
}
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-04-14 15:11:55 -04:00
*initfile_str=calloc(sizeof(char), strlen(rhs)-5+1);
2023-04-12 19:05:01 -04:00
strcpy(*initfile_str, rhs+5);
}
// matches any argument that starts with 'file_txt:'
else if (strncmp(rhs,"file_txt:",9)==0){
parameters->init=INIT_FILE_TXT;
*initfile_str=calloc(sizeof(char), strlen(rhs)-9+1);
strcpy(*initfile_str, rhs+9);
}
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);
}
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
// read args from file
int args_from_file(
char** params,
unsigned int* command,
unsigned int* nthreads,
char** savefile_str,
char** utfile_str,
char* file_str
){
char* line;
unsigned int len=256;
unsigned int pos=0;
char* line_realloc;
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
line=calloc(sizeof(char), len);
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
if(pos>=3){
// find line starting with "#!"
if(line[0]=='#' && line[1]=='!'){
wordexp_t pwordexp;
wordexp(line+2,&pwordexp,0);
// 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
pos=0;
line[pos]='\0';
}
// add to buffer
else {
// check that there is room in buffer
if(pos==len){
// too short: reallocate
line_realloc=calloc(sizeof(char), 2*len);
for(pos=0;pos<len;pos++){
line_realloc[pos]=line[pos];
}
free(line);
line=line_realloc;
len=2*len;
}
// add c to line
line[pos]=c;
pos++;
line[pos]='\0';
}
}
free(line);
// close file
fclose(file);
return(0);
}
// set driving force
_Complex double* set_driving(
nstrophy_parameters parameters
){
2023-04-25 17:51:14 -04:00
_Complex double* g=calloc(sizeof(_Complex double),parameters.K1*(2*parameters.K2+1)+parameters.K2);
switch(parameters.driving){
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;
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
){
2023-05-15 20:29:06 -04:00
_Complex double* u0=calloc(sizeof(_Complex double),parameters->K1*(2*parameters->K2+1)+parameters->K2);
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:
2023-05-15 20:29:06 -04:00
init_random(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->seed, parameters->irreversible);
2022-05-26 15:05:30 -04:00
break;
case INIT_GAUSSIAN:
2023-05-15 20:29:06 -04:00
init_gaussian(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->irreversible);
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);
// 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);
}
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:
2023-05-15 20:29:06 -04:00
init_gaussian(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->irreversible);
2022-05-26 15:05:30 -04:00
break;
}
return u0;
}