16 #include "ordinary_differential_equations.h"
67 set(other_ordinary_differential_equations);
91 if(
this != &other_ordinary_differential_equations)
187 return(
"RungeKutta");
191 return(
"RungeKuttaFehlberg");
195 std::ostringstream buffer;
197 buffer <<
"OpenNN Exception: OrdinaryDifferentialEquations class.\n"
198 <<
"std::string write_solution_method(void) const method.\n"
199 <<
"Unknown solution method.\n";
201 throw std::logic_error(buffer.str());
350 if(new_solution_method ==
"RungeKutta")
354 else if(new_solution_method ==
"RungeKuttaFehlberg")
360 std::ostringstream buffer;
362 buffer <<
"OpenNN Exception: OrdinaryDifferentialEquations class.\n"
363 <<
"void set_solution_method(const std::string&) method.\n"
364 <<
"Unknown solution method: " << new_solution_method <<
".\n";
366 throw std::logic_error(buffer.str());
493 solution(i+1,0) = solution(i,0) + h;
497 variables[0] = solution(i,0);
501 variables[1+j] = solution(i,1+j);
508 variables[0] = solution(i,0) + h/2.0;
512 variables[1+j] = solution(i,1+j) + h*c[0][j]/2.0;
519 variables[0] = solution(i,0) + h/2.0;
523 variables[1+j] = solution(i,1+j) + h*c[1][j]/2.0;
530 variables[0] = solution(i+1,0);
534 variables[1+j] = solution(i,1+j) + h*c[2][j]/2.0;
543 solution(i+1,1+j) = solution(i,1+j) + h*(c[0][j] + 2.0*c[1][j] + 2.0*c[2][j] + c[3][j])/6.0;
585 final_solution[0] = final_solution[0] + h;
589 variables[0] = final_solution[0];
593 variables[1+j] = final_solution[1+j];
600 variables[0] = final_solution[0] + h/2.0;
604 variables[1+j] = final_solution[1+j] + h*c[0][j]/2.0;
611 variables[0] = final_solution[0] + h/2.0;
615 variables[1+j] = final_solution[1+j] + h*c[1][j]/2.0;
622 variables[0] = final_solution[0];
626 variables[1+j] = final_solution[1+j] + h*c[2][j]/2.0;
635 final_solution[1+j] = final_solution[1+j] + h*(c[0][j] + 2.0*c[1][j] + 2.0*c[2][j] + c[3][j])/6.0;
639 return(final_solution);
650 const double epsilon = 1.0e-12;
652 const double a2 = 1.0/5.0;
653 const double a3 = 3.0/10.0;
654 const double a4 = 3.0/5.0;
655 const double a5 = 1.0;
656 const double a6 = 7.0/8.0;
658 const double b21 = 1.0/5.0;
659 const double b31 = 3.0/40.0;
660 const double b32 = 9.0/40.0;
661 const double b41 = 3.0/10.0;
662 const double b42 = -9.0/10.0;
663 const double b43 = 6.0/5.0;
664 const double b51 = -11.0/54.0;
665 const double b52 = 5.0/2.0;
666 const double b53 = -70.0/27.0;
667 const double b54 = 35.0/27.0;
668 const double b61 = 1631.0/55296.0;
669 const double b62 = 175.0/512.0;
670 const double b63 = 575.0/13824.0;
671 const double b64 = 44275.0/110592.0;
672 const double b65 = 253.0/4096.0;
674 const double c41 = 37.0/378.0;
675 const double c42 = 0.0;
676 const double c43 = 250.0/621.0;
677 const double c44 = 125.0/594.0;
678 const double c45 = 0.0;
679 const double c46 = 512.0/1771.0;
681 const double c51 = 2825.0/27648.0;
682 const double c52 = 0.0;
683 const double c53 = 18575.0/48384.0;
684 const double c54 = 13525.0/55296.0;
685 const double c55 = 277.0/14336.0;
686 const double c56 = 1.0/4.0;
688 const double d1 = c41 - c51;
689 const double d2 = c42 - c52;
690 const double d3 = c43 - c53;
691 const double d4 = c44 - c54;
692 const double d5 = c45 - c55;
693 const double d6 = c46 - c56;
712 size_t point_index = 0;
729 hmin = 32.0*epsilon*fabs(solution(point_index,0));
735 std::cout <<
"OpenNN Warning: OrdinaryDifferentialEquations class.\n"
736 <<
"calculate_Runge_Kutta_Fehlberg_solution() method.\n"
737 <<
"Step size is less than smallest allowable." << std::endl;
750 variables[0] = solution(point_index,0);
754 variables[1+j] = solution(point_index,1+j);
761 variables[0] = solution(point_index,0) + a2*h;
765 variables[1+j] = solution(point_index,1+j)+ b21*c[0][j];
772 variables[0] = solution(point_index,0) + a3*h;
776 variables[1+j] = solution(point_index,1+j) + b31*c[0][j] + b32*c[1][j];
783 variables[0] = solution(point_index,0) + a4*h;
787 variables[1+j] = solution(point_index,1+j) + b41*c[0][j] + b42*c[1][j] + b43*c[2][j];
794 variables[0] = solution(point_index,0) + a5*h;
798 variables[1+j] = solution(point_index,1+j) + b51*c[0][j] + b52*c[1][j] + b53*c[2][j] + b54*c[3][j];
805 variables[0] = solution(point_index,0) + a6*h;
809 variables[1+j] = solution(point_index,1+j) + b61*c[0][j] + b62*c[1][j] + b63*c[2][j] + b64*c[3][j] + b65*c[4][j];
818 errors[j] = fabs(d1*c[0][j] + d2*c[1][j] + d3*c[2][j] + d4*c[3][j] + d5*c[4][j] + d6*c[5][j]);
825 solution(point_index+1,0) = solution(point_index,0) + h;
829 solution(point_index+1,1+j) = solution(point_index,1+j) + c51*c[0][j] + c52*c[1][j] + c53*c[2][j] + c54*c[3][j] + c55*c[4][j] + c56*c[5][j];
836 h *= 0.9*pow(fabs(
tolerance/error), 0.2);
839 if(point_index >= size)
845 std::cout <<
"OpenNN Warning: OrdinaryDifferentialEquations class." << std::endl
846 <<
"calculate_Runge_Kutta_Fehlberg_solution() method." << std::endl
847 <<
"Solution size is " << size << std::endl;
851 std::ostringstream buffer;
853 buffer <<
"OpenNN Exception: OrdinaryDifferentialEquations class." << std::endl
854 <<
"calculate_Runge_Kutta_Fehlberg_solution() method." << std::endl
855 <<
"Solution size is bigger than greatest allowable." << std::endl;
857 throw std::logic_error(buffer.str());
867 h *= 0.9*pow(fabs(
tolerance/error), 0.25);
886 const double epsilon = 1.0e-12;
888 const double a2 = 1.0/5.0;
889 const double a3 = 3.0/10.0;
890 const double a4 = 3.0/5.0;
891 const double a5 = 1.0;
892 const double a6 = 7.0/8.0;
894 const double b21 = 1.0/5.0;
895 const double b31 = 3.0/40.0;
896 const double b32 = 9.0/40.0;
897 const double b41 = 3.0/10.0;
898 const double b42 = -9.0/10.0;
899 const double b43 = 6.0/5.0;
900 const double b51 = -11.0/54.0;
901 const double b52 = 5.0/2.0;
902 const double b53 = -70.0/27.0;
903 const double b54 = 35.0/27.0;
904 const double b61 = 1631.0/55296.0;
905 const double b62 = 175.0/512.0;
906 const double b63 = 575.0/13824.0;
907 const double b64 = 44275.0/110592.0;
908 const double b65 = 253.0/4096.0;
910 const double c41 = 37.0/378.0;
911 const double c42 = 0.0;
912 const double c43 = 250.0/621.0;
913 const double c44 = 125.0/594.0;
914 const double c45 = 0.0;
915 const double c46 = 512.0/1771.0;
917 const double c51 = 2825.0/27648.0;
918 const double c52 = 0.0;
919 const double c53 = 18575.0/48384.0;
920 const double c54 = 13525.0/55296.0;
921 const double c55 = 277.0/14336.0;
922 const double c56 = 1.0/4.0;
924 const double d1 = c41 - c51;
925 const double d2 = c42 - c52;
926 const double d3 = c43 - c53;
927 const double d4 = c44 - c54;
928 const double d5 = c45 - c55;
929 const double d6 = c46 - c56;
961 hmin = 32.0*epsilon*fabs(final_solution[0]);
967 std::cout <<
"OpenNN Warning: OrdinaryDifferentialEquations class.\n"
968 <<
"calculate_Runge_Kutta_Fehlberg_solution() method.\n"
969 <<
"Step size is less than smallest allowable." << std::endl;
982 variables[0] = final_solution[0];
986 variables[1+j] = final_solution[1+j];
993 variables[0] = final_solution[0] + a2*h;
997 variables[1+j] = final_solution[1+j]+ b21*c[0][j];
1004 variables[0] = final_solution[0] + a3*h;
1008 variables[1+j] = final_solution[1+j] + b31*c[0][j] + b32*c[1][j];
1015 variables[0] = final_solution[0] + a4*h;
1019 variables[1+j] = final_solution[1+j] + b41*c[0][j] + b42*c[1][j] + b43*c[2][j];
1026 variables[0] = final_solution[0] + a5*h;
1030 variables[1+j] = final_solution[1+j] + b51*c[0][j] + b52*c[1][j] + b53*c[2][j] + b54*c[3][j];
1037 variables[0] = final_solution[0] + a6*h;
1041 variables[1+j] = final_solution[1+j] + b61*c[0][j] + b62*c[1][j] + b63*c[2][j] + b64*c[3][j] + b65*c[4][j];
1050 errors[j] = fabs(d1*c[0][j] + d2*c[1][j] + d3*c[2][j] + d4*c[3][j] + d5*c[4][j] + d6*c[5][j]);
1057 final_solution[0] += h;
1061 final_solution[1+j] += c51*c[0][j] + c52*c[1][j] + c53*c[2][j] + c54*c[3][j] + c55*c[4][j] + c56*c[5][j];
1066 h *= 0.9*pow(fabs(
tolerance/error), 0.2);
1071 h *= 0.9*pow(fabs(
tolerance/error), 0.25);
1076 return(final_solution);
1092 case RungeKuttaFehlberg:
1100 std::ostringstream buffer;
1102 buffer <<
"OpenNN Error: OrdinaryDifferentialEquations class\n"
1103 <<
"Vector<double> calculate_solutions(const NeuralNetwork&) const method.\n"
1104 <<
"Unknown solution method.\n";
1106 throw std::logic_error(buffer.str());
1125 case RungeKuttaFehlberg:
1133 std::ostringstream buffer;
1135 buffer <<
"OpenNN Exception: ScalingLayer class\n"
1136 <<
"Vector<double> calculate_final_solutions(const NeuralNetwork&) const method.\n"
1137 <<
"Unknown solution method.\n";
1139 throw std::logic_error(buffer.str());
1152 std::ostringstream buffer;
1154 buffer <<
"Mathematical model\n"
1166 <<
"Display: " <<
display << std::endl;
1168 return(buffer.str());
1179 tinyxml2::XMLDocument* document =
new tinyxml2::XMLDocument;
1181 std::ostringstream buffer;
1183 tinyxml2::XMLElement* ordinary_differential_equations_element = document->NewElement(
"OrdinaryDifferentialEquations");
1185 document->InsertFirstChild(ordinary_differential_equations_element);
1189 tinyxml2::XMLElement* element = document->NewElement(
"IndependentVariablesNumber");
1190 ordinary_differential_equations_element->LinkEndChild(element);
1195 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1196 element->LinkEndChild(text);
1201 tinyxml2::XMLElement* element = document->NewElement(
"DependentVariablesNumber");
1202 ordinary_differential_equations_element->LinkEndChild(element);
1207 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1208 element->LinkEndChild(text);
1213 tinyxml2::XMLElement* element = document->NewElement(
"InitialIndependentVariable");
1214 ordinary_differential_equations_element->LinkEndChild(element);
1219 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1220 element->LinkEndChild(text);
1225 tinyxml2::XMLElement* element = document->NewElement(
"FinalIndependentVariable");
1226 ordinary_differential_equations_element->LinkEndChild(element);
1231 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1232 element->LinkEndChild(text);
1237 tinyxml2::XMLElement* element = document->NewElement(
"InitialDependentVariables");
1238 ordinary_differential_equations_element->LinkEndChild(element);
1243 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1244 element->LinkEndChild(text);
1249 tinyxml2::XMLElement* element = document->NewElement(
"SolutionMethod");
1250 ordinary_differential_equations_element->LinkEndChild(element);
1253 element->LinkEndChild(text);
1258 tinyxml2::XMLElement* element = document->NewElement(
"PointsNumber");
1259 ordinary_differential_equations_element->LinkEndChild(element);
1264 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1265 element->LinkEndChild(text);
1270 tinyxml2::XMLElement* element = document->NewElement(
"Tolerance");
1271 ordinary_differential_equations_element->LinkEndChild(element);
1276 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1277 element->LinkEndChild(text);
1282 tinyxml2::XMLElement* element = document->NewElement(
"InitialSize");
1283 ordinary_differential_equations_element->LinkEndChild(element);
1288 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1289 element->LinkEndChild(text);
1294 tinyxml2::XMLElement* element = document->NewElement(
"WarningSize");
1295 ordinary_differential_equations_element->LinkEndChild(element);
1300 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1301 element->LinkEndChild(text);
1306 tinyxml2::XMLElement* element = document->NewElement(
"ErrorSize");
1307 ordinary_differential_equations_element->LinkEndChild(element);
1312 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1313 element->LinkEndChild(text);
1318 tinyxml2::XMLElement* element = document->NewElement(
"Display");
1319 ordinary_differential_equations_element->LinkEndChild(element);
1324 tinyxml2::XMLText* text = document->NewText(buffer.str().c_str());
1325 element->LinkEndChild(text);
1341 const tinyxml2::XMLElement* element = document.FirstChildElement(
"DependentVariablesNumber");
1345 const char* text = element->GetText();
1353 catch(
const std::logic_error& e)
1355 std::cout << e.what() << std::endl;
1363 const tinyxml2::XMLElement* element = document.FirstChildElement(
"InitialIndependentVariable");
1367 const char* text = element->GetText();
1375 catch(
const std::logic_error& e)
1377 std::cout << e.what() << std::endl;
1385 const tinyxml2::XMLElement* element = document.FirstChildElement(
"FinalIndependentVariable");
1389 const char* text = element->GetText();
1397 catch(
const std::logic_error& e)
1399 std::cout << e.what() << std::endl;
1407 const tinyxml2::XMLElement* element = document.FirstChildElement(
"InitialDependentVariables");
1411 const char* text = element->GetText();
1418 new_initial_dependent_variables.
parse(text);
1422 catch(
const std::logic_error& e)
1424 std::cout << e.what() << std::endl;
1432 const tinyxml2::XMLElement* element = document.FirstChildElement(
"SolutionMethod");
1436 const char* text = element->GetText();
1442 std::string new_solution_method(text);
1446 catch(
const std::logic_error& e)
1448 std::cout << e.what() << std::endl;
1456 const tinyxml2::XMLElement* element = document.FirstChildElement(
"PointsNumber");
1460 const char* text = element->GetText();
1468 catch(
const std::logic_error& e)
1470 std::cout << e.what() << std::endl;
1478 const tinyxml2::XMLElement* element = document.FirstChildElement(
"Tolerance");
1482 const char* text = element->GetText();
1490 catch(
const std::logic_error& e)
1492 std::cout << e.what() << std::endl;
1500 const tinyxml2::XMLElement* element = document.FirstChildElement(
"InitialSize");
1504 const char* text = element->GetText();
1512 catch(
const std::logic_error& e)
1514 std::cout << e.what() << std::endl;
1522 const tinyxml2::XMLElement* element = document.FirstChildElement(
"WarningSize");
1526 const char* text = element->GetText();
1534 catch(
const std::logic_error& e)
1536 std::cout << e.what() << std::endl;
1544 const tinyxml2::XMLElement* element = document.FirstChildElement(
"ErrorSize");
1548 const char* text = element->GetText();
1556 catch(
const std::logic_error& e)
1558 std::cout << e.what() << std::endl;
1566 const tinyxml2::XMLElement* display_element = document.FirstChildElement(
"Display");
1570 const char* display_text = display_element->GetText();
1576 std::string display_string(display_text);
1580 catch(
const std::logic_error& e)
1582 std::cout << e.what() << std::endl;
1600 solution.
save(file_name);
void parse(const std::string &)
virtual ~OrdinaryDifferentialEquations(void)
double final_independent_variable
Final value for the only independent variable.
const double & get_initial_independent_variable(void) const
Returns the initial value of the independent variable.
Vector< double > calculate_Runge_Kutta_final_solution(const NeuralNetwork &) const
SolutionMethod
Enumeration of available methods for numerical integration of ordinary differential equations...
virtual Vector< double > calculate_final_solutions(const NeuralNetwork &) const
void set_initial_independent_variable(const double &)
void set_points_number(const size_t &)
void set_solution_method(const SolutionMethod &)
void set_initial_size(const size_t &)
void set_final_independent_variable(const double &)
const size_t & get_error_size(void) const
Returns an error size for the solutions in the Runge-Kutta-Fehlberg method.
std::string write_solution_method(void) const
Returns a string with the name of the numerical method to be used for integration of the ordinary dif...
void set_initial_dependent_variable(const size_t &, const double &)
void save(const std::string &) const
Matrix< double > calculate_Runge_Kutta_Fehlberg_solution(const NeuralNetwork &) const
const size_t & get_initial_size(void) const
Returns the initial size to be reserved for the solutions in the Runge-Kutta-Fehlberg method...
void set_tolerance(const double &)
virtual Vector< double > calculate_dependent_variables_dots(const NeuralNetwork &, const Vector< double > &) const =0
This pure virtual method calculates the derivatives of the dependent variables with respect to the in...
OrdinaryDifferentialEquations(void)
double initial_independent_variable
Initial value for the only independent variable.
size_t warning_size
Number of points at which the the Runge-Kutta-Fehlberg method displays a warning message.
void set_initial_dependent_variables(const Vector< double > &)
size_t error_size
Number of points at which the the Runge-Kutta-Fehlberg method throws an exception.
size_t count_variables_number(void) const
Matrix< double > calculate_Runge_Kutta_solution(const NeuralNetwork &) const
virtual void from_XML(const tinyxml2::XMLDocument &)
std::string to_string(void) const
Returns a string representation of the current ordinary differential equations object.
void set_display(const bool &)
double tolerance
Tolerance in the Runge-Kutta-Fehlberg method.
virtual Matrix< double > calculate_solutions(const NeuralNetwork &) const
const SolutionMethod & get_solution_method(void) const
Returns the numerical method to be used for integration of the ordinary differential equation...
size_t points_number
Number of points in the Runge-Kutta method.
size_t initial_size
Initial number of points in the Runge-Kutta-Fehlberg method.
OrdinaryDifferentialEquations & operator=(const OrdinaryDifferentialEquations &)
const double & get_final_independent_variable(void) const
Returns the final value of the independent variable.
size_t dependent_variables_number
Number of dependent variables defining the mathematical model.
bool display
Flag for displaying warnings.
void set_dependent_variables_number(const size_t &)
const double & get_tolerance(void) const
Returns the tolerance in the Runge-Kutta-Fehlberg method.
T calculate_maximum(void) const
Returns the largest element in the vector.
const double & get_initial_dependent_variable(const size_t &) const
virtual void set_default(void)
void set_error_size(const size_t &)
Vector< double > initial_dependent_variables
Initial values for the dependent variables.
void set_warning_size(const size_t &)
const size_t & get_points_number(void) const
Returns the number of integration points in the Runge-Kutta method.
void set(const OrdinaryDifferentialEquations &)
SolutionMethod solution_method
Numerical integration method (Runge-Kutta or Runge-Kutta-Fehlberg).
virtual void save_data(const NeuralNetwork &, const std::string &) const
const Vector< double > & get_initial_dependent_variables(void) const
Returns the initial values of the independent variables.
size_t independent_variables_number
Number of independent variables defining the mathematical model.
Vector< double > calculate_Runge_Kutta_Fehlberg_final_solution(const NeuralNetwork &) const
const size_t & get_warning_size(void) const
Returns a warning size for the solutions in the Runge-Kutta-Fehlberg method.
bool operator==(const OrdinaryDifferentialEquations &) const
virtual tinyxml2::XMLDocument * to_XML(void) const