#define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include #include #include "argument_utils.h" // Convert 'struct timeval' into seconds in double prec. floating point #define WALLTIME(t) ((double)(t).tv_sec + 1e-6 * (double)(t).tv_usec) // Option to change numerical precision typedef int64_t int_t; typedef double real_t; // Simulation parameters: size, step count, and how often to save the state int_t N = 256, M = 256, max_iteration = 4000, snapshot_freq = 20; // Wave equation parameters, time step is derived from the space step const real_t c = 1.0, dx = 1.0, dy = 1.0; real_t dt; // Buffers for three time steps, indexed with 2 ghost points for the boundary real_t *buffers[3] = { NULL, NULL, NULL }; #define U_prv(i,j) buffers[0][((i)+1)*(N+2)+(j)+1] #define U(i,j) buffers[1][((i)+1)*(N+2)+(j)+1] #define U_nxt(i,j) buffers[2][((i)+1)*(N+2)+(j)+1] // Rotate the time step buffers. void move_buffer_window ( void ) { real_t *temp = buffers[0]; buffers[0] = buffers[1]; buffers[1] = buffers[2]; buffers[2] = temp; } // Save the present time step in a numbered file under 'data/' void domain_save ( int_t step ) { char filename[256]; // Ensure output directory exists (ignore error if it already exists) if (mkdir("data", 0755) != 0 && errno != EEXIST) { perror("mkdir data"); exit(EXIT_FAILURE); } snprintf(filename, sizeof(filename), "data/%05" PRId64 ".dat", step); FILE *out = fopen(filename, "wb"); if (out == NULL) { perror("fopen output file"); fprintf(stderr, "Failed to open '%s' for writing.\n", filename); exit(EXIT_FAILURE); } for ( int_t i = 0; i < M; ++i ) { size_t written = fwrite ( &U(i,0), sizeof(real_t), (size_t)N, out ); if ( written != (size_t)N ) { perror("fwrite"); fclose(out); exit(EXIT_FAILURE); } } if ( fclose(out) != 0 ) { perror("fclose"); exit(EXIT_FAILURE); } } // Neumann (reflective) boundary condition void boundary_condition ( void ) { // Vertical ghost layers (bottom and top) for (int_t i=0; iM; N = options->N; max_iteration = options->max_iteration; snapshot_freq = options->snapshot_frequency; if (M < 2 || N < 2) { fprintf(stderr, "M and N must be >= 2\n"); exit(EXIT_FAILURE); } // Set up the initial state of the domain domain_initialize(); struct timeval t_start, t_end; gettimeofday ( &t_start, NULL ); simulate(); gettimeofday ( &t_end, NULL ); printf ( "Total elapsed time: %lf seconds\n", WALLTIME(t_end) - WALLTIME(t_start) ); // Clean up and shut down domain_finalize(); exit ( EXIT_SUCCESS ); }