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.Assert;
30  import org.junit.Test;
31  
32  
33  public class FirstOrderConverterTest {
34  
35      @Test
36      public void testDoubleDimension() {
37          for (int i = 1; i < 10; ++i) {
38              SecondOrderODE eqn2 = new Equations(i, 0.2);
39              FirstOrderConverter eqn1 = new FirstOrderConverter(eqn2);
40              Assert.assertTrue(eqn1.getDimension() == (2 * eqn2.getDimension()));
41          }
42      }
43  
44      @Test
45      public void testDecreasingSteps()
46                      throws MathIllegalArgumentException, MathIllegalStateException {
47  
48          double previousError = Double.NaN;
49          for (int i = 0; i < 10; ++i) {
50  
51              double step  = FastMath.pow(2.0, -(i + 1));
52              double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, step)
53                              - FastMath.sin(4.0);
54              if (i > 0) {
55                  Assert.assertTrue(FastMath.abs(error) < FastMath.abs(previousError));
56              }
57              previousError = error;
58  
59          }
60      }
61  
62      @Test
63      public void testSmallStep()
64                      throws MathIllegalArgumentException, MathIllegalStateException {
65          double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 1.0e-4)
66                          - FastMath.sin(4.0);
67          Assert.assertTrue(FastMath.abs(error) < 1.0e-10);
68      }
69  
70      @Test
71      public void testBigStep()
72                      throws MathIllegalArgumentException, MathIllegalStateException {
73          double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 0.5)
74                          - FastMath.sin(4.0);
75          Assert.assertTrue(FastMath.abs(error) > 0.1);
76      }
77  
78      private static class Equations
79      implements SecondOrderODE {
80  
81          private int n;
82  
83          private double omega2;
84  
85          public Equations(int n, double omega) {
86              this.n = n;
87              omega2 = omega * omega;
88          }
89  
90          public int getDimension() {
91              return n;
92          }
93  
94          public double[] computeSecondDerivatives(double t, double[] y, double[] yDot) {
95              final double[] yDDot = new double[n];
96              for (int i = 0; i < n; ++i) {
97                  yDDot[i] = -omega2 * y[i];
98              }
99              return yDDot;
100         }
101 
102     }
103 
104     private double integrateWithSpecifiedStep(double omega,
105                                               double t0, double t,
106                                               double step) throws MathIllegalArgumentException, MathIllegalStateException {
107         double[] y0 = new double[2];
108         y0[0] = FastMath.sin(omega * t0);
109         y0[1] = omega * FastMath.cos(omega * t0);
110         ClassicalRungeKuttaIntegrator i = new ClassicalRungeKuttaIntegrator(step);
111         final ODEStateAndDerivative finalstate =
112                         i.integrate(new FirstOrderConverter(new Equations(1, omega)), new ODEState(t0, y0), t);
113         return finalstate.getPrimaryState()[0];
114     }
115 
116 }