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.DerivativeException;
21  import org.apache.commons.math.ode.StepHandler;
22  import org.apache.commons.math.ode.StepInterpolator;
23  
24  /**
25   * This class is used to handle steps for the test problems
26   * integrated during the junit tests for the ODE integrators.
27   */
28  class TestProblemHandler
29    implements StepHandler {
30  
31    /** Associated problem. */
32    private TestProblemAbstract problem;
33  
34    /** Maximal errors encountered during the integration. */
35    private double maxValueError;
36    private double maxTimeError;
37  
38    /** Error at the end of the integration. */
39    private double lastError;
40  
41    /** Time at the end of integration. */
42    private double lastTime;
43  
44    /** ODE solver used. */
45    private FirstOrderIntegrator integrator;
46  
47    /** Expected start for step. */
48    private double expectedStepStart;
49  
50    /**
51     * Simple constructor.
52     * @param problem problem for which steps should be handled
53     * @param integrator ODE solver used
54     */
55    public TestProblemHandler(TestProblemAbstract problem, FirstOrderIntegrator integrator) {
56      this.problem = problem;
57      this.integrator = integrator;
58      reset();
59    }
60  
61    public boolean requiresDenseOutput() {
62      return true;
63    }
64  
65    public void reset() {
66      maxValueError = 0;
67      maxTimeError  = 0;
68      lastError     = 0;
69      expectedStepStart = problem.getInitialTime();
70    }
71  
72    public void handleStep(StepInterpolator interpolator,
73                           boolean isLast)
74      throws DerivativeException {
75  
76      double start = integrator.getCurrentStepStart();
77      maxTimeError = Math.max(maxTimeError, Math.abs(start - expectedStepStart));
78      expectedStepStart = start + integrator.getCurrentSignedStepsize();
79  
80      double pT = interpolator.getPreviousTime();
81      double cT = interpolator.getCurrentTime();
82      double[] errorScale = problem.getErrorScale();
83  
84      // store the error at the last step
85      if (isLast) {
86        double[] interpolatedY = interpolator.getInterpolatedState();
87        double[] theoreticalY  = problem.computeTheoreticalState(cT);
88        for (int i = 0; i < interpolatedY.length; ++i) {
89          double error = Math.abs(interpolatedY[i] - theoreticalY[i]);
90          if (error > lastError) {
91            lastError = error;
92          }
93        }
94        lastTime = cT;
95      }
96  
97      // walk through the step
98      for (int k = 0; k <= 20; ++k) {
99  
100       double time = pT + (k * (cT - pT)) / 20;
101       interpolator.setInterpolatedTime(time);
102       double[] interpolatedY = interpolator.getInterpolatedState();
103       double[] theoreticalY  = problem.computeTheoreticalState(interpolator.getInterpolatedTime());
104 
105       // update the errors
106       for (int i = 0; i < interpolatedY.length; ++i) {
107         double error = errorScale[i] * Math.abs(interpolatedY[i] - theoreticalY[i]);
108         if (error > maxValueError) {
109           maxValueError = error;
110         }
111       }
112 
113     }
114   }
115 
116   /**
117    * Get the maximal value error encountered during integration.
118    * @return maximal value error
119    */
120   public double getMaximalValueError() {
121     return maxValueError;
122   }
123 
124   /**
125    * Get the maximal time error encountered during integration.
126    * @return maximal time error
127    */
128   public double getMaximalTimeError() {
129     return maxTimeError;
130   }
131 
132   /**
133    * Get the error at the end of the integration.
134    * @return error at the end of the integration
135    */
136   public double getLastError() {
137     return lastError;
138   }
139 
140   /**
141    * Get the time at the end of the integration.
142    * @return time at the end of the integration.
143    */
144   public double getLastTime() {
145     return lastTime;
146   }
147 
148 }