1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
// Euler method and variants.
//
// Copyright (C) 2020 Juan Marín Noguera
//
// This file is part of Solvned.
//
// Solvned is free software: you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Solvned is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Solvned. If not, see <https://www.gnu.org/licenses/>.
package method
import "github.com/JwanMan/mned"
func eulerStep(ivp *mned.IVP, h float64) bool {
deriv, ok := ivp.Derivative(ivp.Start)
if !ok {
return false
}
for i := 0; i < len(deriv); i++ {
ivp.Start.Value[i] += h * deriv[i]
}
return true
}
// Make an instance of the Euler method with the given step, which must be
// positive. For a problem `x'(t)=f(t,x(t)), x(t0)=x0`, a step of the Euler
// method is given by `x(t0+step) = x(t0) + step*f(t0,x(t0))`.
func Euler(step float64) mned.Method {
return mned.FixedStepMethod{Step: step, Method: eulerStep}
}
// Make an instance of the adaptive version of the Euler method given the
// tolerance, the initial step, and the minimum and maximum steps.
func AdaptiveEuler(
tolerance float64, step float64, hmin float64, hmax float64,
) mned.Method {
return &mned.AdaptiveStepMethod{
Step: step,
Hmin: hmin,
Hmax: hmax,
Tolerance: tolerance,
Method: eulerStep,
Order: 1,
}
}
func modEulerStep(ivp *mned.IVP, h float64) bool {
deriv, ok := ivp.Derivative(ivp.Start)
if !ok {
return false
}
point := ivp.Start.Clone()
point.Time += h
for i, v := range deriv {
point.Value[i] += h * v
}
deriv2, ok := ivp.Derivative(point)
for i, _ := range deriv {
ivp.Start.Value[i] += h * (deriv[i] + deriv2[i]) / 2
}
return true
}
// Make an instance of the modified Euler method with the given step, which must
// be positive. This is a FixedStepMethod given by
// `x(t+h)=x(t) + h/2 * (f(t,x(t)) + f(t+h,x(t)+h*f(t,x(t))))`.
func ModifiedEuler(step float64) mned.Method {
return mned.FixedStepMethod{Step: step, Method: modEulerStep}
}
|