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 }