/* PROGRAM: Simple Heat * AUTHOR: Aaron Weeden (Shodor Education Foundation) * DATE: November 2013 * * See the README for instructions on compiling and running this program. */ #include #include #include #include #include #include #include int main(int argc, char **argv) { /* Parameters (what the model is given) */ int timeStepCount = 3; int rowCount = 3; int columnCount = 3; float initialTemperature = 100.0; /* Data Structure (what the model has) */ typedef struct { float temperatureNow; float temperatureNext; int neighborCount; } point_t; int pointCount; point_t *points; int pointIndex; int timeStepIndex; int option; /* get user input */ while ((option = getopt(argc, argv, "t:r:c:i:")) != -1) { switch(option) { case 't': errno = 0; timeStepCount = strtol(optarg, NULL, 10); if (errno) { fprintf(stderr, "%s: timeStepCount conversion failed: %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } break; case 'r': errno = 0; rowCount = strtol(optarg, NULL, 10); if (errno) { fprintf(stderr, "%s: rowCount conversion failed: %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } break; case 'c': errno = 0; columnCount = strtol(optarg, NULL, 10); if (errno) { fprintf(stderr, "%s: columnCount conversion failed: %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } break; case 'i': errno = 0; initialTemperature = strtof(optarg, NULL); if (errno) { fprintf(stderr, "%s: initialTemperature conversion failed: %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } break; default: fprintf(stderr, "Usage: %s -t -r -c -i \n", argv[0]); exit(EXIT_FAILURE); } } /* valiate input */ if (timeStepCount <= 0) { fprintf(stderr, "%s: cannot simulate with < 1 time step\n", argv[0]); errno = EINVAL; } if (rowCount <= 0) { fprintf(stderr, "%s: cannot simulate with < 1 row\n", argv[0]); errno = EINVAL; } if (columnCount <= 0) { fprintf(stderr, "%s: cannot simulate with < 1 column\n", argv[0]); errno = EINVAL; } if (initialTemperature < 0) { fprintf(stderr, "%s: cannot simulate with < 0 temperature\n", argv[0]); errno = EINVAL; } if (rowCount > 0 && columnCount > 0 && rowCount * columnCount < 0) { fprintf(stderr, "%s: area of object is too large\n", argv[0]); errno = EINVAL; } if (errno == EINVAL) { exit(EXIT_FAILURE); } /* Algorithm (how the model computes) */ /* 1: calculate number of points */ pointCount = rowCount * columnCount; /* allocate memory */ points = (point_t*)malloc(pointCount * sizeof(point_t)); for ( /* 2: start at point 0 */ pointIndex = 0; /* 3: is point outside the object? */ pointIndex < pointCount; /* 10: move on to the next point */ pointIndex++ ) { /* 4: set initial temperature */ if (pointIndex % columnCount == 0) { points[pointIndex].temperatureNow = initialTemperature; } else { points[pointIndex].temperatureNow = 0.0; } /* 5: assume 4 neighbors */ points[pointIndex].neighborCount = 4; /* 6: top row has 1 less neighbor */ if (pointIndex < columnCount) { points[pointIndex].neighborCount--; } /* 7: bottom row has 1 less neighbor */ if (pointIndex >= (rowCount-1) * columnCount) { points[pointIndex].neighborCount--; } /* 8: left column has 1 less neighbor */ if (pointIndex % columnCount == 0) { points[pointIndex].neighborCount--; } /* 9: right column has 1 less neighbor */ if (pointIndex % columnCount == columnCount-1) { points[pointIndex].neighborCount--; } } for ( /* 11: start at time step 0 */ timeStepIndex = 0; /* 12: are we finished? */ timeStepIndex < timeStepCount; /* 32: move on to the next time step */ timeStepIndex++ ) { for ( /* 13: start at point 0 */ pointIndex = 0; /* 14: is point outside the object? */ pointIndex < pointCount; /* 17: move on to the next point */ pointIndex++ ) { /* 15: print temperature */ printf("%.2f ", points[pointIndex].temperatureNow); /* 16: print newline between rows */ if (pointIndex % columnCount == columnCount-1) { printf("\n"); } } /* 18: print newline between time steps */ printf("\n"); for ( /* 19: start at point 0 */ pointIndex = 0; /* 20: is point outside the object? */ pointIndex < pointCount; /* 27: move on to the next point */ pointIndex++ ) { /* 21: initialize next temperature */ points[pointIndex].temperatureNext = 0.0; /* 22: add top neighbor */ if (pointIndex >= columnCount) { points[pointIndex].temperatureNext += points[pointIndex-columnCount].temperatureNow; } /* 23: add bottom neighbor */ if (pointIndex < (rowCount-1) * columnCount) { points[pointIndex].temperatureNext += points[pointIndex+columnCount].temperatureNow; } /* 24: add left neighbor */ if (pointIndex % columnCount > 0) { points[pointIndex].temperatureNext += points[pointIndex-1].temperatureNow; } /* 25: add right neighbor */ if (pointIndex % columnCount < columnCount-1) { points[pointIndex].temperatureNext += points[pointIndex+1].temperatureNow; } /* 26: divide by number of neighbors */ points[pointIndex].temperatureNext = points[pointIndex].temperatureNext / points[pointIndex].neighborCount; } for ( /* 28: start at point 0 */ pointIndex = 0; /* 29: is point outside the object? */ pointIndex < pointCount; /* 31: move on to the next point */ pointIndex++ ) { /* 30: advance temperature */ points[pointIndex].temperatureNow = points[pointIndex].temperatureNext; } } /* deallocate memory */ free(points); return 0; }