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 }