jeudi 23 avril 2020

MPI and fpermissive errors around MPI_Init

Alright so this program is meant to simulate a solar system by semi-randomly generating a star, semi-randomly generating planets around the star, simulating the passing of time (using MPI to spread out the computational load), and determining habitability of resulting planets. I should have it commented for readability.

I am however having a problem with getting MPI working. As far as I can tell I'm doing something wrong that prevents it from initializing properly. Here's the errors I get.

OrbitPlus.cpp:323:50: error: invalid conversion from ‘char’ to ‘char**’ [-fpermissive]
     system1 = Time( system, n , dt , argc, **argv);
                                                  ^
OrbitPlus.cpp:191:33: error:   initializing argument 5 of ‘std::vector<std::vector<float> > Time(std::vector<std::vector<float> >, int, float, int, char**)’ [-fpermissive]
 std::vector<std::vector<float>> Time( std::vector<std::vector<float>> system , int n, float dt, int argc, char **argv){
                                 ^

I do find it interesting that both errors are considered fpermissive errors if when I compile it with - mpic++ -std=c++11 -o OrbitPlus OrbitPlus.cpp

So it seems if I was feeling adventurous I could just run the code with -fpermissive option and roll the dice, but I don't feel like being so brave. Clearly the errors are related to each other.

Here's my code.

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <math.h>
#include <complex>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <algorithm>

#include "mpi.h"

double MyRandom(){

  //////////////////////////
  //Random Number Generator
  //Returns number between 0-99
  //////////////////////////

  double y = 0;
  unsigned seed = time(0);
  std::srand(seed);
  uint64_t x = std::rand();

  x ^= x << 13;
  x ^= x >> 7;
  x ^= x << 17;

  x = (1070739 * x) % 2199023255530;
  y = x / 21990232555.31 ;
  return y;
}
////////////////////////

///////////////////////
std::tuple< char , float , float , float , int > Star(){

  ////////////////////////////
  //Star will generate a Star
  //Randomly or User Selected
  //Class, Luminosity, Probability, Radius, Mass, Temperature
  //Stars always take up 99% of the mass of the system.
  ///////////////////////////

  char Class;
  int choice = 8;
  float L, R, M, T;
  double y = 4;
  std::tuple< char , float , float , float , float > star( Class , L  , R , M , T) ;
  std::cout << "Select Star Class (OBAFGKM) or Select 8 for Random" << std::endl;
  std::cout << "1 = O, 2 = B, 3 = A, 4 = F, 5 = G, 6 = K, 7 = M : ";
  std::cin >> choice;
  if ( choice == 8 ) {
    y = MyRandom();
    if (y <= 0.003) choice = 1;
    if ((y > 0.003) && (y <= 0.133)) choice = 2;
    if ((y > 0.133) && (y <= 0.733)) choice = 3;
    if ((y > 0.733) && (y <= 3.733)) choice = 4;
    if ((y > 3.733) && (y <= 11.333)) choice = 5;
    if ((y > 11.333) && (y <= 23.433)) choice = 6;
    else choice = 7;
  }

  if (choice == 1) {
    Class = 'O';
    L = 30000;
    R = 0.0307;
    M = 16;
    T = 30000;
  }

  if (choice == 2) {
    Class = 'B';
    L = 15000;
    R = 0.0195;
    M = 9;
    T = 20000;
  }

  if (choice == 3) {
    Class = 'A';
    L = 15;
    R = 0.00744;
    M = 1.7;
    T = 8700;
  }

  if (choice == 4) {
    Class = 'F';
    L = 3.25;
    R = 0.00488;
    M = 1.2;
    T = 6750;
  }

  if (choice == 5) {
    Class = 'G';
    L = 1;
    R = 0.00465;
    M = 1;
    T = 5700;
  }

  if (choice == 6) {
    Class = 'K';
    L = 0.34;
    R = 0.00356;
    M = 0.62;
    T = 4450;
  }

  if (choice == 7) {
    Class = 'M';
    L = 0.08;
    R = 0.00326;
    M = 0.26;
    T = 3000;
  }

  return star;
}
////////////

///////////
std::vector< std::vector<float> > Planet( float L, float R, float M, int T, int n){

///////////////////////////
//Planet generates the Planets
//Random 1 - 10, Random distribution 0.06 - 6 JAU unless specified by User
//Frost line Calculated, First Planet after Frost line is the Jupiter
//The Jupiter will have the most mass of all Jovian worlds
//Otherwise divided into Jovian and Terrestrial Worlds, Random Masses within groups
//Also calculates if a planet is in the Habitable Zone
////////////////////////////

float frostline, innerCHZ, outerCHZ;
float a = 0.06; // a - albedo
float m = M / 100; //Mass of the Jupiter always 1/100th mass of the Star.
std::vector<float> sys;
std::vector<std::vector <float>> system;

for (int i = 0 ; i < n ; i++){
  sys.push_back( MyRandom()/10 * 3 ) ; //Distances in terms of Sol AU
                         }
  sort(sys.begin(), sys.end() );
  for (int i = 0 ; i < n ; i++){
    system[i].push_back(sys[i]);
    system[i].push_back(0); //system[i][0] is x, system[i][1] is y
}

frostline = (0.6 * T / 150) * (0.6 * T/150) * R / sqrt(1 - a);
innerCHZ = sqrt(L / 1.1);
outerCHZ = sqrt(L / 0.53);

for (int i = 0 ; i < n ; i++){
  if (system[i][0] <= frostline) {
    float tmass = m * 0.0003 * MyRandom();
    system[i].push_back(tmass) ; //system[i][2] is mass, [3] is marker for the Jupiter
    system[i].push_back(0) ;
  }

  if ((system[i][0] >= frostline) && (system[i-1][0] < frostline)){
      system[i].push_back(m) ;
      float J = 1;
      system[i].push_back(J) ;
  }

  if ((system[i][0] >= frostline) && (system[i-1][0] >= frostline)) {
      float jmass = m * 0.01 * MyRandom();
      system[i].push_back(jmass) ;
      system[i].push_back(0) ;
  }

  if ((system[i][0] >= innerCHZ) && (system[i][0] <= outerCHZ)){
      float H = 1;
      system[i].push_back(H);
  }
  else system[i].push_back(0); //[4] is habitable marker

  }

  return system;
}
////////////

////////////
std::vector<std::vector<float>> Time( std::vector<std::vector<float>> system , int n, float dt, int argc, char **argv){

  #define ASIZE 3 //Setup
  int MPI_Init(int *argc, char ***argv);
  int rank, numtasks = n, namelen, rc;
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  MPI_Status status;

  MPI_Init( &argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Get_processor_name(processor_name, &namelen);

  rc = MPI_Bcast(&system, ASIZE, MPI_DOUBLE, 0, MPI_COMM_WORLD); //Master
  // Broadcast computed initial values to all other processes

  if (rc != MPI_SUCCESS) {
    fprintf(stderr, "Oops! An error occurred in MPI_Bcast()\n");
    MPI_Abort(MPI_COMM_WORLD, rc);
  }

  //Slaves
  const float pi = 4 * atan(1.0);
  const float G = 6.67 * pow(10,-11);
  float a_x, a_y;

  for (int i = 0 ; i < n; i++) {
    if (rank != i){
      a_x = G * system[i][2] * (system[i][0]-system[rank][0]) / ((system[i][0]-system[rank][0]) * (system[i][0]-system[rank][0]));
      a_y = G * system[i][2] * (system[i][1]-system[rank][1]) / ((system[i][1]-system[rank][1]) * (system[i][1]-system[rank][1]));
    }
    if (rank == i){
      a_x = G * system[i][2] * 100 * system[i][0] / (system[i][0] * system[i][0]);
      a_y = G * system[i][2] * 100 * system[i][1] / (system[i][1] * system[i][1]);
    }
    a_x += a_x;
    a_y += a_y;
  }

  for (int i=0; i < n; i++){
    system[i][0] += system[i][5] * dt + 0.5 * a_x * dt * dt;
    system[i][1] += system[i][6] * dt + 0.5 * a_y * dt * dt;
    system[i][5] += a_x * dt;
    system[i][6] += a_y * dt;
  }

  for(int i=0 ; i<n ; i++){
    for(int j=0 ; j<i ; j++){
      if (system[j][0] == 0 && system[j][1] == 0){
    system.erase(system.begin() + j);
      } // crash into star
      if (system[j][0] == system[i][0] && system[j][1] == system[i][1]){
    system[i][2] += system[j][2];
    system.erase(system.begin() + j);
      } // planet crash
    } //check co-ordinates
  } // planet destroy loop

  for(int i = 0 ; i < n ; i++){
    if (sqrt(system[i][0]*system[i][0] + system[i][1]*system[i][1]) >= 60) system.erase(system.begin() + i);
  }

  //Send results back to the first process
  if (rank != 0){// All processes except the one of rank 0
    MPI_Send(&system, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
  }
  else {
    for (int j = 1; j < numtasks; j++) {
      MPI_Recv(&system, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 1,
           MPI_COMM_WORLD, &status);
    }
  }

  MPI_Finalize();

  ///////////////////////////
  //Time advances the solar system.
  //Plots the Orbits
  //Uses MPI to spread it's calculations.
  ///////////////////////////

  return system;
}
////////////

////////////
std::vector<bool> FinalCheck( std::vector<std::vector<float>> system, std::vector<bool> Water, int n){

///////////////////////////
//Final Checks
//Reports if a Planet spent the whole Time in the Habitable Zone
///////////////////////////

for (int i = 0 ; i < n ; i++){
  if (system[i][4] == 1.0) Water.push_back(true);
  else Water.push_back(false);
  }
return Water;
}
////////////

////////////
int main(int argc, char** argv){

  char Class;
  float L, R, M, T;

  std::tuple< char , float , float , float , float > star( Class , L , R , M , T );
  star = Star();

  int n = MyRandom()/10 + 1;

  std::vector<std::vector <float>> system ;
  std::vector<std::vector <float>> system1 ;
  system = Planet( L , R , M, T, n);

  float G = 6.67 * pow(10,-11), pi = 4 * atan(1.0), dt;
  for (int i = 0; i < n; i++){
    if (system[i][3] == 1){
      dt = 2 * pi * .01 * pow(system[i][0] * 1.5 * pow(10,8), 1.5) / sqrt(G * M * 2 * pow(10,30));
    }
    system[i].push_back(0.0); //system[i][5] is speed in x-axis                                                                                                                                
    system[i].push_back( sqrt(6.67 * pow(10,-11) * 2 * pow(10,30) * M / system[i][0])); //system[i][6] is speed in y-axis                                                                      
  }

  std::ofstream Finder;
  std::ofstream Report;
  Finder.open("plotdata.dat");
  Report.open("report.txt");
  Finder << "# Plot Co-ordinates" << std::endl;

  for (int i = 0 ; i < 1000 ; i++) {
    system1 = Time( system, n , dt , argc, **argv);
    for (int j=0 ; j<n ; j++){
      Finder << "[color " << j << "] " << system[j][0] << " " << system[j][1] << std::endl;
      if((system[j][4] == 1.0) && ( (sqrt(system[j][0] * system[j][0] + system[j][1] * system[j][1]) < sqrt(L / 1.1) ) || ((sqrt(system[j][0] * system[j][0] + system[j][1] * system[j][1]) > sqrt(L / 0.53)) ))) system[j][4] = 0.0;
    }
    system = system1;
  }
  Finder.close();
  int m;
  m = system.size()/system[0].size();

  std::vector<bool> Water;
  Water = FinalCheck( system, Water, n);

  //Report
  for (int i = 0 ; i < n ; i++){
    Report << "Planet " << i << "ends up at" << system[i][0] << " and " << system[i][1] << "has mass " << system[i][2] ;
    if (system[i][3] == 1) Report << ", which is the 'Jupiter' of the system." ;
    if (system[i][4] == 1) Report << ", which can have liquid water on the surface." ;
  }
  Report.close();
  ///////////////////////////
  //Report cleans everything up and gives the results
  //Shows the plot, lists the Planets
  //Reports the Positions and Masses of all Planets
  //Reports which was the Jupiter and which if any were Habitable
  //////////////////////////
  return 0;
}

Any thoughts the gurus here have would be appreciated, especially with getting rid of those -fpermissive errors.

Aucun commentaire:

Enregistrer un commentaire