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.math.ode;
19  
20  import org.apache.commons.math.ode.events.EventHandler;
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   *    x'' = -x
28   * </pre>
29   * And when x decreases down to 0, the state should be changed as follows :
30   * <pre>
31   *   x' -> -x'
32   * </pre>
33   * The theoretical solution of this problem is x = |sin(t+a)|
34   * </p>
35  
36   */
37  public class TestProblem4
38    extends TestProblemAbstract {
39  
40    /** Serializable version identifier. */
41    private static final long serialVersionUID = -5910438521889015745L;
42  
43    /** Time offset. */
44    private double a;
45  
46    /** theoretical state */
47    private double[] y;
48  
49    /** Simple constructor. */
50    public TestProblem4() {
51      super();
52      a = 1.2;
53      double[] y0 = { Math.sin(a), Math.cos(a) };
54      setInitialConditions(0.0, y0);
55      setFinalConditions(15);
56      double[] errorScale = { 1.0, 0.0 };
57      setErrorScale(errorScale);
58      y = new double[y0.length];
59    }
60   
61    /**
62     * Copy constructor.
63     * @param problem problem to copy
64     */
65    public TestProblem4(TestProblem4 problem) {
66      super(problem);
67      a = problem.a;
68      y = problem.y.clone();
69    }
70  
71    /** {@inheritDoc} */
72    public TestProblem4 copy() {
73      return new TestProblem4(this);
74    }
75  
76    @Override
77    public EventHandler[] getEventsHandlers() {
78      return new EventHandler[] { new Bounce(), new Stop() };
79    }
80  
81    @Override
82    public void doComputeDerivatives(double t, double[] y, double[] yDot) {
83      yDot[0] =  y[1];
84      yDot[1] = -y[0];
85    }
86  
87    @Override
88    public double[] computeTheoreticalState(double t) {
89      double sin = Math.sin(t + a);
90      double cos = Math.cos(t + a);
91      y[0] = Math.abs(sin);
92      y[1] = (sin >= 0) ? cos : -cos;
93      return y;
94    }
95  
96    private static class Bounce implements EventHandler {
97  
98      private static final long serialVersionUID = 1356097180027801200L;
99      private int sign;
100 
101     public Bounce() {
102       sign = +1;
103     }
104 
105     public double g(double t, double[] y) {
106       return sign * y[0];
107     }
108 
109     public int eventOccurred(double t, double[] y, boolean increasing) {
110       // this sign change is needed because the state will be reset soon
111       sign = -sign;
112       return EventHandler.RESET_STATE;
113     }
114   
115     public void resetState(double t, double[] y) {
116       y[0] = -y[0];
117       y[1] = -y[1];
118     }
119 
120   }
121 
122   private static class Stop implements EventHandler {
123 
124     private static final long serialVersionUID = 6975050568227951931L;
125 
126     public Stop() {
127     }
128 
129     public double g(double t, double[] y) {
130       return t - 12.0;
131     }
132 
133     public int eventOccurred(double t, double[] y, boolean increasing) {
134       return EventHandler.STOP;
135     }
136   
137     public void resetState(double t, double[] y) {
138     }
139 
140   }
141 
142 }