void init_KidaVortex(struct Field fldi) { double a = param.vortex_a; double b = param.vortex_b; int i,j,k; double w0, x, y; double chi; chi = b / a; w0 = 1.0/chi*(chi + 1.0)/(chi-1.0); // According to Kida! for(i = 0 ; i < NX/NPROC ; i++) { x = - param.lx / 2 + (param.lx * (i + rank * NX / NPROC)) / NX; for(j = 0 ; j < NY ; j++) { y = - param.ly / 2 + (param.ly * j) / NY; #ifdef WITH_2D if(x * x / (a * a) + y * y / (b * b) < 1) { // we are in the vortex wr1[j + (NY+2) * i] = -w0; } else { wr1[j + (NY+2) * i] = 0.0; } #else for(k = 0 ; k < NZ ; k++) { if(x * x / (a * a) + y * y / (b * b) < 1) { // we are in the vortex wr1[k + j*(NZ+2) + (NZ+2) * NY * i] = -w0; } else { wr1[k + j*(NZ+2) + (NZ+2) * NY * i] = 0.0; } } #endif } } // transform gfft_r2c(wr1); for(i = 0 ; i < NTOTAL_COMPLEX ; i++) { fldi.vx[ i ] += I * ky[i] * w1[i] * ik2t[i]; fldi.vy[ i ] += -I * kxt[i] * w1[i] * ik2t[i]; } // done return; }
void init_Bench(struct Field fldi) { const double a = 0.3; const double b = 0.4; int i,j,k; double w0, x, y; double chi; chi = b / a; w0 = 1.0/chi*(chi + 1)/(chi-1.0); // According to Kida! for(i = 0 ; i < NX/NPROC ; i++) { x = - param.lx / 2. + (param.lx * (i + rank * NX / NPROC)) / NX; for(j = 0 ; j < NY ; j++) { y = - param.ly / 2. + (param.ly * j) / NY; for(k = 0 ; k < NZ ; k++) { if(x * x / (a * a) + y * y / (b * b) < 1) { // we are in the vortex wr1[k + j*(NZ+2) + (NZ+2) * NY * i] = -w0; } else { wr1[k + j*(NZ+2) + (NZ+2) * NY * i] = 0.0; } } } } // transform gfft_r2c(wr1); for(i = 0 ; i < NTOTAL_COMPLEX ; i++) { fldi.vx[ i ] += I * ky[i] * w1[i] * ik2t[i]; fldi.vy[ i ] += -I * kxt[i] * w1[i] * ik2t[i]; } // Brake vertical symmetry if(rank==0) { fldi.vx[1] = 1000.0 / NTOTAL; fldi.vy[1] = 1000.0 / NTOTAL; #ifdef MHD fldi.bx[1] = 1000.0 / NTOTAL; fldi.by[1] = 1000.0 / NTOTAL; #endif } // done return; }
void u_iii_forcing(struct Field fldi, double dt) { double *x, *y, *z; int i,j,k; x = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (x == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for x allocation"); y = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (y == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for y allocation"); z = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (z == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for z allocation"); // Initialize the arrays for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = 0 ; k < NZ ; k++) { x[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.lx / 2 + (param.lx * (i + rank * NX / NPROC)) / NX; y[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.ly / 2 + (param.ly * j ) / NY; z[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.lz / 2 + (param.lz * k ) / NZ; } } } // Initialize the extra points (k=NZ and k=NZ+1) to zero to prevent stupid things from happening... for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = NZ ; k < NZ + 2 ; k++) { x[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; y[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; z[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; } } } // Init work array to zero for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = 0 ; k < NZ + 2 ; k++) { wr4[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr5[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr6[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; } } } /******************************************************************* ** This part can be modified ************************** ********************************************************************/ // The velocity field vx,vy,vz is stored in wr1,wr2,wr3 for(i = 0 ; i < 2*NTOTAL_COMPLEX ; i++) { wr4[i] = param.modified_ABC_flow_D*( cos(x[i]/param.modified_ABC_flow_m)*( param.modified_ABC_flow_A*param.modified_ABC_flow_kz*sin(z[i] /(double) param.modified_ABC_flow_kz ) + param.modified_ABC_flow_C*param.modified_ABC_flow_ky*cos(y[i] /(double) param.modified_ABC_flow_ky) ) + sin(x[i]/param.modified_ABC_flow_m)/param.modified_ABC_flow_m*( 0 ) ); wr5[i] = param.modified_ABC_flow_D*( cos(x[i]/param.modified_ABC_flow_m)*( param.modified_ABC_flow_B*param.modified_ABC_flow_kx*sin(x[i] /(double) param.modified_ABC_flow_kx ) + param.modified_ABC_flow_A*param.modified_ABC_flow_kz*cos(z[i] /(double) param.modified_ABC_flow_kz) ) + sin(x[i]/param.modified_ABC_flow_m)/param.modified_ABC_flow_m*( param.modified_ABC_flow_B*cos(x[i] /(double) param.modified_ABC_flow_kx) + param.modified_ABC_flow_C*sin(y[i] /(double) param.modified_ABC_flow_ky) ) ); wr6[i] = param.modified_ABC_flow_D*( cos(x[i]/param.modified_ABC_flow_m)*( param.modified_ABC_flow_C*param.modified_ABC_flow_ky*sin(y[i] /(double) param.modified_ABC_flow_ky ) + param.modified_ABC_flow_B*param.modified_ABC_flow_kx*cos(x[i] /(double) param.modified_ABC_flow_kx) ) + sin(x[i]/param.modified_ABC_flow_m)/param.modified_ABC_flow_m*( -param.modified_ABC_flow_A*cos(z[i] /(double) param.modified_ABC_flow_kz) + -param.modified_ABC_flow_B*sin(x[i] /(double) param.modified_ABC_flow_kx) ) ); } gfft_r2c(wr4); gfft_r2c(wr5); gfft_r2c(wr6); for(i = 0 ; i < NTOTAL_COMPLEX ; i++) { w4[i] = w4[i] * mask[i]; w5[i] = w5[i] * mask[i]; w6[i] = w6[i] * mask[i]; } for( i = 0; i < NX_COMPLEX/NPROC; i++) { for( j = 0; j < NY_COMPLEX; j++) { for( k = 0; k < NZ_COMPLEX; k++) { fldi.vx[ IDX3D ] += w4[ IDX3D ] * (1 - exp(-nu*k2t[IDX3D]*dt)) ; fldi.vy[ IDX3D ] += w5[ IDX3D ] * (1 - exp(-nu*k2t[IDX3D]*dt)) ; fldi.vz[ IDX3D ] += w6[ IDX3D ] * (1 - exp(-nu*k2t[IDX3D]*dt)) ; } } } #ifdef U_III_FORCING_EXTRA gfft_c2r_t(w4); gfft_c2r_t(w5); gfft_c2r_t(w6); #ifdef _OPENMP #pragma omp parallel for private(i) schedule(static) #endif for( i = 0 ; i < 2*NTOTAL_COMPLEX ; i++) { wr10[i] = wr4[i] * wr4[i] / ((double) NTOTAL*NTOTAL); wr11[i] = wr5[i] * wr5[i] / ((double) NTOTAL*NTOTAL); #ifndef WITH_2D wr12[i] = wr6[i] * wr6[i] / ((double) NTOTAL*NTOTAL); #endif wr7[i] = wr4[i] * wr5[i] / ((double) NTOTAL*NTOTAL); wr8[i] = wr4[i] * wr6[i] / ((double) NTOTAL*NTOTAL); wr9[i] = wr5[i] * wr6[i] / ((double) NTOTAL*NTOTAL); } gfft_r2c_t(wr10); gfft_r2c_t(wr11); #ifndef WITH_2D gfft_r2c_t(wr12); #endif gfft_r2c_t(wr7); gfft_r2c_t(wr8); gfft_r2c_t(wr9); #ifdef _OPENMP #pragma omp parallel for private(i) schedule(static) #endif for( i = 0 ; i < NTOTAL_COMPLEX ; i++) { fldi.vx[i] += I * mask[i] / (nu * k2t) * (1 - exp(-nu*k2t[IDX3D]*dt)) * ( kxt[i] * w10[i] + ky[i] * w7[i] + kz[i] * w8[i] ); fldi.vy[i] += I * mask[i] / (nu * k2t) * (1 - exp(-nu*k2t[IDX3D]*dt)) * ( kxt[i] * w7[i] + ky[i] * w11[i] + kz[i] * w9[i] ); fldi.vz[i] += I * mask[i] / (nu * k2t) * (1 - exp(-nu*k2t[IDX3D]*dt)) * ( kxt[i] * w8[i] + ky[i] * w9[i] + kz[i] * w12[i] ); // since kz=0 in 2D, kz*w6 gives 0, even if w6 is some random array } #endif projector(fldi.vx,fldi.vy,fldi.vz); return; }
void init_SpatialStructure(struct Field fldi) { double *x,*y,*z; int i,j,k; /******************************************************************* ** This part does not need to be modified ************************** ********************************************************************/ // Allocate coordinate arrays x = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (x == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for x allocation"); y = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (y == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for y allocation"); z = (double *) fftw_malloc( sizeof(double complex) * NTOTAL_COMPLEX); if (z == NULL) ERROR_HANDLER( ERROR_CRITICAL, "No memory for z allocation"); // Initialize the arrays for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = 0 ; k < NZ ; k++) { x[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.lx / 2 + (param.lx * (i + rank * NX / NPROC)) / NX; y[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.ly / 2 + (param.ly * j ) / NY; z[k + (NZ + 2) * j + (NZ + 2) * NY * i] = - param.lz / 2 + (param.lz * k ) / NZ; } } } // Initialize the extra points (k=NZ and k=NZ+1) to zero to prevent stupid things from happening... for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = NZ ; k < NZ + 2 ; k++) { x[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; y[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; z[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; } } } // Init work array to zero for(i = 0 ; i < NX/NPROC ; i++) { for(j = 0 ; j < NY ; j++) { for(k = 0 ; k < NZ + 2 ; k++) { wr1[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr2[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr3[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr4[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr5[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; wr6[k + (NZ + 2) * j + (NZ + 2) * NY * i] = 0.0; } } } /******************************************************************* ** This part can be modified ************************** ********************************************************************/ // The velocity field vx,vy,vz is stored in wr1,wr2,wr3 // The magnetic field bx,by,bz is stored in wr4,wr5,wr6 (ignored if MHD is not set) for(i = 0 ; i < 2*NTOTAL_COMPLEX ; i++) { // Example: init a flux tube in the x direction+a vertical displacement // wr4[i] = exp(-(y[i]*y[i]+z[i]*z[i])*20.0); // wr3[i] = 0.5*cos(x[i] * 2.0 * M_PI); // Example: twisted flux tube + vertical displacement wr4[i] = exp(-(y[i]*y[i]+z[i]*z[i])/(0.2*0.2)); wr5[i] = fabs(z[i])*1.0*wr4[i]; wr6[i] = -fabs(y[i])*1.0*wr4[i]; wr3[i] = 0.5*cos(x[i] * 2.0 * M_PI); if (i==3*NY*(NZ+2)) fprintf(stderr," %d %e",i,x[i]); } /******************************************************************* ** This part does not need to be modified ************************** ********************************************************************/ // Fourier transform everything gfft_r2c(wr1); gfft_r2c(wr2); gfft_r2c(wr3); gfft_r2c(wr4); gfft_r2c(wr5); gfft_r2c(wr6); // Transfer data in the relevant array (including dealiasing mask) for(i = 0 ; i < NTOTAL_COMPLEX ; i++) { fldi.vx[i] += w1[i] * mask[i]; fldi.vy[i] += w2[i] * mask[i]; fldi.vz[i] += w3[i] * mask[i]; #ifdef MHD fldi.bx[i] += w4[i] * mask[i]; fldi.by[i] += w5[i] * mask[i]; fldi.bz[i] += w6[i] * mask[i]; #endif } // free memory fftw_free(x); fftw_free(y); fftw_free(z); //done return; }