#include <iostream>
#include <vector>
#include <cmath>
#include <mpi.h>
const double PI = 3.14159265358979323846;
// Function to initialize temperature
void initialize_temperature(std::vector<double>& T, int M, int rank, int size, double dx) {
int local_size = M / size;
for (int i = 0; i < local_size; ++i) {
double x = (rank * local_size + i) * dx;
T
[i
] = 100 * sin(PI
* x
); // Initial temperature distribution }
}
// Function to print temperature (gathered at rank 0)
void print_temperature(const std::vector<double>& T, int M, int rank, int size, double dx) {
if (rank == 0) {
std::vector<double> full_T(M + 1, 0.0);
MPI_Gather(T.data(), M / size, MPI_DOUBLE, full_T.data(), M / size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
std::cout << "Temperature:\n";
for (int i = 0; i <= M; ++i) {
std::cout << i * dx << " " << full_T[i] << "\n";
}
std::cout << "\n";
} else {
MPI_Gather(T.data(), M / size, MPI_DOUBLE, nullptr, 0, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
}
// Function to perform the finite difference simulation
void heat_conduction_simulation(int M, int time_steps, double alpha, double dx, double dt, int rank, int size) {
int local_size = M / size;
std::vector<double> T(local_size, 0.0); // Temperature at current time step
std::vector<double> T_new(local_size, 0.0); // Temperature at next time step
initialize_temperature(T, M, rank, size, dx);
// Print initial state (gathered at rank 0)
if (rank == 0) std::cout << "Initial state:\n";
print_temperature(T, M, rank, size, dx);
// Buffers for boundary exchange
double left_boundary = 0.0, right_boundary = 0.0;
// Time-stepping loop
for (int t = 0; t < time_steps; ++t) {
// Exchange boundary data
if (rank > 0) {
MPI_Send(&T[0], 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD);
MPI_Recv(&left_boundary, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
if (rank < size - 1) {
MPI_Send(&T[local_size - 1], 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD);
MPI_Recv(&right_boundary, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
// Update interior points
for (int i = 1; i < local_size - 1; ++i) {
T_new[i] = T[i] + alpha * dt / (dx * dx) * (T[i + 1] - 2 * T[i] + T[i - 1]);
}
// Update boundary points
if (rank > 0) {
T_new[0] = T[0] + alpha * dt / (dx * dx) * (T[1] - 2 * T[0] + left_boundary);
}
if (rank < size - 1) {
T_new[local_size - 1] = T[local_size - 1] + alpha * dt / (dx * dx) *
(right_boundary - 2 * T[local_size - 1] + T[local_size - 2]);
}
// Swap T and T_new
T.swap(T_new);
// Print intermediate states (optional, at rank 0)
if (t % (time_steps / 10) == 0 && rank == 0) {
std::cout << "Time step " << t << ":\n";
print_temperature(T, M, rank, size, dx);
}
}
// Final state (gathered at rank 0)
if (rank == 0) std::cout << "Final state:\n";
print_temperature(T, M, rank, size, dx);
}
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int N = 1; // Rod length in meters
int M = 50; // Number of spatial divisions
double dx = static_cast<double>(N) / M; // Spatial step size
double alpha = 0.01; // Thermal diffusivity
double dt = 0.0001; // Time step size
int time_steps = 1000; // Number of time steps
if (M % size != 0) {
if (rank == 0) {
std::cerr << "Error: Number of spatial divisions (M) must be divisible by number of processes.\n";
}
MPI_Finalize();
return 1;
}
heat_conduction_simulation(M, time_steps, alpha, dx, dt, rank, size);
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxtcGkuaD4KCmNvbnN0IGRvdWJsZSBQSSA9IDMuMTQxNTkyNjUzNTg5NzkzMjM4NDY7CgovLyBGdW5jdGlvbiB0byBpbml0aWFsaXplIHRlbXBlcmF0dXJlCnZvaWQgaW5pdGlhbGl6ZV90ZW1wZXJhdHVyZShzdGQ6OnZlY3Rvcjxkb3VibGU+JiBULCBpbnQgTSwgaW50IHJhbmssIGludCBzaXplLCBkb3VibGUgZHgpIHsKICAgIGludCBsb2NhbF9zaXplID0gTSAvIHNpemU7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IGxvY2FsX3NpemU7ICsraSkgewogICAgICAgIGRvdWJsZSB4ID0gKHJhbmsgKiBsb2NhbF9zaXplICsgaSkgKiBkeDsKICAgICAgICBUW2ldID0gMTAwICogc2luKFBJICogeCk7IC8vIEluaXRpYWwgdGVtcGVyYXR1cmUgZGlzdHJpYnV0aW9uCiAgICB9Cn0KCi8vIEZ1bmN0aW9uIHRvIHByaW50IHRlbXBlcmF0dXJlIChnYXRoZXJlZCBhdCByYW5rIDApCnZvaWQgcHJpbnRfdGVtcGVyYXR1cmUoY29uc3Qgc3RkOjp2ZWN0b3I8ZG91YmxlPiYgVCwgaW50IE0sIGludCByYW5rLCBpbnQgc2l6ZSwgZG91YmxlIGR4KSB7CiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiBmdWxsX1QoTSArIDEsIDAuMCk7CiAgICAgICAgTVBJX0dhdGhlcihULmRhdGEoKSwgTSAvIHNpemUsIE1QSV9ET1VCTEUsIGZ1bGxfVC5kYXRhKCksIE0gLyBzaXplLCBNUElfRE9VQkxFLCAwLCBNUElfQ09NTV9XT1JMRCk7CgogICAgICAgIHN0ZDo6Y291dCA8PCAiVGVtcGVyYXR1cmU6XG4iOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDw9IE07ICsraSkgewogICAgICAgICAgICBzdGQ6OmNvdXQgPDwgaSAqIGR4IDw8ICIgIiA8PCBmdWxsX1RbaV0gPDwgIlxuIjsKICAgICAgICB9CiAgICAgICAgc3RkOjpjb3V0IDw8ICJcbiI7CiAgICB9IGVsc2UgewogICAgICAgIE1QSV9HYXRoZXIoVC5kYXRhKCksIE0gLyBzaXplLCBNUElfRE9VQkxFLCBudWxscHRyLCAwLCBNUElfRE9VQkxFLCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICB9Cn0KCi8vIEZ1bmN0aW9uIHRvIHBlcmZvcm0gdGhlIGZpbml0ZSBkaWZmZXJlbmNlIHNpbXVsYXRpb24Kdm9pZCBoZWF0X2NvbmR1Y3Rpb25fc2ltdWxhdGlvbihpbnQgTSwgaW50IHRpbWVfc3RlcHMsIGRvdWJsZSBhbHBoYSwgZG91YmxlIGR4LCBkb3VibGUgZHQsIGludCByYW5rLCBpbnQgc2l6ZSkgewogICAgaW50IGxvY2FsX3NpemUgPSBNIC8gc2l6ZTsKICAgIHN0ZDo6dmVjdG9yPGRvdWJsZT4gVChsb2NhbF9zaXplLCAwLjApOyAgICAgLy8gVGVtcGVyYXR1cmUgYXQgY3VycmVudCB0aW1lIHN0ZXAKICAgIHN0ZDo6dmVjdG9yPGRvdWJsZT4gVF9uZXcobG9jYWxfc2l6ZSwgMC4wKTsgLy8gVGVtcGVyYXR1cmUgYXQgbmV4dCB0aW1lIHN0ZXAKCiAgICBpbml0aWFsaXplX3RlbXBlcmF0dXJlKFQsIE0sIHJhbmssIHNpemUsIGR4KTsKCiAgICAvLyBQcmludCBpbml0aWFsIHN0YXRlIChnYXRoZXJlZCBhdCByYW5rIDApCiAgICBpZiAocmFuayA9PSAwKSBzdGQ6OmNvdXQgPDwgIkluaXRpYWwgc3RhdGU6XG4iOwogICAgcHJpbnRfdGVtcGVyYXR1cmUoVCwgTSwgcmFuaywgc2l6ZSwgZHgpOwoKICAgIC8vIEJ1ZmZlcnMgZm9yIGJvdW5kYXJ5IGV4Y2hhbmdlCiAgICBkb3VibGUgbGVmdF9ib3VuZGFyeSA9IDAuMCwgcmlnaHRfYm91bmRhcnkgPSAwLjA7CgogICAgLy8gVGltZS1zdGVwcGluZyBsb29wCiAgICBmb3IgKGludCB0ID0gMDsgdCA8IHRpbWVfc3RlcHM7ICsrdCkgewogICAgICAgIC8vIEV4Y2hhbmdlIGJvdW5kYXJ5IGRhdGEKICAgICAgICBpZiAocmFuayA+IDApIHsKICAgICAgICAgICAgTVBJX1NlbmQoJlRbMF0sIDEsIE1QSV9ET1VCTEUsIHJhbmsgLSAxLCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICAgICAgICAgIE1QSV9SZWN2KCZsZWZ0X2JvdW5kYXJ5LCAxLCBNUElfRE9VQkxFLCByYW5rIC0gMSwgMCwgTVBJX0NPTU1fV09STEQsIE1QSV9TVEFUVVNfSUdOT1JFKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJhbmsgPCBzaXplIC0gMSkgewogICAgICAgICAgICBNUElfU2VuZCgmVFtsb2NhbF9zaXplIC0gMV0sIDEsIE1QSV9ET1VCTEUsIHJhbmsgKyAxLCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICAgICAgICAgIE1QSV9SZWN2KCZyaWdodF9ib3VuZGFyeSwgMSwgTVBJX0RPVUJMRSwgcmFuayArIDEsIDAsIE1QSV9DT01NX1dPUkxELCBNUElfU1RBVFVTX0lHTk9SRSk7CiAgICAgICAgfQoKICAgICAgICAvLyBVcGRhdGUgaW50ZXJpb3IgcG9pbnRzCiAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPCBsb2NhbF9zaXplIC0gMTsgKytpKSB7CiAgICAgICAgICAgIFRfbmV3W2ldID0gVFtpXSArIGFscGhhICogZHQgLyAoZHggKiBkeCkgKiAoVFtpICsgMV0gLSAyICogVFtpXSArIFRbaSAtIDFdKTsKICAgICAgICB9CgogICAgICAgIC8vIFVwZGF0ZSBib3VuZGFyeSBwb2ludHMKICAgICAgICBpZiAocmFuayA+IDApIHsKICAgICAgICAgICAgVF9uZXdbMF0gPSBUWzBdICsgYWxwaGEgKiBkdCAvIChkeCAqIGR4KSAqIChUWzFdIC0gMiAqIFRbMF0gKyBsZWZ0X2JvdW5kYXJ5KTsKICAgICAgICB9CiAgICAgICAgaWYgKHJhbmsgPCBzaXplIC0gMSkgewogICAgICAgICAgICBUX25ld1tsb2NhbF9zaXplIC0gMV0gPSBUW2xvY2FsX3NpemUgLSAxXSArIGFscGhhICogZHQgLyAoZHggKiBkeCkgKgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJpZ2h0X2JvdW5kYXJ5IC0gMiAqIFRbbG9jYWxfc2l6ZSAtIDFdICsgVFtsb2NhbF9zaXplIC0gMl0pOwogICAgICAgIH0KCiAgICAgICAgLy8gU3dhcCBUIGFuZCBUX25ldwogICAgICAgIFQuc3dhcChUX25ldyk7CgogICAgICAgIC8vIFByaW50IGludGVybWVkaWF0ZSBzdGF0ZXMgKG9wdGlvbmFsLCBhdCByYW5rIDApCiAgICAgICAgaWYgKHQgJSAodGltZV9zdGVwcyAvIDEwKSA9PSAwICYmIHJhbmsgPT0gMCkgewogICAgICAgICAgICBzdGQ6OmNvdXQgPDwgIlRpbWUgc3RlcCAiIDw8IHQgPDwgIjpcbiI7CiAgICAgICAgICAgIHByaW50X3RlbXBlcmF0dXJlKFQsIE0sIHJhbmssIHNpemUsIGR4KTsKICAgICAgICB9CiAgICB9CgogICAgLy8gRmluYWwgc3RhdGUgKGdhdGhlcmVkIGF0IHJhbmsgMCkKICAgIGlmIChyYW5rID09IDApIHN0ZDo6Y291dCA8PCAiRmluYWwgc3RhdGU6XG4iOwogICAgcHJpbnRfdGVtcGVyYXR1cmUoVCwgTSwgcmFuaywgc2l6ZSwgZHgpOwp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhcioqIGFyZ3YpIHsKICAgIE1QSV9Jbml0KCZhcmdjLCAmYXJndik7CgogICAgaW50IHJhbmssIHNpemU7CiAgICBNUElfQ29tbV9yYW5rKE1QSV9DT01NX1dPUkxELCAmcmFuayk7CiAgICBNUElfQ29tbV9zaXplKE1QSV9DT01NX1dPUkxELCAmc2l6ZSk7CgogICAgaW50IE4gPSAxOyAgICAgICAgICAgICAgICAgIC8vIFJvZCBsZW5ndGggaW4gbWV0ZXJzCiAgICBpbnQgTSA9IDUwOyAgICAgICAgICAgICAgICAgLy8gTnVtYmVyIG9mIHNwYXRpYWwgZGl2aXNpb25zCiAgICBkb3VibGUgZHggPSBzdGF0aWNfY2FzdDxkb3VibGU+KE4pIC8gTTsgLy8gU3BhdGlhbCBzdGVwIHNpemUKICAgIGRvdWJsZSBhbHBoYSA9IDAuMDE7ICAgICAgICAvLyBUaGVybWFsIGRpZmZ1c2l2aXR5CiAgICBkb3VibGUgZHQgPSAwLjAwMDE7ICAgICAgICAgLy8gVGltZSBzdGVwIHNpemUKICAgIGludCB0aW1lX3N0ZXBzID0gMTAwMDsgICAgICAvLyBOdW1iZXIgb2YgdGltZSBzdGVwcwoKICAgIGlmIChNICUgc2l6ZSAhPSAwKSB7CiAgICAgICAgaWYgKHJhbmsgPT0gMCkgewogICAgICAgICAgICBzdGQ6OmNlcnIgPDwgIkVycm9yOiBOdW1iZXIgb2Ygc3BhdGlhbCBkaXZpc2lvbnMgKE0pIG11c3QgYmUgZGl2aXNpYmxlIGJ5IG51bWJlciBvZiBwcm9jZXNzZXMuXG4iOwogICAgICAgIH0KICAgICAgICBNUElfRmluYWxpemUoKTsKICAgICAgICByZXR1cm4gMTsKICAgIH0KCiAgICBoZWF0X2NvbmR1Y3Rpb25fc2ltdWxhdGlvbihNLCB0aW1lX3N0ZXBzLCBhbHBoYSwgZHgsIGR0LCByYW5rLCBzaXplKTsKCiAgICBNUElfRmluYWxpemUoKTsKICAgIHJldHVybiAwOwp9