1 package nl.tudelft.simulation.jstats.ode;
2
3 import org.djutils.event.LocalEventProducer;
4
5 import nl.tudelft.simulation.jstats.ode.integrators.NumericalIntegrator;
6 import nl.tudelft.simulation.jstats.ode.integrators.NumericalIntegratorType;
7
8
9
10
11
12
13
14
15
16
17
18
19
20 public abstract class DifferentialEquation extends LocalEventProducer implements DifferentialEquationInterface
21 {
22
23 private static final long serialVersionUID = 1L;
24
25
26 private NumericalIntegrator integrator = null;
27
28
29 @SuppressWarnings("checkstyle:visibilitymodifier")
30 protected double[] lastY = null;
31
32
33 @SuppressWarnings("checkstyle:visibilitymodifier")
34 protected double stepSize = Double.NaN;
35
36
37 @SuppressWarnings("checkstyle:visibilitymodifier")
38 protected double lastX = Double.NaN;
39
40
41
42
43
44
45 public DifferentialEquation(final double stepSize, final NumericalIntegratorType integratorType)
46 {
47 super();
48 this.stepSize = stepSize;
49 this.integrator = integratorType.getInstance(stepSize, this);
50 }
51
52
53 @Override
54 public void initialize(final double x0, final double[] y0)
55 {
56 this.lastX = x0;
57 this.lastY = y0;
58 }
59
60
61 @Override
62 public double[] y(final double x)
63 {
64
65 if (Double.isNaN(this.lastX))
66 {
67 throw new RuntimeException("differential equation not initialized");
68 }
69
70 if (x == this.lastX)
71 {
72 return this.lastY;
73 }
74
75
76 if (Math.signum(this.stepSize) != Math.signum(x - this.lastX))
77 {
78 throw new RuntimeException("Sign of the stepsize does not integrate towards x from x0");
79 }
80 return this.integrateY(x, this.lastX, this.lastY);
81 }
82
83
84
85
86
87
88
89
90 @SuppressWarnings("checkstyle:finalparameters")
91 protected double[] integrateY(final double x, double initialX, double[] initialY)
92 {
93
94 if (this.stepSize > 0)
95 {
96 while (x > initialX + this.stepSize)
97 {
98 initialY = this.integrator.next(initialX, initialY);
99 initialX = initialX + this.stepSize;
100 }
101 }
102 else
103 {
104 while (x < initialX + this.stepSize)
105 {
106 initialY = this.integrator.next(initialX, initialY);
107 initialX = initialX + this.stepSize;
108 }
109 }
110
111
112 double[] nextValue = this.integrator.next(initialX, initialY);
113 double ratio = (x - initialX) / this.stepSize;
114 for (int i = 0; i < initialY.length; i++)
115 {
116 initialY[i] = initialY[i] + ratio * (nextValue[i] - initialY[i]);
117 }
118 this.lastX = x;
119 this.lastY = initialY;
120 return initialY;
121 }
122
123
124
125
126 public NumericalIntegrator getIntegrator()
127 {
128 return this.integrator;
129 }
130
131
132
133
134 public void setIntegrator(final NumericalIntegrator integrator)
135 {
136 this.integrator = integrator;
137 }
138
139 }