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.DerivativeException; 021 import org.apache.commons.math.ode.ODEIntegrator; 022 import org.apache.commons.math.ode.sampling.StepHandler; 023 import org.apache.commons.math.ode.sampling.StepInterpolator; 024 025 /** 026 * This class is used to handle steps for the test problems 027 * integrated during the junit tests for the ODE integrators. 028 */ 029 public class TestProblemHandler 030 implements StepHandler { 031 032 /** Associated problem. */ 033 private TestProblemAbstract problem; 034 035 /** Maximal errors encountered during the integration. */ 036 private double maxValueError; 037 private double maxTimeError; 038 039 /** Error at the end of the integration. */ 040 private double lastError; 041 042 /** Time at the end of integration. */ 043 private double lastTime; 044 045 /** ODE solver used. */ 046 private ODEIntegrator integrator; 047 048 /** Expected start for step. */ 049 private double expectedStepStart; 050 051 /** 052 * Simple constructor. 053 * @param problem problem for which steps should be handled 054 * @param integrator ODE solver used 055 */ 056 public TestProblemHandler(TestProblemAbstract problem, ODEIntegrator integrator) { 057 this.problem = problem; 058 this.integrator = integrator; 059 reset(); 060 } 061 062 public boolean requiresDenseOutput() { 063 return true; 064 } 065 066 public void reset() { 067 maxValueError = 0; 068 maxTimeError = 0; 069 lastError = 0; 070 expectedStepStart = Double.NaN; 071 } 072 073 public void handleStep(StepInterpolator interpolator, 074 boolean isLast) 075 throws DerivativeException { 076 077 double start = integrator.getCurrentStepStart(); 078 if (Math.abs((start - problem.getInitialTime()) / integrator.getCurrentSignedStepsize()) > 0.001) { 079 // multistep integrators do not handle the first steps themselves 080 // so we have to make sure the integrator we look at has really started its work 081 if (!Double.isNaN(expectedStepStart)) { 082 maxTimeError = Math.max(maxTimeError, Math.abs(start - expectedStepStart)); 083 } 084 expectedStepStart = start + integrator.getCurrentSignedStepsize(); 085 } 086 087 double pT = interpolator.getPreviousTime(); 088 double cT = interpolator.getCurrentTime(); 089 double[] errorScale = problem.getErrorScale(); 090 091 // store the error at the last step 092 if (isLast) { 093 double[] interpolatedY = interpolator.getInterpolatedState(); 094 double[] theoreticalY = problem.computeTheoreticalState(cT); 095 for (int i = 0; i < interpolatedY.length; ++i) { 096 double error = Math.abs(interpolatedY[i] - theoreticalY[i]); 097 lastError = Math.max(error, lastError); 098 } 099 lastTime = cT; 100 } 101 102 // walk through the step 103 for (int k = 0; k <= 20; ++k) { 104 105 double time = pT + (k * (cT - pT)) / 20; 106 interpolator.setInterpolatedTime(time); 107 double[] interpolatedY = interpolator.getInterpolatedState(); 108 double[] theoreticalY = problem.computeTheoreticalState(interpolator.getInterpolatedTime()); 109 110 // update the errors 111 for (int i = 0; i < interpolatedY.length; ++i) { 112 double error = errorScale[i] * Math.abs(interpolatedY[i] - theoreticalY[i]); 113 maxValueError = Math.max(error, maxValueError); 114 } 115 } 116 } 117 118 /** 119 * Get the maximal value error encountered during integration. 120 * @return maximal value error 121 */ 122 public double getMaximalValueError() { 123 return maxValueError; 124 } 125 126 /** 127 * Get the maximal time error encountered during integration. 128 * @return maximal time error 129 */ 130 public double getMaximalTimeError() { 131 return maxTimeError; 132 } 133 134 /** 135 * Get the error at the end of the integration. 136 * @return error at the end of the integration 137 */ 138 public double getLastError() { 139 return lastError; 140 } 141 142 /** 143 * Get the time at the end of the integration. 144 * @return time at the end of the integration. 145 */ 146 public double getLastTime() { 147 return lastTime; 148 } 149 150 }