program heat2D !$use OMP_LIB implicit none integer :: niter,i,j,t,rank real(8), allocatable, dimension(:,:) :: U0,U1 real(8) :: alpha,totaltime,Dt,Stab,DtAlpha integer, dimension(1:2) :: Nx real(8), dimension(1:2) :: Lx,Dx,DxDx,InvDxDx character(len=4) :: charbuff niter = 8000 Nx(:) = 700 alpha = 0.4d0 totaltime = 0.005d0 Dt = totaltime/((niter-1)*1.0d0) Lx(:) = 1.0d0 Dx(:) = Lx(:)/((Nx(:)-1)*1.0d0) InvDxDx(:) = 1.0d0/(Dx(:)*Dx(:)) DxDx(:) = Dx(:)*Dx(:) Stab = alpha*Dt*(InvDxDx(1)) + alpha*Dt*(InvDxDx(2)) DtAlpha = Dt*alpha print *, "Stability factor (need < 0.5): ",stab if(stab > 0.5d0) stop print *,"Calculating, please wait..." allocate(U0(0:Nx(1)+1,0:Nx(2)+1),U1(0:Nx(1)+1,0:Nx(2)+1)) U0(:,:) = 1.0d0 U0(100:150,200:250) = -10.0d0 U0(300:350,400:450) = +12.0d0 U1(:,:) = U0(:,:) rank = 0 write(charbuff,'(I4.4)') rank open(10+rank,file=trim(adjustl('IN'//'.'//trim(adjustl(charbuff))//'.dat'))) do j=1,Nx(2),10 do i=1,Nx(1),10 write(10,*) i,j+(rank*Nx(2)),U0(i,j) end do end do close(10+rank) !$OMP PARALLEL DEFAULT(SHARED) PRIVATE(i,j,t) do t=1,niter ! print *,t !$OMP DO SCHEDULE(RUNTIME) do j=1,Nx(2) do i=1,Nx(1) U1(i,j) = U0(i,j) + DtAlpha* & & ( (U0(i+1,j)-2.0*U0(i,j)+U0(i-1,j))*InvDxDx(1) + & & (U0(i,j+1)-2.0*U0(i,j)+U0(i,j-1))*InvDxDx(2) ) end do end do !$OMP END DO !$OMP DO SCHEDULE(RUNTIME) do j=1,Nx(2) do i=1,Nx(1) U0(i,j) = U1(i,j) + DtAlpha* & & ( (U1(i+1,j)-2.0*U1(i,j)+U1(i-1,j))*InvDxDx(1) + & & (U1(i,j+1)-2.0*U1(i,j)+U1(i,j-1))*InvDxDx(2) ) end do end do !$OMP END DO end do !$OMP END PARALLEL rank = 0 write(charbuff,'(I4.4)') rank open(10+rank,file=trim(adjustl('OUT'//'.'//trim(adjustl(charbuff))//'.dat'))) do j=1,Nx(2),10 do i=1,Nx(1),10 write(10,*) i,j+(rank*Nx(2)),U0(i,j) end do end do close(10+rank) deallocate(U0,U1) end program heat2D 2 versions, both from Adrien Cassagne. One with 1D arrays, second one with 2D arrays. #include #include #include int main(int argc, char** argv) { int niter,i,j,t,rank; double alpha,totaltime,Dt,Stab,DtAlpha; int Nx[2]; double Lx[2], Dx[2], DxDx[2], InvDxDx[2]; // parameters niter = 8000; Nx[0] = 700; Nx[1] = 700; alpha = 0.4; totaltime = 0.005; // initializations computation Dt = totaltime/((niter-1)*1.0); Lx[0] = 1.0; Lx[1] = 1.0; Dx[0] = Lx[0]/((Nx[0]-1)*1.0); Dx[1] = Lx[1]/((Nx[1]-1)*1.0); InvDxDx[0] = 1.0/(Dx[0]*Dx[0]); InvDxDx[1] = 1.0/(Dx[1]*Dx[1]); DxDx[0] = Dx[0]*Dx[0]; DxDx[1] = Dx[1]*Dx[1]; Stab = alpha*Dt*(InvDxDx[0]) + alpha*Dt*(InvDxDx[1]); DtAlpha = Dt*alpha; // verify stability condition printf("Stability factor (need < 0.5): %lf\n", Stab); if(Stab > 0.5) exit(0); double *U0 = malloc((Nx[0]+2) * (Nx[1]+2) * sizeof(double)); double *U1 = malloc((Nx[0]+2) * (Nx[1]+2) * sizeof(double)); // init grid for(j = 0; j < Nx[1]+2; ++j) for(i = 0; i < Nx[0]+2; ++i) { U0[i+j*Nx[0]] = 1.0; U1[i+j*Nx[0]] = 1.0; if(i >= 100 && i <= 150 && j>=200 && j<=250) { U0[i+j*Nx[0]] = -10.0; U1[i+j*Nx[0]] = -10.0;} if(i >= 300 && i <= 350 && j>=400 && j<=450) { U0[i+j*Nx[0]] = 12.0; U1[i+j*Nx[0]] = 12.0;} } rank = 0; char fileName[2048]; sprintf(fileName, "IN.%d.dat", rank); FILE *file = NULL; file = fopen(fileName, "w"); for(j = 1; j < Nx[0]+1; j += 10) for(i = 1; i < Nx[1]+1; i += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i+j*Nx[0]]); fclose(file); printf("Calculating, please wait...\n"); #pragma omp parallel default(shared) private(t,i,j) for(t = 0; t < niter; ++t) { #pragma omp for schedule(runtime) for(j = 1; j < Nx[1]+1; ++j) for(i = 1; i < Nx[0]+1; ++i) U1[i+j*Nx[0]] = U0[i+j*Nx[0]] + DtAlpha * ((U0[i+1+j*Nx[0]] -2.0*U0[i+j*Nx[0]] + U0[i-1+j*Nx[0]] )*InvDxDx[0] + (U0[i+(j+1)*Nx[0]] -2.0*U0[i+j*Nx[0]] + U0[i+(j-1)*Nx[0]])*InvDxDx[1]); #pragma omp for schedule(runtime) for(j = 1; j < Nx[1]+1; ++j) for(i = 1; i < Nx[0]+1; ++i) U0[i+j*Nx[0]] = U1[i+j*Nx[0]] + DtAlpha * ((U1[i+1+j*Nx[0]] -2.0*U1[i+j*Nx[0]] + U1[i-1+j*Nx[0]] )*InvDxDx[0] + (U1[i+(j+1)*Nx[0]] -2.0*U1[i+j*Nx[0]] + U1[i+(j-1)*Nx[0]])*InvDxDx[1] ); } sprintf(fileName, "OUT.%d.dat", rank); file = fopen(fileName, "w"); for(j = 1; j < Nx[1]+1; j += 10) for(i = 1; i < Nx[0]+1; i += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i+j*Nx[0]]); fclose(file); free(U0); free(U1); return 0; } #include #include #include int main(int argc, char** argv) { int niter,i,j,t,rank; double alpha,totaltime,Dt,Stab,DtAlpha; int Nx[2]; double Lx[2], Dx[2], DxDx[2], InvDxDx[2]; // parameters niter = 8000; Nx[0] = 700; Nx[1] = 700; alpha = 0.4; totaltime = 0.005; // initializations computation Dt = totaltime/((niter-1)*1.0); Lx[0] = 1.0; Lx[1] = 1.0; Dx[0] = Lx[0]/((Nx[0]-1)*1.0); Dx[1] = Lx[1]/((Nx[1]-1)*1.0); InvDxDx[0] = 1.0/(Dx[0]*Dx[0]); InvDxDx[1] = 1.0/(Dx[1]*Dx[1]); DxDx[0] = Dx[0]*Dx[0]; DxDx[1] = Dx[1]*Dx[1]; Stab = alpha*Dt*(InvDxDx[0]) + alpha*Dt*(InvDxDx[1]); DtAlpha = Dt*alpha; // verify stability condition printf("Stability factor (need < 0.5): %lf\n", Stab); if(Stab > 0.5) exit(0); // dynamic allocations double **U0 = (double**)malloc((Nx[0]+2) * sizeof(double*)); for(i = 0; i < Nx[0]+2; ++i) U0[i] = (double*)malloc((Nx[1]+2) * sizeof(double)); double **U1 = (double**)malloc((Nx[0]+2) * sizeof(double*)); for(i = 0; i < Nx[0]+2; ++i) U1[i] = (double*)malloc((Nx[1]+2) * sizeof(double)); // init grid for(i = 0; i < Nx[0]+2; ++i) for(j = 0; j < Nx[1]+2; ++j) { U0[i][j] = 1.0; U1[i][j] = 1.0; if(i >= 100 && i <= 150 && j>=200 && j<=250) { U0[i][j] = -10.0; U1[i][j] = -10.0; } if(i >= 300 && i <= 350 && j>=400 && j<=450) { U0[i][j] = 12.0; U1[i][j] = 12.0; } } rank = 0; char fileName[2048]; sprintf(fileName, "IN.%d.dat", rank); // print inpout FILE *file = NULL; file = fopen(fileName, "w"); /* for(i = 1; i < Nx[0]+1; i += 10) for(j = 1; j < Nx[1]+1; j += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i][j]); */ for(j = 1; j < Nx[1]+1; j += 10) for(i = 1; i < Nx[0]+1; i += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i][j]); fclose(file); printf("Calculating, please wait...\n"); #pragma omp parallel default(shared) private(t,i,j) for(t = 0; t < niter; ++t) { #pragma omp for schedule(runtime) for(i = 1; i < Nx[0]+1; ++i) for(j = 1; j < Nx[1]+1; ++j) U1[i][j] = U0[i][j] + DtAlpha * ((U0[i+1][j ] -2.0*U0[i][j] + U0[i-1][j ])*InvDxDx[0] + (U0[i ][j+1] -2.0*U0[i][j] + U0[i ][j-1])*InvDxDx[1]); #pragma omp for schedule(runtime) for(i = 1; i < Nx[0]+1; ++i) for(j = 1; j < Nx[1]+1; ++j) U0[i][j] = U1[i][j] + DtAlpha * ((U1[i+1][j ] -2.0*U1[i][j] + U1[i-1][j ])*InvDxDx[0] + (U1[i ][j+1] -2.0*U1[i][j] + U1[i ][j-1])*InvDxDx[1]); } // print output sprintf(fileName, "OUT.%d.dat", rank); file = fopen(fileName, "w"); /* for(i = 1; i < Nx[0]+1; i += 10) for(j = 1; j < Nx[1]+1; j += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i][j]); */ for(j = 1; j < Nx[1]+1; j += 10) for(i = 1; i < Nx[0]+1; i += 10) fprintf(file, "%d\t%d\t%lf\n", i, j, U0[i][j]); fclose(file); // free buffers for(i = 0; i < Nx[0]+2; ++i) free(U0[i]); free(U0); for(i = 0; i < Nx[0]+2; ++i) free(U1[i]); free(U1); return 0; }