Garmaine Staff asked 2 years ago

Long time Reader, First time Asker.

So I'm working on a coding project of which the long term goal is to make a solar system simulator. The idea is that that it whips up a randomized solar system with a few rules like 'at formation the first planet after the frostline has to be the largest gas giant' etc, and calculates the orbits to check for stability.

Obviously it's not done yet, I'm having some trouble with using the arrays in the subroutines. I know that you can't directly take arrays in and out of functions, but you can take pointers to said arrays in and out of functions if you do it right.

I apparently have not done it right below. I've tried to comment and make the code as readable as possible, here it is.

#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"

using namespace std;

double MyRandom(){

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

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

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

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

///////////////////////
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;
string Choice;
float L, R, M;
int T;
tuple< char& , float& , float& , float& , int& > star( Class = 'i', L = 1 , R = 1 , M = 1 , T = 3000) ;
cout << "Select Star Class (OBAFGKM) or Select R for Random: ";
cin >> Choice;
if ( Choice == "R" ) {
    double y;
    y = MyRandom();
    if (y <= 0.003) Class = 'O';
    if ((y > 0.003) && (y <= 0.133)) Class = 'B';
    if ((y > 0.133) && (y <= 0.733)) Class = 'A';
    if ((y > 0.733) && (y <= 3.733)) Class = 'F';
    if ((y > 3.733) && (y <= 11.333)) Class = 'G';
    if ((y > 11.333) && (y <= 23.433)) Class = 'K';
    else Class = 'M';
    }
    if (Class == 'O') {
        L = 30000;
        R = 0.0307;
        M = 16;
        T = 30000;
    }
    if (Class == 'B') {
        L = 15000;
        R = 0.0195;
        M = 9;
        T = 20000;
    }
    if (Class == 'A') {
        L = 15;
        R = 0.00744;
        M = 1.7;
        T = 8700;
    }
    if (Class == 'F') {
        L = 3.25;
        R = 0.00488;
        M = 1.2;
        T = 6750;
    }
    if (Class == 'G') {
        L = 1;
        R = 0.00465;
        M = 1;
        T = 5700;
    }
    if (Class == 'K') {
        L = 0.34;
        R = 0.00356;
        M = 0.62;
        T = 4450;
    }
    if (Class == 'M') {
        L = 0.08;
        R = 0.00326;
        M = 0.26;
        T = 3000;
    }

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

////////////
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.
    float sys[n];
    float* system[n][5] = {{0}};

    for (int i = 0 ; i < n ; i++){
        sys[i] = MyRandom()/10 * 3; //Distances in terms of Sol AU
    }
    sort(sys, sys + n );
    for (int i = 0 ; i < n ; i++){
        system[i][0] = &sys[i];
        system[i][1] = 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][2] = &tmass ; //system[i][2] is mass, [3] is marker for the Jupter
            system[i][3] = 0 ;
        }

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

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

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

    }

    return system[n][5];
}
////////////

////////////
float* Time( float *system , int n){

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

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

////////////
void FinalCheck( float system){

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

/*for (int i = 0 ; i < row ; i++){
    if (system[i][4] == 1.0) {
        cout << "Planet " << i << " in this system is Habitable." ;
        }
    // The Habitable stat only means liquid water can exist on the surface
    // Add pi if planet enters habitable zone, minus 1 if it leaves.
    // If planet was habitable but left, assuming all life was destroyed
    }
*/
}
////////////

int main(){

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

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

int n = MyRandom()/10 + 1;

float * system[n][5] = {{0}};
float system1[n][5] = {{0}};
system[n][5] = Planet( L , R , M, T, n);

for (int i = 0 ; i < 100 ; i++) {
 system1[n][5] = Time( *system, n );
 system[n][5] = &system1[n][5];
}
FinalCheck( *system[n][5]);

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

The problem is when I run a compiler over this line 227 gets flagged –

  system1[n][5] = Time( *system, n );

With the following error:

  error: cannot convert 'float**' to 'float*' for argument '1' to 'float* Time(float*, int)

I get that this means that the compiler things I'm trying to equate a pointer-to-a-pointer with a pointer, but I'm not sure how it arrived at that conclusion or how to fix it. I'd appreciate help with this, especially the second part. I also would love to hear anything about passing arrays through subroutines as apparently I'm not doing it right, or at least not well.

Update 1 : – Got the short-term fix in and the compiler makes it through but gives a segmentation fault (core dumped) error when I try to run it. Looks like I have some reading and updates to do though with the namespace, the pointers, and possibly changing the arrays into vectors instead. Feels like if I concentrate on those first it might fix the segmentation error.