C source /*
* It evolves the equation:
* u,t + u,x + u,y = 0
* Using a Lax scheme.
* The initial data is a cruddy gaussian.
* Boundaries are flat: copying the value of the neighbour
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NX 100
#define NY 100
#define LX 2.0
#define LY 2.0
#define sigma 0.1
#define tmax 100
/*
* conversions from discrete to real coordinates
*/
float ix2x(int ix){
return ((ix-1) - (NX-1) / 2.0)*LX/(NX-1);
}
float iy2y(int iy){
return ((iy-1) - (NY-1) / 2.0)*LY/(NY-1);
}
/* Function for evaluating the results that calculates the sum of the array values */
float summa(int nx, int ny, float* val){
float summma=0.0;
int ix,iy;
for(iy=1;iy<=ny;++iy)
for(ix=1;ix<=nx;++ix){
summma+=val[((nx+2)*iy)+ix];
}
return(summma);
}
/*
* initialize the system with a gaussian temperature distribution
*/
int init_transport(float *temp){
int ix,iy;
float x,y;
for(iy=1;iy<=NY;++iy)
for(ix=1;ix<=NX;++ix){
x=ix2x(ix);
y=iy2y(iy);
temp[((NX+2)*iy)+ix] = tmax*exp((-((x*x)+(y*y)))/(2.0*(sigma*sigma)));
}
return 0;
}
/*
* save the temperature distribution
* the ascii format is suitable for splot gnuplot function
*/
int save_gnuplot(char *filename, float *temp) {
int ix,iy;
FILE *fp;
fp = fopen(filename, "w");
for(iy=1;iy<=NY;++iy){
for(ix=1;ix<=NX;++ix)
fprintf(fp, "\t%f\t%f\t%g\n", ix2x(ix), iy2y(iy), temp[((NX+2)*iy)+ix]);
fprintf(fp, "\n");
}
fclose(fp);
return 0;
}
int update_boundaries_FLAT(float *temp){
int ix=0, iy=0;
for(iy=0;iy<=NY+1;++iy){
temp[(NX+2)*iy] = temp[((NX+2)*iy)+1];
temp[((NX+2)*iy)+(NX+1)] = temp[((NX+2)*iy)+NX];
}
for(ix=0;ix<=NX+1;++ix){
temp[ix] = temp[(NX+2)+ix];
temp[((NX+2)*(NY+1))+ix] = temp[((NX+2)*NY)+ix];
}
return 0;
}
int evolve(float dtfact, float *temp, float *temp_new){
float dx, dt;
int ix, iy;
float temp0;
dx = 2*LX/NX;
dt = dtfact*dx/sqrt(3.0);
for(iy=1;iy<=NY;++iy)
for(ix=1;ix<=NX;++ix){
temp0 = temp[((NX+2)*iy)+ix];
temp_new[((NX+2)*iy)+ix] = temp0-0.5*dt*(temp[((NX+2)*(iy+1))+ix]
-temp[((NX+2)*(iy-1))+ix]+temp[((NX+2)*iy)+(ix+1)]-temp[((NX+2)*iy)+(ix-1)])/dx;
}
for(iy=0;iy<=NY+1;++iy)
for(ix=0;ix<=NX+1;++ix)
temp[((NX+2)*iy)+ix] = temp_new[((NX+2)*iy)+ix];
return 0;
}
int main(int argc, char* argv[]){
int i=0, nRow=NX+2, nCol=NY+2;
float *temp, *temp_new;
temp = (float *) malloc (nRow*nCol*sizeof(float));
temp_new = (float *) malloc (nRow*nCol*sizeof(float));
init_transport(temp);
update_boundaries_FLAT(temp);
float before=summa(NX, NY, temp);
printf(" sum temp before: %f\n",before);
save_gnuplot("transport.dat", temp);
for(i=1;i<=500;++i) {
evolve(0.1, temp, temp_new);
update_boundaries_FLAT(temp);
}
float after=summa(NX, NY, temp);
printf(" sum temp after: %f\n",after);
save_gnuplot("transport_end.dat", temp);
free(temp);
free(temp_new);
return 0;
}
Fortran source !
! It evolves the equation:
! u,t + u,x + u,y = 0
! Using a Lax scheme.
! The initial data is a cruddy gaussian.
! Boundaries are flat: copying the value of the neighbour
!
module transport
implicit none
save
integer, parameter :: NX=100
integer, parameter :: NY=100
real, parameter :: LX=2.0
real, parameter :: LY=2.0
real temp(0:NX+1 , 0:NY+1)
real temp_new(0:NX+1 , 0:NY+1)
CONTAINS
!conversions from discrete to real coordinates
real function ix2x(ix)
integer ix
ix2x = ((ix-1)-(NX-1)/ 2.0)*LX/(NX-1)
end function ix2x
real function iy2y(iy)
integer iy
iy2y = ((iy-1)-(NY-1)/ 2.0)*LY/(NY-1)
end function iy2y
! initialize the system with a gaussian temperature distribution
subroutine init_transport
integer ix,iy
real x,y
real,parameter :: sigma = 0.1
real,parameter :: tmax = 100
do iy=1,NY
do ix=1,NX
x=ix2x(ix)
y=iy2y(iy)
temp(ix,iy) = tmax*exp(-(x**2+y**2)/(2.0*sigma**2))
enddo
enddo
end subroutine init_transport
! save the temperature distribution
! the ascii format is suitable for splot gnuplot function
subroutine save_gnuplot(filename)
character(len=*) filename
integer ix,iy
open(unit=20,file=filename,form='formatted')
do iy=1,NY
do ix=1,NX
write(20,*) ix2x(ix),iy2y(iy),temp(ix,iy)
enddo
write(20,*)
enddo
close(20)
end subroutine save_gnuplot
subroutine update_boundaries_FLAT
temp(0 , 1:NY) = temp(1 , 1:NY)
temp(NX+1, 1:NY) = temp(NX , 1:NY)
temp(1:NX , 0) = temp(1:NX , 1)
temp(1:NX , NY+1) = temp(1:NX , NY)
end subroutine update_boundaries_FLAT
subroutine evolve(dtfact)
real :: dtfact
real :: dx,dt
integer :: ix,iy
real :: temp0
dx = 2*LX/NX
dt = dtfact*dx/sqrt(3.0)
do iy=1,NY
do ix=1,NX
temp0 = temp(ix,iy)
temp_new(ix,iy) = temp0 - 0.5 * dt * (temp(ix+1,iy)-temp(ix-1,iy)+temp(ix,iy+1)-temp(ix,iy-1)) / dx
enddo
enddo
temp = temp_new
end subroutine evolve
end module transport
program prova
use transport
implicit none
integer i
call init_transport
call update_boundaries_FLAT
write(*,*) 'sum temp before',sum(temp(1:NX,1:NY))
call save_gnuplot('transport.dat')
do i=1,500
call evolve(0.1)
call update_boundaries_FLAT
enddo
call save_gnuplot('transport_end.dat')
write(*,*) 'sum temp after',sum(temp(1:NX,1:NY))
end program prova
Jobscript template (FERMI) #!/bin/bash
# @ job_type=bluegene
# @ bg_size=64
# @ wall_clock_limit = 00:10:00
# @ account_no =
# @ queue
module load bgq-gnu zlib
runjob --np 1 --env-all : ./transport-serial.x
Jobscript template (PLX) #!/bin/bash
#PBS -N transser
#PBS -l select=1:ncpus=1:mpiprocs=1
#PBS -l walltime=0:10:00
#PBS -A
#PBS -q debug
cd $PBS_O_WORKDIR
./transport-serial.x