Ordinary Differential Equations

## Functions

void | forward_euler_step (const double dx, const double x, std::valarray< double > *y, std::valarray< double > *dy)
| Compute next step approximation using the forward-Euler method. More...
double | forward_euler (double dx, double x0, double x_max, std::valarray< double > *y, bool save_to_file=false)
| Compute approximation using the forward-Euler method in the given limits. More...
void | midpoint_euler_step (const double dx, const double &x, std::valarray< double > *y, std::valarray< double > *dy)
| Compute next step approximation using the midpoint-Euler method. More...
double | midpoint_euler (double dx, double x0, double x_max, std::valarray< double > *y, bool save_to_file=false)
| Compute approximation using the midpoint-Euler method in the given limits. More...
void | semi_implicit_euler_step (const double dx, const double &x, std::valarray< double > *y, std::valarray< double > *dy)
| Compute next step approximation using the semi-implicit-Euler method. More...
double | semi_implicit_euler (double dx, double x0, double x_max, std::valarray< double > *y, bool save_to_file=false)
| Compute approximation using the semi-implicit-Euler method in the given limits. More...

## Detailed Description

Integration functions for implementations with solving ordinary differential equations (ODEs) of any order and and any number of independent variables.

## Function Documentation

## forward_euler()

double forward_euler | ( | double | dx,
|  | double | x0,
|  | double | x_max,
|  | std::valarray< double > * | y,
|  | bool | save_to_file = `false`
| ) |  |

Compute approximation using the forward-Euler method in the given limits.

Parameters

  [in] | dx | step size
  [in] | x0 | initial value of independent variable
  [in] | x_max | final value of independent variable
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in] | save_to_file | flag to save results to a CSV file (1) or not (0)

Returns
  time taken for computation in seconds

{
std::valarray<double> dy = *y;
std::ofstream fp;
if (save_to_file) {
fp.open("forward_euler.csv", std::ofstream::out);
if (!fp.is_open()) {
std::perror("Error! ");
}
}
std::size_t L = y->size();
/* start integration */
std::clock_t t1 = std::clock();
double x = x0;
do { // iterate for each step of independent variable
if (save_to_file && fp.is_open()) {
// write to file
fp << x << ",";
for (int i = 0; i < L - 1; i++) {
fp << y[0][i] << ","; // NOLINT
}
fp << y[0][L - 1] << "\n"; // NOLINT
}
forward_euler_step(dx, x, y, &dy); // perform integration
x += dx; // update step
} while (x <= x_max); // till upper limit of independent variable
/* end of integration */
std::clock_t t2 = std::clock();
if (fp.is_open()) {
fp.close();
}
return static_cast<double>(t2 - t1) / CLOCKS_PER_SEC;
}
std::ofstream
std::clock
T clock(T... args)
std::clock_t
std::ofstream::close
T close(T... args)
forward_euler_step
void forward_euler_step(const double dx, const double x, std::valarray< double > *y, std::valarray< double > *dy)
Compute next step approximation using the forward-Euler method.
Definition: ode_forward_euler.cpp:86
std::ofstream::is_open
T is_open(T... args)
std::ofstream::open
T open(T... args)
std::perror
T perror(T... args)
std::size_t
std::valarray< double >
Here is the call graph for this function:

## forward_euler_step()

void forward_euler_step | ( | const double | dx,
|  | const double | x,
|  | std::valarray< double > * | y,
|  | std::valarray< double > * | dy
| ) |  |

Compute next step approximation using the forward-Euler method.

\[y_{n+1}=y_n + dx\cdot f\left(x_n,y_n\right)\]

Parameters

  [in] | dx | step size
  [in] | x | take \(x_n\) and compute \(x_{n+1}\)
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in,out] | dy | compute \(f\left(x_n,y_n\right)\)

{
problem(x, y, dy);
*y += *dy * dx;
}
problem
void problem(const double &x, std::valarray< double > *y, std::valarray< double > *dy)
Problem statement for a system with first-order differential equations. Updates the system differenti...
Definition: ode_forward_euler.cpp:54
Here is the call graph for this function:

## midpoint_euler()

double midpoint_euler | ( | double | dx,
|  | double | x0,
|  | double | x_max,
|  | std::valarray< double > * | y,
|  | bool | save_to_file = `false`
| ) |  |

Compute approximation using the midpoint-Euler method in the given limits.

Parameters

  [in] | dx | step size
  [in] | x0 | initial value of independent variable
  [in] | x_max | final value of independent variable
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in] | save_to_file | flag to save results to a CSV file (1) or not (0)

Returns
  time taken for computation in seconds

