Sample solution

Content

#include <cassert>
#include <mpi.h>
#include <printf.hpp>
#include <hpc/aux/slices.hpp>

using namespace std;
using namespace hpc::aux;

constexpr double a = 0;
constexpr double b = 1;
constexpr unsigned int N = 100; /* number of intervals */

// numerical integration according to the Simpson rule
// for f over the interval [a,b] using n subintervals
template <typename T, typename F>
T simpson(F f, T a, T b, int n) {
   assert(n > 0 && a <= b);
   T value = f(a)/2 + f(b)/2;
   T x = a;
   for (int i = 1; i < n; ++i) {
      T xleft = x; x = a + i * (b - a) / n;
      value += f(x) + 2 * f((xleft + x)/2);
   }
   value += 2 * f((x + b)/2);
   value *= (b - a) / n / 3;
   return value;
}

int main(int argc, char** argv) {
   MPI_Init(&argc, &argv);

   int nof_processes; MPI_Comm_size(MPI_COMM_WORLD, &nof_processes);
   int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank);

   UniformSlices<unsigned int> slices(nof_processes, N);
   auto first_interval = slices.offset(rank);
   auto nofintervals = slices.size(rank);
   auto next_interval = first_interval + nofintervals;

   double x0 = a + first_interval * (b - a) / N;
   double x1 = a + next_interval * (b - a) / N;
   double value = simpson([](double x) -> double {
	 return 4 / (1 + x*x);
   }, x0, x1, nofintervals);

   if (rank) {
      MPI_Send(&value, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
   } else {
      double sum = value;
      for (int i = 0; i + 1 < nof_processes; ++i) {
	 MPI_Status status;
	 double value;
	 MPI_Recv(&value, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
	    0, MPI_COMM_WORLD, &status);
	 sum += value;
      }
      fmt::printf("%.15lf\n", sum);
   }
   MPI_Finalize();
}
theon$ mpiCC -g -std=c++17 -I/home/numerik/pub/pp/ss19/lib -o mpi-simpson mpi-simpson.cpp
theon$ mpirun -np 4 mpi-simpson
3.141592653589793
theon$ 
heim$ OMPI_CXX=g++-8.3 mpiCC -g -std=c++17 -I/home/numerik/pub/pp/ss19/lib -o mpi-simpson mpi-simpson.cpp -Wno-literal-suffix
/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.3.0/cc1plus: error while loading shared libraries: libmpfr.so.4: cannot open shared object file: No such file or directory
heim$ mpirun -np 4 mpi-simpson
--------------------------------------------------------------------------
Open MPI tried to fork a new process via the "execve" system call but
failed.  Open MPI checks many things before attempting to launch a
child process, but nothing is perfect. This error may be indicative
of another problem on the target host, or even something as silly as
having specified a directory for your application. Your job will now
abort.

  Local host:        heim
  Working dir:       /home/numerik/pp/ss19/sessions/session05
  Application name:  /home/borchert/pp/ss19/sessions/session05/mpi-simpson
  Error:             No such file or directory
--------------------------------------------------------------------------
--------------------------------------------------------------------------
mpirun was unable to start the specified application as it encountered an
error:

Error code: 1
Error name: (null)
Node: heim

when attempting to start process rank 0.
--------------------------------------------------------------------------
[heim:02138] 3 more processes have sent help message help-orte-odls-default.txt / execve error
[heim:02138] Set MCA parameter "orte_base_help_aggregate" to 0 to see all help / error messages
4 total processes failed to start
heim$