SIMLIB/C++ 3.09
Loading...
Searching...
No Matches
ni_euler.cc
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2// ni_euler.cc
3//
4// Copyright (c) 1991-2004 Petr Peringer
5// Copyright (c) 1996-1997 David Leska
6//
7// This library is licensed under GNU Library GPL. See the file COPYING.
8//
9
10//
11// numerical integration: Euler's method
12//
13
14////////////////////////////////////////////////////////////////////////////
15// interface
16//
17#include "simlib.h"
18#include "internal.h"
19#include "ni_euler.h"
20#include <cmath>
21#include <cstddef>
22
23
24////////////////////////////////////////////////////////////////////////////
25// implementation
26//
27
28namespace simlib3 {
29
31
32
33////////////////////////////////////////////////////////////////////////////
34// Euler's method
35//
36/* Formula:
37
38 y'(t) = f(t, y);
39 y(t+h/2) = y(t) + h/2 * y'(t);
40 y'(t+h/2) = f(t+h/2, y(t+h/2));
41 y(t+h) = y(t+h/2) + h/2 * y'(t+h/2);
42 y'(t+h) = f(t+h, y(t+h));
43 err = h * |y'(t) - y'(t+h/2)|;
44*/
45
47{
48 const double err_coef = 0.02; // limits an error range
49 static double dthlf; // half step
50 size_t i; // auxiliary variables for loops to go through list
51 Iterator ip, end_it; // of integrators
52 static bool DoubleStepFlag; // flag - allow increasing (doubling) the step
53
54 Dprintf((" Euler integration step ")); // print debugging info
55 Dprintf((" Time = %g, optimal step = %g", (double)Time, OptStep));
56
57 end_it=LastIntegrator(); // end of container of integrators
58
59 //--------------------------------------------------------------------------
60 // Step of method
61 //--------------------------------------------------------------------------
62
63begin_step: // beginning of step
64
66
67 dthlf = 0.5*SIMLIB_StepSize; // half step
68
69 SIMLIB_ContractStepFlag = false; // clear reduce step flag
70 SIMLIB_ContractStep = 0.5*dthlf; // implicitly reduce to half
71
72 for(ip=FirstIntegrator(),i=0; ip!=end_it; ip++,i++) {
73 A[i] = (*ip)->GetOldDiff();
74 (*ip)->SetState((*ip)->GetOldState() + dthlf*(*ip)->GetDiff()); // state y(t+h/2)
75 }
76
77 ////////////////////////////////////////////////////////////// 1/2 of step
78
81
82 SIMLIB_Dynamic(); // compute new state of model (1)
83
84 if(StateCond()) { // check on changes of state conditions in 1/2 of step
85 goto begin_step;
86 }
87
88 bool wasContractStepFlag = SIMLIB_ContractStepFlag; // remember value
89 SIMLIB_ContractStepFlag = false; // not reduce step
90 SIMLIB_ContractStep = dthlf; // implicitly reduce to half of step
91
92 StoreState(di, si, xi); // store values in 1/2 of step
93
94 for(ip=FirstIntegrator(),i=0; ip!=end_it; ip++,i++) {
95 // difference of differentiations for error estimation
96 A[i] -= (*ip)->GetDiff();
97 (*ip)->SetState(si[i] + dthlf*(*ip)->GetDiff());
98 }
99
100 //////////////////////////////////////////////////////////// end of step
101
104
105 SIMLIB_Dynamic(); // compute new state of model (2)
106
107 //--------------------------------------------------------------------------
108 // Check on accuracy of numerical integration, estimate error
109 //--------------------------------------------------------------------------
110
111 DoubleStepFlag = true; // allow doubling the step
112 SIMLIB_ERRNO = 0; // OK
113 for(ip=FirstIntegrator(),i=0; ip!=end_it; ip++,i++) {
114 double eerr; // estimated error
115 double terr; // greatest allowed error
116
117 eerr = fabs(SIMLIB_StepSize*A[i]); // error estimation
119
120 if(eerr < err_coef*terr) // allowed tolerantion is fulfiled with provision
121 continue;
122
123 if(eerr > terr) { // allowed tolerantion is overfulfiled
124 if(SIMLIB_StepSize > SIMLIB_MinStep) { // reducing step is possible
125 SIMLIB_OptStep = 0.5*SIMLIB_StepSize; // halve optimal step
126 if(SIMLIB_OptStep < SIMLIB_MinStep) { // limit of optimal step
128 }
130 IsEndStepEvent = false;
131 goto begin_step; // compute again with smaller step
132 }
133 // reducing step is unpossible
134 SIMLIB_ERRNO++; // requested accuracy cannot be achieved
135 _Print("\n Integrator[%lu] ",(unsigned long)i);
136 if(SIMLIB_ConditionFlag) // event has been within the step
137 break;
138 }
139
140 DoubleStepFlag = false; // disable increasing SIMLIB_OptStep,
141 // accuracy is sufficient, but not well
142 } // for
143
144 if(SIMLIB_ERRNO) {
146 }
147
148 //--------------------------------------------------------------------------
149 // Computation is continuing, compute y(t+h)
150 //--------------------------------------------------------------------------
151
152 if(wasContractStepFlag) {
153 // step reducing has been requested in half step and it is unpossible
154 RestoreState(dthlf, di, si, xi); // restore halfstep state
155 } else { // go to half step and complete the computation
156
157 GoToState(di, si, xi);
158
159 SIMLIB_StepStartTime += dthlf;
161
162 //-----------------------------------------------------------------------
163 // Analyse system at the end of the step
164 //-----------------------------------------------------------------------
165
166 if(StateCond()) { // check on changes of state conditions at end of step
167 goto begin_step;
168 }
169 }
170
171 //--------------------------------------------------------------------------
172 // Results of step have been accepted, take fresh step
173 //--------------------------------------------------------------------------
174
175 // increase step, if accuracy was good
176 // step increasing is allowed
177 // && method is not used to start multi-step method
178 if(DoubleStepFlag && !IsStartMode()) {
179 SIMLIB_OptStep += SIMLIB_OptStep; // step doubling
180 }
181 SIMLIB_OptStep = min(SIMLIB_OptStep,SIMLIB_MaxStep); // limit step size
182
183} // EULER::Integrate
184
185
186}
187
virtual void Integrate(void) override
Definition: ni_euler.cc:46
Memory A
Definition: ni_euler.h:24
StatusMemory xi
Definition: ni_euler.h:25
Memory di
Definition: ni_euler.h:24
Memory si
Definition: ni_euler.h:24
static Iterator LastIntegrator(void)
Definition: simlib.h:1084
static bool IsEndStepEvent
Definition: simlib.h:1079
IntegratorContainer::iterator Iterator
Definition: simlib.h:1080
static bool StateCond(void)
check on changes of state conditions
Definition: numint.cc:175
static Iterator FirstIntegrator(void)
Definition: simlib.h:1081
bool IsStartMode(void)
Definition: simlib.h:1154
static void StoreState(Memory &di, Memory &si, StatusMemory &xi)
store state of integrators and status variables
Definition: numint.cc:570
static void RestoreState(double dthlf, Memory &di, Memory &si, StatusMemory &xi)
restore state of integrators and status variables
Definition: numint.cc:594
static void GoToState(Memory &di, Memory &si, StatusMemory &xi)
move startpoint to given state
Definition: numint.cc:622
@ AccuracyError
Definition: errors.h:23
Internal header file for SIMLIB/C++.
#define Dprintf(f)
Definition: internal.h:100
#define _SetTime(t, x)
macro for simple assignement to internal time variables
Definition: internal.h:228
Implementation of class CalendarList interface is static - using global functions in SQS namespace.
Definition: algloop.cc:32
const double & Time
model time (is NOT the block)
Definition: run.cc:48
bool SIMLIB_ConditionFlag
Definition: cond.cc:30
double SIMLIB_RelativeError
relative error
Definition: intg.cc:43
double SIMLIB_OptStep
optimal step
Definition: intg.cc:37
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
bool SIMLIB_ContractStepFlag
requests shorter step
Definition: intg.cc:58
void SIMLIB_Dynamic()
performs evaluation of integrators and status blocks
Definition: continuous.cc:35
int _Print(const char *fmt,...)
output of messages to stdout, too
Definition: print.cc:68
double min(double a, double b)
Definition: internal.h:285
double max(double a, double b)
Definition: internal.h:286
void SIMLIB_warning(const enum _ErrEnum N)
print warning message and continue
Definition: error.cc:74
double SIMLIB_AbsoluteError
absolute error
Definition: intg.cc:42
double SIMLIB_MinStep
minimal step
Definition: intg.cc:38
double SIMLIB_MaxStep
max. step
Definition: intg.cc:39
int SIMLIB_ERRNO
Definition: intg.cc:32
const double & OptStep
optimal integration step
Definition: intg.cc:49
double SIMLIB_ContractStep
requested step size
Definition: intg.cc:59
double SIMLIB_StepStartTime
last step time
Definition: intg.cc:34
double SIMLIB_StepSize
actual step
Definition: intg.cc:40
double SIMLIB_DeltaTime
Time-SIMLIB_StepStartTime.
Definition: intg.cc:35
Modified Euler method.
Main SIMLIB/C++ interface.