Algorithms_in_C  1.0.0
Set of algorithms implemented in C.
ode_midpoint_euler.c File Reference

Solve a multivariable first order ordinary differential equation (ODEs) using midpoint Euler method More...

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Include dependency graph for ode_midpoint_euler.c:

Macros

#define order   2
 

Functions

void problem (const double *x, double *y, double *dy)
 Problem statement for a system with first-order differential equations. Updates the system differential variables. More...
 
void exact_solution (const double *x, double *y)
 Exact solution of the problem. Used for solution comparison. More...
 
void midpoint_euler_step (double dx, double *x, double *y, double *dy)
 Compute next step approximation using the midpoint-Euler method. More...
 
double midpoint_euler (double dx, double x0, double x_max, double *y, char save_to_file)
 Compute approximation using the midpoint-Euler method in the given limits. More...
 
int main (int argc, char *argv[])
 

Detailed Description

Solve a multivariable first order ordinary differential equation (ODEs) using midpoint Euler method

Authors
Krishna Vedala

The ODE being solved is:

\begin{eqnarray*} \dot{u} &=& v\\ \dot{v} &=& -\omega^2 u\\ \omega &=& 1\\ [x_0, u_0, v_0] &=& [0,1,0]\qquad\ldots\text{(initial values)} \end{eqnarray*}

The exact solution for the above problem is:

\begin{eqnarray*} u(x) &=& \cos(x)\\ v(x) &=& -\sin(x)\\ \end{eqnarray*}

The computation results are stored to a text file midpoint_euler.csv and the exact soltuion results in exact.csv for comparison. Implementation solution

To implement Van der Pol oscillator, change the problem function to:

const double mu = 2.0;
dy[0] = y[1];
dy[1] = mu * (1.f - y[0] * y[0]) * y[1] - y[0];
See also
ode_forward_euler.c, ode_semi_implicit_euler.c

Macro Definition Documentation

◆ order

#define order   2

number of dependent variables in problem

Function Documentation

◆ exact_solution()

void exact_solution ( const double *  x,
double *  y 
)

Exact solution of the problem. Used for solution comparison.

Parameters
[in]xindependent variable
[in,out]ydependent variable
68 {
69  y[0] = cos(x[0]);
70  y[1] = -sin(x[0]);
71 }

◆ main()

int main ( int  argc,
char *  argv[] 
)

Main Function

147 {
148  double X0 = 0.f; /* initial value of x0 */
149  double X_MAX = 10.F; /* upper limit of integration */
150  double Y0[] = {1.f, 0.f}; /* initial value Y = y(x = x_0) */
151  double step_size;
152 
153  if (argc == 1)
154  {
155  printf("\nEnter the step size: ");
156  scanf("%lg", &step_size);
157  }
158  else
159  // use commandline argument as independent variable step size
160  step_size = atof(argv[1]);
161 
162  // get approximate solution
163  double total_time = midpoint_euler(step_size, X0, X_MAX, Y0, 1);
164  printf("\tTime = %.6g ms\n", total_time);
165 
166  /* compute exact solution for comparion */
167  FILE *fp = fopen("exact.csv", "w+");
168  if (fp == NULL)
169  {
170  perror("Error! ");
171  return -1;
172  }
173  double x = X0;
174  double *y = &(Y0[0]);
175  printf("Finding exact solution\n");
176  clock_t t1 = clock();
177 
178  do
179  {
180  fprintf(fp, "%.4g,%.4g,%.4g\n", x, y[0], y[1]); // write to file
181  exact_solution(&x, y);
182  x += step_size;
183  } while (x <= X_MAX);
184 
185  clock_t t2 = clock();
186  total_time = (t2 - t1) / CLOCKS_PER_SEC;
187  printf("\tTime = %.6g ms\n", total_time);
188  fclose(fp);
189 
190  return 0;
191 }
Here is the call graph for this function:

◆ midpoint_euler()

double midpoint_euler ( double  dx,
double  x0,
double  x_max,
double *  y,
char  save_to_file 
)

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

Parameters
[in]dxstep size
[in]x0initial value of independent variable
[in]x_maxfinal value of independent variable
[in,out]ytake \(y_n\) and compute \(y_{n+1}\)
[in]save_to_fileflag to save results to a CSV file (1) or not (0)
Returns
time taken for computation in seconds
110 {
111  double dy[order];
112 
113  FILE *fp = NULL;
114  if (save_to_file)
115  {
116  fp = fopen("midpoint_euler.csv", "w+");
117  if (fp == NULL)
118  {
119  perror("Error! ");
120  return -1;
121  }
122  }
123 
124  /* start integration */
125  clock_t t1 = clock();
126  double x = x0;
127  do // iterate for each step of independent variable
128  {
129  if (save_to_file && fp)
130  fprintf(fp, "%.4g,%.4g,%.4g\n", x, y[0], y[1]); // write to file
131  midpoint_euler_step(dx, &x, y, dy); // perform integration
132  x += dx; // update step
133  } while (x <= x_max); // till upper limit of independent variable
134  /* end of integration */
135  clock_t t2 = clock();
136 
137  if (save_to_file && fp)
138  fclose(fp);
139 
140  return (double)(t2 - t1) / CLOCKS_PER_SEC;
141 }
Here is the call graph for this function:

◆ midpoint_euler_step()

void midpoint_euler_step ( double  dx,
double *  x,
double *  y,
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]dxstep size
[in,out]xtake \(x_n\) and compute \(x_{n+1}\)
[in,out]ytake \(y_n\) and compute \(y_{n+1}\)
[in,out]dycompute \(y_n+\frac{1}{2}dx\,f\left(x_n,y_n\right)\)
84 {
85  problem(x, y, dy);
86  double tmp_x = (*x) + 0.5 * dx;
87  double tmp_y[order];
88  int o;
89  for (o = 0; o < order; o++)
90  tmp_y[o] = y[o] + 0.5 * dx * dy[o];
91 
92  problem(&tmp_x, tmp_y, dy);
93 
94  for (o = 0; o < order; o++)
95  y[o] += dx * dy[o];
96 }
Here is the call graph for this function:

◆ problem()

void problem ( const double *  x,
double *  y,
double *  dy 
)

Problem statement for a system with first-order differential equations. Updates the system differential variables.

Note
This function can be updated to and ode of any order.
Parameters
[in]xindependent variable(s)
[in,out]ydependent variable(s)
[in,out]dyfirst-derivative of dependent variable(s)
55 {
56  const double omega = 1.F; // some const for the problem
57  dy[0] = y[1]; // x dot
58  dy[1] = -omega * omega * y[0]; // y dot
59 }
exact_solution
void exact_solution(const double *x, double *y)
Exact solution of the problem. Used for solution comparison.
Definition: ode_midpoint_euler.c:67
midpoint_euler_step
void midpoint_euler_step(double dx, double *x, double *y, double *dy)
Compute next step approximation using the midpoint-Euler method.
Definition: ode_midpoint_euler.c:83
order
#define order
Definition: ode_midpoint_euler.c:43
midpoint_euler
double midpoint_euler(double dx, double x0, double x_max, double *y, char save_to_file)
Compute approximation using the midpoint-Euler method in the given limits.
Definition: ode_midpoint_euler.c:108
problem
void problem(const double *x, double *y, double *dy)
Problem statement for a system with first-order differential equations. Updates the system differenti...
Definition: ode_midpoint_euler.c:54