C++ changing instance variables [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to write a program to calculate an n-body problem. I have run into a problem trying to change my code so it would be easily adaptable for any number of bodies. There seems to be a problem with the function corr(), the changes made to some variables of the instances of the class particle in this function seem to get lost after the function corr() has been used. How do i solve this problem?
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <fstream>
#define h 1000.0
#define G 6.67384*pow(10.0,-11)
using namespace std;
class particle{
public:
double kx1,kx2,kx3,kx4, kv1, kv2, kv3, kv4;
double ky1, ky2, ky3, ky4, kvy1, kvy2, kvy3, kvy4;
double x,y,vx,vy,m;
double dist(particle aap){
double dx = x - aap.x;
double dy = y - aap.y;
return sqrt(pow(dx,2.0)+pow(dy,2.0));
}
double g(double x1, double y1,particle aap){
return G*aap.m*(aap.x-x1)/pow(dist(aap),3.0);
}
double p(double x1, double y1, particle aap){
return G*aap.m*(aap.y-y1)/pow(dist(aap),3.0);
}
void update(){ //zet het object 1 stap vooruit
x = x + (1/6.0)*(kx1+2*kx2+2*kx3+kx4);
vx = vx + (1/6.0)*(kv1+2*kv2+2*kv3+kv4);
y = y + (1/6.0)*(ky1+2*ky2+2*ky3+ky4);
vy = vy + (1/6.0)*(kvy1+2*kvy2+2*kvy3+kvy4);
}
void create(double x1, double y1, double vx1, double vy1, double m1){
x = x1;
y = y1;
vx = vx1;
vy = vy1;
m =m1;
}
bool operator ==(particle &other){
if(x == other.x && y == other.y && vx == other.vx && vy == other.vy){
return true;
}
}
};
particle zon, maan, aarde;
void set(){
zon.create(1, 1, -2, 1, 2*pow(10.0,30));
aarde.create(1.5*pow(10.0,11), 0, 2, 29780, 6*pow(10.0,24));
maan.create(aarde.x + 1, aarde .y + 3.844399*pow(10.0,8), aarde.vx + -1022.0, aarde.vy + 1, 7.3347*pow(10.0,22));
}
double xforce(double x1, double y1, particle aap){ //kracht in de x-richting
particle bodies[] = {zon, aarde, maan};
double fx;
for (int i = 0; i < 3; i++){
if (bodies[i].x == aap.x && bodies[i].y == aap.y && bodies[i].vx == aap.vx && bodies[i].vy == aap.vy ){;}
else{
fx += aap.g(x1,y1,bodies[i]);
}
}
return fx;
}
double yforce(double x1, double y1, particle aap){ //kracht in de y-richting
particle bodies[] = {zon, aarde, maan};
double fy;
for (int i = 0; i <= 3; i++){
if (bodies[i].x == aap.x && bodies[i].y == aap.y && bodies[i].vx == aap.vx && bodies[i].vy == aap.vy) {;}
else{
fy += aap.p(x1,y1,bodies[i]);
}
}
return fy;
}
void corr(particle body){
body.kx1 = h*body.vx;
body.kv1 = h*xforce(body.x, body.y, body);
body.ky1 = h*body.vy;
body.kvy1 =h*yforce(body.x, body.y, body);
body.kx2 = h*(body.vx + 0.5*body.kv1);
body.kv2 = h*xforce(body.x + 0.5*body.kx1, body.y + 0.5*body.ky1, body);
body.ky2 = h*(body.vy + 0.5*body.kvy1);
body.kvy2 = h*yforce(body.x + 0.5*body.kx1, body.y + 0.5*body.ky1, body);
body.kx3 = h*(body.vx+ 0.5*body.kv2);
body.kv3 = h*xforce(body.x + 0.5*body.kx2, body.y + 0.5*body.ky2, body);
body.ky3 = h*(body.vy+ 0.5*body.kvy2);
body.kvy3 = h*yforce(body.x + 0.5*body.kx2, body.y + 0.5*body.ky2,body);
body.kx4 = h*(body.vx+body.kv3);
body.kv4 = h*xforce(body.x+ body.kx3, body.y + body.ky3, body);
body.ky4 = h*(body.vy + body.kvy3);
body.kvy4 = h*yforce(body.x + body.kx3, body.y + body.ky3, body);
}
void bereken(){
set();
ofstream file;
file.open("3body.txt");
for(int i =0; i <=30000; i++){
corr(maan);
corr(zon);
corr(aarde);
zon.update();
aarde.update();
maan.update();
file << i*h <<" "<< zon.x << " "<< zon.y << " "<< zon.vx<< " "<< zon.vy <<" "<< aarde.x << " " << aarde.y <<" "<< aarde.vx <<" " << aarde.vy <<" "<< maan.x<<" "<<maan.y<<"\n";
}
file.close();
}
int main()
{
set();
bereken();
system("pause");
return 0;
}

Just use references:
void corr(particle& body)
The same fix has to be applied in other places. What you currently have is a code that COPIES your object, does some calculations on it and then just deletes this temporary object... By using reference (&) you effectively "share" the object between the caller and callee.
In your class methods you should also use references for passing this object, but this time for efficiency reasons - it's simple to pass reference (usually the same as pointer), but copying this huge object takes time.

The suggestion made by Freddie Chopin worked and fixed the function corr(). Now however i came across the fact that the functions xforce() and yforce() don't work properly. They are supposed to return the total force on a certain particle, which they do in the first step, but after that they seem to be returning wrong values. Anyone has an idea why that happens?

Related

sum of series in c++ using if Conditional

am trying to solve the equation in c++ sum of series and am getting the right result
but I just trying to use the if statement to get the same answer of this equation
but always am getting struggling with it
# include <math.h>
#include <iostream>
using namespace std;
int main()
{
double x = 1;
double som = 0;
double lim_nbr = pow(10.0, -6);
int n = 1;
do{
x = 1.0 / ((n*n*4.0 - 1) * n);
som += x;
n+=1;
}while (x >= lim_nbr);
double correctSum = 2.0*log(2.0) -1.0 ;
cout << "Sum = " << som << endl;
cout << "Sumcorrect = " << correctSum << endl;
}
In this case for you to calculate a loop shape using only if, an alternative is to use recursive functions, look at this example:
#include <math.h>
#include <iostream>
using namespace std;
double calc(double lim_nbr, double som, double x, int n)
{
if(x >= lim_nbr || som == 0)
{
x = 1.0 / ((n*n*4.0 - 1) * n);
som += x;
n+=1;
calc(lim_nbr, som, x, n);
}
else
{
return som;
}
}
int main()
{
double lim_nbr = pow(10.0, -6);
/* Call the function with the initial values */
double som = calc(lim_nbr, 0, 1, 1);
cout << "SumWithIf = " << som <<endl;
}
The result you are getting using the do while loop is an approximation to the exact value that you are getting in correctSum. correctSum is the result obtained by adding the series upto infinte terms, however your do while loop calculates only up to a finite number of terms. Therefore the difference of the two values shows up as the error.

Loss of trig precision [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
For a gravity simulation, I need to find the angle between two objects so I can apply the force. However, I am losing precision and I don't know where. Here is the minimal code that can reproduce the issue.
#include<iostream>
using namespace std;
struct Vector2f
{
float x, y;
};
Vector2f operator-(Vector2f& left, Vector2f& right)
{
return Vector2f{ left.x - right.x, left.y - right.y };
}
double pi = 3.141592653589793238463;
double angle(Vector2f& one, Vector2f& two)
{
Vector2f normal(one - two);
if (!normal.x && !normal.y)
{
return 0.0f;
}
float theta = -(atan((double)(normal.y / normal.x)) - pi / 2);
if (normal.x < 0)
{
return (theta - pi / 2);
}
else
{
return (theta + pi / 2);
}
}
int main()
{
Vector2f one{ 0,0 };
for (int i = -100; i <= 100; i += 100)
{
for (int j = -100; j <= 100; j += 100)
{
Vector2f two{ i,j };
cout << i << ", " << j << endl;
cout << "sin:\t" << sin(angle(one, two)) * 180.0f / pi << endl;
cout << "cos:\t" << cos(angle(one, two)) * 180.0f / pi << endl;
cout << endl;
}
}
return 0;
}
For instance, where I should be getting 45 (comparing (0,0) with (100, -100) due to the grid), I am getting answers like 40.5142 and 57.2958. I understand if the precision lost were less than a degree, but this is ridiculous. I want all the output from this code to be multiples of 45, basically for those without trig knowledge. Changing the datatype of Vector2f to double does not affect the end result. Could you help me find the issue?
I am using VS 2015, but it happens similarly on VS 2013.
sin(angle(one, two)) * 180.0f / pi doesn't make sense.
it should be
sin(angle(one, two))
And you may print your angle
std::cout << angle(one, two)) * 180.0f / pi << " degree\n";
std::cout << angle(one, two)) << " radian\n";