{
std::valarray<double> dy = y[0];
std::ofstream fp;
if (save_to_file) {
fp.open("midpoint_euler.csv", std::ofstream::out);
if (!fp.is_open()) {
std::perror("Error! ");
}
}
std::size_t L = y->size();
/* start integration */
std::clock_t t1 = std::clock();
double x = x0;
do { // iterate for each step of independent variable
if (save_to_file && fp.is_open()) {
// write to file
fp << x << ",";
for (int i = 0; i < L - 1; i++) {
fp << y[0][i] << ",";
}
fp << y[0][L - 1] << "\n";
}
midpoint_euler_step(dx, x, y, &dy); // perform integration
x += dx; // update step
} while (x <= x_max); // till upper limit of independent variable
/* end of integration */
std::clock_t t2 = std::clock();
if (fp.is_open())
fp.close();
return static_cast<double>(t2 - t1) / CLOCKS_PER_SEC;
}
midpoint_euler_step
void midpoint_euler_step(const double dx, const double &x, std::valarray< double > *y, std::valarray< double > *dy)
Compute next step approximation using the midpoint-Euler method.
Definition: ode_midpoint_euler.cpp:85
Here is the call graph for this function:

## midpoint_euler_step()

void midpoint_euler_step | ( | const double | dx,
|  | const double & | x,
|  | std::valarray< double > * | y,
|  | std::valarray< double > * | dy
| ) |  |

Compute next step approximation using the midpoint-Euler method.

\[y_{n+1} = y_n + dx\, f\left(x_n+\frac{1}{2}dx, y_n + \frac{1}{2}dx\,f\left(x_n,y_n\right)\right)\]

Parameters

  [in] | dx | step size
  [in] | x | take \(x_n\) and compute \(x_{n+1}\)
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in,out] | dy | compute \(f\left(x_n,y_n\right)\)

{
problem(x, y, dy);
double tmp_x = x + 0.5 * dx;
std::valarray<double> tmp_y = y[0] + dy[0] * (0.5 * dx);
problem(tmp_x, &tmp_y, dy);
y[0] += dy[0] * dx;
}
problem
void problem(const double &x, std::valarray< double > *y, std::valarray< double > *dy)
Problem statement for a system with first-order differential equations. Updates the system differenti...
Definition: ode_midpoint_euler.cpp:53
Here is the call graph for this function:

## semi_implicit_euler()

double semi_implicit_euler | ( | double | dx,
|  | double | x0,
|  | double | x_max,
|  | std::valarray< double > * | y,
|  | bool | save_to_file = `false`
| ) |  |

Compute approximation using the semi-implicit-Euler method in the given limits.

Parameters

  [in] | dx | step size
  [in] | x0 | initial value of independent variable
  [in] | x_max | final value of independent variable
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in] | save_to_file | flag to save results to a CSV file (1) or not (0)

Returns
  time taken for computation in seconds

{
std::valarray<double> dy = y[0];
std::ofstream fp;
if (save_to_file) {
fp.open("semi_implicit_euler.csv", std::ofstream::out);
if (!fp.is_open()) {
std::perror("Error! ");
}
}
std::size_t L = y->size();
/* start integration */
std::clock_t t1 = std::clock();
double x = x0;
do { // iterate for each step of independent variable
if (save_to_file && fp.is_open()) {
// write to file
fp << x << ",";
for (int i = 0; i < L - 1; i++) {
fp << y[0][i] << ",";
}
fp << y[0][L - 1] << "\n";
}
semi_implicit_euler_step(dx, x, y, &dy); // perform integration
x += dx; // update step
} while (x <= x_max); // till upper limit of independent variable
/* end of integration */
std::clock_t t2 = std::clock();
if (fp.is_open())
fp.close();
return static_cast<double>(t2 - t1) / CLOCKS_PER_SEC;
}
semi_implicit_euler_step
void semi_implicit_euler_step(const double dx, const double &x, std::valarray< double > *y, std::valarray< double > *dy)
Compute next step approximation using the semi-implicit-Euler method.
Definition: ode_semi_implicit_euler.cpp:82
Here is the call graph for this function:

## semi_implicit_euler_step()

void semi_implicit_euler_step | ( | const double | dx,
|  | const double & | x,
|  | std::valarray< double > * | y,
|  | std::valarray< double > * | dy
| ) |  |

Compute next step approximation using the semi-implicit-Euler method.

\[y_{n+1}=y_n + dx\cdot f\left(x_n,y_n\right)\]

Parameters

  [in] | dx | step size
  [in] | x | take \(x_n\) and compute \(x_{n+1}\)
  [in,out] | y | take \(y_n\) and compute \(y_{n+1}\)
  [in,out] | dy | compute \(f\left(x_n,y_n\right)\)

{
problem(x, y, dy); // update dy once
y[0][0] += dx * dy[0][0]; // update y0
problem(x, y, dy); // update dy once more
dy[0][0] = 0.f; // ignore y0
y[0] += dy[0] * dx; // update remaining using new dy
}
problem
void problem(const double &x, std::valarray< double > *y, std::valarray< double > *dy)
Problem statement for a system with first-order differential equations. Updates the system differenti...
Definition: ode_semi_implicit_euler.cpp:53
Here is the call graph for this function: