#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mpi.h>
// Conversion from degrees to radians
double degtorad(double degang) {
return ((M_PI * degang) / 180.0);
}
// Function to be integrated (replace with your actual function)
double func(double x) {
return tan(x
); // Example function }
// Trapezoidal rule function with OpenMP parallelization
double trap(int n, double h, double *fx) {
double area = 0.0;
#pragma omp parallel for reduction(+:area) private(i)
for (int i = 0; i < n; i++) {
area += h * func(a + i * h); // Use actual function here
}
return area;
}
int main() {
int rank, size, n_local, n_global = 2; // Initial guess for global n
double a, b, h, area, local_area;
double *x, *fx;
double diff, tol = 1.0e-6;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Enter a and b in process 0
if (rank == 0) {
scanf("%lf %lf", &a
, &b
); }
// Broadcast a and b to all processes
MPI_Bcast(&a, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(&b, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
// Find optimal n in parallel using a doubling strategy
while (1) {
// Calculate local sub-interval size on each process
h = (b - a) / (n_global - 1);
n_local = n_global / size + (rank < n_global % size); // Account for uneven distribution
// Allocate memory for x and fx on each process
x
= (double*)malloc(n_local
* sizeof(double)); fx
= (double*)malloc(n_local
* sizeof(double));
// Calculate x and fx values (can be parallelized within each process)
for (int i = 0; i < n_local; i++) {
x[i] = a + rank * (b - a) / size + i * h;
fx[i] = func(degtorad(x[i])); // Convert to radians before function call
}
// Call trap function (parallelized) to find local area
local_area = trap(n_local, h, fx);
// Free memory for x and fx
// Gather local areas from all processes and sum on process 0
MPI_Reduce(&local_area, &area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("n = %d, Area = %lf, Difference = %lf\n", n_global
, area
, diff
); if (diff < tol) {
break;
}
}
// Double the global number of intervals for the next iteration
n_global *= 2;
// Check for potential overflow of n_global
int ret = MPI_Bcast(&n_global, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (ret != MPI_SUCCESS) {
printf("Error: MPI_Bcast failed (%d)\n", ret
); MPI_Finalize();
return 1;
}
}
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPG1waS5oPgoKLy8gQ29udmVyc2lvbiBmcm9tIGRlZ3JlZXMgdG8gcmFkaWFucwpkb3VibGUgZGVndG9yYWQoZG91YmxlIGRlZ2FuZykgewogIHJldHVybiAoKE1fUEkgKiBkZWdhbmcpIC8gMTgwLjApOwp9CgovLyBGdW5jdGlvbiB0byBiZSBpbnRlZ3JhdGVkIChyZXBsYWNlIHdpdGggeW91ciBhY3R1YWwgZnVuY3Rpb24pCmRvdWJsZSBmdW5jKGRvdWJsZSB4KSB7CiAgcmV0dXJuIHRhbih4KTsgLy8gRXhhbXBsZSBmdW5jdGlvbgp9CgovLyBUcmFwZXpvaWRhbCBydWxlIGZ1bmN0aW9uIHdpdGggT3Blbk1QIHBhcmFsbGVsaXphdGlvbgpkb3VibGUgdHJhcChpbnQgbiwgZG91YmxlIGgsIGRvdWJsZSAqZngpIHsKICBkb3VibGUgYXJlYSA9IDAuMDsKCiAgI3ByYWdtYSBvbXAgcGFyYWxsZWwgZm9yIHJlZHVjdGlvbigrOmFyZWEpIHByaXZhdGUoaSkKICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgYXJlYSArPSBoICogZnVuYyhhICsgaSAqIGgpOyAvLyBVc2UgYWN0dWFsIGZ1bmN0aW9uIGhlcmUKICB9CgogIHJldHVybiBhcmVhOwp9CgppbnQgbWFpbigpIHsKICBpbnQgcmFuaywgc2l6ZSwgbl9sb2NhbCwgbl9nbG9iYWwgPSAyOyAvLyBJbml0aWFsIGd1ZXNzIGZvciBnbG9iYWwgbgogIGRvdWJsZSBhLCBiLCBoLCBhcmVhLCBsb2NhbF9hcmVhOwogIGRvdWJsZSAqeCwgKmZ4OwogIGRvdWJsZSBkaWZmLCB0b2wgPSAxLjBlLTY7CiAgTVBJX1N0YXR1cyBzdGF0dXM7CgogIE1QSV9Jbml0KCZhcmdjLCAmYXJndik7CiAgTVBJX0NvbW1fcmFuayhNUElfQ09NTV9XT1JMRCwgJnJhbmspOwogIE1QSV9Db21tX3NpemUoTVBJX0NPTU1fV09STEQsICZzaXplKTsKCiAgLy8gRW50ZXIgYSBhbmQgYiBpbiBwcm9jZXNzIDAKICBpZiAocmFuayA9PSAwKSB7CiAgICBwcmludGYoIkVudGVyIGEgYW5kIGJcbiIpOwogICAgc2NhbmYoIiVsZiAlbGYiLCAmYSwgJmIpOwogIH0KCiAgLy8gQnJvYWRjYXN0IGEgYW5kIGIgdG8gYWxsIHByb2Nlc3NlcwogIE1QSV9CY2FzdCgmYSwgMSwgTVBJX0RPVUJMRSwgMCwgTVBJX0NPTU1fV09STEQpOwogIE1QSV9CY2FzdCgmYiwgMSwgTVBJX0RPVUJMRSwgMCwgTVBJX0NPTU1fV09STEQpOwoKICAvLyBGaW5kIG9wdGltYWwgbiBpbiBwYXJhbGxlbCB1c2luZyBhIGRvdWJsaW5nIHN0cmF0ZWd5CiAgd2hpbGUgKDEpIHsKICAgIC8vIENhbGN1bGF0ZSBsb2NhbCBzdWItaW50ZXJ2YWwgc2l6ZSBvbiBlYWNoIHByb2Nlc3MKICAgIGggPSAoYiAtIGEpIC8gKG5fZ2xvYmFsIC0gMSk7CiAgICBuX2xvY2FsID0gbl9nbG9iYWwgLyBzaXplICsgKHJhbmsgPCBuX2dsb2JhbCAlIHNpemUpOyAvLyBBY2NvdW50IGZvciB1bmV2ZW4gZGlzdHJpYnV0aW9uCgogICAgLy8gQWxsb2NhdGUgbWVtb3J5IGZvciB4IGFuZCBmeCBvbiBlYWNoIHByb2Nlc3MKICAgIHggPSAoZG91YmxlKiltYWxsb2Mobl9sb2NhbCAqIHNpemVvZihkb3VibGUpKTsKICAgIGZ4ID0gKGRvdWJsZSopbWFsbG9jKG5fbG9jYWwgKiBzaXplb2YoZG91YmxlKSk7CgogICAgLy8gQ2FsY3VsYXRlIHggYW5kIGZ4IHZhbHVlcyAoY2FuIGJlIHBhcmFsbGVsaXplZCB3aXRoaW4gZWFjaCBwcm9jZXNzKQogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuX2xvY2FsOyBpKyspIHsKICAgICAgeFtpXSA9IGEgKyByYW5rICogKGIgLSBhKSAvIHNpemUgKyBpICogaDsKICAgICAgZnhbaV0gPSBmdW5jKGRlZ3RvcmFkKHhbaV0pKTsgLy8gQ29udmVydCB0byByYWRpYW5zIGJlZm9yZSBmdW5jdGlvbiBjYWxsCiAgICB9CgogICAgLy8gQ2FsbCB0cmFwIGZ1bmN0aW9uIChwYXJhbGxlbGl6ZWQpIHRvIGZpbmQgbG9jYWwgYXJlYQogICAgbG9jYWxfYXJlYSA9IHRyYXAobl9sb2NhbCwgaCwgZngpOwoKICAgIC8vIEZyZWUgbWVtb3J5IGZvciB4IGFuZCBmeAogICAgZnJlZSh4KTsKICAgIGZyZWUoZngpOwoKICAgIC8vIEdhdGhlciBsb2NhbCBhcmVhcyBmcm9tIGFsbCBwcm9jZXNzZXMgYW5kIHN1bSBvbiBwcm9jZXNzIDAKICAgIE1QSV9SZWR1Y2UoJmxvY2FsX2FyZWEsICZhcmVhLCAxLCBNUElfRE9VQkxFLCBNUElfU1VNLCAwLCBNUElfQ09NTV9XT1JMRCk7CgogICAgaWYgKHJhbmsgPT0gMCkgewogICAgICBkaWZmID0gZmFicyhhcmVhIC0gbG9nKDIuMCkpOwogICAgICBwcmludGYoIm4gPSAlZCwgQXJlYSA9ICVsZiwgRGlmZmVyZW5jZSA9ICVsZlxuIiwgbl9nbG9iYWwsIGFyZWEsIGRpZmYpOwogICAgICBpZiAoZGlmZiA8IHRvbCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgLy8gRG91YmxlIHRoZSBnbG9iYWwgbnVtYmVyIG9mIGludGVydmFscyBmb3IgdGhlIG5leHQgaXRlcmF0aW9uCiAgICBuX2dsb2JhbCAqPSAyOwoKICAgIC8vIENoZWNrIGZvciBwb3RlbnRpYWwgb3ZlcmZsb3cgb2Ygbl9nbG9iYWwKICAgIGludCByZXQgPSBNUElfQmNhc3QoJm5fZ2xvYmFsLCAxLCBNUElfSU5ULCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICBpZiAocmV0ICE9IE1QSV9TVUNDRVNTKSB7CiAgICAgIHByaW50ZigiRXJyb3I6IE1QSV9CY2FzdCBmYWlsZWQgKCVkKVxuIiwgcmV0KTsKICAgICAgTVBJX0ZpbmFsaXplKCk7CiAgICAgIHJldHVybiAxOwogICAgfQogIH0KCiAgTVBJX0ZpbmFsaXplKCk7CiAgcmV0dXJuIDA7Cn0K