Julia Set rendering code

I am working on escape-time fractals as my 12th grade project, to be written in c++ , using the simple graphics.h library that is outdated but seems sufficient.
The code for generating the Mandelbrot set seems to work, and I assumed that Julia sets would be a variation of the same. Here is the code:
(Here, fx and fy are simply functions to convert the actual complex co-ordinates like (-0.003,0.05) to an actual value of a pixel on the screen.)
int p;
x0=0, y0=0;
long double r, i;
cout<<"Enter c"<<endl;
cin>>r>>i;
for(int i= fx(-2); i<=fx(2); i++)
{
for(int j= fy(-2); j>=fy(2); j--)
{
long double x=0.0, y= 0.0,t;
x= gx(i), y= gy(j);
int k= -1;
while(( x*x + y*y <4)&& k<it-1)
{
t= x*x - y*y + r;
y= 2*x*y + i ;
x=t;
k++;
}
p= k*pd;
setcolor(COLOR(colour[p][0],colour[p][1],colour[p][2]));
putpixel(i,j,getcolor());
}
}
But this does not seem to be the case. The output window shows the entire circle of radius=2 with the colour corresponding to an escape time of 1 iteration.
Also, on trying to search for a solution to this problem, I've seen that all the algorithms others have used initializes the initial co-ordinates somewhat like this:
x = (col - width/2)*4.0/width;
y = (row - height/2)*4.0/width;
Could somebody explain what I'm missing out?
I guess that the main problem is that the variable i (imaginary part) is mistakenly overridden by the loop variable i. So the line
y= 2*x*y + i;
gives the incorrect result. This variable should be renamed as, say im. The corrected version is attached below, Since I don't have graphics.h, I used the screen as the output.
#include <iostream>
using namespace std;
#define WIDTH 40
#define HEIGHT 60
/* real to screen */
#define fx(x) ((int) ((x + 2)/4.0 * WIDTH))
#define fy(y) ((int) ((2 - y)/4.0 * HEIGHT))
/* screen to real */
#define gx(i) ((i)*4.0/WIDTH - 2)
#define gy(j) ((j)*4.0/HEIGHT - 2)
static void julia(int it, int pd)
{
int p;
long double re = -0.75, im = 0;
long double x0 = 0, y0 = 0;
cout << "Enter c" << endl;
cin >> re >> im;
for (int i = fx(-2.0); i <= fx(2.0); i++)
{
for (int j = fy(-2.0); j >= fy(2.0); j--)
{
long double x = gx(i), y = gy(j), t;
int k = 0;
while (x*x + y*y < 4 && k < it)
{
t = x*x - y*y + re;
y = 2*x*y + im;
x = t;
k++;
}
p = (int) (k * pd);
//setcolor(COLOR(colour[p][0],colour[p][1],colour[p][2]));
//putpixel(i,j,getcolor());
cout << p; // for ASCII output
}
cout << endl; // for ASCII output
}
}
int main(void)
{
julia(9, 1);
return 0;
}
and the output with input -0.75 0 is given below.
0000000000000000000000000000000000000000000000000000000000000
0000000000000000000001111111111111111111000000000000000000000
0000000000000000011111111111111111111111111100000000000000000
0000000000000001111111111111111111111111111111000000000000000
0000000000000111111111111122222222211111111111110000000000000
0000000000011111111111122222349432222211111111111100000000000
0000000001111111111112222233479743322222111111111111000000000
0000000011111111111222222334999994332222221111111111100000000
0000000111111111112222223345999995433222222111111111110000000
0000011111111111122222234479999999744322222211111111111100000
0000011111111111222222346899999999986432222221111111111100000
0000111111111111222223359999999999999533222221111111111110000
0001111111111112222233446999999999996443322222111111111111000
0011111111111112222233446999999999996443322222111111111111100
0011111111111122222333456899999999986543332222211111111111100
0111111111111122223334557999999999997554333222211111111111110
0111111111111122233345799999999999999975433322211111111111110
0111111111111122233457999999999999999997543322211111111111110
0111111111111122334469999999999999999999644332211111111111110
0111111111111122345999999999999999999999995432211111111111110
0111111111111122379999999999999999999999999732211111111111110
0111111111111122345999999999999999999999995432211111111111110
0111111111111122334469999999999999999999644332211111111111110
0111111111111122233457999999999999999997543322211111111111110
0111111111111122233345799999999999999975433322211111111111110
0111111111111122223334557999999999997554333222211111111111110
0011111111111122222333456899999999986543332222211111111111100
0011111111111112222233446999999999996443322222111111111111100
0001111111111112222233446999999999996443322222111111111111000
0000111111111111222223359999999999999533222221111111111110000
0000011111111111222222346899999999986432222221111111111100000
0000011111111111122222234479999999744322222211111111111100000
0000000111111111112222223345999995433222222111111111110000000
0000000011111111111222222334999994332222221111111111100000000
0000000001111111111112222233479743322222111111111111000000000
0000000000011111111111122222349432222211111111111100000000000
0000000000000111111111111122222222211111111111110000000000000
0000000000000001111111111111111111111111111111000000000000000
0000000000000000011111111111111111111111111100000000000000000
0000000000000000000001111111111111111111000000000000000000000
0000000000000000000000000000000000000000000000000000000000000
would you please tell how you display the image by using these graphics.h library
//setcolor(COLOR(colour[p][0],colour[p][1],colour[p][2]));
//putpixel(i,j,getcolor());

