RKF45 algorithm
This commit is contained in:
parent
315e9a98de
commit
5db3680b31
13
README.md
13
README.md
@ -68,7 +68,9 @@ should be a `;` sperated list of `key=value` pairs. The possible keys are
|
|||||||
|
|
||||||
* `print_freq` (long int, default 1000): only print every `print_freq` steps.
|
* `print_freq` (long int, default 1000): only print every `print_freq` steps.
|
||||||
|
|
||||||
* `starting_time` (long int, default 0): start the computation at this step.
|
* `starting_step` (long int, default 0): start the computation at this step.
|
||||||
|
|
||||||
|
* `starting_time` (double, default starting_time*delta): start the computation at this time.
|
||||||
|
|
||||||
* `driving`: either `zero` for no driving, `test` (default) for a testing
|
* `driving`: either `zero` for no driving, `test` (default) for a testing
|
||||||
driving force or `file:<filename>` or `file_txt:<filename>` to read the
|
driving force or `file:<filename>` or `file_txt:<filename>` to read the
|
||||||
@ -91,7 +93,14 @@ should be a `;` sperated list of `key=value` pairs. The possible keys are
|
|||||||
|
|
||||||
* `random_seed` (int, default ): seed for random initialization.
|
* `random_seed` (int, default ): seed for random initialization.
|
||||||
|
|
||||||
* `algorithm`: either `RK4` for Runge-Kutta 4, or `RK2` for Runge-Kutta 2.
|
* `algorithm`: either `RK4` for Runge-Kutta 4, `RK2` for Runge-Kutta 2, or
|
||||||
|
`RKF45` for the Runge-Kutta-Fehlberg adaptive step method.
|
||||||
|
|
||||||
|
* `adaptive_tolerance` (double, default 1e-11): when using an adaptive step
|
||||||
|
method, this is the maximal allowed relative error.
|
||||||
|
|
||||||
|
* `adaptive_factor` (double, default 0.9): when using the RKF45 method, the
|
||||||
|
step gets adjusted by `factor*delta*(tolerance/error)^(1/5)`.
|
||||||
|
|
||||||
|
|
||||||
# Interrupting/resuming the computation
|
# Interrupting/resuming the computation
|
||||||
|
@ -29,6 +29,9 @@ limitations under the License.
|
|||||||
#define INIT_FILE 3
|
#define INIT_FILE 3
|
||||||
#define INIT_FILE_TXT 4
|
#define INIT_FILE_TXT 4
|
||||||
|
|
||||||
#define ALGORITHM_RK4 4
|
#define ALGORITHM_RK4 1
|
||||||
#define ALGORITHM_RK2 2
|
#define ALGORITHM_RK2 2
|
||||||
|
#define ALGORITHM_ADAPTIVE_THRESHOLD 1000
|
||||||
|
// adaptive algorithms: index > ALGORITHM_ADAPTIVE_THRESHOLD
|
||||||
|
#define ALGORITHM_RKF45 1001
|
||||||
|
|
||||||
|
86
src/main.c
86
src/main.c
@ -46,9 +46,12 @@ typedef struct nstrophy_parameters {
|
|||||||
double nu;
|
double nu;
|
||||||
double delta;
|
double delta;
|
||||||
double L;
|
double L;
|
||||||
|
double adaptive_tolerance;
|
||||||
|
double adaptive_factor;
|
||||||
uint64_t print_freq;
|
uint64_t print_freq;
|
||||||
int seed;
|
int seed;
|
||||||
uint64_t starting_time;
|
uint64_t starting_step;
|
||||||
|
double starting_time;
|
||||||
unsigned int driving;
|
unsigned int driving;
|
||||||
unsigned int init;
|
unsigned int init;
|
||||||
unsigned int algorithm;
|
unsigned int algorithm;
|
||||||
@ -64,12 +67,12 @@ int print_params(nstrophy_parameters parameters, char* initfile_str, char* drivi
|
|||||||
// read command line arguments
|
// read command line arguments
|
||||||
int read_args(int argc, const char* argv[], char** params, unsigned int* command, unsigned int* nthreads, char** savefile_str);
|
int read_args(int argc, const char* argv[], char** params, unsigned int* command, unsigned int* nthreads, char** savefile_str);
|
||||||
int read_params(char* param_str, nstrophy_parameters* parameters, char** initfile_str, char** drivingfile_str);
|
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);
|
int set_parameter(char* lhs, char* rhs, nstrophy_parameters* parameters, bool* setN1, bool* setN2, bool* set_starting_time, char** initfile_str, char** drivingfile_str);
|
||||||
|
|
||||||
// set driving force
|
// set driving force
|
||||||
_Complex double* set_driving(nstrophy_parameters parameters);
|
_Complex double* set_driving(nstrophy_parameters parameters);
|
||||||
// set initial condition
|
// set initial condition
|
||||||
_Complex double* set_init(nstrophy_parameters parameters);
|
_Complex double* set_init(nstrophy_parameters* parameters);
|
||||||
|
|
||||||
// signal handler
|
// signal handler
|
||||||
void sig_handler (int signo);
|
void sig_handler (int signo);
|
||||||
@ -134,7 +137,7 @@ int main (
|
|||||||
// set driving force
|
// set driving force
|
||||||
g=set_driving(parameters);
|
g=set_driving(parameters);
|
||||||
// set initial condition
|
// set initial condition
|
||||||
u0=set_init(parameters);
|
u0=set_init(¶meters);
|
||||||
|
|
||||||
// close initfile (do this early, so that it is possible to use the same file for init and save)
|
// close initfile (do this early, so that it is possible to use the same file for init and save)
|
||||||
if (parameters.initfile!=NULL){
|
if (parameters.initfile!=NULL){
|
||||||
@ -169,15 +172,15 @@ int main (
|
|||||||
|
|
||||||
// run command
|
// run command
|
||||||
if (command==COMMAND_UK){
|
if (command==COMMAND_UK){
|
||||||
uk(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, parameters.starting_time, nthreads, savefile);
|
uk(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, parameters.starting_step, parameters.starting_time, nthreads, savefile);
|
||||||
}
|
}
|
||||||
else if(command==COMMAND_ENSTROPHY){
|
else if(command==COMMAND_ENSTROPHY){
|
||||||
// register signal handler to handle aborts
|
// register signal handler to handle aborts
|
||||||
signal(SIGINT, sig_handler);
|
signal(SIGINT, sig_handler);
|
||||||
enstrophy(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, parameters.starting_time, nthreads, savefile, (char*)argv[0], param_str, savefile_str);
|
enstrophy(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, parameters.starting_step, parameters.starting_time, nthreads, savefile, (char*)argv[0], param_str, savefile_str);
|
||||||
}
|
}
|
||||||
else if(command==COMMAND_QUIET){
|
else if(command==COMMAND_QUIET){
|
||||||
quiet(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, parameters.starting_time, u0, g, parameters.irreversible, parameters.algorithm, nthreads, savefile);
|
quiet(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.nsteps, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, parameters.starting_step, u0, g, parameters.irreversible, parameters.algorithm, nthreads, savefile);
|
||||||
}
|
}
|
||||||
else if(command==0){
|
else if(command==0){
|
||||||
fprintf(stderr, "error: no command specified\n");
|
fprintf(stderr, "error: no command specified\n");
|
||||||
@ -261,6 +264,9 @@ int print_params(
|
|||||||
case ALGORITHM_RK2:
|
case ALGORITHM_RK2:
|
||||||
fprintf(file,", algorithm=RK2");
|
fprintf(file,", algorithm=RK2");
|
||||||
break;
|
break;
|
||||||
|
case ALGORITHM_RKF45:
|
||||||
|
fprintf(file,", algorithm=RKF45, tolerance=%.15e, factor=%.15e",parameters.adaptive_tolerance, parameters.adaptive_factor);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(file,", algorithm=RK4");
|
fprintf(file,", algorithm=RK4");
|
||||||
break;
|
break;
|
||||||
@ -371,6 +377,7 @@ int read_params(
|
|||||||
// whether N was set explicitly
|
// whether N was set explicitly
|
||||||
bool setN1=false;
|
bool setN1=false;
|
||||||
bool setN2=false;
|
bool setN2=false;
|
||||||
|
bool set_starting_time=false;
|
||||||
// whether lhs (false is rhs)
|
// whether lhs (false is rhs)
|
||||||
bool lhs=true;
|
bool lhs=true;
|
||||||
|
|
||||||
@ -384,9 +391,12 @@ int read_params(
|
|||||||
//nu=2^-11
|
//nu=2^-11
|
||||||
parameters->nu=0.00048828125;
|
parameters->nu=0.00048828125;
|
||||||
parameters->L=2*M_PI;
|
parameters->L=2*M_PI;
|
||||||
|
parameters->adaptive_tolerance=1e-11;
|
||||||
|
parameters->adaptive_factor=0.9;
|
||||||
parameters->nsteps=10000000;
|
parameters->nsteps=10000000;
|
||||||
parameters->print_freq=1000;
|
parameters->print_freq=1000;
|
||||||
parameters->starting_time=0;
|
parameters->starting_time=0;
|
||||||
|
parameters->starting_step=0;
|
||||||
parameters->seed=17;
|
parameters->seed=17;
|
||||||
parameters->driving=DRIVING_TEST;
|
parameters->driving=DRIVING_TEST;
|
||||||
parameters->drivingfile=NULL;
|
parameters->drivingfile=NULL;
|
||||||
@ -413,7 +423,7 @@ int read_params(
|
|||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
//set parameter
|
//set parameter
|
||||||
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, initfile_str, drivingfile_str);
|
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, &set_starting_time, initfile_str, drivingfile_str);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -440,7 +450,7 @@ int read_params(
|
|||||||
|
|
||||||
// set last param
|
// set last param
|
||||||
if (*param_str!='\0'){
|
if (*param_str!='\0'){
|
||||||
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, initfile_str, drivingfile_str);
|
ret=set_parameter(buffer_lhs, buffer_rhs, parameters, &setN1, &setN2, &set_starting_time, initfile_str, drivingfile_str);
|
||||||
if(ret<0){
|
if(ret<0){
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -459,6 +469,10 @@ int read_params(
|
|||||||
parameters->N2=smallest_pow2(3*(parameters->K2));
|
parameters->N2=smallest_pow2(3*(parameters->K2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if starting_time not set explicitly and algorithm is not adaptive, set it to delta*starting_step
|
||||||
|
if (!set_starting_time && parameters->algorithm<ALGORITHM_ADAPTIVE_THRESHOLD){
|
||||||
|
parameters->starting_time=parameters->delta*parameters->starting_step;
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +484,7 @@ int set_parameter(
|
|||||||
nstrophy_parameters* parameters,
|
nstrophy_parameters* parameters,
|
||||||
bool* setN1,
|
bool* setN1,
|
||||||
bool* setN2,
|
bool* setN2,
|
||||||
|
bool* set_starting_time,
|
||||||
char** initfile_str,
|
char** initfile_str,
|
||||||
char** drivingfile_str
|
char** drivingfile_str
|
||||||
){
|
){
|
||||||
@ -570,6 +585,20 @@ int set_parameter(
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strcmp(lhs,"print_freq")==0){
|
else if (strcmp(lhs,"print_freq")==0){
|
||||||
ret=sscanf(rhs,"%lu",&(parameters->print_freq));
|
ret=sscanf(rhs,"%lu",&(parameters->print_freq));
|
||||||
if(ret!=1){
|
if(ret!=1){
|
||||||
@ -584,13 +613,21 @@ int set_parameter(
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(lhs,"starting_time")==0){
|
else if (strcmp(lhs,"starting_step")==0){
|
||||||
ret=sscanf(rhs,"%lu",&(parameters->starting_time));
|
ret=sscanf(rhs,"%lu",&(parameters->starting_step));
|
||||||
if(ret!=1){
|
if(ret!=1){
|
||||||
fprintf(stderr, "error: parameter 'starting_time' should be an unsigned integer\n got '%s'\n",rhs);
|
fprintf(stderr, "error: parameter 'starting_step' should be a long unsigned integer\n got '%s'\n",rhs);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(lhs,"starting_time")==0){
|
||||||
|
ret=sscanf(rhs,"%lf",&(parameters->starting_time));
|
||||||
|
if(ret!=1){
|
||||||
|
fprintf(stderr, "error: parameter 'starting_time' should be a double\n got '%s'\n",rhs);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
*set_starting_time=true;
|
||||||
|
}
|
||||||
else if (strcmp(lhs,"driving")==0){
|
else if (strcmp(lhs,"driving")==0){
|
||||||
if (strcmp(rhs,"zero")==0){
|
if (strcmp(rhs,"zero")==0){
|
||||||
parameters->driving=DRIVING_ZERO;
|
parameters->driving=DRIVING_ZERO;
|
||||||
@ -648,6 +685,9 @@ int set_parameter(
|
|||||||
else if (strcmp(rhs,"RK2")==0){
|
else if (strcmp(rhs,"RK2")==0){
|
||||||
parameters->algorithm=ALGORITHM_RK2;
|
parameters->algorithm=ALGORITHM_RK2;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(rhs,"RKF45")==0){
|
||||||
|
parameters->algorithm=ALGORITHM_RKF45;
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
fprintf(stderr, "error: unrecognized algorithm '%s'\n",rhs);
|
fprintf(stderr, "error: unrecognized algorithm '%s'\n",rhs);
|
||||||
return(-1);
|
return(-1);
|
||||||
@ -692,29 +732,35 @@ _Complex double* set_driving(
|
|||||||
|
|
||||||
// set initial condition
|
// set initial condition
|
||||||
_Complex double* set_init(
|
_Complex double* set_init(
|
||||||
nstrophy_parameters parameters
|
nstrophy_parameters* parameters
|
||||||
){
|
){
|
||||||
_Complex double* u0=calloc(sizeof(_Complex double),parameters.K1*(2*parameters.K2+1)+parameters.K2);
|
_Complex double* u0=calloc(sizeof(_Complex double),parameters->K1*(2*parameters->K2+1)+parameters->K2);
|
||||||
|
|
||||||
switch(parameters.init){
|
switch(parameters->init){
|
||||||
case INIT_RANDOM:
|
case INIT_RANDOM:
|
||||||
init_random(u0, parameters.init_en, parameters.K1, parameters.K2, parameters.L, parameters.seed, parameters.irreversible);
|
init_random(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->seed, parameters->irreversible);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_GAUSSIAN:
|
case INIT_GAUSSIAN:
|
||||||
init_gaussian(u0, parameters.init_en, parameters.K1, parameters.K2, parameters.L, parameters.irreversible);
|
init_gaussian(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->irreversible);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_FILE:
|
case INIT_FILE:
|
||||||
init_file_bin(u0, parameters.K1, parameters.K2, parameters.initfile);
|
init_file_bin(u0, parameters->K1, parameters->K2, parameters->initfile);
|
||||||
|
if(parameters->algorithm>ALGORITHM_ADAPTIVE_THRESHOLD){
|
||||||
|
// read delta
|
||||||
|
fread(&(parameters->delta), sizeof(double), 1, parameters->initfile);
|
||||||
|
// read start time
|
||||||
|
fread(&(parameters->starting_time), sizeof(double), 1, parameters->initfile);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_FILE_TXT:
|
case INIT_FILE_TXT:
|
||||||
init_file_txt(u0, parameters.K1, parameters.K2, parameters.initfile);
|
init_file_txt(u0, parameters->K1, parameters->K2, parameters->initfile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
init_gaussian(u0, parameters.init_en, parameters.K1, parameters.K2, parameters.L, parameters.irreversible);
|
init_gaussian(u0, parameters->init_en, parameters->K1, parameters->K2, parameters->L, parameters->irreversible);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,26 +32,34 @@ int uk(
|
|||||||
double nu,
|
double nu,
|
||||||
double delta,
|
double delta,
|
||||||
double L,
|
double L,
|
||||||
|
double adaptive_tolerance,
|
||||||
|
double adaptive_factor,
|
||||||
_Complex double* u0,
|
_Complex double* u0,
|
||||||
_Complex double* g,
|
_Complex double* g,
|
||||||
bool irreversible,
|
bool irreversible,
|
||||||
unsigned int algorithm,
|
unsigned int algorithm,
|
||||||
uint64_t print_freq,
|
uint64_t print_freq,
|
||||||
uint64_t starting_time,
|
uint64_t starting_step,
|
||||||
|
double starting_time,
|
||||||
unsigned int nthreads,
|
unsigned int nthreads,
|
||||||
FILE* savefile
|
FILE* savefile
|
||||||
){
|
){
|
||||||
|
double time=starting_time;
|
||||||
_Complex double* u;
|
_Complex double* u;
|
||||||
_Complex double* tmp1;
|
_Complex double* tmp1;
|
||||||
_Complex double* tmp2;
|
_Complex double* tmp2;
|
||||||
_Complex double* tmp3;
|
_Complex double* tmp3;
|
||||||
|
_Complex double* tmp4;
|
||||||
|
_Complex double* tmp5;
|
||||||
|
_Complex double* tmp6;
|
||||||
|
_Complex double* tmp7;
|
||||||
uint64_t t;
|
uint64_t t;
|
||||||
fft_vect fft1;
|
fft_vect fft1;
|
||||||
fft_vect fft2;
|
fft_vect fft2;
|
||||||
fft_vect ifft;
|
fft_vect ifft;
|
||||||
int kx,ky;
|
int kx,ky;
|
||||||
|
|
||||||
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads);
|
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6, &tmp7, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads, algorithm);
|
||||||
// copy initial condition
|
// copy initial condition
|
||||||
copy_u(u, u0, K1, K2);
|
copy_u(u, u0, K1, K2);
|
||||||
|
|
||||||
@ -68,16 +76,22 @@ int uk(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
for(t=starting_time;nsteps==0 || t<starting_time+nsteps;t++){
|
for(t=starting_step;nsteps==0 || t<starting_step+nsteps;t++){
|
||||||
if(algorithm==ALGORITHM_RK2){
|
if(algorithm==ALGORITHM_RK2){
|
||||||
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
||||||
} else {
|
} else if (algorithm==ALGORITHM_RK4) {
|
||||||
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
||||||
|
} else if (algorithm==ALGORITHM_RKF45) {
|
||||||
|
delta=ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"bug: unknown algorithm: %u, contact ian.jauslin@rutgers,edu\n",algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time+=delta;
|
||||||
|
|
||||||
if(t%print_freq==0){
|
if(t%print_freq==0){
|
||||||
fprintf(stderr,"%lu % .8e ",t,t*delta);
|
fprintf(stderr,"%lu % .8e ",t,time);
|
||||||
printf("%8lu % .15e ",t,t*delta);
|
printf("%8lu % .15e ",t,time);
|
||||||
|
|
||||||
for(kx=-K1;kx<=K1;kx++){
|
for(kx=-K1;kx<=K1;kx++){
|
||||||
for (ky=-K2;ky<=K2;ky++){
|
for (ky=-K2;ky<=K2;ky++){
|
||||||
@ -96,7 +110,7 @@ int uk(
|
|||||||
// save final entry to savefile
|
// save final entry to savefile
|
||||||
write_vec_bin(u, K1, K2, savefile);
|
write_vec_bin(u, K1, K2, savefile);
|
||||||
|
|
||||||
ns_free_tmps(u, tmp1, tmp2, tmp3, fft1, fft2, ifft);
|
ns_free_tmps(u, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, fft1, fft2, ifft, algorithm);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,12 +124,15 @@ int enstrophy(
|
|||||||
double nu,
|
double nu,
|
||||||
double delta,
|
double delta,
|
||||||
double L,
|
double L,
|
||||||
|
double adaptive_tolerance,
|
||||||
|
double adaptive_factor,
|
||||||
_Complex double* u0,
|
_Complex double* u0,
|
||||||
_Complex double* g,
|
_Complex double* g,
|
||||||
bool irreversible,
|
bool irreversible,
|
||||||
unsigned int algorithm,
|
unsigned int algorithm,
|
||||||
uint64_t print_freq,
|
uint64_t print_freq,
|
||||||
uint64_t starting_time,
|
uint64_t starting_step,
|
||||||
|
double starting_time,
|
||||||
unsigned int nthreads,
|
unsigned int nthreads,
|
||||||
FILE* savefile,
|
FILE* savefile,
|
||||||
// for interrupt recovery
|
// for interrupt recovery
|
||||||
@ -127,6 +144,11 @@ int enstrophy(
|
|||||||
_Complex double* tmp1;
|
_Complex double* tmp1;
|
||||||
_Complex double* tmp2;
|
_Complex double* tmp2;
|
||||||
_Complex double* tmp3;
|
_Complex double* tmp3;
|
||||||
|
_Complex double* tmp4;
|
||||||
|
_Complex double* tmp5;
|
||||||
|
_Complex double* tmp6;
|
||||||
|
_Complex double* tmp7;
|
||||||
|
double time=starting_time;
|
||||||
double alpha, enstrophy;
|
double alpha, enstrophy;
|
||||||
double avg_a,avg_en,avg_en_x_a;
|
double avg_a,avg_en,avg_en_x_a;
|
||||||
// index
|
// index
|
||||||
@ -135,7 +157,7 @@ int enstrophy(
|
|||||||
fft_vect fft2;
|
fft_vect fft2;
|
||||||
fft_vect ifft;
|
fft_vect ifft;
|
||||||
|
|
||||||
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads);
|
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6, &tmp7, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads, algorithm);
|
||||||
// copy initial condition
|
// copy initial condition
|
||||||
copy_u(u, u0, K1, K2);
|
copy_u(u, u0, K1, K2);
|
||||||
|
|
||||||
@ -146,26 +168,38 @@ int enstrophy(
|
|||||||
avg_en_x_a=0;
|
avg_en_x_a=0;
|
||||||
|
|
||||||
// special first case when starting_time is not a multiple of print_freq
|
// special first case when starting_time is not a multiple of print_freq
|
||||||
uint64_t first_box = print_freq - (starting_time % print_freq);
|
uint64_t first_box = print_freq - (starting_step % print_freq);
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
for(t=starting_time;nsteps==0 || t<starting_time+nsteps;t++){
|
for(t=starting_step;nsteps==0 || t<starting_step+nsteps;t++){
|
||||||
if(algorithm==ALGORITHM_RK2){
|
if(algorithm==ALGORITHM_RK2){
|
||||||
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
||||||
} else {
|
} else if (algorithm==ALGORITHM_RK4) {
|
||||||
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
||||||
|
} else if (algorithm==ALGORITHM_RKF45) {
|
||||||
|
delta=ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"bug: unknown algorithm: %u, contact ian.jauslin@rutgers,edu\n",algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time+=delta;
|
||||||
|
|
||||||
alpha=compute_alpha(u, K1, K2, g, L);
|
alpha=compute_alpha(u, K1, K2, g, L);
|
||||||
enstrophy=compute_enstrophy(u, K1, K2, L);
|
enstrophy=compute_enstrophy(u, K1, K2, L);
|
||||||
|
|
||||||
avg_a=average_step(alpha, avg_a, t, starting_time, print_freq, first_box);
|
avg_a=average_step(alpha, avg_a, t, starting_step, print_freq, first_box);
|
||||||
avg_en=average_step(enstrophy, avg_en, t, starting_time, print_freq, first_box);
|
avg_en=average_step(enstrophy, avg_en, t, starting_step, print_freq, first_box);
|
||||||
avg_en_x_a=average_step(enstrophy*alpha, avg_en_x_a, t, starting_time, print_freq, first_box);
|
avg_en_x_a=average_step(enstrophy*alpha, avg_en_x_a, t, starting_step, print_freq, first_box);
|
||||||
|
|
||||||
if(t>starting_time && t%print_freq==0){
|
if(t>starting_step && t%print_freq==0){
|
||||||
fprintf(stderr,"%lu % .8e % .8e % .8e % .8e % .8e % .8e % .8e\n",t,t*delta, avg_a, avg_en_x_a, avg_en, alpha, alpha*enstrophy, enstrophy);
|
// print to stderr so user can follow along
|
||||||
printf("%8lu % .15e % .15e % .15e % .15e % .15e % .15e % .15e\n",t,t*delta, avg_a, avg_en_x_a, avg_en, alpha, alpha*enstrophy, enstrophy);
|
if(algorithm==ALGORITHM_RKF45){
|
||||||
|
fprintf(stderr,"%lu % .8e % .8e % .8e % .8e % .8e % .8e % .8e % .8e\n",t,time, avg_a, avg_en_x_a, avg_en, alpha, alpha*enstrophy, enstrophy, delta);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"%lu % .8e % .8e % .8e % .8e % .8e % .8e % .8e\n",t,time, avg_a, avg_en_x_a, avg_en, alpha, alpha*enstrophy, enstrophy);
|
||||||
|
}
|
||||||
|
// print to stdout
|
||||||
|
printf("%8lu % .15e % .15e % .15e % .15e % .15e % .15e % .15e\n",t,time, avg_a, avg_en_x_a, avg_en, alpha, alpha*enstrophy, enstrophy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch abort signal
|
// catch abort signal
|
||||||
@ -189,11 +223,24 @@ int enstrophy(
|
|||||||
if(params_string!=NULL) {
|
if(params_string!=NULL) {
|
||||||
char* params=calloc(sizeof(char), strlen(params_string)+1);
|
char* params=calloc(sizeof(char), strlen(params_string)+1);
|
||||||
strcpy(params, params_string);
|
strcpy(params, params_string);
|
||||||
|
remove_entry(params, "starting_step");
|
||||||
remove_entry(params, "starting_time");
|
remove_entry(params, "starting_time");
|
||||||
remove_entry(params, "init");
|
remove_entry(params, "init");
|
||||||
remove_entry(params, "nsteps");
|
remove_entry(params, "nsteps");
|
||||||
fprintf(savefile," -p \"%s;starting_time=%lu;nsteps=%lu;init=file:%s\"", params, t+1, (nsteps+starting_time < t+1 ? 0 : nsteps+starting_time-t-1), savefile_string);
|
if(algorithm>ALGORITHM_ADAPTIVE_THRESHOLD){
|
||||||
|
remove_entry(params, "delta");
|
||||||
|
}
|
||||||
|
fprintf(savefile," -p \"%s;starting_step=%lu;nsteps=%lu;init=file:%s", params, t+1, (nsteps+starting_step < t+1 ? 0 : nsteps+starting_step-t-1), savefile_string);
|
||||||
free(params);
|
free(params);
|
||||||
|
// write delta if adaptive, and not writing binary
|
||||||
|
if(algorithm>ALGORITHM_ADAPTIVE_THRESHOLD && (savefile==stderr || savefile==stdout)){
|
||||||
|
fprintf(savefile,";delta=%.15e;starting_time=%.15e", delta, starting_time);
|
||||||
|
}
|
||||||
|
// write starting_time if not adaptive
|
||||||
|
if(algorithm<ALGORITHM_ADAPTIVE_THRESHOLD){
|
||||||
|
fprintf(savefile,";starting_time=%.15e", starting_time);
|
||||||
|
}
|
||||||
|
fprintf(savefile,"\"");
|
||||||
}
|
}
|
||||||
fprintf(savefile," enstrophy\n");
|
fprintf(savefile," enstrophy\n");
|
||||||
|
|
||||||
@ -202,10 +249,17 @@ int enstrophy(
|
|||||||
write_vec(u, K1, K2, savefile);
|
write_vec(u, K1, K2, savefile);
|
||||||
} else {
|
} else {
|
||||||
write_vec_bin(u, K1, K2, savefile);
|
write_vec_bin(u, K1, K2, savefile);
|
||||||
|
// extra binary data for adaptive algorithm
|
||||||
|
if(algorithm>ALGORITHM_ADAPTIVE_THRESHOLD){
|
||||||
|
// first binary entry: delta
|
||||||
|
fwrite(&delta, sizeof(double), 1, savefile);
|
||||||
|
// ssecond binary entry: starting time
|
||||||
|
fwrite(&starting_time, sizeof(double), 1, savefile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ns_free_tmps(u, tmp1, tmp2, tmp3, fft1, fft2, ifft);
|
ns_free_tmps(u, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, fft1, fft2, ifft, algorithm);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +273,9 @@ int quiet(
|
|||||||
double nu,
|
double nu,
|
||||||
double delta,
|
double delta,
|
||||||
double L,
|
double L,
|
||||||
uint64_t starting_time,
|
double adaptive_tolerance,
|
||||||
|
double adaptive_factor,
|
||||||
|
uint64_t starting_step,
|
||||||
_Complex double* u0,
|
_Complex double* u0,
|
||||||
_Complex double* g,
|
_Complex double* g,
|
||||||
bool irreversible,
|
bool irreversible,
|
||||||
@ -231,28 +287,36 @@ int quiet(
|
|||||||
_Complex double* tmp1;
|
_Complex double* tmp1;
|
||||||
_Complex double* tmp2;
|
_Complex double* tmp2;
|
||||||
_Complex double* tmp3;
|
_Complex double* tmp3;
|
||||||
|
_Complex double* tmp4;
|
||||||
|
_Complex double* tmp5;
|
||||||
|
_Complex double* tmp6;
|
||||||
|
_Complex double* tmp7;
|
||||||
uint64_t t;
|
uint64_t t;
|
||||||
fft_vect fft1;
|
fft_vect fft1;
|
||||||
fft_vect fft2;
|
fft_vect fft2;
|
||||||
fft_vect ifft;
|
fft_vect ifft;
|
||||||
|
|
||||||
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads);
|
ns_init_tmps(&u, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6, &tmp7, &fft1, &fft2, &ifft, K1, K2, N1, N2, nthreads, algorithm);
|
||||||
// copy initial condition
|
// copy initial condition
|
||||||
copy_u(u, u0, K1, K2);
|
copy_u(u, u0, K1, K2);
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
for(t=starting_time;nsteps==0 || t<starting_time+nsteps;t++){
|
for(t=starting_step;nsteps==0 || t<starting_step+nsteps;t++){
|
||||||
if(algorithm==ALGORITHM_RK2){
|
if(algorithm==ALGORITHM_RK2){
|
||||||
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
ns_step_rk2(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, irreversible);
|
||||||
} else {
|
} else if (algorithm==ALGORITHM_RK4) {
|
||||||
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
ns_step_rk4(u, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, irreversible);
|
||||||
|
} else if (algorithm==ALGORITHM_RKF45) {
|
||||||
|
delta=ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, delta, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"bug: unknown algorithm: %u, contact ian.jauslin@rutgers,edu\n",algorithm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save final entry to savefile
|
// save final entry to savefile
|
||||||
write_vec(u, K1, K2, savefile);
|
write_vec(u, K1, K2, savefile);
|
||||||
|
|
||||||
ns_free_tmps(u, tmp1, tmp2, tmp3, fft1, fft2, ifft);
|
ns_free_tmps(u, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, fft1, fft2, ifft, algorithm);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,6 +327,10 @@ int ns_init_tmps(
|
|||||||
_Complex double ** tmp1,
|
_Complex double ** tmp1,
|
||||||
_Complex double ** tmp2,
|
_Complex double ** tmp2,
|
||||||
_Complex double ** tmp3,
|
_Complex double ** tmp3,
|
||||||
|
_Complex double ** tmp4,
|
||||||
|
_Complex double ** tmp5,
|
||||||
|
_Complex double ** tmp6,
|
||||||
|
_Complex double ** tmp7,
|
||||||
fft_vect* fft1,
|
fft_vect* fft1,
|
||||||
fft_vect* fft2,
|
fft_vect* fft2,
|
||||||
fft_vect* ifft,
|
fft_vect* ifft,
|
||||||
@ -270,15 +338,31 @@ int ns_init_tmps(
|
|||||||
int K2,
|
int K2,
|
||||||
int N1,
|
int N1,
|
||||||
int N2,
|
int N2,
|
||||||
unsigned int nthreads
|
unsigned int nthreads,
|
||||||
|
unsigned int algorithm
|
||||||
){
|
){
|
||||||
// velocity field
|
// velocity field
|
||||||
*u=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
*u=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
|
||||||
// allocate tmp vectors for computation
|
// allocate tmp vectors for computation
|
||||||
|
if(algorithm==ALGORITHM_RK2){
|
||||||
|
*tmp1=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp2=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
} else if (algorithm==ALGORITHM_RK4){
|
||||||
*tmp1=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
*tmp1=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
*tmp2=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
*tmp2=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
*tmp3=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
*tmp3=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
} else if (algorithm==ALGORITHM_RKF45){
|
||||||
|
*tmp1=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp2=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp3=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp4=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp5=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp6=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
*tmp7=calloc(sizeof(_Complex double),K1*(2*K2+1)+K2);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"bug: unknown algorithm: %u, contact ian.jauslin@rutgers,edu\n",algorithm);
|
||||||
|
};
|
||||||
|
|
||||||
// init threads
|
// init threads
|
||||||
fftw_init_threads();
|
fftw_init_threads();
|
||||||
@ -301,9 +385,14 @@ int ns_free_tmps(
|
|||||||
_Complex double* tmp1,
|
_Complex double* tmp1,
|
||||||
_Complex double* tmp2,
|
_Complex double* tmp2,
|
||||||
_Complex double* tmp3,
|
_Complex double* tmp3,
|
||||||
|
_Complex double* tmp4,
|
||||||
|
_Complex double* tmp5,
|
||||||
|
_Complex double* tmp6,
|
||||||
|
_Complex double* tmp7,
|
||||||
fft_vect fft1,
|
fft_vect fft1,
|
||||||
fft_vect fft2,
|
fft_vect fft2,
|
||||||
fft_vect ifft
|
fft_vect ifft,
|
||||||
|
unsigned int algorithm
|
||||||
){
|
){
|
||||||
// free memory
|
// free memory
|
||||||
fftw_destroy_plan(fft1.fft_plan);
|
fftw_destroy_plan(fft1.fft_plan);
|
||||||
@ -315,9 +404,24 @@ int ns_free_tmps(
|
|||||||
|
|
||||||
fftw_cleanup_threads();
|
fftw_cleanup_threads();
|
||||||
|
|
||||||
free(tmp3);
|
if(algorithm==ALGORITHM_RK2){
|
||||||
free(tmp2);
|
|
||||||
free(tmp1);
|
free(tmp1);
|
||||||
|
free(tmp2);
|
||||||
|
} else if (algorithm==ALGORITHM_RK4){
|
||||||
|
free(tmp1);
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp3);
|
||||||
|
} else if (algorithm==ALGORITHM_RKF45){
|
||||||
|
free(tmp1);
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp3);
|
||||||
|
free(tmp4);
|
||||||
|
free(tmp5);
|
||||||
|
free(tmp6);
|
||||||
|
free(tmp7);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"bug: unknown algorithm: %u, contact ian.jauslin@rutgers,edu\n",algorithm);
|
||||||
|
};
|
||||||
|
|
||||||
free(u);
|
free(u);
|
||||||
|
|
||||||
@ -462,6 +566,105 @@ int ns_step_rk2(
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// next time step
|
||||||
|
// adaptive RK algorithm (Runge-Kutta-Fehlberg)
|
||||||
|
double ns_step_rkf45(
|
||||||
|
_Complex double* u,
|
||||||
|
double tolerance,
|
||||||
|
double factor,
|
||||||
|
int K1,
|
||||||
|
int K2,
|
||||||
|
int N1,
|
||||||
|
int N2,
|
||||||
|
double nu,
|
||||||
|
double delta,
|
||||||
|
double L,
|
||||||
|
_Complex double* g,
|
||||||
|
fft_vect fft1,
|
||||||
|
fft_vect fft2,
|
||||||
|
fft_vect ifft,
|
||||||
|
_Complex double* k1,
|
||||||
|
_Complex double* k2,
|
||||||
|
_Complex double* k3,
|
||||||
|
_Complex double* k4,
|
||||||
|
_Complex double* k5,
|
||||||
|
_Complex double* k6,
|
||||||
|
_Complex double* tmp,
|
||||||
|
bool irreversible
|
||||||
|
){
|
||||||
|
int kx,ky;
|
||||||
|
double err;
|
||||||
|
|
||||||
|
// k1: u(t)
|
||||||
|
ns_rhs(k1, u, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// k2 : u(t+1/4*delta)
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
tmp[klookup_sym(kx,ky,K2)]=u[klookup_sym(kx,ky,K2)]+delta/4*k1[klookup_sym(kx,ky,K2)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns_rhs(k2, tmp, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// k3 : u(t+3/8*delta)
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
tmp[klookup_sym(kx,ky,K2)]=u[klookup_sym(kx,ky,K2)]+delta*(3./32*k1[klookup_sym(kx,ky,K2)]+9./32*k2[klookup_sym(kx,ky,K2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns_rhs(k3, tmp, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// k4 : u(t+12./13*delta)
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
tmp[klookup_sym(kx,ky,K2)]=u[klookup_sym(kx,ky,K2)]+delta*(1932./2197*k1[klookup_sym(kx,ky,K2)]-7200./2197*k2[klookup_sym(kx,ky,K2)]+7296./2197*k3[klookup_sym(kx,ky,K2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns_rhs(k4, tmp, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// k5 : u(t+1*delta)
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
tmp[klookup_sym(kx,ky,K2)]=u[klookup_sym(kx,ky,K2)]+delta*(439./216*k1[klookup_sym(kx,ky,K2)]-8*k2[klookup_sym(kx,ky,K2)]+3680./513*k3[klookup_sym(kx,ky,K2)]-845./4104*k4[klookup_sym(kx,ky,K2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns_rhs(k5, tmp, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// k6 : u(t+1./2*delta)
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
tmp[klookup_sym(kx,ky,K2)]=u[klookup_sym(kx,ky,K2)]+delta*(-8./27*k1[klookup_sym(kx,ky,K2)]+2*k2[klookup_sym(kx,ky,K2)]-3544./2565*k3[klookup_sym(kx,ky,K2)]+1859./4104*k4[klookup_sym(kx,ky,K2)]-11./40*k5[klookup_sym(kx,ky,K2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns_rhs(k6, tmp, K1, K2, N1, N2, nu, L, g, fft1, fft2, ifft, irreversible);
|
||||||
|
|
||||||
|
// compute error
|
||||||
|
err=0;
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
// difference between 5th order and 4th order
|
||||||
|
err+=cabs(delta*(1./360*k1[klookup_sym(kx,ky,K2)]-128./4275*k3[klookup_sym(kx,ky,K2)]-2197./75240*k4[klookup_sym(kx,ky,K2)]+1./50*k5[klookup_sym(kx,ky,K2)]+2./55*k6[klookup_sym(kx,ky,K2)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// new delta
|
||||||
|
delta=factor*delta*pow(tolerance/err,0.2);
|
||||||
|
// compare relative error with tolerance
|
||||||
|
if(err<tolerance){
|
||||||
|
// add to output
|
||||||
|
for(kx=0;kx<=K1;kx++){
|
||||||
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
|
u[klookup_sym(kx,ky,K2)]+=delta*(16./135*k1[klookup_sym(kx,ky,K2)]+6656./12825*k3[klookup_sym(kx,ky,K2)]+28561./56430*k4[klookup_sym(kx,ky,K2)]-9./50*k5[klookup_sym(kx,ky,K2)]+2./55*k6[klookup_sym(kx,ky,K2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
// error too big: repeat with smaller step
|
||||||
|
else{
|
||||||
|
return(ns_step_rkf45(u,tolerance,factor,K1,K2,N1,N2,nu,delta,L,g,fft1,fft2,ifft,k1,k2,k3,k4,k5,k6,tmp,irreversible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// right side of Irreversible/Reversible Navier-Stokes equation
|
// right side of Irreversible/Reversible Navier-Stokes equation
|
||||||
int ns_rhs(
|
int ns_rhs(
|
||||||
_Complex double* out,
|
_Complex double* out,
|
||||||
|
@ -34,19 +34,19 @@ typedef struct fft_vects {
|
|||||||
} fft_vect;
|
} fft_vect;
|
||||||
|
|
||||||
// compute u_k
|
// compute u_k
|
||||||
int uk( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, uint64_t print_freq, uint64_t starting_time, unsigned int nthreadsl, FILE* savefile);
|
int uk( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, uint64_t print_freq, uint64_t starting_step, double starting_time, unsigned int nthreadsl, FILE* savefile);
|
||||||
|
|
||||||
// compute enstrophy and alpha
|
// compute enstrophy and alpha
|
||||||
int enstrophy( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, uint64_t print_freq, uint64_t starting_time, unsigned int nthreads, FILE* savefile, char* cmd_string, char* params_string, char* savefile_string);
|
int enstrophy( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, uint64_t print_freq, uint64_t starting_step, double starting_time, unsigned int nthreads, FILE* savefile, char* cmd_string, char* params_string, char* savefile_string);
|
||||||
|
|
||||||
// compute solution as a function of time, but do not print anything (useful for debugging)
|
// compute solution as a function of time, but do not print anything (useful for debugging)
|
||||||
int quiet( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, uint64_t starting_time, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, unsigned int nthreads, FILE* savefile);
|
int quiet( int K1, int K2, int N1, int N2, uint64_t nsteps, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, uint64_t starting_step, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, unsigned int nthreads, FILE* savefile);
|
||||||
|
|
||||||
|
|
||||||
// initialize vectors for computation
|
// initialize vectors for computation
|
||||||
int ns_init_tmps( _Complex double **u, _Complex double ** tmp1, _Complex double **tmp2, _Complex double **tmp3, fft_vect* fft1, fft_vect *fft2, fft_vect *ifft, int K1, int K2, int N1, int N2, unsigned int nthreads);
|
int ns_init_tmps( _Complex double **u, _Complex double ** tmp1, _Complex double **tmp2, _Complex double **tmp3, _Complex double **tmp4, _Complex double **tmp5, _Complex double **tmp6, _Complex double **tmp7, fft_vect* fft1, fft_vect *fft2, fft_vect *ifft, int K1, int K2, int N1, int N2, unsigned int nthreads, unsigned int algorithm);
|
||||||
// release vectors
|
// release vectors
|
||||||
int ns_free_tmps( _Complex double* u, _Complex double* tmp1, _Complex double *tmp2,_Complex double *tmp3, fft_vect fft1, fft_vect fft2, fft_vect ifft);
|
int ns_free_tmps( _Complex double* u, _Complex double* tmp1, _Complex double *tmp2,_Complex double *tmp3, _Complex double *tmp4, _Complex double *tmp5, _Complex double *tmp6, _Complex double *tmp7, fft_vect fft1, fft_vect fft2, fft_vect ifft, unsigned int algorithm);
|
||||||
|
|
||||||
// copy u0 to u
|
// copy u0 to u
|
||||||
int copy_u( _Complex double* u, _Complex double* u0, int K1, int K2);
|
int copy_u( _Complex double* u, _Complex double* u0, int K1, int K2);
|
||||||
@ -56,6 +56,8 @@ int copy_u( _Complex double* u, _Complex double* u0, int K1, int K2);
|
|||||||
int ns_step_rk4( _Complex double* u, int K1, int K2, int N1, int N2, double nu, double delta, double L, _Complex double* g, fft_vect fft1, fft_vect fft2,fft_vect ifft, _Complex double* tmp1, _Complex double *tmp2, _Complex double *tmp3, bool irreversible);
|
int ns_step_rk4( _Complex double* u, int K1, int K2, int N1, int N2, double nu, double delta, double L, _Complex double* g, fft_vect fft1, fft_vect fft2,fft_vect ifft, _Complex double* tmp1, _Complex double *tmp2, _Complex double *tmp3, bool irreversible);
|
||||||
// RK2
|
// RK2
|
||||||
int ns_step_rk2( _Complex double* u, int K1, int K2, int N1, int N2, double nu, double delta, double L, _Complex double* g, fft_vect fft1, fft_vect fft2,fft_vect ifft, _Complex double* tmp1, _Complex double *tmp2, bool irreversible);
|
int ns_step_rk2( _Complex double* u, int K1, int K2, int N1, int N2, double nu, double delta, double L, _Complex double* g, fft_vect fft1, fft_vect fft2,fft_vect ifft, _Complex double* tmp1, _Complex double *tmp2, bool irreversible);
|
||||||
|
// adaptive RK algorithm (Runge-Kutta-Fehlberg)
|
||||||
|
double ns_step_rkf45( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double delta, double L, _Complex double* g, fft_vect fft1, fft_vect fft2, fft_vect ifft, _Complex double* k1, _Complex double* k2, _Complex double* k3, _Complex double* k4, _Complex double* k5, _Complex double* k6, _Complex double* tmp, bool irreversible);
|
||||||
|
|
||||||
// right side of Irreversible/reversible Navier-Stokes equation
|
// right side of Irreversible/reversible Navier-Stokes equation
|
||||||
int ns_rhs( _Complex double* out, _Complex double* u, int K1, int K2, int N1, int N2, double nu, double L, _Complex double* g, fft_vect fft1, fft_vect fft2, fft_vect ifft, bool irreversible);
|
int ns_rhs( _Complex double* out, _Complex double* u, int K1, int K2, int N1, int N2, double nu, double L, _Complex double* g, fft_vect fft1, fft_vect fft2, fft_vect ifft, bool irreversible);
|
||||||
|
Loading…
Reference in New Issue
Block a user