/* Explicitly solves the 2D heat conduction equation: dT/dt = alpha * div^2 T Note that this requires the HDF5 to compile ('module load hdf5' on the MSU HPCC, or http://www.hdfgroup.org/HDF5/). Compilation: g++ -L/usr/local/lib -lhdf5_hl -lhdf5 -h/usr/local/include conduction_2d.C -o conduction Run: ./conduction There are several user-modifiable parameters, defined in main(). Written by: Brian O'Shea, oshea@msu.edu */ #include "hdf5.h" #include "hdf5_hl.h" #include int create_ICs(double **Temperature, int xgrid, int ygrid, double xstart, double xend, double ystart, double yend, int simulation_type); double calculate_dt(double dx, double dy, double alpha); int calculate_Tdot(double **Temperature, double **Tdot, double alpha, int xgrid, int ygrid, double dx, double dy, int simulation_type); int update_Temp(double **Temperature, double **Tdot, double dt, int padded_x, int padded_y); int write_data_output(double **Temperature, int grid_x, int grid_y, int this_output); int main(){ /* --------- User needs to set all of this stuff --------- */ int grid_x=200,grid_y=200; // grid x,y cell dimensions double stop_time = 5.0; // stop time: around 5 is good for gaussian pulse, 2 for sine wave. int simulation_type = 1; // 1 = gaussian pulse, 2 = infinite sine wave double dt_data_output = 0.1; // output cadence (make it small for lots of data outputs) /* --------- End of user-set parameters --------- */ double x_min=-10.0, x_max=10.0; // grid x min, max values double y_min=-10.0, y_max=10.0; // grid y min, max values double alpha = 1.0; // conductivity double **Temperature=NULL; double **Tdot=NULL; double dx, dy, dt; int i,j,padded_x,padded_y; // Grid is padded by 2 cells in each direction for boundary conditions padded_x = grid_x+2; padded_y = grid_y+2; /* The two arrays that we need: temperature and dT/dt. These are padded by 2 compared to what the user has specified so that we can take into account the boundary conditions. So, we have to dynamically allocate these arrays and then set them to some default values. */ Temperature = new double*[padded_x]; Tdot = new double*[padded_x]; for(i=0; i next_output_time) dt = next_output_time - this_time; // calculate dT/dt calculate_Tdot(Temperature, Tdot, alpha, grid_x, grid_y, dx, dy, simulation_type); // update temperature update_Temp(Temperature, Tdot, dt, padded_x, padded_y); // increment time, cycle this_time += dt; this_cycle++; // write out data if it's time. if( this_time >= next_output_time){ write_data_output(Temperature, grid_x, grid_y, ++this_output); next_output_time += dt_data_output; } printf("Cycle, dt, time, next output: %d -- %lf, %lf, %lf\n", this_cycle, dt, this_time, next_output_time); } // write data out one last time. if( this_time >= next_output_time) write_data_output(Temperature, grid_x, grid_y, ++this_output); return 0; } /* Initializes initial temperature field as either a gaussian pulse (simulation_type = 1) or an infinite set of sine waves (simulation_type = 2). Inputs: **Temperature: Temperature field xgrid, ygrid: cells along x,y edges (padded by 2 in each dimension) xstart, xend: position of non-padded x start, end (spatial, not cells) ystart, yend: as x simulation_type: determines whether it's a gaussian pulse (1) or sine waves (2). */ int create_ICs(double **Temperature, int xgrid, int ygrid, double xstart, double xend, double ystart, double yend, int simulation_type){ int i,j; // keep track of background temp double background_temperature = Temperature[0][0]; double dx, dy, my_x, my_y, x_center, y_center; dx = (xend-xstart)/double(xgrid); dy = (yend-ystart)/double(ygrid); x_center = (xend+xstart)/2.0; y_center = (yend+ystart)/2.0; //printf("dx,dy: %e %e\n",dx, dy); //printf("x,y center: %e %e\n", x_center, y_center); if(simulation_type==1){ // set up gaussian pulse // make pulse fairly narrow double fwhm = fabs(xend-xstart)/8.0; // loop through cells calculating position, then setting temperature to pulse for(i=1; i