const std::vector<T> linearDiffusion(const std::vector<T> & signal, T time, T step_size = 0.25, BorderInterpolation interpolation_method = CONTINUED) { /* The general formulation of a nonlinear diffusion is * * d/dt f(x, t) = div grad f(x, t) = laplace f(x, t) * * In the 1-dimensional case, the divergence and the gradient simplify to * an ordinary differentiation. Thus we get * * d/dt f(x, t) = d^2/dx^2 f(x, t) * * The diffusion equation can be easily solved by using the following * approximation * * d/dt f(x, t) = [f(x, t+h) - f(x, t) ] / h * * where h is the step size. With this, we get * * d/dt f(x, t+h) = f(x, t) + h * d^2/dx^2 f(x, t) * * Iterating until t + n * h = time, yields the solution. */ // If time == 0 return the unchanged signal. if (Tools::isZero(time)) { return signal; } // Modify step_size such, that after n iterations, time is really reached. step_size = time / std::ceil(time / step_size); // Compute the diffusion. const unsigned N = signal.size(); std::vector<T> B(N); std::vector<T> diffused_signal = signal; for (T t = step_size; t <= time; t += step_size) { const std::vector<T> & derivative = secondDerivative(diffused_signal, interpolation_method); for (unsigned i = 0; i < signal.size(); ++i) { diffused_signal[i] = diffused_signal[i] + step_size * derivative[i]; } } return diffused_signal; }
// A function to solver Burgers equation void Solver_FFTW::burgersSolver_FFTW(){ /*=============================================== get V at t=0 ===============================================*/ for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ temp_Velocity[i*numOfYGrid+j] = v[i][j]; } } fftw_execute(plan_r2c); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid/2 + 1; j++){ V[i][j][0] = temp_U[i*(numOfYGrid/2+1) + j][0]; V[i][j][1] = temp_U[i*(numOfYGrid/2+1) + j][1]; } } fftw_execute(plan_c2r); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ v[i][j] = temp_Velocity[i*numOfYGrid + j]/(numOfXGrid*numOfYGrid); } } /*=============================================== get W at t=0 ===============================================*/ for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ temp_Velocity[i*numOfYGrid+j] = w[i][j]; } } fftw_execute(plan_r2c); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid/2 + 1; j++){ W[i][j][0] = temp_U[i*(numOfYGrid/2+1)+j][0]; W[i][j][1] = temp_U[i*(numOfYGrid/2+1)+j][1]; } } fftw_execute(plan_c2r); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ w[i][j] = temp_Velocity[i*numOfYGrid+j]/(numOfXGrid*numOfYGrid); } } Output *out = new Output(numOfXGrid,numOfYGrid,v,w,0,initE,_VELOCITY); /*============================================== Time step iteration ==============================================*/ for(long int t = 0; t < TIME_N;t++){ //First step, get V and W for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ temp_Velocity[i*numOfYGrid+j] = v[i][j]; } } fftw_execute(plan_r2c); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid/2 + 1; j++){ V[i][j][0] = temp_U[i*(numOfYGrid/2+1)+j][0]; V[i][j][1] = temp_U[i*(numOfYGrid/2+1)+j][1]; } } for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid; j++){ temp_Velocity[i*numOfYGrid+j] = w[i][j]; } } fftw_execute(plan_r2c); for(int i = 0; i < numOfXGrid; i++){ for(int j = 0; j < numOfYGrid/2 + 1; j++){ W[i][j][0] = temp_U[i*(numOfYGrid/2+1)+j][0]; W[i][j][1] = temp_U[i*(numOfYGrid/2+1)+j][1]; } } /*============================= Second step: get v_x,v_y,w_x,w_y /*=============================*/ firstDerivative(); /* if(t == 0){ Output* out_1 = new Output(numOfXGrid,numOfYGrid,v_x,v_y,0,initE,_DERIVATIVEv); Output* out_2 = new Output(numOfYGrid,numOfYGrid,w_x,w_y,0,initE,_DERIVATIVEw); } */ /*============================= Third step: get v_x_x,v_y_y,w_x_x,w_y_y =============================*/ secondDerivative(); /* if(t == 0){ Output* out_1 = new Output(numOfXGrid,numOfYGrid,v_x_x,v_y_y,0,initE,_DDERIVATIVEv); Output* out_2 = new Output(numOfYGrid,numOfYGrid,w_x_x,w_y_y,0,initE,_DDERIVATIVEw); } */ /*============================= Forth step: sampling force =============================*/ samplingForce(); /*============================= Last step: Adams-Bashforth method =============================*/ adamsMethod(t); //calculate energy in some steps, this energy is not rescaled if((t+1)%ENERGY_OUTPUT == 0){ double E = calculateE(); energy << log((t+1)*TIME_STEP) + log(sqrt(initE*(numOfYGrid-1)/(numOfXGrid-1))/(numOfXGrid-1)) << "\t"; energy << log(E) - log(initE*(numOfYGrid-1)/(numOfXGrid-1))<< endl; } //generate output in some steps, this output is rescaled, see output.cpp if((t+1)%GENERATE_OUTPUT == 0){ Output* out_1 = new Output(numOfXGrid,numOfYGrid,v,w,t+1,initE,_VELOCITY); Output* out_2 = new Output(numOfXGrid,numOfYGrid,v_x,v_y,t+1,initE,_DERIVATIVEv); Output* out_3 = new Output(numOfYGrid,numOfYGrid,w_x,w_y,t+1,initE,_DERIVATIVEw); cout << "t=" << t+1 << "_completed" << endl; } } //empty the memory energy.close(); fftw_destroy_plan(plan_c2r); fftw_destroy_plan(plan_r2c); fftw_destroy_plan(plan_firstD); fftw_destroy_plan(plan_secondD); return; }