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.SwitchingFunction;
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  class TestProblem4
38    extends TestProblemAbstract {
39  
40    /** Time offset. */
41    private double a;
42  
43    /** theoretical state */
44    private double[] y;
45  
46    /** Simple constructor. */
47    public TestProblem4() {
48      super();
49      a = 1.2;
50      double[] y0 = { Math.sin(a), Math.cos(a) };
51      setInitialConditions(0.0, y0);
52      setFinalConditions(15);
53      double[] errorScale = { 1.0, 0.0 };
54      setErrorScale(errorScale);
55      y = new double[y0.length];
56    }
57   
58    /**
59     * Copy constructor.
60     * @param problem problem to copy
61     */
62    public TestProblem4(TestProblem4 problem) {
63      super(problem);
64      a = problem.a;
65      y = (double[]) problem.y.clone();
66    }
67  
68    /**
69     * Clone operation.
70     * @return a copy of the instance
71     */
72    public Object clone() {
73      return new TestProblem4(this);
74    }
75  
76    public SwitchingFunction[] getSwitchingFunctions() {
77      return new SwitchingFunction[] { new Bounce(), new Stop() };
78    }
79  
80    public void doComputeDerivatives(double t, double[] y, double[] yDot) {
81      yDot[0] =  y[1];
82      yDot[1] = -y[0];
83    }
84  
85    public double[] computeTheoreticalState(double t) {
86      double sin = Math.sin(t + a);
87      double cos = Math.cos(t + a);
88      y[0] = Math.abs(sin);
89      y[1] = (sin >= 0) ? cos : -cos;
90      return y;
91    }
92  
93    private static class Bounce implements SwitchingFunction {
94  
95      private static final long serialVersionUID = 1356097180027801200L;
96      private int sign;
97  
98      public Bounce() {
99        sign = +1;
100     }
101 
102     public double g(double t, double[] y) {
103       return sign * y[0];
104     }
105 
106     public int eventOccurred(double t, double[] y) {
107       // this sign change is needed because the state will be reset soon
108       sign = -sign;
109       return SwitchingFunction.RESET_STATE;
110     }
111   
112     public void resetState(double t, double[] y) {
113       y[1] = -y[1];
114     }
115 
116   }
117 
118   private static class Stop implements SwitchingFunction {
119 
120     private static final long serialVersionUID = 6975050568227951931L;
121 
122     public Stop() {
123     }
124 
125     public double g(double t, double[] y) {
126       return t - 12.0;
127     }
128 
129     public int eventOccurred(double t, double[] y) {
130       return SwitchingFunction.STOP;
131     }
132   
133     public void resetState(double t, double[] y) {
134     }
135 
136   }
137 
138 }