001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.ode;
019    
020    import org.apache.commons.math.ode.events.EventHandler;
021    
022    /**
023     * This class is used in the junit tests for the ODE integrators.
024    
025     * <p>This specific problem is the following differential equation :
026     * <pre>
027     *    x'' = -x
028     * </pre>
029     * And when x decreases down to 0, the state should be changed as follows :
030     * <pre>
031     *   x' -> -x'
032     * </pre>
033     * The theoretical solution of this problem is x = |sin(t+a)|
034     * </p>
035    
036     */
037    public class TestProblem4
038      extends TestProblemAbstract {
039    
040      /** Serializable version identifier. */
041      private static final long serialVersionUID = -5910438521889015745L;
042    
043      /** Time offset. */
044      private double a;
045    
046      /** theoretical state */
047      private double[] y;
048    
049      /** Simple constructor. */
050      public TestProblem4() {
051        super();
052        a = 1.2;
053        double[] y0 = { Math.sin(a), Math.cos(a) };
054        setInitialConditions(0.0, y0);
055        setFinalConditions(15);
056        double[] errorScale = { 1.0, 0.0 };
057        setErrorScale(errorScale);
058        y = new double[y0.length];
059      }
060     
061      /**
062       * Copy constructor.
063       * @param problem problem to copy
064       */
065      public TestProblem4(TestProblem4 problem) {
066        super(problem);
067        a = problem.a;
068        y = problem.y.clone();
069      }
070    
071      /** {@inheritDoc} */
072      public TestProblem4 copy() {
073        return new TestProblem4(this);
074      }
075    
076      @Override
077      public EventHandler[] getEventsHandlers() {
078        return new EventHandler[] { new Bounce(), new Stop() };
079      }
080    
081      @Override
082      public void doComputeDerivatives(double t, double[] y, double[] yDot) {
083        yDot[0] =  y[1];
084        yDot[1] = -y[0];
085      }
086    
087      @Override
088      public double[] computeTheoreticalState(double t) {
089        double sin = Math.sin(t + a);
090        double cos = Math.cos(t + a);
091        y[0] = Math.abs(sin);
092        y[1] = (sin >= 0) ? cos : -cos;
093        return y;
094      }
095    
096      private static class Bounce implements EventHandler {
097    
098        private static final long serialVersionUID = 1356097180027801200L;
099        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    }