View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.ode;
24  
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.exception.MathIllegalStateException;
27  import org.hipparchus.ode.nonstiff.ClassicalRungeKuttaIntegrator;
28  import org.hipparchus.util.FastMath;
29  import org.junit.jupiter.api.Test;
30  
31  import static org.junit.jupiter.api.Assertions.assertEquals;
32  import static org.junit.jupiter.api.Assertions.assertTrue;
33  
34  
35  class FirstOrderConverterTest {
36  
37      @Test
38      void testDoubleDimension() {
39          for (int i = 1; i < 10; ++i) {
40              SecondOrderODE eqn2 = new Equations(i, 0.2);
41              FirstOrderConverter eqn1 = new FirstOrderConverter(eqn2);
42              assertEquals(eqn1.getDimension(), (2 * eqn2.getDimension()));
43          }
44      }
45  
46      @Test
47      void testDecreasingSteps()
48          throws MathIllegalArgumentException, MathIllegalStateException {
49  
50          double previousError = Double.NaN;
51          for (int i = 0; i < 10; ++i) {
52  
53              double step  = FastMath.pow(2.0, -(i + 1));
54              double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, step)
55                              - FastMath.sin(4.0);
56              if (i > 0) {
57                  assertTrue(FastMath.abs(error) < FastMath.abs(previousError));
58              }
59              previousError = error;
60  
61          }
62      }
63  
64      @Test
65      void testSmallStep()
66          throws MathIllegalArgumentException, MathIllegalStateException {
67          double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 1.0e-4)
68                          - FastMath.sin(4.0);
69          assertTrue(FastMath.abs(error) < 1.0e-10);
70      }
71  
72      @Test
73      void testBigStep()
74          throws MathIllegalArgumentException, MathIllegalStateException {
75          double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 0.5)
76                          - FastMath.sin(4.0);
77          assertTrue(FastMath.abs(error) > 0.1);
78      }
79  
80      private static class Equations
81      implements SecondOrderODE {
82  
83          private int n;
84  
85          private double omega2;
86  
87          public Equations(int n, double omega) {
88              this.n = n;
89              omega2 = omega * omega;
90          }
91  
92          public int getDimension() {
93              return n;
94          }
95  
96          public double[] computeSecondDerivatives(double t, double[] y, double[] yDot) {
97              final double[] yDDot = new double[n];
98              for (int i = 0; i < n; ++i) {
99                  yDDot[i] = -omega2 * y[i];
100             }
101             return yDDot;
102         }
103 
104     }
105 
106     private double integrateWithSpecifiedStep(double omega,
107                                               double t0, double t,
108                                               double step) throws MathIllegalArgumentException, MathIllegalStateException {
109         double[] y0 = new double[2];
110         y0[0] = FastMath.sin(omega * t0);
111         y0[1] = omega * FastMath.cos(omega * t0);
112         ClassicalRungeKuttaIntegrator i = new ClassicalRungeKuttaIntegrator(step);
113         final ODEStateAndDerivative finalstate =
114                         i.integrate(new FirstOrderConverter(new Equations(1, omega)), new ODEState(t0, y0), t);
115         return finalstate.getPrimaryState()[0];
116     }
117 
118 }