I'm having trouble with a for loop!

I'm trying to solve a differential equation using Euler's method like so;

\displaystyle\frac{dy}{dx} = 7{y^2}cos(y^2)-3e^{xy}, \ \ \ 0 \leq x \leq 1 \ \ \ y(0) = 0

This is solved using the algorithm

y_{n+1} = y_n + hf(x_n , y_n)

Where h is the step size and f is the right hand side of the ODE.

Now, I need to write a program to solve this ODE , using an appropriate step size, and outputting a table of values with x and y in the range 0\leq x \leq 1

Heres my program;

#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <fstream>

using namespace std;

double f(double x, double y)
{
return 7*y*y*cos(y*y)-3*exp(x*y);
}

int main()
{

ofstream output;

// Define an output file to store the table
output.open("/home/mbbx7ms5/NetBeansProjects/Data/coursework3data.csv");
if(!output.is_open())
{

cout << " File not opened \n";
throw;
}

double n=100.;
double h=1./n;
double y_new,y_curr;
y_curr=0;

for(int i=1;i<=n;i++)
{
float x_i=h*i;
y_new = y_curr + h*f(x_i,y_curr);
y_curr = y_new;

output << i << " , " << x_i << " , " << y_curr << "\n";
}

}

Here, I've just set n=100 so the step size is h=0.01.

Now what I want to do is run the program with different values of n, say, ranging from 10 to 10000.

How do I change my code so that I get a table of increasing values for n, with corresponding values for y(1).

I initially tried putting in another for loop for values of n, increasing in increments of 100. But the problem I got was that the table displayed all values of y_i, when I just want the last value.

Can someone help me? I ultimately want to show that the solution converges for larger values of n.

2
Contributors
3
Replies
7
Views
6 Years
Discussion Span
Last Post by Unimportant

Modify your for loop according to the values of n you want to iterate.

for numbers ranging from 10 to 10000:

for( i=10; i<10001; ++i ) {
}

would work just fine, so what's missing?

for( i=start; i<end+1; ++i ) {
}

just accept start and end as values from the user.

You can easily store each result from the for loop in an array, try using vector if you don't want to define a max size.

struct result_info {
double i, x_i, y_curr;
result_info(); // whatever constructor
result_info( double a, double b, double c ) : i(a), x_i(b), y_curr(c) { }
}
std::vector<result_info> res;
res.push_back( result_info( i, x_i, y_curr ) );
output << res.back().i << " , " << res.back().x_i << " , " << res.back().y_curr << "\n";

Hope that helps, good luck!

Edited by Unimportant: n/a

quick, concise response! many thanks

Hi Unimp.

Many thanks for your speedy reply...I'm new to C++ and so vectors aren't something I've come across just yet. Nevertheless I tried what you suggested, and I think I get your approach.

But I figured out an alternative that required a minimum amont of tinkering and got me the value for y(1) for several different values for n.

Before the loop for the main iteration, I declared x_i and put another for loop around the whole thing, so that the iteration is performed for differnt step sizes.

Then I simply defined the output in between the two loops so that y(1) is shown in a table for increasing values of n.

Here's the modified code,

#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <vector>
#include <fstream>

using namespace std;

double f(double x, double y)

{
return 7*y*y*cos(y*y)-3*exp(x*y);
}

int main()
{

ofstream output;

// Define an output file to store the table
output.open("/home/mshaikh/NetBeansProjects/Data/3.12data.csv");
if(!output.is_open())
{

// File will not open if directory doesn't exist
cout << " File not opened \n";
throw;
}
double x_i;
for (int n=10;n<=100;n+=10)
{

double y_new,y_curr;
y_curr=0;

for(int i=1;i<=n;++i)
{

double h=1./n;
x_i=h*i;
y_new = y_curr + h*f(x_i,y_curr);
y_curr = y_new;

}
output << n << " , " << y_new << " , " << "\n";
}

return (0);

So in this code, a total of 10 iterations are performed, first with n=10 (step size h=0.1) then going up in increments of 10 upto n=100 (step size h=0.01).

Tell me what you think!

Regards

If it does what you want it to do then I'd say it's fine.

If you want to improve it, make it perform the calculations in 1 iteration, as you pass every value of n either way (remove redundancy). You could also make it easier to get a wider variety of data, based on whatever criteria you want.

The reason I recommended using a struct (or class) for the data, is so you could expand on what you are doing and handle each case automatically. Sorting can also become trivial.

For example, if you know the output of the entire expression based on a single variable, why not simply pass that variable to an object constructor in the first place?

class Example {
public:
Example() { } // useless default constructor, modify if necessary
Example( double n, double i ) {
double h=1./n;
x_i = h*i;
// etc
// you might use a parent class to track y
}
print() { std::cout << a << " , " << b << "\n"; } // example
double get_a() { return a; }
private:
double a, b, c; // example private variables
};

So if you have a vector of Example (std::vector<Example>), you can simply iterate from say, 1 to 100, and in the constructor of Example, process all 10 possible values of "n" to create all variations of the object at once. This has a neat side effect of giving you related data in the same area.

Good luck!