patterncppMinor
Solving an ODE numerically with forward Euler method
Viewed 0 times
forwardsolvingmethododewithnumericallyeuler
Problem
The goal is to solve an ODE numerically with forward Euler method. The programs works well (numerical solution really near analytical one). The problem I see is that the Euler scheme don't jump to eyes, probably because of
push_back() functions. This approach is the only one I found to let the time of simulation (number of steps) be variable (change only the t_max constant). Do you have any idea to improve the clarity of the program?/* R. M.
20.08.2012
Exercice 1.2 of Computational Physics, N. Giordano and H. Nakanishi
Euler method to solve: dv/dt = a - bv
*/
#include
#include
#include
#include
void calculate(std::vector& time, std::vector& velocity, const double t_max, const double dt, const double a, const double b)
{
const int iterations(t_max / dt);
for(int i(1); i & time, const std::vector& velocity, const std::string& filename)
{
std::ofstream file_out(filename);
for(int i(0); i time({0}); // Initial time (t = 0)
std::vector velocity({0}); // Initial velocity (v = 0)
calculate(time, velocity, t_max, dt, a, b);
save(time, velocity, "veocity.dat");
return 0;
}Solution
The smallest change that might make it more readable is to
It's generally a good idea to
if you're keeping two vectors synchronized like this, it's sometimes nicer to replace them with a single vector whose elements have two fields:
this is more of an aesthetic preference though, and it isn't clearly better in your case.
resize the vectors first, so you can index the elements rather than calling push_back.It's generally a good idea to
reserve vectors before a loop anyway if you know how big they're going to end up, and resize will handle that too.void calculate(std::vector& time, std::vector& velocity,
const double t_max, const double dt, const double a, const double b)
{
const int iterations(t_max / dt);
time.resize(iterations, 0.);
velocity.resize(iterations, 0.);
for(int i(1); i < iterations; i++)
{
time[i] = time[i-1] + dt;
velocity[i] = a * dt + (1 - b*dt) * velocity[i-1];
}
}if you're keeping two vectors synchronized like this, it's sometimes nicer to replace them with a single vector whose elements have two fields:
struct step {
double time;
double velocity;
};
void calculate(std::vector& steps,
const double t_max, const double dt, const double a, const double b)
{
const int iterations(t_max / dt);
steps.resize(iterations);
for(int i(1); i < iterations; i++)
{
steps[i].time = steps[i-1].time + dt;
steps[i].velocity = a*dt + (1 - b*dt) * steps[i-1].velocity;
}
}this is more of an aesthetic preference though, and it isn't clearly better in your case.
Code Snippets
void calculate(std::vector<double>& time, std::vector<double>& velocity,
const double t_max, const double dt, const double a, const double b)
{
const int iterations(t_max / dt);
time.resize(iterations, 0.);
velocity.resize(iterations, 0.);
for(int i(1); i < iterations; i++)
{
time[i] = time[i-1] + dt;
velocity[i] = a * dt + (1 - b*dt) * velocity[i-1];
}
}struct step {
double time;
double velocity;
};
void calculate(std::vector<step>& steps,
const double t_max, const double dt, const double a, const double b)
{
const int iterations(t_max / dt);
steps.resize(iterations);
for(int i(1); i < iterations; i++)
{
steps[i].time = steps[i-1].time + dt;
steps[i].velocity = a*dt + (1 - b*dt) * steps[i-1].velocity;
}
}Context
StackExchange Code Review Q#14877, answer score: 2
Revisions (0)
No revisions yet.