/* * heat diffusion example, as discussed in textbook. * * command line arguments are number of points, maximum number of * iterations, convergence threshold, and optional flag "values" * to print final values. * timing information goes to stdout, final values to stderr. * * sequential version, using OpenMP timing function. */ #include #include #include #include #include #define LEFTVAL 1.0 #define RIGHTVAL 10.0 void parse_arguments(int argc, char *argv[], int *nx, int *maxsteps, double *threshold, int *print_flag); void initialize(double uk[], double ukp1[], int nx); void print_values(double uk[], int nx); int main(int argc, char *argv[]) { int nx; int maxsteps; double threshold; int print_flag; double *uk; double *ukp1; double *temp; double dx, dt; double start_time, end_time; double maxdiff, diff; int step, i; parse_arguments(argc, argv, &nx, &maxsteps, &threshold, &print_flag); start_time = omp_get_wtime(); uk = malloc(sizeof(double) * nx); ukp1 = malloc(sizeof(double) * nx); if (!uk || !ukp1) { fprintf(stderr, "Unable to allocate memory\n"); return EXIT_FAILURE; } dx = 1.0/nx; dt = 0.5*dx*dx; maxdiff = threshold; initialize(uk, ukp1, nx); for (step = 0; (step < maxsteps) && (maxdiff >= threshold); ++step) { /* compute new values */ for (i = 1; i < nx-1; ++i) { ukp1[i]=uk[i]+ (dt/(dx*dx))*(uk[i+1]-2*uk[i]+uk[i-1]); } /* check for convergence */ maxdiff = 0.0; for (i = 1; i < nx-1; ++i) { diff = fabs(uk[i] - ukp1[i]); if (diff > maxdiff) maxdiff = diff; } /* "copy" ukp1 to uk by swapping pointers */ temp = ukp1; ukp1 = uk; uk = temp; } end_time = omp_get_wtime(); if (print_flag) { print_values(uk, nx); } printf("sequential program:\n"); printf("nx = %d, maxsteps = %d, threshold = %g\n", nx, maxsteps, threshold); if (maxdiff < threshold) { printf("converged in %d iterations\n", step); } else { printf("failed to converge in %d iterations, maxdiff = %g\n", step, maxdiff); } printf("execution time = %g\n", end_time - start_time); /* clean up and end */ return EXIT_SUCCESS; } void parse_arguments(int argc, char *argv[], int *nx, int *maxsteps, double *threshold, int *print_flag) { char *usage_msg = "usage is %s points max_iterations convergence_threshold [\"values\"]\n"; if (argc < 4) { fprintf(stderr, usage_msg, argv[0]); exit(EXIT_FAILURE); } *nx = 0; *maxsteps = 0; *threshold = 0.0; *nx = atoi(argv[1]); *maxsteps = atoi(argv[2]); *threshold = atof(argv[3]); *print_flag = 0; if ((*nx <= 0) || (*maxsteps <= 0) || (*threshold <= 0)) { fprintf(stderr, usage_msg, argv[0]); exit(EXIT_FAILURE); } if ((argc > 4) && (strcmp(argv[4], "values") == 0)) { *print_flag = 1; } } void initialize(double uk[], double ukp1[], int nx) { int i; uk[0] = LEFTVAL; uk[nx-1] = RIGHTVAL; for (i = 1; i < nx-1; ++i) uk[i] = 0.0; for (i = 0; i < nx; ++i) ukp1[i] = uk[i]; } void print_values(double uk[], int nx) { int i; for (i = 0; i < nx; ++i) { fprintf(stderr, "uk[%010d] = %14.10f\n", i, uk[i]); } }