1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.numerical.integration;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.algebra.WrongSizeException;
20 import com.irurueta.numerical.EvaluationException;
21 import com.irurueta.numerical.interpolation.InterpolationException;
22 import com.irurueta.numerical.interpolation.PolynomialInterpolator;
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public abstract class RombergMatrixIntegrator<T extends MatrixQuadrature> extends MatrixIntegrator {
37
38
39
40
41 public static final double EPS = 3.0e-9;
42
43
44
45
46 private static final int JMAX = 14;
47
48
49
50
51 private static final int JMAXP = JMAX + 1;
52
53
54
55
56 private static final int K = 5;
57
58
59
60
61 protected final T q;
62
63
64
65
66 protected final double eps;
67
68
69
70
71 private final Matrix[] s = new Matrix[JMAX];
72
73
74
75
76 private final double[] h = new double[JMAXP];
77
78
79
80
81
82
83
84 protected RombergMatrixIntegrator(final T q, final double eps) {
85 this.q = q;
86 this.eps = eps;
87 }
88
89
90
91
92
93
94
95 @SuppressWarnings("Duplicates")
96 @Override
97 public void integrate(final Matrix result) throws IntegrationException {
98 try {
99 final var rows = q.getRows();
100 final var columns = q.getColumns();
101 final var elems = rows * columns;
102 for (var i = 0; i < JMAX; i++) {
103 s[i] = new Matrix(rows, columns);
104 }
105
106 final var interpolators = new PolynomialInterpolator[elems];
107 final var sInterp = new double[elems][JMAX];
108 for (int i = 0; i < elems; i++) {
109 sInterp[i] = new double[JMAX];
110 interpolators[i] = new PolynomialInterpolator(h, sInterp[i], K, false);
111 }
112
113 h[0] = 1.0;
114 for (int j = 1; j <= JMAX; j++) {
115 q.next(s[j - 1]);
116
117 for (var i = 0; i < elems; i++) {
118 sInterp[i][j - 1] = s[j - 1].getElementAtIndex(i);
119 }
120 if (j >= K) {
121 var finished = true;
122 for (var i = 0; i < elems; i++) {
123 final var ss = interpolators[i].rawinterp(j - K, 0.0);
124 if (Double.isNaN(ss)) {
125 throw new IntegrationException("NaN was found");
126 }
127 result.setElementAtIndex(i, ss);
128 if (Math.abs(interpolators[i].getDy()) > eps * Math.abs(ss)) {
129 finished = false;
130 }
131 }
132
133 if (finished) {
134 return;
135 }
136 }
137 h[j] = h[j - 1] / 9.0;
138 }
139 } catch (final EvaluationException | InterpolationException | WrongSizeException e) {
140 throw new IntegrationException(e);
141 }
142
143
144 throw new IntegrationException();
145 }
146
147
148
149
150
151
152 @Override
153 public IntegratorType getIntegratorType() {
154 return IntegratorType.ROMBERG;
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 public static RombergMatrixIntegrator<MatrixQuadrature> create(
172 final double a, final double b, final MatrixSingleDimensionFunctionEvaluatorListener listener,
173 final double eps, final QuadratureType quadratureType) throws WrongSizeException {
174 return switch (quadratureType) {
175 case MID_POINT -> cast(new RombergMidPointQuadratureMatrixIntegrator(a, b, listener, eps));
176 case INFINITY_MID_POINT -> cast(new RombergInfinityMidPointQuadratureMatrixIntegrator(a, b, listener, eps));
177 case LOWER_SQUARE_ROOT_MID_POINT ->
178 cast(new RombergLowerSquareRootMidPointQuadratureMatrixIntegrator(a, b, listener, eps));
179 case UPPER_SQUARE_ROOT_MID_POINT ->
180 cast(new RombergUpperSquareRootMidPointQuadratureMatrixIntegrator(a, b, listener, eps));
181 case EXPONENTIAL_MID_POINT ->
182 cast(new RombergExponentialMidPointQuadratureMatrixIntegrator(a, listener, eps));
183 case DOUBLE_EXPONENTIAL_RULE ->
184 cast(new RombergDoubleExponentialRuleQuadratureMatrixIntegrator(a, b, listener, eps));
185 default -> cast(new RombergTrapezoidalQuadratureMatrixIntegrator(a, b, listener, eps));
186 };
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public static RombergMatrixIntegrator<MatrixQuadrature> create(
203 final double a, final double b, final MatrixSingleDimensionFunctionEvaluatorListener listener,
204 final QuadratureType quadratureType) throws WrongSizeException {
205 return switch (quadratureType) {
206 case MID_POINT -> cast(new RombergMidPointQuadratureMatrixIntegrator(a, b, listener));
207 case INFINITY_MID_POINT -> cast(new RombergInfinityMidPointQuadratureMatrixIntegrator(a, b, listener));
208 case LOWER_SQUARE_ROOT_MID_POINT ->
209 cast(new RombergLowerSquareRootMidPointQuadratureMatrixIntegrator(a, b, listener));
210 case UPPER_SQUARE_ROOT_MID_POINT ->
211 cast(new RombergUpperSquareRootMidPointQuadratureMatrixIntegrator(a, b, listener));
212 case EXPONENTIAL_MID_POINT -> cast(new RombergExponentialMidPointQuadratureMatrixIntegrator(a, listener));
213 case DOUBLE_EXPONENTIAL_RULE ->
214 cast(new RombergDoubleExponentialRuleQuadratureMatrixIntegrator(a, b, listener));
215 default -> cast(new RombergTrapezoidalQuadratureMatrixIntegrator(a, b, listener));
216 };
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public static RombergMatrixIntegrator<MatrixQuadrature> create(
232 final double a, final double b, final MatrixSingleDimensionFunctionEvaluatorListener listener,
233 final double eps) throws WrongSizeException {
234 return create(a, b, listener, eps, DEFAULT_QUADRATURE_TYPE);
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248 public static RombergMatrixIntegrator<MatrixQuadrature> create(
249 final double a, final double b, final MatrixSingleDimensionFunctionEvaluatorListener listener)
250 throws WrongSizeException {
251 return create(a, b, listener, DEFAULT_QUADRATURE_TYPE);
252 }
253
254
255
256
257
258
259
260 private static RombergMatrixIntegrator<MatrixQuadrature> cast(final RombergMatrixIntegrator<?> integrator) {
261
262 return (RombergMatrixIntegrator<MatrixQuadrature>) integrator;
263 }
264 }