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
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -lm
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0
LDFLAGS=-lm
all: test ring
test: ring_test.o
......
......@@ -8,7 +8,8 @@
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\
Opdracht 4: Parallel programming - Ringcommunicatie}
Opdracht 4: Parallel programming \\
Deel 1: Ringcommunicatie}
\author{Tadde\"us Kroes (6054129)}
\begin{document}
......
CC=gcc
CC=mpicc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -D_GNU_SOURCE
LDFLAGS=-lm
all: seq
all: seq par
seq: seq.o
par: par.o
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 @@
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\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)}
\begin{document}
......
......@@ -4,18 +4,18 @@
#include <math.h>
double **y = NULL, dx;
int x_steps, calc_steps, print_resolution;
int steps, time;
/*
*
*/
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);
// The string is attached at both ends
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) {
void init_plucked(double l, double xp) {
double x;
for( int i = 0; i < x_steps; i++ ) {
for( int i = 0; i < steps; i++ ) {
x = i * dx;
y[0][i] = x < xp ? x / xp : (l - x) / (l - xp);
}
// The string is attached at both ends
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
......@@ -40,7 +40,7 @@ void init_plucked(double l, double xp) {
#define PRINT_FORMAT "%e"
void print(int index) {
for( int i = 0; i < x_steps; i++ ) {
for( int i = 0; i < steps; i++ ) {
if( i )
printf(" ");
......@@ -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;
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 < x_steps - 1; i++ ) {
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]);
......@@ -68,7 +68,7 @@ void calculate_steps(int calc_steps, double tau) {
#ifdef VERBOSE
// 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 )
printf(" ");
......@@ -83,8 +83,8 @@ void calculate_steps(int calc_steps, double tau) {
#endif
// Iterate over the length of the string for each time interval step
for( t = 2; t < calc_steps; t++ ) {
for( i = 1; i < x_steps - 1; i++ ) {
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]);
}
......@@ -100,11 +100,11 @@ void calculate_steps(int calc_steps, double tau) {
}
int main(int argc, const char **argv) {
int calc_steps, i;
int time, i;
void (*init_method)(double, double);
double l, tau, constant;
// Parse argument
// Parse arguments
if( argc < 7 ) {
printf("Usage: %s INIT_METHOD CALCULATION_STEPS LENGTH DX TAU N|XP\n",
argv[0]);
......@@ -120,7 +120,7 @@ int main(int argc, const char **argv) {
return EXIT_FAILURE;
}
calc_steps = atoi(argv[2]);
time = atoi(argv[2]);
l = atof(argv[3]);
dx = atof(argv[4]);
tau = atof(argv[5]);
......@@ -128,7 +128,7 @@ int main(int argc, const char **argv) {
// Allocate a 3xN two-dimensional area that functions as a cyclic buffer
// 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 ) {
puts("Error: could not allocate memory.");
......@@ -136,13 +136,13 @@ int main(int argc, const char **argv) {
}
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)
(*init_method)(l, constant);
// Calculate the specified number of steps
calculate_steps(calc_steps, tau);
calculate_steps(time, tau);
// Free allocated memory
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