delta_max and fix cabs2
This commit is contained in:
parent
4ffbe1e978
commit
34b7a0c277
@ -105,6 +105,9 @@ should be a `;` sperated list of `key=value` pairs. The possible keys are
|
|||||||
* `adaptive_factor` (double, default 0.9): when using the RKF45 method, the
|
* `adaptive_factor` (double, default 0.9): when using the RKF45 method, the
|
||||||
step gets adjusted by `factor*delta*(tolerance/error)^(1/5)`.
|
step gets adjusted by `factor*delta*(tolerance/error)^(1/5)`.
|
||||||
|
|
||||||
|
* `max_delta` (double, default 1e-2): when using the adaptive step, do not
|
||||||
|
exceet `delta_max`.
|
||||||
|
|
||||||
|
|
||||||
# Interrupting/resuming the computation
|
# Interrupting/resuming the computation
|
||||||
|
|
||||||
|
@ -103,6 +103,88 @@ We truncate the Fourier modes and assume that $\hat u_k=0$ if $|k_1|>K_1$ or $|k
|
|||||||
\end{equation}
|
\end{equation}
|
||||||
\bigskip
|
\bigskip
|
||||||
|
|
||||||
|
\point{\bf Runge-Kutta methods}.
|
||||||
|
To solve the equation numerically, we will use Runge-Kutta methods, which compute an approximate value $\hat u_k^{(n)}$ for $\hat u_k(t_n)$.
|
||||||
|
{\tt nstrophy} supports the 4th order Runge-Kutta ({\tt RK4}) and 2nd order Runge-Kutta ({\tt RK2}) algorithms.
|
||||||
|
In addition, several variable step methods are implemented:
|
||||||
|
\begin{itemize}
|
||||||
|
\item the Runge-Kutta-Dormand-Prince method ({\tt RKDP54}), which is of 5th order, and adjusts the step by comparing to a 4th order method;
|
||||||
|
\item the Runge-Kutta-Fehlberg method ({\tt RKF45}), which is of 4th order, and adjusts the step by comparing to a 5th order method;
|
||||||
|
\item the Runge-Kutta-Bogacki-Shampine method ({\tt RKBS32}), which is of 3d order, and adjusts the step by comparing to a 2nd order method.
|
||||||
|
\end{itemize}
|
||||||
|
In these adaptive step methods, two steps are computed at different orders: $\hat u_k^{(n)}$ and $\hat U_k^{(n)}$, the step size is adjusted at every step in such a way that the error is small enough:
|
||||||
|
\begin{equation}
|
||||||
|
\|\hat u^{(n)}-\hat U^{(n)}\|
|
||||||
|
<\epsilon_{\mathrm{target}}
|
||||||
|
\end{equation}
|
||||||
|
for some given $\epsilon_{\mathrm{target}}$, set using the {\tt adaptive\_tolerance} parameter.
|
||||||
|
The choice of the norm matters, and will be discussed below.
|
||||||
|
If the error is larger than the target, then the step size is decreased.
|
||||||
|
How this is done depends on the order of algorithm.
|
||||||
|
If the order is $q$ (here we mean the smaller of the two orders, so 4 for {\tt RKDP54} and {\tt RKF45} and 2 for {\tt RKBS32}), then we expect
|
||||||
|
\begin{equation}
|
||||||
|
\|\hat u^{(n)}-\hat U^{(n)}\|=\delta_n^qC_n
|
||||||
|
.
|
||||||
|
\end{equation}
|
||||||
|
We wish to set $\delta_{n+1}$ so that
|
||||||
|
\begin{equation}
|
||||||
|
\delta_{n+1}^qC_n=\epsilon_{\mathrm{target}}
|
||||||
|
\end{equation}
|
||||||
|
so
|
||||||
|
\begin{equation}
|
||||||
|
\delta_{n+1}
|
||||||
|
=\left(\frac{\epsilon_{\mathrm{target}}}{C_n}\right)^{\frac1q}
|
||||||
|
=\delta_n\left(\frac{\epsilon_{\mathrm{target}}}{\|\hat u^{(n)}-\hat U^{(n)}\|}\right)^{\frac1q}
|
||||||
|
.
|
||||||
|
\label{adaptive_delta}
|
||||||
|
\end{equation}
|
||||||
|
(Actually, to be safe and ensure that $\delta$ decreases sufficiently, we multiply this by a safety factor that can be set using the {\tt adaptive\_factor} parameter.)
|
||||||
|
If the error is smaller than the target, we increase $\delta$ using\-~(\ref{adaptive_delta}) (without the safety factor).
|
||||||
|
To be safe, we also set a maximal value for $\delta$ via the {\tt max\_delta} parameter.
|
||||||
|
\bigskip
|
||||||
|
|
||||||
|
\indent
|
||||||
|
The choice of the norm $\|\cdot\|$ matters.
|
||||||
|
\begin{itemize}
|
||||||
|
\item A naive choice is to take $\|\cdot\|$ to be the normalized $L_1$ norm:
|
||||||
|
\begin{equation}
|
||||||
|
\|f\|:=
|
||||||
|
\frac1{\mathcal N}\sum_k|f_k|
|
||||||
|
,\quad
|
||||||
|
\mathcal N:=\sum_k|\hat u_k^{(n)}-\hat u_k^{(n-1)}|
|
||||||
|
.
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
\item Empirically, we have found that $|\hat u-\hat U|$ behaves like $k^{-3}$ for {\tt RKDP54} and {\tt RKF45}, and like $k^{-\frac32}$ for {\tt RKBS32}, so a norm of the form
|
||||||
|
\begin{equation}
|
||||||
|
\|f\|:=\frac1{\mathcal N}\sum_k|f_k|k^{-3}
|
||||||
|
,\quad
|
||||||
|
\mathcal N:=\sum_k|\hat u_k^{(n)}-\hat u_k^{(n-1)}|k^{-3}
|
||||||
|
\end{equation}
|
||||||
|
or
|
||||||
|
\begin{equation}
|
||||||
|
\|f\|:=\frac1{\mathcal N}\sum_k|f_k|k^{-\frac32}
|
||||||
|
,\quad
|
||||||
|
\mathcal N:=\sum_k|\hat u_k^{(n)}-\hat u_k^{(n-1)}|k^{-\frac32}
|
||||||
|
\end{equation}
|
||||||
|
are sensible choices.
|
||||||
|
|
||||||
|
\item
|
||||||
|
Another option is to define a norm based on the expression of the enstrophy\-~(\ref{enstrophy}):
|
||||||
|
\begin{equation}
|
||||||
|
\|f\|:=\frac1{\mathcal N}\sqrt{\sum_k k^2|f_k|^2}
|
||||||
|
\quad
|
||||||
|
\mathcal N:=\sqrt{\sum_k k^2|\hat u_k^{(n)}|^2}
|
||||||
|
.
|
||||||
|
\end{equation}
|
||||||
|
Doing so controls the error of the enstrophy through
|
||||||
|
\begin{equation}
|
||||||
|
\mathcal N^2|\mathcal En(\hat u)-\mathcal En(\hat U)|\equiv|\|\hat u\|^2-\|\hat U\|^2|\leqslant \|\hat u-\hat U\|(\|\hat u\|+\|\hat U\|)
|
||||||
|
.
|
||||||
|
\end{equation}
|
||||||
|
\end{itemize}
|
||||||
|
\bigskip
|
||||||
|
|
||||||
\point{\bf Reality}.
|
\point{\bf Reality}.
|
||||||
Since $U$ is real, $\hat U_{-k}=\hat U_k^*$, and so
|
Since $U$ is real, $\hat U_{-k}=\hat U_k^*$, and so
|
||||||
\begin{equation}
|
\begin{equation}
|
||||||
@ -271,6 +353,7 @@ and
|
|||||||
+e^{-\frac{4\pi^2}{L^2}\nu t}\sqrt{E(0)}
|
+e^{-\frac{4\pi^2}{L^2}\nu t}\sqrt{E(0)}
|
||||||
\right)^2
|
\right)^2
|
||||||
.
|
.
|
||||||
|
\label{enstrophy}
|
||||||
\end{equation}
|
\end{equation}
|
||||||
\bigskip
|
\bigskip
|
||||||
|
|
||||||
|
22
src/complex_tools.c
Normal file
22
src/complex_tools.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "complex_tools.h"
|
||||||
|
|
||||||
|
// magnitude squared
|
||||||
|
double cabs2(_Complex double x){
|
||||||
|
return (__real__ x)*(__real__ x)+(__imag__ x)*(__imag__ x);
|
||||||
|
}
|
23
src/complex_tools.h
Normal file
23
src/complex_tools.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMPLEXTOOLS_H
|
||||||
|
#define COMPLEXTOOLS_H
|
||||||
|
|
||||||
|
// magnitude squared
|
||||||
|
double cabs2(_Complex double x);
|
||||||
|
|
||||||
|
#endif
|
21
src/main.c
21
src/main.c
@ -47,6 +47,7 @@ typedef struct nstrophy_parameters {
|
|||||||
double L;
|
double L;
|
||||||
double adaptive_tolerance;
|
double adaptive_tolerance;
|
||||||
double adaptive_factor;
|
double adaptive_factor;
|
||||||
|
double max_delta;
|
||||||
double print_freq;
|
double print_freq;
|
||||||
int seed;
|
int seed;
|
||||||
double starting_time;
|
double starting_time;
|
||||||
@ -170,16 +171,16 @@ int main (
|
|||||||
|
|
||||||
// run command
|
// run command
|
||||||
if (command==COMMAND_UK){
|
if (command==COMMAND_UK){
|
||||||
uk(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.final_time, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, parameters.starting_time, nthreads, savefile);
|
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, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, 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);
|
||||||
signal(SIGTERM, sig_handler);
|
signal(SIGTERM, sig_handler);
|
||||||
enstrophy(parameters.K1, parameters.K2, parameters.N1, parameters.N2, parameters.final_time, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, 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.final_time, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, parameters.max_delta, u0, g, parameters.irreversible, parameters.algorithm, parameters.print_freq, 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.final_time, parameters.nu, parameters.delta, parameters.L, parameters.adaptive_tolerance, parameters.adaptive_factor, parameters.starting_time, u0, g, parameters.irreversible, parameters.algorithm, nthreads, savefile);
|
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.starting_time, 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");
|
||||||
@ -264,13 +265,13 @@ int print_params(
|
|||||||
fprintf(file,", algorithm=RK2");
|
fprintf(file,", algorithm=RK2");
|
||||||
break;
|
break;
|
||||||
case ALGORITHM_RKF45:
|
case ALGORITHM_RKF45:
|
||||||
fprintf(file,", algorithm=RKF45, tolerance=%.15e, factor=%.15e",parameters.adaptive_tolerance, parameters.adaptive_factor);
|
fprintf(file,", algorithm=RKF45, tolerance=%.15e",parameters.adaptive_tolerance);
|
||||||
break;
|
break;
|
||||||
case ALGORITHM_RKDP54:
|
case ALGORITHM_RKDP54:
|
||||||
fprintf(file,", algorithm=RKDP54, tolerance=%.15e, factor=%.15e",parameters.adaptive_tolerance, parameters.adaptive_factor);
|
fprintf(file,", algorithm=RKDP54, tolerance=%.15e",parameters.adaptive_tolerance);
|
||||||
break;
|
break;
|
||||||
case ALGORITHM_RKBS32:
|
case ALGORITHM_RKBS32:
|
||||||
fprintf(file,", algorithm=RKBS32, tolerance=%.15e, factor=%.15e",parameters.adaptive_tolerance, parameters.adaptive_factor);
|
fprintf(file,", algorithm=RKBS32, tolerance=%.15e",parameters.adaptive_tolerance);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(file,", algorithm=RK4");
|
fprintf(file,", algorithm=RK4");
|
||||||
@ -397,6 +398,7 @@ int read_params(
|
|||||||
parameters->L=2*M_PI;
|
parameters->L=2*M_PI;
|
||||||
parameters->adaptive_tolerance=1e-11;
|
parameters->adaptive_tolerance=1e-11;
|
||||||
parameters->adaptive_factor=0.9;
|
parameters->adaptive_factor=0.9;
|
||||||
|
parameters->max_delta=1e-2;
|
||||||
parameters->final_time=100000;
|
parameters->final_time=100000;
|
||||||
parameters->print_freq=1;
|
parameters->print_freq=1;
|
||||||
parameters->starting_time=0;
|
parameters->starting_time=0;
|
||||||
@ -597,6 +599,13 @@ int set_parameter(
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strcmp(lhs,"print_freq")==0){
|
else if (strcmp(lhs,"print_freq")==0){
|
||||||
ret=sscanf(rhs,"%lf",&(parameters->print_freq));
|
ret=sscanf(rhs,"%lf",&(parameters->print_freq));
|
||||||
if(ret!=1){
|
if(ret!=1){
|
||||||
|
@ -17,13 +17,12 @@ limitations under the License.
|
|||||||
#include "constants.cpp"
|
#include "constants.cpp"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "navier-stokes.h"
|
#include "navier-stokes.h"
|
||||||
|
#include "complex_tools.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define CABS2(x) ((__real__ x) * (__real__ x) + (__imag__ x) * (__imag__ x))
|
|
||||||
|
|
||||||
// compute solution as a function of time
|
// compute solution as a function of time
|
||||||
int uk(
|
int uk(
|
||||||
int K1,
|
int K1,
|
||||||
@ -36,6 +35,7 @@ int uk(
|
|||||||
double L,
|
double L,
|
||||||
double adaptive_tolerance,
|
double adaptive_tolerance,
|
||||||
double adaptive_factor,
|
double adaptive_factor,
|
||||||
|
double max_delta,
|
||||||
_Complex double* u0,
|
_Complex double* u0,
|
||||||
_Complex double* g,
|
_Complex double* g,
|
||||||
bool irreversible,
|
bool irreversible,
|
||||||
@ -94,7 +94,7 @@ int uk(
|
|||||||
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
||||||
} else if (algorithm==ALGORITHM_RKDP54) {
|
} else if (algorithm==ALGORITHM_RKDP54) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, max_delta, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
||||||
} else if (algorithm==ALGORITHM_RKBS32) {
|
} else if (algorithm==ALGORITHM_RKBS32) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
||||||
@ -144,6 +144,7 @@ int enstrophy(
|
|||||||
double L,
|
double L,
|
||||||
double adaptive_tolerance,
|
double adaptive_tolerance,
|
||||||
double adaptive_factor,
|
double adaptive_factor,
|
||||||
|
double max_delta,
|
||||||
_Complex double* u0,
|
_Complex double* u0,
|
||||||
_Complex double* g,
|
_Complex double* g,
|
||||||
bool irreversible,
|
bool irreversible,
|
||||||
@ -203,7 +204,7 @@ int enstrophy(
|
|||||||
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
||||||
} else if (algorithm==ALGORITHM_RKDP54) {
|
} else if (algorithm==ALGORITHM_RKDP54) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, max_delta, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
||||||
} else if (algorithm==ALGORITHM_RKBS32) {
|
} else if (algorithm==ALGORITHM_RKBS32) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
||||||
@ -317,6 +318,7 @@ int quiet(
|
|||||||
double final_time,
|
double final_time,
|
||||||
double nu,
|
double nu,
|
||||||
double delta,
|
double delta,
|
||||||
|
double max_delta,
|
||||||
double L,
|
double L,
|
||||||
double adaptive_tolerance,
|
double adaptive_tolerance,
|
||||||
double adaptive_factor,
|
double adaptive_factor,
|
||||||
@ -361,7 +363,7 @@ int quiet(
|
|||||||
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
ns_step_rkf45(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, true);
|
||||||
} else if (algorithm==ALGORITHM_RKDP54) {
|
} else if (algorithm==ALGORITHM_RKDP54) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
ns_step_rkdp54(u, adaptive_tolerance, adaptive_factor, max_delta, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, &tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, irreversible, time==starting_time);
|
||||||
} else if (algorithm==ALGORITHM_RKBS32) {
|
} else if (algorithm==ALGORITHM_RKBS32) {
|
||||||
// only compute k1 on the first step
|
// only compute k1 on the first step
|
||||||
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
ns_step_rkbs32(u, adaptive_tolerance, adaptive_factor, K1, K2, N1, N2, nu, &step, &next_step, L, g, fft1, fft2, ifft, &tmp1, tmp2, tmp3, &tmp4, tmp5, irreversible, time==starting_time);
|
||||||
@ -856,6 +858,7 @@ int ns_step_rkdp54(
|
|||||||
_Complex double* u,
|
_Complex double* u,
|
||||||
double tolerance,
|
double tolerance,
|
||||||
double factor,
|
double factor,
|
||||||
|
double max_delta,
|
||||||
int K1,
|
int K1,
|
||||||
int K2,
|
int K2,
|
||||||
int N1,
|
int N1,
|
||||||
@ -946,10 +949,13 @@ int ns_step_rkdp54(
|
|||||||
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
for(ky=(kx>0 ? -K2 : 1);ky<=K2;ky++){
|
||||||
// difference between 5th order and 4th order
|
// difference between 5th order and 4th order
|
||||||
// use the norm |u_k|^2k^2 (to get a bound on the error of the enstrophy)
|
// use the norm |u_k|^2k^2 (to get a bound on the error of the enstrophy)
|
||||||
err+=(kx*kx+ky*ky)*CABS2((*delta)*(-71./57600*(*k1)[klookup_sym(kx,ky,K2)]+71./16695*k3[klookup_sym(kx,ky,K2)]-71./1920*k4[klookup_sym(kx,ky,K2)]+17253./339200*k5[klookup_sym(kx,ky,K2)]-22./525*k6[klookup_sym(kx,ky,K2)]+1./40*(*k2)[klookup_sym(kx,ky,K2)]));
|
err+=(kx*kx+ky*ky)*cabs2((*delta)*(-71./57600*(*k1)[klookup_sym(kx,ky,K2)]+71./16695*k3[klookup_sym(kx,ky,K2)]-71./1920*k4[klookup_sym(kx,ky,K2)]+17253./339200*k5[klookup_sym(kx,ky,K2)]-22./525*k6[klookup_sym(kx,ky,K2)]+1./40*(*k2)[klookup_sym(kx,ky,K2)]));
|
||||||
relative+=(kx*kx+ky*ky)*(CABS2(tmp[klookup_sym(kx,ky,K2)]-u[klookup_sym(kx,ky,K2)]));
|
//relative+=(kx*kx+ky*ky)*(CABS2(tmp[klookup_sym(kx,ky,K2)]-u[klookup_sym(kx,ky,K2)]));
|
||||||
|
relative+=(kx*kx+ky*ky)*(cabs2(u[klookup_sym(kx,ky,K2)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err=sqrt(err);
|
||||||
|
relative=sqrt(relative);
|
||||||
|
|
||||||
// compare relative error with tolerance
|
// compare relative error with tolerance
|
||||||
if(err<relative*tolerance){
|
if(err<relative*tolerance){
|
||||||
@ -959,8 +965,8 @@ int ns_step_rkdp54(
|
|||||||
u[klookup_sym(kx,ky,K2)]=tmp[klookup_sym(kx,ky,K2)];
|
u[klookup_sym(kx,ky,K2)]=tmp[klookup_sym(kx,ky,K2)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// next delta to use in future steps
|
// next delta to use in future steps (do not exceed max_delta)
|
||||||
*next_delta=(*delta)*pow(relative*tolerance/err,1./5);
|
*next_delta=fmin(max_delta, (*delta)*pow(relative*tolerance/err,1./5));
|
||||||
|
|
||||||
// k1 in the next step will be this k4 (first same as last)
|
// k1 in the next step will be this k4 (first same as last)
|
||||||
tmp=*k1;
|
tmp=*k1;
|
||||||
@ -971,7 +977,7 @@ int ns_step_rkdp54(
|
|||||||
else{
|
else{
|
||||||
*delta=factor*(*delta)*pow(relative*tolerance/err,1./5);
|
*delta=factor*(*delta)*pow(relative*tolerance/err,1./5);
|
||||||
// this will reuse the same k1 without re-computing it
|
// this will reuse the same k1 without re-computing it
|
||||||
ns_step_rkdp54(u,tolerance,factor,K1,K2,N1,N2,nu,delta,next_delta,L,g,fft1,fft2,ifft,k1,k2,k3,k4,k5,k6,tmp,irreversible,false);
|
ns_step_rkdp54(u,tolerance,factor,max_delta,K1,K2,N1,N2,nu,delta,next_delta,L,g,fft1,fft2,ifft,k1,k2,k3,k4,k5,k6,tmp,irreversible,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -33,13 +33,13 @@ typedef struct fft_vects {
|
|||||||
} fft_vect;
|
} fft_vect;
|
||||||
|
|
||||||
// compute u_k
|
// compute u_k
|
||||||
int uk( int K1, int K2, int N1, int N2, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, double print_freq, double starting_time, unsigned int nthreadsl, FILE* savefile);
|
int uk( int K1, int K2, int N1, int N2, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, double max_delta, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, double print_freq, 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, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, double print_freq, double 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, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, double max_delta, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, double print_freq, 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, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, double 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, double final_time, double nu, double delta, double L, double adaptive_tolerance, double adaptive_factor, double max_delta, double starting_time, _Complex double* u0, _Complex double* g, bool irreversible, unsigned int algorithm, unsigned int nthreads, FILE* savefile);
|
||||||
|
|
||||||
|
|
||||||
// initialize vectors for computation
|
// initialize vectors for computation
|
||||||
@ -58,7 +58,7 @@ int ns_step_rk2( _Complex double* u, int K1, int K2, int N1, int N2, double nu,
|
|||||||
// Runge-Kutta-Fehlberg
|
// Runge-Kutta-Fehlberg
|
||||||
int ns_step_rkf45( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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, bool compute_k1);
|
int ns_step_rkf45( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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, bool compute_k1);
|
||||||
// Runge-Kutta-Dromand-Prince
|
// Runge-Kutta-Dromand-Prince
|
||||||
int ns_step_rkdp54( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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, bool compute_k1);
|
int ns_step_rkdp54( _Complex double* u, double tolerance, double factor, double max_delta, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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, bool compute_k1);
|
||||||
// Runge-Kutta-Bogacki-Shampine
|
// Runge-Kutta-Bogacki-Shampine
|
||||||
int ns_step_rkbs32( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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* tmp, bool irreversible, bool compute_k1);
|
int ns_step_rkbs32( _Complex double* u, double tolerance, double factor, int K1, int K2, int N1, int N2, double nu, double* delta, double* next_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* tmp, bool irreversible, bool compute_k1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user