In C++ finding sinx value with Taylor's Series

I am trying to write a block of codes in C++ that calculates sinX value with Taylor's series.
#include <iostream>
using namespace std;
// exp example
#include <cstdio> // printf
#include <cmath> // exp
double toRadians(double angdeg) //convert to radians to degree
{ //x is in radians
const double PI = 3.14159265358979323846;
return angdeg / 180.0 * PI;
}
double fact(double x) //factorial function
{ //Simply calculates factorial for denominator
if(x==0 || x==1)
return 1;
else
x * fact(x - 1);
}
double mySin(double x) //mySin function
{
double sum = 0.0;
for(int i = 0; i < 9; i++)
{
double top = pow(-1, i) * pow(x, 2 * i + 1); //calculation for nominator
double bottom = fact(2 * i + 1); //calculation for denominator
sum = sum + top / bottom; //1 - x^2/2! + x^4/4! - x^6/6!
}
return sum;
}
int main()
{
double param = 45, result;
result = mySin(toRadians(param)); //This is my sin value
cout << "Here is my homemade sin : " << result << endl;
result = sin(param); //This is library value
cout << "Here is the API sin : " << result << endl;
return 0;
}
So my program works without any error. My output is exactly:
Here is my homemade sin : nan
Here is the API sin:0.850904
I know I am making a big logic mistake but I couldn't find it out. It is my second week with C++. I am more familiar with Java. I coded the same thing and It worked absolutely perfect. The answers matched each other.
Thanks for your time and attention!
in fact, you miss the return: x*fact(x-1); should be return x*fact(x-1);. You can see the compiler complaining if you turn the warnings on. For example, with GCC, calling g++ -Wall program.cpp gives Warning: control reaches end of non-void function for the factorial function.
The API sin also needs the angle in radians, so change result=sin(param); into result=sin(toRadians(param));. Generally, if in doubt about the API, consult the docs, like here.
Your codes seems to have some logical mistakes. Here is my corrected one:
#include <iostream>
using namespace std;
double radians(double degrees) // converts degrees to radians
{
double radians;
double const pi = 3.14159265358979323846;
radians = (pi/180)*degrees;
return radians;
}
double factorial(int x) //calculates the factorial
{
double fact = 1;
for(; x >= 1 ; x--)
{
fact = x * fact;
}
return fact;
}
double power(double x,double n) //calculates the power of x
{
double output = 1;
while(n>0)
{
output =( x*output);
n--;
}
return output;
}
float sin(double radians) //value of sine by Taylors series
{
double a,b,c;
float result = 0;
for(int y=0 ; y!=9 ; y++)
{
a= power(-1,y);
b= power(radians,(2*y)+1);
c= factorial((2*y)+1);
result = result+ (a*b)/c;
}
return result;
}
double n,output;
int main()
{
cout<<"enter the value\t";
cin>>n;
n = radians(n);
cout<< "\nthe value in radians is\t"<< n << "\n";
output = sin(n);
cout<< "\nsine of the given value is\t"<< output;
return 0;
}
The intention of this program was to use custom functions instead of libraries to make learning for others easy.
There are four user defined functions in this program.The first three user defined functions 'radians()', 'factorial()','power()', are apparently simple functions that perform operations as their name suggests.
The fourth function 'sin()' takes input in radians given by the function 'radians()'. The sin function uses Taylors series iterated term wise in the function's 'for(int y= 0;y!=9;y++)' loop till nine iterations to calculate the output.The 'for()' loop iterates the general mathematical expression: Term(n)=((-1)^n).(x^(2n+1))/(2n+1)!
sin(x)= x- x^3/3! + x^5/5! -x^7/7! + x^9/9!
=x-x^3/2*3 (1- x^2/4*5 + x^4/4*5*6*7 + x^6/4*5*6*7*8*9)
=x - x^3/2*3 {1- x^2/4*5(1- x^2/6*7 + x^4/6*7*8*9)}
=x - x^3/2*3 [{1- x^2/4*5 ( 1- x^2/6*7 (1- x^2/8*9))}]
=x(1 - x^2/2*3 [{1- x^2/4*5 ( 1- x^2/6*7 (1- x^2/8*9))}])
double sin_series_recursion(double x, int n){
static double r=1;
if(n>1){
r=1-((x*x*r)/(n*(n-1)));
return sin_series_recursion(x,n-2);
}else return r*x;
}

