diff --git a/config/config.c b/config/config.c new file mode 100644 index 0000000..7d1c1b7 --- /dev/null +++ b/config/config.c @@ -0,0 +1,58 @@ +#include +#include + +typedef struct configuration { + int n; + double north; + double east; + double south; + double west; + double init_value; + double threshold; +} configuration; + +int load_config(configuration *config) { + char property[100]; + char *value; + FILE *fp; + + fp = fopen("jacobi.conf", "r"); + if (fp == NULL) { + perror("Error opening file jacobi.conf"); + return 1; + } + while (fgets(property, 100, fp) != NULL) { + if (property[0] == '\n' || property[0] == '#') { + /* Skip empty lines and comments */ + continue; + } + value = strchr(property, ' '); + if (value == NULL) { + fclose(fp); + perror("Error reading file jacobi.conf"); + return 1; + } + value[0] = '\0'; + value += sizeof(char); + value[strlen(value) - 1] = '\0'; + if (strcmp(property, "N") == 0) { + sscanf(value, "%d", &(config->n)); + } else if (strcmp(property, "NORTH") == 0) { + sscanf(value, "%lf", &(config->north)); + } else if (strcmp(property, "EAST") == 0) { + sscanf(value, "%lf", &(config->east)); + } else if (strcmp(property, "SOUTH") == 0) { + sscanf(value, "%lf", &(config->south)); + } else if (strcmp(property, "WEST") == 0) { + sscanf(value, "%lf", &(config->west)); + } else if (strcmp(property, "INIT_VALUE") == 0) { + sscanf(value, "%lf", &(config->init_value)); + } else if (strcmp(property, "THRESHOLD") == 0) { + sscanf(value, "%lf", &(config->threshold)); + } else { + printf("Unknown property %s\n", property); + } + } + fclose(fp); + return 0; +} diff --git a/config/config.h b/config/config.h new file mode 100644 index 0000000..32635dd --- /dev/null +++ b/config/config.h @@ -0,0 +1,11 @@ +typedef struct configuration { + int n; + double north; + double east; + double south; + double west; + double init_value; + double threshold; +} configuration; + +int load_config(configuration *config); diff --git a/sequential/Makefile b/sequential/Makefile new file mode 100644 index 0000000..aacf23e --- /dev/null +++ b/sequential/Makefile @@ -0,0 +1,12 @@ +CC=gcc +CFLAGS=-Wall -lm -std=c99 + +all: config jacobi_sequential.c + ${CC} ${CFLAGS} config.o jacobi_sequential.c -o jacobi.out + +config: ../config/config.c + ${CC} -c ${CFLAGS} ../config/config.c + +.PHONY: clean +clean: + rm -f *.out *.o diff --git a/sequential/jacobi.conf b/sequential/jacobi.conf new file mode 100644 index 0000000..95ce868 --- /dev/null +++ b/sequential/jacobi.conf @@ -0,0 +1,16 @@ +# Configuration file for the Jacobi project. + +# The size of the matrix (borders excluded). +N 10 + +# The value at each border. +NORTH 0.0 +EAST 0.0 +SOUTH 300.0 +WEST 0.0 + +# The initial value to assign at each internal cell. +INIT_VALUE 0.0 + +# The threshold that determines the convergence. +THRESHOLD 1.0 diff --git a/sequential/jacobi_sequential.c b/sequential/jacobi_sequential.c new file mode 100644 index 0000000..6061dce --- /dev/null +++ b/sequential/jacobi_sequential.c @@ -0,0 +1,68 @@ +/* + * Sequential version. + * No paralleliization used. + */ + +#include +#include +#include "../config/config.h" + +typedef struct borders { + double north; + double east; + double south; + double west; +} borders; + +void compute_jacobi(int n, double init_value, double threshold, borders b); + +int main(int argc, char* argv[]) { + int config_loaded; + configuration config; + borders b; + + config_loaded = load_config(&config); + if (config_loaded != 0) { + return 1; + } + + b.north = config.north; + b.east = config.east; + b.south = config.south; + b.west = config.west; + + compute_jacobi(config.n, config.init_value, config.threshold, b); + + return 0; +} + +void compute_jacobi(int n, double init_value, double threshold, borders b) { + double x[n + 2][n + 2]; + double max_diff, new_x; + int i, j; + + /* Initialize boundary regions */ + for (i = 1; i <= n; i++) { + x[0][i] = b.north; + x[n + 1][i] = b.south; + x[i][0] = b.west; + x[i][n + 1] = b.east; + } + /* Initialize the rest of the matrix */ + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + x[i][j] = init_value; + } + } + /* Iterative refinement of x until values converge */ + do { + max_diff = 0; + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + new_x = 0.25 * (x[i - 1][j] + x[i][j + 1] + x[i + 1][j] + x[i][j - 1]); + max_diff = (double) fmax(max_diff, fabs(new_x - x[i][j])); + x[i][j] = new_x; + } + } + } while (max_diff > threshold); +}