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

ModSim ass4 taddeus: Added sequential vibrating string program (untested).

parent 8ca8c52e
CC=mpicc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O2
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0
all: test ring
test: ring_test.o
......
CC=mpicc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O2
CC=gcc
CFLAGS=-Wall -Wextra -pedantic -std=c99 -O0 -D_GNU_SOURCE
LDFLAGS=-lm
all: vibstring
vibstring: main.o
all: seq
seq: seq.o
clean:
rm -vf *.o vibstring
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
//#define DEBUG
#define DEBUG
#define LOOP 100
#define STRIDE 10000
#define REPEAT 7
/*
*
*/
double **init_sinus(double l, double dx, double n, int *steps) {
double **y;
int i;
*steps = (int)ceil(l / dx);
y = (double**)malloc(3 * *steps * sizeof(double));
const int data_size = LOOP * STRIDE;
for( i = 0; i < *steps; i++ )
y[i][0] = sin(n * M_PI * i * dx / l);
return y;
}
/*
* The master task measures the time between the sending and receiving of data.
*
*/
void (int tasks, int rank) {
double *data = malloc(data_size * sizeof(double));
MPI_Status status;
int size, measurement,
source = (rank - 1 + tasks) % tasks, target = (rank + 1) % tasks;
// Increase the message length with a fixed STRIDE
for( size = STRIDE; size <= data_size; size += STRIDE ) {
// Repeat the measurement
for( measurement = 1; measurement <= REPEAT; measurement++ ) {
MPI_Recv(data, size, MPI_DOUBLE, source, MPI_ANY_TAG,
MPI_COMM_WORLD, &status);
MPI_Send(data, size, MPI_DOUBLE, target, 0, MPI_COMM_WORLD);
}
double **init_plucked(double l, double dx, double xp, int *steps) {
double **y, x;
int i;
*steps = (int)ceil(l / dx);
y = (double**)malloc(3 * *steps * sizeof(double));
for( i = 0; i < *steps; i++ ) {
x = i * dx;
y[i][0] = x < xp ? x / xp : (l - x) / (l - xp);
}
free(data);
// The string is attached at both ends
y[0][2] = y[0][1] = y[0][0];
y[*steps - 1][2] = y[*steps - 1][1] = y[*steps - 1][0];
return y;
}
int main(int argc, char **argv) {
int tasks, rank, error;
void iterate(double **y, int steps, double dx, double T) {
double x;
int i, prev = 0, current = 1, next = 2;
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;
// 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 = 2; i < steps; i++ ) {
x = i * dx;
y[i][1] = y[i][0] + .5 * T * T * (y[i-1][0] - 2 * y[i][0] + y[i-1][0]);
}
MPI_Comm_size(MPI_COMM_WORLD, &tasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Iterate over the length of the string
for( i = 1; i < steps - 1; i++ ) {
y[i][next] = 2 * y[i][current] - y[i][prev]
+ T * T * (y[i-1][current] - 2 * y[i][current] + y[i+1][current]);
if( !rank )
master(tasks);
else
slave(tasks, rank);
prev = current;
current = next;
next = (next + 1) % 3;
}
free(y);
}
int main(int argc, const char **argv) {
int steps;
double **(*method)(double, double, double, int*);
if( argc < 5 ) {
printf("Usage: %s INIT_METHOD L DX T N|XP\n", argv[0]);
return EXIT_FAILURE;
}
if( !strcmp(argv[1], "sinus") ) {
method = init_sinus;
} else if( !strcmp(argv[1], "plucked") ) {
method = init_plucked;
} else {
printf("Unknown method '%s'.\n", argv[1]);
return EXIT_FAILURE;
}
MPI_Finalize();
iterate((*method)(atof(argv[2]), atof(argv[3]), atof(argv[5]), &steps),
steps, atof(argv[3]), atof(argv[4]));
return EXIT_SUCCESS;
}
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