C++ Segmentation Fault on Differential Solver

I have written a program to approximate the solutions to ordinary differential equations using Adam's Method.
Running the program with gdb gives me:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f3ffff8
0x0000000100003977 in std::vector<double, std::allocator<double> >::push_back (this=0x100005420, __x=#0x100005310) at stl_vector.h:604
604 this->_M_impl.construct(this->_M_impl._M_finish, __x);
Clearly something is wrong with my treatment of vector.push_back, but I do not know where to begin looking. I can not think of a case where modifying a vector is illegal.
Call differentiate() to begin. Mathematics is done in step(). Adaptive time advancing across an interval with advance(). Check the chosen time step with checkdt() before running step() again.
Sorry for the huge code dump. I am sure many improvements can be made purely from the standpoint of C++, without knowledge of the mathematics:
//============================================================================
// Description : An Adam's Method Ordinary Differential Equation Approximation
// Disclaimer : Posted to StackOverflow for help on a segmentation fault
//============================================================================
#include <iostream> //IO
#include <vector> //std::vector
#include <cmath> //abs, pow, sqrt
#include <numeric> //accumulate
using namespace std;
/* Terminology:
* f(t, y) = the ordinary differential equation that will be solved
* y(t) = solution of f at point t.
* told = the previous point at which f was evaluated and solved
* tnow = the current point at which f is evaluated and solved
* tnew = the new (interesting) point at which f will be evaluated and solved
*
* Yold = the corrected solution of the differential equation at told
* Ynow = the corrected solution of the differential equation at tnow
* Ynew = the corrected solution of the differential equation at tnew
*
* fold = the value of the given differential equation at told
= f(told, Yold)
* fnow = the value of the given differential equation at tnow
= f(tnow, Ynow)
* fnew = the value of the given differential equation at tnew
= f(tnew, Ynew)
*
* Pnew = prediction for the value of Ynew
* dt = abs(tnew - tnow)
* dtold = abs(tnow - told)
*/
//Information storage
struct simTime {
double told;
double tnow;
double tnew;
double dt;
double dtold;
double tol;
double agrow;
double ashrink;
double dtmin;
double dtmax;
double endTime;
double fold;
double fnow;
double fnew;
double Yold;
double Ynow;
double Ynew;
double Pnew;
int stepsSinceRejection;
int stepsRejected;
int stepsAccepted;
} test;
//Define global variables
std::vector<double> errorIndicators(0);
std::vector<double> solutions(0);
std::vector<double> differencesDDY(0);
std::vector<double> differencesDDYSquared(0);
std::vector<double> timesTNew(0);
//Function declarations
void step(double fnow, double fold, double Ynow, double tnew, double tnow,
double dtold, double dt, double(*f)(double t, double y), double told);
void advance();
void shiftvariables();
void printvector(std::vector<double>& vec);
void differentiate(double(*f)(double t, double y), double y0, double a,
double b);
double f(double t, double y);
void checkdt();
int main() {
differentiate(f, 0, 1, 5);
cout << "Time values:" << endl;
printvector(timesTNew);
cout << "Solutions:" << endl;
printvector(solutions);
cout << "Differences between Prediction and Solution:" << endl;
printvector(differencesDDY);
return 0;
}
//Shift back all the variables to make way for the new values
void shiftvariables() {
test.tnow = test.tnew;
test.dtold = test.dt;
test.Yold = test.Ynow;
test.Ynow = test.Ynew;
test.fold = test.fnow;
test.fnow = test.fnew;
advance();
}
//Ordinary differential equation to be solved
double f(double t, double y) {
return pow(t, 2);
}
//Calculate the predicted and corrected solution at a chosen tnew
void step(double fnow, double fold, double Ynow, double tnew, double tnow,
double dtold, double dt, double(*f)(double t, double y), double told) {
//The calculation for Ynew requires integration. I first thought I would need to
// use my project 1 code to calculate the integration, but now I see in class we
// solved it analytically such that integration is not required:
//Linear prediction of Ynew using Ynow and fnow
double Pnew = Ynow + (dt * fnow) + (dt * dt / (2 * dtold)) * (fnow - fold);
test.Pnew = Pnew;
//Predict the value of f at tnew using Pnew
double fnew = f(tnew, Pnew);
test.fnew = fnew;
//Calculate the corrected solution at tnew
double interpolationFactor = fnew - (fnow + dt * (fnow - fold) / dtold);
double integration = (dt / 6) * (2 * dt + 3 * dtold) / (dt + dtold);
double Ynew = Pnew + interpolationFactor * integration;
test.Ynew = Ynew;
//Update the variables for the next round
shiftvariables();
}
//Check the previous solution and choose a new dt to continue evaluation
void advance() {
//The error indicator is the l2-norm of the prediction minus the correction
double err_ind = sqrt(
std::accumulate(differencesDDYSquared.begin(),
differencesDDYSquared.end(), 0));
errorIndicators.push_back(err_ind);
// Case where I reject the step and retry
if (err_ind > test.tol && test.dt > test.dtmin) {
++test.stepsRejected;
test.stepsSinceRejection = 0;
test.dt = test.dt * 0.5;
test.tnew = test.tnow + test.dt;
checkdt();
}
// Cases where I accept the step and move forward
else {
++test.stepsAccepted;
++test.stepsSinceRejection;
solutions.push_back(test.Ynew);
differencesDDY.push_back(abs(test.Pnew - test.Ynew));
differencesDDYSquared.push_back(pow((test.Pnew - test.Ynew), 2));
//Decrease dt
if (err_ind >= 0.75 * test.tol) {
test.dtold = test.dt;
test.dt = (test.dt * test.ashrink);
test.tnew = test.tnow + test.dt;
checkdt();
}
//Increase dt
else if (err_ind <= test.tol / 4) {
if ((test.stepsRejected != 0) && (test.stepsSinceRejection >= 2)) {
test.dt = (test.dt * test.agrow);
test.tnew = test.tnow + test.dt;
checkdt();
} else if (test.stepsRejected == 0) {
test.dt = (test.dt * test.agrow);
test.tnew = test.tnow + test.dt;
checkdt();
}
}
}
}
//Check that the dt chosen by advance is acceptable
void checkdt() {
if ((test.tnew < test.endTime) && (test.endTime - test.tnew < test.dtmin)) {
cout << "Reached endTime." << endl;
} else if (test.dt < test.dtmin) {
test.dt = test.dtmin;
test.tnew = test.tnow + test.dt;
timesTNew.push_back(test.tnew);
step(test.fnow, test.fold, test.Ynow, test.tnew, test.tnow, test.dtold,
test.dt, f, test.told);
} else if (test.dt > test.dtmax) {
test.dt = test.dtmax;
test.tnew = test.tnow + test.dt;
timesTNew.push_back(test.tnew);
step(test.fnow, test.fold, test.Ynow, test.tnew, test.tnow, test.dtold,
test.dt, f, test.told);
} else if ((test.tnew + test.dt) > test.endTime) {
test.dt = test.endTime - test.tnew;
test.tnew = test.tnow + test.dt;
checkdt();
} else if (((test.tnew + test.dt) < test.endTime)
&& ((test.tnew + 2 * test.dt) > test.endTime)) {
test.dt = (test.endTime - test.tnew) / 2;
test.tnew = test.tnow + test.dt;
checkdt();
}
//If none of the above are satisfied, then the chosen dt
// is ok and proceed with it
else {
timesTNew.push_back(test.tnew);
step(test.fnow, test.fold, test.Ynow, test.tnew, test.tnow, test.dtold,
test.dt, f, test.told);
}
}
//meta function to solve a differential equation, called only once
void differentiate(double(*f)(double t, double y), double y0, double a,
double b) {
//Set the starting conditions for the solving of the differential equation
test.fnow = f(a, y0);
test.endTime = b;
test.Ynow = y0;
//solutions.push_back(y0);
timesTNew.push_back(a);
//Set the constants
test.ashrink = 0.8;
test.agrow = 1.25;
test.dtmin = 0.05;
test.dtmax = 0.5;
test.tol = 0.1;
//Set fold = fnow for the first step
test.fold = test.fnow;
test.tnow = a;
test.told = a - test.dtmin;
test.dtold = abs(test.tnow - test.told);
//Create the first prediction, which will then lead to correcting it with step
advance();
}
// Takes a vector as its only parameters and prints it to stdout
void printvector(std::vector<double>& vec) {
for (vector<double>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << *it << ", ";
}
cout << "\n";
}
Thank you.
Since you're using recursion, could it be possible that you are running out of stack memory, thus causing the segfault? This could happen if either your app recurses too many times or if some bug causes it to recurse infinitely.
Note, as sth suggests in a comment, a debugger may help you decide whether or not this is the case.