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    *      http://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  package org.apache.commons.math4.legacy.ode;
19  
20  import org.apache.commons.math4.core.jdkmath.JdkMath;
21  
22  /**
23   * This class is used in the junit tests for the ODE integrators.
24  
25   * <p>This specific problem is the following differential equation :
26   * <pre>
27   *    y1'' = -y1/r^3  y1 (0) = 1-e  y1' (0) = 0
28   *    y2'' = -y2/r^3  y2 (0) = 0    y2' (0) =sqrt((1+e)/(1-e))
29   *    r = sqrt (y1^2 + y2^2), e = 0.9
30   * </pre>
31   * This is a two-body problem in the plane which can be solved by
32   * Kepler's equation
33   * <pre>
34   *   y1 (t) = ...
35   * </pre>
36   * </p>
37  
38   */
39  public class TestProblem3
40    extends TestProblemAbstract {
41  
42    /** Eccentricity */
43    private double e;
44  
45    /** theoretical state */
46    private double[] y;
47  
48    /**
49     * Simple constructor.
50     * @param e eccentricity
51     */
52    public TestProblem3(double e) {
53      super();
54      this.e = e;
55      double[] y0 = { 1 - e, 0, 0, JdkMath.sqrt((1+e)/(1-e)) };
56      setInitialConditions(0.0, y0);
57      setFinalConditions(20.0);
58      double[] errorScale = { 1.0, 1.0, 1.0, 1.0 };
59      setErrorScale(errorScale);
60      y = new double[y0.length];
61    }
62  
63    /**
64     * Simple constructor.
65     */
66    public TestProblem3() {
67      this(0.1);
68    }
69  
70    @Override
71    public void doComputeDerivatives(double t, double[] y, double[] yDot) {
72  
73      // current radius
74      double r2 = y[0] * y[0] + y[1] * y[1];
75      double invR3 = 1 / (r2 * JdkMath.sqrt(r2));
76  
77      // compute the derivatives
78      yDot[0] = y[2];
79      yDot[1] = y[3];
80      yDot[2] = -invR3  * y[0];
81      yDot[3] = -invR3  * y[1];
82    }
83  
84    @Override
85    public double[] computeTheoreticalState(double t) {
86  
87      // solve Kepler's equation
88      double E = t;
89      double d = 0;
90      double corr = 999.0;
91      for (int i = 0; i < 50 && JdkMath.abs(corr) > 1.0e-12; ++i) {
92        double f2  = e * JdkMath.sin(E);
93        double f0  = d - f2;
94        double f1  = 1 - e * JdkMath.cos(E);
95        double f12 = f1 + f1;
96        corr  = f0 * f12 / (f1 * f12 - f0 * f2);
97        d -= corr;
98        E = t + d;
99      }
100 
101     double cosE = JdkMath.cos(E);
102     double sinE = JdkMath.sin(E);
103 
104     y[0] = cosE - e;
105     y[1] = JdkMath.sqrt(1 - e * e) * sinE;
106     y[2] = -sinE / (1 - e * cosE);
107     y[3] = JdkMath.sqrt(1 - e * e) * cosE / (1 - e * cosE);
108 
109     return y;
110   }
111 }