TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
ode_semi_implicit_euler.cpp
Go to the documentation of this file.
1
38#include <cmath>
39#include <ctime>
40#include <fstream>
41#include <iostream>
42#include <valarray>
43
53void problem(const double &x, std::valarray<double> *y,
54 std::valarray<double> *dy) {
55 const double omega = 1.F; // some const for the problem
56 dy[0][0] = y[0][1]; // x dot
57 dy[0][1] = -omega * omega * y[0][0]; // y dot
58}
59
66void exact_solution(const double &x, std::valarray<double> *y) {
67 y[0][0] = std::cos(x);
68 y[0][1] = -std::sin(x);
69}
70
82void semi_implicit_euler_step(const double dx, const double &x,
83 std::valarray<double> *y,
84 std::valarray<double> *dy) {
85 problem(x, y, dy); // update dy once
86 y[0][0] += dx * dy[0][0]; // update y0
87 problem(x, y, dy); // update dy once more
88
89 dy[0][0] = 0.f; // ignore y0
90 y[0] += dy[0] * dx; // update remaining using new dy
91}
92
103double semi_implicit_euler(double dx, double x0, double x_max,
104 std::valarray<double> *y,
105 bool save_to_file = false) {
106 std::valarray<double> dy = y[0];
107
108 std::ofstream fp;
109 if (save_to_file) {
110 fp.open("semi_implicit_euler.csv", std::ofstream::out);
111 if (!fp.is_open()) {
112 std::perror("Error! ");
113 }
114 }
115
116 std::size_t L = y->size();
117
118 /* start integration */
119 std::clock_t t1 = std::clock();
120 double x = x0;
121 do { // iterate for each step of independent variable
122 if (save_to_file && fp.is_open()) {
123 // write to file
124 fp << x << ",";
125 for (int i = 0; i < L - 1; i++) {
126 fp << y[0][i] << ",";
127 }
128 fp << y[0][L - 1] << "\n";
129 }
130
131 semi_implicit_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 std::clock_t t2 = std::clock();
136
137 if (fp.is_open())
138 fp.close();
139
140 return static_cast<double>(t2 - t1) / CLOCKS_PER_SEC;
141}
142
153void save_exact_solution(const double &X0, const double &X_MAX,
154 const double &step_size,
155 const std::valarray<double> &Y0) {
156 double x = X0;
157 std::valarray<double> y = Y0;
158
159 std::ofstream fp("exact.csv", std::ostream::out);
160 if (!fp.is_open()) {
161 std::perror("Error! ");
162 return;
163 }
164 std::cout << "Finding exact solution\n";
165
166 std::clock_t t1 = std::clock();
167 do {
168 fp << x << ",";
169 for (int i = 0; i < y.size() - 1; i++) {
170 fp << y[i] << ",";
171 }
172 fp << y[y.size() - 1] << "\n";
173
174 exact_solution(x, &y);
175
176 x += step_size;
177 } while (x <= X_MAX);
178
179 std::clock_t t2 = std::clock();
180 double total_time = static_cast<double>(t2 - t1) / CLOCKS_PER_SEC;
181 std::cout << "\tTime = " << total_time << " ms\n";
182
183 fp.close();
184}
185
189int main(int argc, char *argv[]) {
190 double X0 = 0.f; /* initial value of x0 */
191 double X_MAX = 10.F; /* upper limit of integration */
192 std::valarray<double> Y0 = {1.f, 0.f}; /* initial value Y = y(x = x_0) */
193 double step_size;
194
195 if (argc == 1) {
196 std::cout << "\nEnter the step size: ";
197 std::cin >> step_size;
198 } else {
199 // use commandline argument as independent variable step size
200 step_size = std::atof(argv[1]);
201 }
202
203 // get approximate solution
204 double total_time = semi_implicit_euler(step_size, X0, X_MAX, &Y0, true);
205 std::cout << "\tTime = " << total_time << " ms\n";
206
207 /* compute exact solution for comparion */
208 save_exact_solution(X0, X_MAX, step_size, Y0);
209
210 return 0;
211}
int main()
Main function.
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.
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.
void save_exact_solution(const double &X0, const double &X_MAX, const double &step_size, const std::valarray< double > &Y0)
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...
void exact_solution(const double &x, std::valarray< double > *y)
Exact solution of the problem. Used for solution comparison.