0% found this document useful (0 votes)
2 views

Parallelization Techniques Heat Conduction

The document describes three approaches for simulating heat distribution along a rod: a serial simulation in C, a parallel simulation using OpenMP, and a parallel simulation using MPI. Each approach includes code snippets and explanations of key sections, highlighting differences in initialization, temperature updates, and performance. The document concludes with a comparison of the approaches in terms of parallelism, communication, complexity, performance, and use cases.

Uploaded by

MASTER JII
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Parallelization Techniques Heat Conduction

The document describes three approaches for simulating heat distribution along a rod: a serial simulation in C, a parallel simulation using OpenMP, and a parallel simulation using MPI. Each approach includes code snippets and explanations of key sections, highlighting differences in initialization, temperature updates, and performance. The document concludes with a comparison of the approaches in terms of parallelism, communication, complexity, performance, and use cases.

Uploaded by

MASTER JII
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

Approach 1: Serial Simulation in C

Code Overview: The serial version of the program simulates the heat distribution along a
rod over time using the finite difference method. In this approach:

 We initialize the temperature distribution along the rod, with the initial condition
given by

where LLL is the length of the rod.

 The temperature at each point is updated in time using the heat equation:

where α\alphaα is the thermal diffusivity constant, and Δx and Δt are the spatial and time
steps, respectively.

 The boundaries are held at a fixed temperature T0=0T_0 = 0T0=0, as per the
problem specification.

Explanation of Key Sections:

1. Initialization Function: The temperature array is initialized using a sine function


to represent the initial temperature distribution across the rod.

2. Temperature Update Function: The temperature is updated using the finite


difference method at each time step. The function calculates the new temperature at
each point by considering the previous temperature values and applying the heat
equation.

3. Main Simulation Loop: In the main function, the program iterates through time
steps, calling the temperature update function at each step and swapping the old
and new temperature arrays.

CODE

#include <iostream>

#include <cmath>

#include <vector>

#include <iomanip>
using namespace std;

const double alpha = 0.01;

const double pi = 3.141592653589793;

