I am trying to integrate functions, which includes changing of variables with ICDF function (gsl_cdf_gaussian_Pinv(x[1], 1)), but the results are always wrong:
#include <fstream>
#include <iostream>
#include <memory>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <math.h>
#include <stdio.h>
#include <gaussinv.c>
#define _USE_MATH_DEFINES
using namespace std;
double f(double[], int);
double int_mcnd(double(*)(double[], int), double[], double[], int, int);
double varr[100];
int k = 0;
double hj = 0;
double mj = 1;
# include "sobol.hpp"
int DIM_NUM = 10;
int main() {
const int n = 10; /* define how many integrals */
// const int m = 1000000; /* define how many points */
double a[n] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* left end-points */
double b[n] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /* right end-points */
double result;
int i, m;
int ntimes;
cout.setf(ios::fixed | ios::showpoint);
// current time in seconds (begin calculations)
time_t seconds_i;
seconds_i = time(NULL);
m = 1; // initial number of intervals
ntimes = 20; // number of interval doublings with nmax=2^ntimes
cout << setw(12) << n << "D Integral" << endl;
for (i = 0; i <= ntimes; i = i + 1) {
result = int_mcnd(f, a, b, n, m);
cout << setw(10) << m << " " << setprecision(30) << result << endl;
m = m * 2;
}
// current time in seconds (end of calculations)
time_t seconds_f;
seconds_f = time(NULL);
cout << endl << "total elapsed time = " << seconds_f - seconds_i << " seconds" << endl << endl;
return 0;
}
double f(double x[], int n) {
double y;
int j;
y = 0.0;
/* define Multidimensional Gaussian distribution and covariance */
/* X=(x1, k=2, mu = (0, covariance matrix = (v 0 0 0
* x2 0 0 v 0 0
* x3 0 0 0 v 0
* x4) 0) 0 0 0 v) */
double v = 1;
double determinant = pow(v, 10);
double inverse = 1 / v;
double rang = gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1) - gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1) +
gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1);
y = (1 / sqrt(pow(2 * M_PI, 10) * determinant) * exp(-0.5 * (inverse * pow(gsl_cdf_gaussian_Pinv(x[0], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[1], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[2], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[3], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[4], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[5], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[6], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[7], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[8], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[9], 1), 2))));
return y;
}
/*==============================================================
input:
fn - a multiple argument real function (supplied by the user)
a[] - left end-points of the interval of integration
b[] - right end-points of the interval of integration
n - dimension of integral
m - number of random points
output:
r - result of integration
================================================================*/
double int_mcnd(double(*fn)(double[], int), double a[], double b[], int n, int m) {
double r, x[n], p;
int i, j;
double rarr[DIM_NUM];
long long int seed;
seed = 1;
long long int seed_in;
long long int seed_out;
srand(time(NULL)); /* initial seed value (use system time) */
r = 0.0;
p = 1.0;
// step 1: calculate the common factor p
for (j = 0; j < n; j = j + 1) {
// p = p * (b[j] - a[j]);
p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1));
}
// step 2: integration
for (i = 1; i <= m; i = i + 1) {
seed_in = seed;
i8_sobol(DIM_NUM, &seed, rarr);
seed_out = seed;
// calculate random x[] points
for (j = 0; j < n; j = j + 1) {
x[j] = a[j] + (b[j] - a[j]) * rarr[j];
}
r = r + fn(x, n);
}
cout << endl << "p = " << p << " seconds" << endl << endl;
r = r * p / m;
return r;
}
The problem is in the parametrization parameter p, which I suggest to be
p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1))
instead of standard - p = p * (b[j] - a[j]);
I want to integrate not only within [0,1]^N intervals, but also in [-20;20].
I can't define my mistake. Can somebody help, please?
Related
I'm trying to implement the shooting method which is used to solve 2nd-order ordinary differential equations with boundary conditions in C++. The equation is d^2y/dx^2 = 2ydy/dx. The boundary conditions provided are at x = 0, u1 =0.5 and at x = 1, u1 =1. The step size for x is 0.25. The values of U1 and U2 are being solved simultaneously at each x/iteration. However, on printing the values of U1 and U2 I get 0 as the output.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int i{0}, j{0};
double K1_one, K2_one, K3_one, K4_one, K_one;
double K1_two, K2_two, K3_two, K4_two, K_two;
double x[5] = {0, 0.25, 0.5, 0.75, 1};
double U1[5] = {0.5};
double U2[5] = {};
double G1{0}, G2{0}, G3{0};
double a{0}, b{0};
double f1(double u2)
{
return u2;
}
double f2(double u1, double u2)
{
return 2 * u1 * u2;
}
double RK4_f1(double U2[5])
{
K1_one = 0.25 * (f1(U2[i - 1]));
K2_one = 0.25 * (f1(U2[i - 1] + K1_one / 2));
K3_one = 0.25 * (f1(U2[i - 1] + K2_one / 2));
K4_one = 0.25 * (f1(U2[i - 1] + K3_one));
K_one = (K1_one + 2 * K2_one + 2 * K3_one + K4_one) / 6;
U1[i] = U1[i - 1] + K_one;
a = U1[i];
return a;
}
double RK4_f2(double U1[5], double U2[5])
{
K1_two = 0.25 * (f2(U1[i - 1], U2[i - 1]));
K2_two = 0.25 * (f2(U1[i - 1] + 0.25 / 2, U2[i - 1] + K1_two / 2));
K3_two = 0.25 * (f2(U1[i - 1] + 0.25 / 2, U2[i - 1] + K2_two / 2));
K4_two = 0.25 * (f2(U1[i - 1] + 0.25, U2[i - 1] + K3_two));
K_two = (K1_two + 2 * K2_two + 2 * K3_two + K4_two) / 6;
U2[i] = U2[i - 1] + K_two;
b = U2[i];
return b;
}
int main()
{
cout << "Enter your first random guess for u2" << endl;
cin >> G1;
U2[0] = G1;
cout << "\nu1[i]\tu2[i]\n"
<< endl;
for (int i = 1; i < 5; i++)
{
for (int j = 1; j <= 2; j++)
{
if (j == 1)
{
a = RK4_f1(U2);
}
else
{
b = RK4_f2(U1, U2);
}
}
cout << a << "\t" << b << endl;
}
cout << "Enter your second random guess for u2" << endl;
cin >> G2;
U2[0] = G2;
cout << "\nu1[i]\tu2[i]\n"
<< endl;
for (int i = 1; i < 5; i++)
{
for (int j = 1; j <= 2; j++)
{
if (j == 1)
{
a = RK4_f1(U2);
}
else
{
b = RK4_f2(U1, U2);
}
}
cout << a << "\t" << b << endl;
}
}
Using the formula in the pic, I need to write a program that allows the user to calculate sin(x), cos(x), tan(x). The user should enter the angle in degrees, and then the program should transform it into radians before performing the three requested calculations. For each requested calculation (i.e., sin(x), cos(x), tan(x)), I only need to calculate the first 15 terms of the series.
The problem seems to be in the arrays of the last block in the code, it keeps returning wrong results of the tan(x) series; how can I fix it?
#include <iostream>
using namespace std;
//create a function to convert angles from degrees to radian
double convertToRadian(double deg)
{ //formula : radian = (degree * pi)/180
const double pi = 3.14159265359; //declaring pi's value as a constant
return (deg * (pi / 180)); //returning the radian value
}
//create a function to calculate the exponent/power
double power(double base, unsigned int exp)
{
double result = 1;
for(int i = 0; i < exp; i++){
result = result * base;
}
return result;
}
//create a function to get the factorial of a value
double factorial(int fac)
{
if(fac > 1)
return fac * factorial(fac - 1);
else
return 1;
}
//create a function to print out arrays as we will use it to print the terms in the series
void printTerms(double terms[15])
{ for (int i = 0; i < 15; i++)
{
cout<<terms[i]<<endl;
}
}
int main()
{
double degree; //declare the variables used in the program
double valueOfCos, valueOfSin, valueOfTan; //declare variables for terms of each function
cout << "Enter angle (x) in degrees: " << endl; //prompt for user to enter angle in deg
cin >> degree;
double radian = convertToRadian(degree); //first, converting from degrees to radian
//make an array for the first 15 terms of cos(x):
double cos[15];
//make a loop to insert values in the array
for (int n = 0; n < 15; n++)
{ //type the maclaurin series formula for cos(x):
valueOfCos = (( power(-1 , n)) / (factorial(2*n))) * (power(radian, (2*n)));
cos[n] = valueOfCos;
}
//print out the first 15 terms of cos(x) in the maclaurin series:
cout << "cos(x)= ";
printTerms (cos);
//make an array for the first 15 terms of sin(x):
double sin[15];
for (int n = 0; n < 15; n++)
{
valueOfSin = ((power(-1 , n)) / (factorial((2*n + 1)))) * (power(radian, (2*n + 1)));
sin[n] = valueOfSin;
}
cout << "sin(x)= ";
printTerms (sin);
double tan[15];
for (int n = 0; n < 15; n++)
{ double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730),
(7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730),
(8553103/6),(-23749461029/870),(8615841276005/14322) };
for (int i = 0; i < 15; i++)
{
double firstNum = 0, secondNum = 0 , thirdNum = 0 , denominator = 0;
firstNum = power(-1 , n);
secondNum = power(2 , 2*n + 2);
thirdNum = ((secondNum) - 1);
denominator = factorial(2*n + 2);
valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[i])) / denominator) *
(power(radian, 2*n + 1));
tan [n] = valueOfTan;
}
}
cout << "tan(x)= ";
printTerms (tan);
return 0;
}
This loop : for (int n = 0; n < 15; n++) is not running or entire expression. You'll need to correct something like this :
double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730),(7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730),(8553103/6),(-23749461029/870),(8615841276005/14322) };
for (int n = 0; n < 15; n++){
double firstNum = 0, secondNum = 0 , thirdNum = 0 , denominator = 0;
firstNum = power(-1 , n);
secondNum = power(2 , 2*n + 2);
thirdNum = ((secondNum) - 1);
denominator = factorial(2*n + 2);
valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[n])) / denominator) * (power(radian, 2*n + 1));
tan [n] = valueOfTan;
}
}
You are incorrectly calculating the tan value.
In valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[i])) / denominator) * (power(radian, 2 * n + 1));
Instead of bernoulli[i], you need to have bernoulli[2*i+2] as per the formulae.
And one more suggestion please pull the double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730), (7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730), (8553103/6),(-23749461029/870),(8615841276005/14322) array initialization out of the for loop, as it's constant you don't need to initialize it every time unnecessarily. It will increase your code runtime
how do I replace the pow() function in two cases in my code ?
I think this can be done with a for loop
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b, h, PI = 3.141592;
int n;
cin >> a >> b >> h >> n;
for (double x = a; x <= b; x += h) {
double ans = 1, y;
for (int k = 0; k <= n; k++) {
ans *= cos(k * PI / 4) * pow(x, k);
for (int i = 2; i <= k; i++) {
ans /= i;
}
}
y = pow(exp(cos(x * sin(PI / 4))), x * cos(PI / 4));
cout << ans << " " << y << " " << fabs(y-ans) << endl;
}
return 0;
}
Do not write everything in main.
Define double S(double x, int n) and double U(double x).
each element of sum can be calculated based on previous element.
cos(k * M_PI / 4) has repeating values so it can be stored in table.
double S(double x, int n)
{
double a = 1;
double s = a;
constexpr double q = std::cos(M_PI / 4);
constexpr double cos_val[]{ 1, q, 0, -q, -1, -q, 0, q };
for (int k = 1; k <= n; ++k) {
a *= x / k;
s += cos_val[k & 7] * a
}
return s;
}
For the inner loop, you need not calculate the power in each iteration if you consider that on the previous iteration you already calculated pow(x,k-1) and that pow(x,k) == pow(x,k-1)*x:
double pow_x = 1; // on first iteration pow(x,0) == 1
for (int k = 0; k <= n; k++) {
ans *= cos(k * PI / 4) * pow_x;
// ...
pow_x *= x; // pow(x,k) -> pow(x,k+1)
}
The second use of pow in your code cannot be easily replaced, because of the floating point exponent. You would have to rewrite pow to get the same result. However, your code does not match the formula in the image. The image says (pseudo maths notation):
e ^ ( x * C1 ) * C2
your code is calculating
y = pow(exp(cos(x * sin(PI / 4))), x * cos(PI / 4));
( e^(C2) ) ^ (x * C1)
change it to
y = exp(x * cos(PI / 4)) * cos(x * sin(PI / 4))
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.
EDIT 1 - Code as presented will now completely compile - but will return a Segmentation fault during the Star routine. After the user inputs the star type but before it actually makes a star as far as I can tell.
I wanna use monte-carlo integration method, and my code is below. As u can see i determined the interval integration but the result is wrong ! Whats wrong with this code ?
any help will be appreciated .
#include <iostream>
#include <math.h>
#include <stdlib.h>
#define N 500
using namespace std;
double Func(double x) { return pow(x, 2) + 1; }
double Monte_Carlo(double Func(double), double xmin, double xmax, double ymin,
double ymax)
{
int acc = 0;
int tot = 0;
for (int count = 0; count < N; count++)
{
double x0 = (double)rand() / 4 + (-2);
double y0 = (double)rand() / 4 + 0;
float x = x0 / (float)RAND_MAX;
float y = y0 / (float)RAND_MAX;
cout << x << endl;
if (y <= Func(x))
acc++;
tot++;
// cout << "Dgage" << tot << '\t' << acc << endl;
}
double Coeff = acc / N;
return (xmax - xmin) * (1.2 * Func(xmax)) * Coeff;
}
int main()
{
cout << "Integral value is: " << Monte_Carlo(Func, -2, 2, 0, 4) << endl;
system("pause");
return 0;
}
The Monte_Carlo function is making things more complicated then they need to be. For integrating a 1-dimensional function, all we have to do is sample the value of the function a bunch of times within the region we're integrating over:
#include <random>
double Monte_Carlo(double Func(double), double xmin, double xmax, int N)
{
// This is the distribution we're using to generate inputs
auto x_dist = std::uniform_real_distribution<>(xmin, xmax);
// This is the random number generator itself
auto rng = std::default_random_engine();
// Calculate the total of N random samples
double total = 0.0;
for(int i = 0; i < N; i++) {
double x = x_dist(rng); // Generate a value
total += Func(x);
}
// Return the size of the interval times the total,
// divided by the number of samples
return (xmax - xmin) * total / N;
}
If we run this code with N = 1000, we get an integral value of 9.20569, which is pretty close to the exact answer (9.33333...).
// It's much more efficent to use x*x instead of pow
double func(double x) { return x * x + 1; }
int main()
{
cout << "Integral value is: " << Monte_Carlo(func, -2, 2, 1000) << endl;
getchar(); // Pause until the user presses enter
return 0;
}
We can also try multiple values of N, to have the program show how it converges. The following program calculates the integral with N being powers of 2 from 0 to 30
#include <iostream>
#include <cmath>
#include <random>
using namespace std;
double func(double x) { return x*x + 1; }
double Monte_Carlo(double Func(double), double xmin, double xmax, int N) {
auto x_dist = std::uniform_real_distribution<>(xmin, xmax);
auto rng = std::default_random_engine();
double total = 0.0;
for(int i = 0; i < N; i++) {
double x = x_dist(rng); // Generate a value
total += Func(x);
}
return (xmax - xmin) * total / N;
}
int main() {
int N = 1;
for(int i = 0; i < 31; i++) {
std::cout << "N = " << N << "\t\tintegral = " << Monte_Carlo(func, -2, 2, N) << endl;
N *= 2; // Double N
}
}
The output shows that the monte carlo method does actually converge:
N = 1 integral = 12.6889
N = 2 integral = 8.39917
N = 4 integral = 7.97521
N = 8 integral = 9.24233
N = 16 integral = 9.75632
N = 32 integral = 9.87064
N = 64 integral = 9.46945
N = 128 integral = 9.27281
N = 256 integral = 9.27395
N = 512 integral = 9.17546
N = 1024 integral = 9.19097
N = 2048 integral = 9.26203
N = 4096 integral = 9.37979
N = 8192 integral = 9.36167
N = 16384 integral = 9.28918
N = 32768 integral = 9.29766
N = 65536 integral = 9.31101
N = 131072 integral = 9.3227
N = 262144 integral = 9.32588
N = 524288 integral = 9.32805
N = 1048576 integral = 9.32726
N = 2097152 integral = 9.32722
N = 4194304 integral = 9.331
N = 8388608 integral = 9.33082
N = 16777216 integral = 9.33174
N = 33554432 integral = 9.33164
N = 67108864 integral = 9.33303
N = 134217728 integral = 9.33283
N = 268435456 integral = 9.33327
N = 536870912 integral = 9.33325
N = 1073741824 integral = 9.33333