/************************************************************************************************ * * * rb.c * * * * * * Solves the rayleigh-benard equation in bousinesq approximation. * * Pseudospectral scheme for spatial derivatives, * * RK4 for temporal integration. * * Volume penalization for no-slip boundary conditions. * * * * * * compile with * * gcc -std=c99 -O3 -Wall -o rb rb.c -I(FFTW3_PATH)/include * * -L(FFTW3_PATH)/lib -lfftw3 -I(DISLIN_PATH) -L(DISLIN_PATH) -ldislin -lm * * * * * * author: Johannes Luelff (johannes.luelff@uni-muenster.de) * * * ************************************************************************************************/ #include #include #include #include #include #include "fftw3.h" #include "dislin.h" #define USE_DISLIN //constants etc. #define PI 3.14159265358979323846264338327950288419716939937510582097494459230781 const int N = 256; //Grid resolution const double L = 2*PI; //Physical length //Rayleigh-Benard parameters const double nu = 1e-2; const double kappa = 1e-2; const double alpha = 1; const double beta = 1; //time(step) double t; double dt=2e-3; const int MAX_ITER = 40*1000; const int EVERY_DISPLAY = 40; //qvec is the statevector; qvec[0] is the vorticity field, qvec[1] the temperature field complex *qvec[2]; double *qvec_real[2]; complex *ux, *uy; complex *nonlin[2], *Nx[2], *Ny[2]; complex *rk1[2], *rk2[2], *rk3[2], *rk4[2], *rktmp[2]; double *kvec[3]; float *dis_real, *dis_spec; //penalization terms double *wampe; const double wampe_eps = 1e-2; //fftw plans fftw_plan plan_r2c, plan_c2r; //two routines to handle the FT void fftR2C(complex *arr) { fftw_execute_dft_r2c(plan_r2c, (double*)arr, (complex*)arr); for(int i=0; i pow(2.0/3.0 * (N/2+1), 2)) arr[i] = 0; } //calculates nonlinear part of our equations void calcNonlin(complex *in[2], complex *out[2]) { //calc velocity ux[0] = 0; uy[0] = 0; for(int i=1; imax1) max1 = dis_real[i*N+j]; } } assignArrays(ctmp, in2); fftC2R(ctmp); for(int i=0; imax2) max2 = dis_spec[i*N+j]; } } if(min1==max1) { min1 -= 1e-3; max1 += 1e-3; } erase(); axspos(2970*0.1f,2970*0.85f); autres(N,N); titlin("omega", 1); char s[256]; sprintf(s, "t=%f", t); titlin(s, 3); graf3(0,L,0,L/2, 0,L,0,L/2, min1, max1, min1, (max1-min1)/2); title(); crvmat(dis_real, N, N, ((512/N)<=0)?1:(512/N), ((512/N)<=0)?1:(512/N)); endgrf(); if(min2==max2) { min2 -= 1e-3; max2 += 1e-3; } axspos(2970*1.1f,2970*0.85f); autres(N,N); titlin("Theta", 1); sprintf(s, "dt=%f", dt); titlin(s, 3); graf3(0,L,0,L/2, 0,L,0,L/2, min2, max2, min2, (max2-min2)/2); title(); crvmat(dis_spec, N, N, ((512/N)<=0)?1:(512/N), ((512/N)<=0)?1:(512/N)); endgrf(); } int main (int argc, char *argv[]) { //allocate memory for(int i=0; i<2; i++) { qvec[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); qvec_real[i] = (double*)fftw_malloc(N*2*(N/2+1) * sizeof(double)); nonlin[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); Nx[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); Ny[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); rk1[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); rk2[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); rk3[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); rk4[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); rktmp[i] = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); } ux = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); uy = (complex*)fftw_malloc(N*(N/2+1) * sizeof(complex)); for(int i=0; i<3; i++) kvec[i] = (double*)fftw_malloc(N*(N/2+1) * sizeof(double)); dis_real = (float*)fftw_malloc(N*N*sizeof(float)); dis_spec = (float*)fftw_malloc(N*N*sizeof(float)); wampe = (double*)fftw_malloc(N*2*(N/2+1)*sizeof(double)); //create plans plan_c2r = fftw_plan_dft_c2r_2d(N, N, qvec[0], (double*)qvec[0], FFTW_ESTIMATE); plan_r2c = fftw_plan_dft_r2c_2d(N, N, (double*)qvec[0], qvec[0], FFTW_ESTIMATE); //init kvec for(int i=0; i1*N/8)&&(j<7*N/8)) ? 0.0 : 1.0; //bottom / top } } //init field for(int i=0; i