void initialize(vector<double>& T, int N, double rodLength, double dx) {

for (int i = 0; i <= N; ++i) {

double x = i * dx;

T[i] = 100.0 * sin(pi * x / rodLength);

void updateTemperature(vector<double>& T, vector<double>& T_new, int N,


double T0, double dt, double dx) {

for (int i = 1; i < N; ++i) {

T_new[i] = T[i] + alpha * dt / (dx * dx) * (T[i - 1] - 2 * T[i] + T[i + 1]);

T_new[0] = T0;

T_new[N] = T0;

void calculateTemperature() {

double rodLength, queryTime, queryPoint;

const double T0 = 0.0;

const double dx = 0.01;

const double dt = 0.0001;


cout << "Enter rod length (in meters): ";

cin >> rodLength;

cout << "Enter query time (in seconds): ";

cin >> queryTime;

cout << "Enter point to query temperature (in meters): ";

cin >> queryPoint;

if (queryPoint < 0 || queryPoint > rodLength) {

cout << "Invalid point. Please enter a value between 0 and " << rodLength << "
meters.\n";

return;

int N = static_cast<int>(rodLength / dx);

vector<double> T(N + 1, T0);

vector<double> T_new(N + 1, T0);

initialize(T, N, rodLength, dx);

int steps = static_cast<int>(queryTime / dt);

for (int step = 0; step < steps; ++step) {

updateTemperature(T, T_new, N, T0, dt, dx);

T.swap(T_new);

int pointIndex = static_cast<int>(queryPoint / dx);


cout << "Temperature at x = " << queryPoint << " m and t = " << queryTime << " s
is: ";

cout << fixed << setprecision(2) << T[pointIndex] << " °C\n";

int main() {

int choice;

do {

cout << "\n=== Temperature Simulation Menu ===\n";

cout << "1. Calculate Temperature at a Specific Point and Time\n";

cout << "2. Exit\n";

cout << "Enter your choice: ";

cin >> choice;

switch (choice) {

case 1:

calculateTemperature();

break;

case 2:

cout << "Exiting the program. Goodbye!\n";

break;

default:

cout << "Invalid choice. Please try again.\n";

} while (choice != 2);


return 0;

Approach 2: Parallel Simulation with OpenMP

Code Overview: The parallel simulation leverages OpenMP (Open Multi-Processing), a


parallel computing API, to distribute the computation across multiple processor cores. The
parallel version introduces the following key improvements:

 Parallel Initialization: We use OpenMP to parallelize the initialization of the


temperature array, allowing for faster setup.

 Parallel Update: The temperature update process is parallelized using OpenMP


directives. The #pragma omp parallel for directive is used to distribute the work of
updating the temperature values across multiple threads.

 Performance: OpenMP provides a significant performance improvement by


dividing the workload among available CPU cores.

Explanation of Key Sections:

1. Parallel Initialization: The initialization of the temperature array is parallelized


using OpenMP to distribute the task of setting each point's initial temperature
across available threads.

2. Parallel Temperature Update: In this function, the temperature updates are done
in parallel using the #pragma omp parallel for directive. The dynamic scheduling
policy is used to assign work to threads dynamically, helping balance the load when
the computational cost varies across iterations.

3. Timing and Performance Measurement: The code measures the execution time
using clock_t and outputs the time taken to complete the simulation. This time
comparison helps demonstrate the performance improvement of the parallel
approach over the serial one.

CODE

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <omp.h>
#include <time.h>

const double alpha = 0.01;

const double pi = 3.141592653589793;

void initialize(double* T, int N, double rodLength, double dx) {

#pragma omp parallel for schedule(static)

for (int i = 0; i <= N; ++i) {

double x = i * dx;

T[i] = 100.0 * sin(pi * x / rodLength);

void updateTemperature(double* T, double* T_new, int N, double T0, double dt,


double dx) {

double factor = alpha * dt / (dx * dx);

#pragma omp parallel for schedule(dynamic, 64)

for (int i = 1; i < N; ++i) {

T_new[i] = T[i] + factor * (T[i - 1] - 2 * T[i] + T[i + 1]);

T_new[0] = T0;

T_new[N] = T0;

void calculateTemperature() {
double rodLength, queryTime, queryPoint;

const double T0 = 0.0;

const double dx = 0.001;

const double dt = 0.00005;

printf("Enter rod length (in meters): ");

scanf("%lf", &rodLength);

printf("Enter query time (in seconds): ");

scanf("%lf", &queryTime);

printf("Enter point to query temperature (in meters): ");

scanf("%lf", &queryPoint);

if (queryPoint < 0 || queryPoint > rodLength) {

printf("Invalid point. Please enter a value between 0 and %.2f meters.\n",


rodLength);

return;

int N = (int)(rodLength / dx);

double* T = (double*)calloc(N + 1, sizeof(double));

double* T_new = (double*)calloc(N + 1, sizeof(double));

omp_set_num_threads(omp_get_num_procs());

initialize(T, N, rodLength, dx);

int steps = (int)(queryTime / dt);


#pragma omp parallel

#pragma omp single

printf("Running in parallel with %d threads.\n", omp_get_num_threads());

clock_t start = clock();

for (int step = 0; step < steps; ++step) {

updateTemperature(T, T_new, N, T0, dt, dx);

double* temp = T;

T = T_new;

T_new = temp;

clock_t end = clock();

double elapsed = (double)(end - start) / CLOCKS_PER_SEC;

int pointIndex = (int)(queryPoint / dx);

printf("Temperature at x = %.2f m and t = %.2f s is: %.2f °C\n", queryPoint,


queryTime, T[pointIndex]);

printf("[Parallel] Elapsed time: %.2f seconds.\n", elapsed);


free(T);

free(T_new);

int main() {

int choice;

do {

printf("\n=== Temperature Simulation Menu ===\n");

printf("1. Run Parallel Simulation\n");

printf("2. Exit\n");

printf("Enter your choice: ");

scanf("%d", &choice);

switch (choice) {

case 1:

calculateTemperature(); // Run parallel version only

break;

case 2:

printf("Exiting the program. Goodbye!\n");

break;

default:

printf("Invalid choice. Please try again.\n");

} while (choice != 2);


return 0;

Approach 3: Parallel Simulation with MPI

Code Overview: The third approach involves using MPI (Message Passing Interface), which
allows for distributed computing across multiple nodes (machines or processors). In this
version:

 The rod is divided into segments, and each process handles a portion of the rod.

 Communication: MPI is used to handle the communication between processes.


Boundary data is exchanged between adjacent processes to maintain consistency.

 Each process updates the temperature for its assigned section of the rod, and after
each step, the results are synchronized across processes.

Explanation of Key Sections:

1. Initialization and Data Distribution: The rod is divided into segments, with each
process handling one segment. The initial temperature is distributed across all
processes using MPI broadcasting.

2. Boundary Communication: Each process sends and receives data to and from
adjacent processes to update the temperature at the boundaries. This ensures that
the simulation remains consistent across all processes.

3. Parallel Update: Each process calculates the temperature for its segment
independently and updates it using the finite difference method. After each time
step, the temperature array is updated, and the boundary values are exchanged.

4. Synchronization and Timing: The code synchronizes processes at each time step
using MPI barriers to ensure all processes are up to date before proceeding to the
next step.

CODE

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <mpi.h>

#include <time.h>
const double alpha = 0.01;

const double pi = 3.141592653589793;

void initialize(double* T, int N, double rodLength, double dx) {

for (int i = 0; i <= N; ++i) {

double x = i * dx;

T[i] = 100.0 * sin(pi * x / rodLength);

void updateTemperature(double* T, double* T_new, int N, double T0, double dt, double dx)
{

double factor = alpha * dt / (dx * dx);

for (int i = 1; i < N; ++i) {

T_new[i] = T[i] + factor * (T[i - 1] - 2 * T[i] + T[i + 1]);

T_new[0] = T0;

T_new[N] = T0;

void calculateTemperature(int rank, int size) {

double rodLength, queryTime, queryPoint;

const double T0 = 0.0;

const double dx = 0.001;

const double dt = 0.00005;


if (rank == 0) {

printf("Enter rod length (in meters): ");

scanf("%lf", &rodLength);

printf("Enter query time (in seconds): ");

scanf("%lf", &queryTime);

printf("Enter point to query temperature (in meters): ");

scanf("%lf", &queryPoint);

MPI_Bcast(&rodLength, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Bcast(&queryTime, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Bcast(&queryPoint, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

if (queryPoint < 0 || queryPoint > rodLength) {

if (rank == 0) {

printf("Invalid point. Please enter a value between 0 and %.2f meters.\n",


rodLength);

return;

int N = (int)(rodLength / dx);

int local_N = N / size;

if (rank == size - 1) {

local_N += N % size;

}
double* T = (double*)calloc(local_N + 2, sizeof(double));

double* T_new = (double*)calloc(local_N + 2, sizeof(double));

initialize(T, local_N, rodLength, dx);

int steps = (int)(queryTime / dt);

MPI_Barrier(MPI_COMM_WORLD);

clock_t start = clock();

for (int step = 0; step < steps; ++step) {

if (rank > 0) {

MPI_Send(&T[1], 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD);

if (rank < size - 1) {

MPI_Send(&T[local_N], 1, MPI_DOUBLE, rank + 1, 1, MPI_COMM_WORLD);

if (rank > 0) {

MPI_Recv(&T[0], 1, MPI_DOUBLE, rank - 1, 1, MPI_COMM_WORLD,


MPI_STATUS_IGNORE);

if (rank < size - 1) {

MPI_Recv(&T[local_N + 1], 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD,


MPI_STATUS_IGNORE);

}
updateTemperature(T, T_new, local_N, T0, dt, dx);

double* temp = T;

T = T_new;

T_new = temp;

clock_t end = clock();

double elapsed = (double)(end - start) / CLOCKS_PER_SEC;

int pointIndex = (int)(queryPoint / dx);

double tempAtPoint;

if (rank == 0) {

tempAtPoint = T[pointIndex];

MPI_Bcast(&tempAtPoint, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

if (rank == 0) {

printf("Temperature at x = %.2f m and t = %.2f s is: %.2f °C\n", queryPoint, queryTime,


tempAtPoint);

printf("[Parallel] Elapsed time: %.2f seconds.\n", elapsed);

free(T);

free(T_new);

}
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 choice;

if (rank == 0) {

do {

printf("\n=== Temperature Simulation Menu ===\n");

printf("1. Run Parallel Simulation\n");

printf("2. Exit\n");

printf("Enter your choice: ");

scanf("%d", &choice);

switch (choice) {

case 1:

calculateTemperature(rank, size);

break;

case 2:

printf("Exiting the program. Goodbye!\n");

break;

default:

printf("Invalid choice. Please try again.\n");


}

} while (choice != 2);

MPI_Finalize();

return 0;

Code Comparison and Performance Discussion

Serial Parallel (OpenMP)


Aspect Parallel (MPI) Simulation
Simulation Simulation

OpenMP (Shared Memory MPI (Distributed Memory


Parallelism None
Model) Model)

Minimal (within shared Extensive (between


Communication No
memory) processes)

Complexity Low Moderate High

High, depends on available High, scales across


Performance Single-threaded
cores machines

Simple cases, Medium to large problems Large-scale problems,


Use Case
small rod on a single machine distributed systems

 Serial Simulation is straightforward but lacks scalability for larger problems or


multi-core systems.

 OpenMP Parallel Simulation significantly improves performance by utilizing


multiple cores on a single machine. It is well-suited for medium-scale problems.

 MPI Parallel Simulation is the most scalable and suitable for large-scale problems
distributed across multiple machines or nodes.

Conclusion
The simulations were implemented using three different approaches: serial, OpenMP
parallel, and MPI parallel. The OpenMP and MPI versions of the simulation showed
significant improvements in performance, particularly for larger problems or those that
require high computational resources. OpenMP provides a quick solution for parallelization
on shared-memory systems, while MPI offers scalability across distributed systems, making
it ideal for large-scale simulations.

You might also like