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.nonstiff;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertTrue;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.io.ObjectInputStream;
27  import java.io.ObjectOutputStream;
28  import java.util.Random;
29  
30  import org.apache.commons.math.ode.ContinuousOutputModel;
31  import org.apache.commons.math.ode.DerivativeException;
32  import org.apache.commons.math.ode.IntegratorException;
33  import org.apache.commons.math.ode.TestProblem3;
34  import org.apache.commons.math.ode.sampling.StepHandler;
35  import org.apache.commons.math.ode.sampling.StepInterpolator;
36  import org.apache.commons.math.ode.sampling.StepInterpolatorTestUtils;
37  import org.junit.Test;
38  
39  public class GraggBulirschStoerStepInterpolatorTest {
40  
41    @Test
42    public void derivativesConsistency()
43    throws DerivativeException, IntegratorException {
44      TestProblem3 pb = new TestProblem3(0.9);
45      double minStep   = 0;
46      double maxStep   = pb.getFinalTime() - pb.getInitialTime();
47      double absTolerance = 1.0e-8;
48      double relTolerance = 1.0e-8;
49  
50      GraggBulirschStoerIntegrator integ =
51        new GraggBulirschStoerIntegrator(minStep, maxStep,
52                                         absTolerance, relTolerance);
53      StepInterpolatorTestUtils.checkDerivativesConsistency(integ, pb, 1.0e-8);
54    }
55  
56    @Test
57    public void serialization()
58      throws DerivativeException, IntegratorException,
59             IOException, ClassNotFoundException {
60  
61      TestProblem3 pb  = new TestProblem3(0.9);
62      double minStep   = 0;
63      double maxStep   = pb.getFinalTime() - pb.getInitialTime();
64      double absTolerance = 1.0e-8;
65      double relTolerance = 1.0e-8;
66  
67      GraggBulirschStoerIntegrator integ =
68        new GraggBulirschStoerIntegrator(minStep, maxStep,
69                                         absTolerance, relTolerance);
70      integ.addStepHandler(new ContinuousOutputModel());
71      integ.integrate(pb,
72                      pb.getInitialTime(), pb.getInitialState(),
73                      pb.getFinalTime(), new double[pb.getDimension()]);
74  
75      ByteArrayOutputStream bos = new ByteArrayOutputStream();
76      ObjectOutputStream    oos = new ObjectOutputStream(bos);
77      for (StepHandler handler : integ.getStepHandlers()) {
78          oos.writeObject(handler);
79      }
80  
81      assertTrue(bos.size () > 34000);
82      assertTrue(bos.size () < 35000);
83  
84      ByteArrayInputStream  bis = new ByteArrayInputStream(bos.toByteArray());
85      ObjectInputStream     ois = new ObjectInputStream(bis);
86      ContinuousOutputModel cm  = (ContinuousOutputModel) ois.readObject();
87  
88      Random random = new Random(347588535632l);
89      double maxError = 0.0;
90      for (int i = 0; i < 1000; ++i) {
91        double r = random.nextDouble();
92        double time = r * pb.getInitialTime() + (1.0 - r) * pb.getFinalTime();
93        cm.setInterpolatedTime(time);
94        double[] interpolatedY = cm.getInterpolatedState ();
95        double[] theoreticalY  = pb.computeTheoreticalState(time);
96        double dx = interpolatedY[0] - theoreticalY[0];
97        double dy = interpolatedY[1] - theoreticalY[1];
98        double error = dx * dx + dy * dy;
99        if (error > maxError) {
100         maxError = error;
101       }
102     }
103 
104     assertTrue(maxError < 5.0e-11);
105 
106   }
107 
108   @Test
109   public void checklone()
110   throws DerivativeException, IntegratorException {
111     TestProblem3 pb = new TestProblem3(0.9);
112     double minStep = 0;
113     double maxStep = pb.getFinalTime() - pb.getInitialTime();
114     double scalAbsoluteTolerance = 1.0e-8;
115     double scalRelativeTolerance = scalAbsoluteTolerance;
116     GraggBulirschStoerIntegrator integ = new GraggBulirschStoerIntegrator(minStep, maxStep,
117                                                                           scalAbsoluteTolerance,
118                                                                           scalRelativeTolerance);
119     integ.addStepHandler(new StepHandler() {
120         public void handleStep(StepInterpolator interpolator, boolean isLast)
121         throws DerivativeException {
122             StepInterpolator cloned = interpolator.copy();
123             double tA = cloned.getPreviousTime();
124             double tB = cloned.getCurrentTime();
125             double halfStep = Math.abs(tB - tA) / 2;
126             assertEquals(interpolator.getPreviousTime(), tA, 1.0e-12);
127             assertEquals(interpolator.getCurrentTime(), tB, 1.0e-12);
128             for (int i = 0; i < 10; ++i) {
129                 double t = (i * tB + (9 - i) * tA) / 9;
130                 interpolator.setInterpolatedTime(t);
131                 assertTrue(Math.abs(cloned.getInterpolatedTime() - t) > (halfStep / 10));
132                 cloned.setInterpolatedTime(t);
133                 assertEquals(t, cloned.getInterpolatedTime(), 1.0e-12);
134                 double[] referenceState = interpolator.getInterpolatedState();
135                 double[] cloneState     = cloned.getInterpolatedState();
136                 for (int j = 0; j < referenceState.length; ++j) {
137                     assertEquals(referenceState[j], cloneState[j], 1.0e-12);
138                 }
139             }
140         }
141         public boolean requiresDenseOutput() {
142             return true;
143         }
144         public void reset() {
145         }
146     });
147     integ.integrate(pb,
148             pb.getInitialTime(), pb.getInitialState(),
149             pb.getFinalTime(), new double[pb.getDimension()]);
150 
151   }
152 
153 }