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.legacy.ode.events.EventHandler;
21  import org.apache.commons.math4.core.jdkmath.JdkMath;
22  
23  /**
24   * This class is used in the junit tests for the ODE integrators.
25  
26   * <p>This specific problem is the following differential equation :
27   * <pre>
28   *    x'' = -x
29   * </pre>
30   * And when x decreases down to 0, the state should be changed as follows :
31   * <pre>
32   *   x' -> -x'
33   * </pre>
34   * The theoretical solution of this problem is x = |sin(t+a)|
35   * </p>
36  
37   */
38  public class TestProblem4
39    extends TestProblemAbstract {
40  
41    /** Time offset. */
42    private double a;
43  
44    /** theoretical state */
45    private double[] y;
46  
47    /** Simple constructor. */
48    public TestProblem4() {
49      super();
50      a = 1.2;
51      double[] y0 = { JdkMath.sin(a), JdkMath.cos(a) };
52      setInitialConditions(0.0, y0);
53      setFinalConditions(15);
54      double[] errorScale = { 1.0, 0.0 };
55      setErrorScale(errorScale);
56      y = new double[y0.length];
57    }
58  
59    @Override
60    public EventHandler[] getEventsHandlers() {
61      return new EventHandler[] { new Bounce(), new Stop() };
62    }
63  
64    /**
65     * Get the theoretical events times.
66     * @return theoretical events times
67     */
68    @Override
69    public double[] getTheoreticalEventsTimes() {
70        return new double[] {
71            1 * JdkMath.PI - a,
72            2 * JdkMath.PI - a,
73            3 * JdkMath.PI - a,
74            4 * JdkMath.PI - a,
75            12.0
76        };
77    }
78  
79    @Override
80    public void doComputeDerivatives(double t, double[] y, double[] yDot) {
81      yDot[0] =  y[1];
82      yDot[1] = -y[0];
83    }
84  
85    @Override
86    public double[] computeTheoreticalState(double t) {
87      double sin = JdkMath.sin(t + a);
88      double cos = JdkMath.cos(t + a);
89      y[0] = JdkMath.abs(sin);
90      y[1] = (sin >= 0) ? cos : -cos;
91      return y;
92    }
93  
94    private static final class Bounce implements EventHandler {
95  
96      private int sign;
97  
98      Bounce() {
99        sign = +1;
100     }
101 
102     @Override
103     public void init(double t0, double[] y0, double t) {
104     }
105 
106     @Override
107     public double g(double t, double[] y) {
108       return sign * y[0];
109     }
110 
111     @Override
112     public Action eventOccurred(double t, double[] y, boolean increasing) {
113       // this sign change is needed because the state will be reset soon
114       sign = -sign;
115       return Action.RESET_STATE;
116     }
117 
118     @Override
119     public void resetState(double t, double[] y) {
120       y[0] = -y[0];
121       y[1] = -y[1];
122     }
123   }
124 
125   private static final class Stop implements EventHandler {
126 
127     Stop() {
128     }
129 
130     @Override
131     public void init(double t0, double[] y0, double t) {
132     }
133 
134     @Override
135     public double g(double t, double[] y) {
136       return t - 12.0;
137     }
138 
139     @Override
140     public Action eventOccurred(double t, double[] y, boolean increasing) {
141       return Action.STOP;
142     }
143 
144     @Override
145     public void resetState(double t, double[] y) {
146     }
147   }
148 }