Commit b545fb9b authored by Taddeüs Kroes's avatar Taddeüs Kroes

ModSim ass4 taddeus: Started work on vibstring MPI integration, source code cleanup.

parent d2902159
CC=mpicc CC=mpicc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -lm CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0
LDFLAGS=-lm
all: test ring all: test ring
test: ring_test.o test: ring_test.o
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex} \setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\ \title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\
Opdracht 4: Parallel programming - Ringcommunicatie} Opdracht 4: Parallel programming \\
Deel 1: Ringcommunicatie}
\author{Tadde\"us Kroes (6054129)} \author{Tadde\"us Kroes (6054129)}
\begin{document} \begin{document}
......
CC=gcc CC=mpicc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -D_GNU_SOURCE CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -D_GNU_SOURCE
LDFLAGS=-lm LDFLAGS=-lm
all: seq all: seq par
seq: seq.o seq: seq.o
par: par.o
clean: clean:
rm -vf *.o vibstring rm -vf *.o seq par
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <mpi.h>
double **y = NULL, dx;
int steps, time, start, rank, tasks;
static inline int first_node() {
return !rank;
}
static inline int last_node() {
return rank == tasks - 1;
}
/*
* Connect the string at both ends by sending the calculated border values and
* receiving the outer borders calculated by the adjacent nodes
*/
void connect(int state) {
double send[2], recv[2];
int source = (rank - 1 + tasks) % tasks, target = (rank + 1) % tasks;
MPI_Status status;
send[0] = y[state][1];
send[1] = y[state][steps];
MPI_Sendrecv(send, 2, MPI_DOUBLE, target, MPI_ANY_TAG, recv, 2, MPI_DOUBLE,
source, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
y[state][0] = recv[0];
y[state][steps + 1] = recv[1];
}
static inline void init_borders() {
// The string is attached at both ends
if( first_node() )
y[2][1] = y[1][1] = y[0][1];
else if( last_node() )
y[2][steps] = y[1][steps] = y[0][steps];
connect(0);
}
/*
* Fill the assigned string section with a sinus shape
*/
void init_sinus(double l, double n) {
for( int i = 0; i < steps; i++ )
y[0][i + 1] = sin(n * M_PI * (i + start) * dx / l);
init_borders();
}
/*
* Fill the assigned string section with a plucked shape
*/
void init_plucked(double l, double xp) {
double x;
for( int i = 0; i < steps; i++ ) {
x = (i + start) * dx;
y[0][i + 1] = x < xp ? x / xp : (l - x) / (l - xp);
}
init_borders();
}
#define VERBOSE
#ifdef VERBOSE
#define PRINT_FORMAT "%e"
void print(int index) {
for( int i = 0; i < steps; i++ ) {
if( i )
printf(" ");
printf(PRINT_FORMAT, y[index][i]);
}
puts("");
}
#endif
/*
*
*/
void calculate_steps(int time, double tau) {
double x;
int i, t, prev = 0, current = 1, next = 2;
// Calculate the position over the entire string at time dt using the
// position at t = 0 and the information that y(x, -dt) == y(x, dt)
for( i = 1; i < steps - 1; i++ ) {
x = i * dx;
y[1][i] = y[0][i] + .5 * tau * tau * (y[0][i-1] - 2 * y[0][i]
+ y[0][i+1]);
}
#ifdef VERBOSE
// Print x values (which are the same for every y-series)
for( i = 0; i < steps; i++ ) {
if( i )
printf(" ");
printf(PRINT_FORMAT, i * dx);
}
puts("");
// Print init states
print(prev);
print(current);
#endif
// Iterate over the length of the string for each time interval step
for( t = 2; t < time; t++ ) {
for( i = 1; i < steps - 1; i++ ) {
y[next][i] = 2 * y[current][i] - y[prev][i] + tau * tau
* (y[current][i-1] - 2 * y[current][i] + y[current][i+1]);
}
#ifdef VERBOSE
print(next);
#endif
prev = current;
current = next;
next = (next + 1) % 3;
}
}
int main(int argc, char **argv) {
int error, time, i, total_steps;
void (*init_method)(double, double);
double l, tau, constant;
// Initialize and setup MPI
if( (error = MPI_Init(&argc, &argv)) != MPI_SUCCESS ) {
printf("MPI_init failed (error %d)\n", error);
MPI_Abort(MPI_COMM_WORLD, error);
return EXIT_FAILURE;
}
MPI_Comm_size(MPI_COMM_WORLD, &tasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Parse arguments
if( argc < 7 ) {
printf("Usage: %s INIT_METHOD CALCULATION_STEPS LENGTH DX TAU N|XP\n",
argv[0]);
return EXIT_FAILURE;
}
if( !strcmp(argv[1], "sinus") ) {
init_method = init_sinus;
} else if( !strcmp(argv[1], "plucked") ) {
init_method = init_plucked;
} else {
printf("Unknown initialization method '%s'.\n", argv[1]);
return EXIT_FAILURE;
}
time = atoi(argv[2]);
l = atof(argv[3]);
dx = atof(argv[4]);
tau = atof(argv[5]);
constant = atof(argv[6]);
// Calculate the indices of the string to calculate
total_steps = (int)ceil(l / dx);
steps = total_steps / tasks;
start = steps * rank;
// Fill in the gap caused by rounding errors in the last node. Also,
// allocate the left and right outer border values that are calculated by
// other nodes
if( rank == tasks - 1 )
steps += total_steps - steps * (tasks - 1);
// Allocate a 3xN two-dimensional area for this part of the string that
// functions as a cyclic buffer for three states of the string (previous,
// current, next)
y = (double **)malloc(3 * sizeof(double *));
for( i = 0; i < 3; i++ )
y[i] = (double *)malloc((steps + 2) * sizeof(double));
// Initialize the string values (sinus/plucked)
(*init_method)(l, constant);
// Calculate the specified number of steps
calculate_steps(time, tau);
// Free allocated memory
for( i = 0; i < 3; i++ )
free(y[i]);
free(y);
// Finalize mPI
MPI_Finalize();
return EXIT_SUCCESS;
}
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex} \setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\ \title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\
Opdracht 4: Parallel programming - Trillende snaar} Opdracht 4: Parallel programming \\
Deel 2: Trillende snaar}
\author{Tadde\"us Kroes (6054129)} \author{Tadde\"us Kroes (6054129)}
\begin{document} \begin{document}
......
...@@ -4,18 +4,18 @@ ...@@ -4,18 +4,18 @@
#include <math.h> #include <math.h>
double **y = NULL, dx; double **y = NULL, dx;
int x_steps, calc_steps, print_resolution; int steps, time;
/* /*
* *
*/ */
void init_sinus(double l, double n) { void init_sinus(double l, double n) {
for( int i = 0; i < x_steps; i++ ) for( int i = 0; i < steps; i++ )
y[0][i] = sin(n * M_PI * i * dx / l); y[0][i] = sin(n * M_PI * i * dx / l);
// The string is attached at both ends // The string is attached at both ends
y[2][0] = y[1][0] = y[0][0]; y[2][0] = y[1][0] = y[0][0];
y[2][x_steps - 1] = y[1][x_steps - 1] = y[0][x_steps - 1]; y[2][steps - 1] = y[1][steps - 1] = y[0][steps - 1];
} }
/* /*
...@@ -24,14 +24,14 @@ void init_sinus(double l, double n) { ...@@ -24,14 +24,14 @@ void init_sinus(double l, double n) {
void init_plucked(double l, double xp) { void init_plucked(double l, double xp) {
double x; double x;
for( int i = 0; i < x_steps; i++ ) { for( int i = 0; i < steps; i++ ) {
x = i * dx; x = i * dx;
y[0][i] = x < xp ? x / xp : (l - x) / (l - xp); y[0][i] = x < xp ? x / xp : (l - x) / (l - xp);
} }
// The string is attached at both ends // The string is attached at both ends
y[2][0] = y[1][0] = y[0][0]; y[2][0] = y[1][0] = y[0][0];
y[2][x_steps - 1] = y[1][x_steps - 1] = y[0][x_steps - 1]; y[2][steps - 1] = y[1][steps - 1] = y[0][steps - 1];
} }
#define VERBOSE #define VERBOSE
...@@ -40,7 +40,7 @@ void init_plucked(double l, double xp) { ...@@ -40,7 +40,7 @@ void init_plucked(double l, double xp) {
#define PRINT_FORMAT "%e" #define PRINT_FORMAT "%e"
void print(int index) { void print(int index) {
for( int i = 0; i < x_steps; i++ ) { for( int i = 0; i < steps; i++ ) {
if( i ) if( i )
printf(" "); printf(" ");
...@@ -54,13 +54,13 @@ void print(int index) { ...@@ -54,13 +54,13 @@ void print(int index) {
/* /*
* *
*/ */
void calculate_steps(int calc_steps, double tau) { void calculate_steps(int time, double tau) {
double x; double x;
int i, t, prev = 0, current = 1, next = 2; int i, t, prev = 0, current = 1, next = 2;
// Calculate the position over the entire string at time dt using the // Calculate the position over the entire string at time dt using the
// position at t = 0 and the information that y(x, -dt) == y(x, dt) // position at t = 0 and the information that y(x, -dt) == y(x, dt)
for( i = 1; i < x_steps - 1; i++ ) { for( i = 1; i < steps - 1; i++ ) {
x = i * dx; x = i * dx;
y[1][i] = y[0][i] + .5 * tau * tau * (y[0][i-1] - 2 * y[0][i] y[1][i] = y[0][i] + .5 * tau * tau * (y[0][i-1] - 2 * y[0][i]
+ y[0][i+1]); + y[0][i+1]);
...@@ -68,7 +68,7 @@ void calculate_steps(int calc_steps, double tau) { ...@@ -68,7 +68,7 @@ void calculate_steps(int calc_steps, double tau) {
#ifdef VERBOSE #ifdef VERBOSE
// Print x values (which are the same for every y-series) // Print x values (which are the same for every y-series)
for( i = 0; i < x_steps; i++ ) { for( i = 0; i < steps; i++ ) {
if( i ) if( i )
printf(" "); printf(" ");
...@@ -83,8 +83,8 @@ void calculate_steps(int calc_steps, double tau) { ...@@ -83,8 +83,8 @@ void calculate_steps(int calc_steps, double tau) {
#endif #endif
// Iterate over the length of the string for each time interval step // Iterate over the length of the string for each time interval step
for( t = 2; t < calc_steps; t++ ) { for( t = 2; t < time; t++ ) {
for( i = 1; i < x_steps - 1; i++ ) { for( i = 1; i < steps - 1; i++ ) {
y[next][i] = 2 * y[current][i] - y[prev][i] + tau * tau y[next][i] = 2 * y[current][i] - y[prev][i] + tau * tau
* (y[current][i-1] - 2 * y[current][i] + y[current][i+1]); * (y[current][i-1] - 2 * y[current][i] + y[current][i+1]);
} }
...@@ -100,11 +100,11 @@ void calculate_steps(int calc_steps, double tau) { ...@@ -100,11 +100,11 @@ void calculate_steps(int calc_steps, double tau) {
} }
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
int calc_steps, i; int time, i;
void (*init_method)(double, double); void (*init_method)(double, double);
double l, tau, constant; double l, tau, constant;
// Parse argument // Parse arguments
if( argc < 7 ) { if( argc < 7 ) {
printf("Usage: %s INIT_METHOD CALCULATION_STEPS LENGTH DX TAU N|XP\n", printf("Usage: %s INIT_METHOD CALCULATION_STEPS LENGTH DX TAU N|XP\n",
argv[0]); argv[0]);
...@@ -120,7 +120,7 @@ int main(int argc, const char **argv) { ...@@ -120,7 +120,7 @@ int main(int argc, const char **argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
calc_steps = atoi(argv[2]); time = atoi(argv[2]);
l = atof(argv[3]); l = atof(argv[3]);
dx = atof(argv[4]); dx = atof(argv[4]);
tau = atof(argv[5]); tau = atof(argv[5]);
...@@ -128,7 +128,7 @@ int main(int argc, const char **argv) { ...@@ -128,7 +128,7 @@ int main(int argc, const char **argv) {
// Allocate a 3xN two-dimensional area that functions as a cyclic buffer // Allocate a 3xN two-dimensional area that functions as a cyclic buffer
// for three states of the string (previous, current, next) // for three states of the string (previous, current, next)
x_steps = (int)ceil(l / dx); steps = (int)ceil(l / dx);
if( (y = (double **)malloc(3 * sizeof(double *))) == NULL ) { if( (y = (double **)malloc(3 * sizeof(double *))) == NULL ) {
puts("Error: could not allocate memory."); puts("Error: could not allocate memory.");
...@@ -136,13 +136,13 @@ int main(int argc, const char **argv) { ...@@ -136,13 +136,13 @@ int main(int argc, const char **argv) {
} }
for( i = 0; i < 3; i++ ) for( i = 0; i < 3; i++ )
y[i] = (double *)malloc(x_steps * sizeof(double)); y[i] = (double *)malloc(steps * sizeof(double));
// Initialize the string values (sinus/plucked) // Initialize the string values (sinus/plucked)
(*init_method)(l, constant); (*init_method)(l, constant);
// Calculate the specified number of steps // Calculate the specified number of steps
calculate_steps(calc_steps, tau); calculate_steps(time, tau);
// Free allocated memory // Free allocated memory
for( i = 0; i < 3; i++ ) for( i = 0; i < 3; i++ )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment