EquationsMapper.java

  1. /*
  2.  * Licensed to the Hipparchus project 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 Hipparchus project 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.  *      https://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. package org.hipparchus.ode;

  18. import java.io.Serializable;

  19. import org.hipparchus.exception.LocalizedCoreFormats;
  20. import org.hipparchus.exception.MathIllegalArgumentException;

  21. /**
  22.  * Class mapping the part of a complete state or derivative that pertains
  23.  * to a specific differential equation.
  24.  * <p>
  25.  * Instances of this class are guaranteed to be immutable.
  26.  * </p>
  27.  * @see SecondaryODE
  28.  */
  29. public class EquationsMapper implements Serializable {

  30.     /** Serializable UID. */
  31.     private static final long serialVersionUID = 20160327L;

  32.     /** Start indices of the components. */
  33.     private final int[] start;

  34.     /** Create a mapper by adding a new equation to another mapper.
  35.      * <p>
  36.      * The new equation will have index {@code mapper.}{@link #getNumberOfEquations()},
  37.      * or 0 if {@code mapper} is null.
  38.      * </p>
  39.      * @param mapper former mapper, with one equation less (null for first equation)
  40.      * @param dimension dimension of the equation state vector
  41.      */
  42.     EquationsMapper(final EquationsMapper mapper, final int dimension) {
  43.         final int index = (mapper == null) ? 0 : mapper.getNumberOfEquations();
  44.         this.start = new int[index + 2];
  45.         if (mapper == null) {
  46.             start[0] = 0;
  47.         } else {
  48.             System.arraycopy(mapper.start, 0, start, 0, index + 1);
  49.         }
  50.         start[index + 1] = start[index] + dimension;
  51.     }

  52.     /** Get the number of equations mapped.
  53.      * @return number of equations mapped
  54.      */
  55.     public int getNumberOfEquations() {
  56.         return start.length - 1;
  57.     }

  58.     /** Return the dimension of the complete set of equations.
  59.      * <p>
  60.      * The complete set of equations correspond to the primary set plus all secondary sets.
  61.      * </p>
  62.      * @return dimension of the complete set of equations
  63.      */
  64.     public int getTotalDimension() {
  65.         return start[start.length - 1];
  66.     }

  67.     /** Map flat arrays to a state and derivative.
  68.      * @param t time
  69.      * @param y state array to map, including primary and secondary components
  70.      * @param yDot state derivative array to map, including primary and secondary components
  71.      * @return mapped state
  72.      * @exception MathIllegalArgumentException if an array does not match total dimension
  73.      */
  74.     public ODEStateAndDerivative mapStateAndDerivative(final double t, final double[] y, final double[] yDot)
  75.         throws MathIllegalArgumentException {

  76.         if (y.length != getTotalDimension()) {
  77.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  78.                                                    y.length, getTotalDimension());
  79.         }

  80.         if (yDot.length != getTotalDimension()) {
  81.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  82.                                                    yDot.length, getTotalDimension());
  83.         }

  84.         final int n = getNumberOfEquations();
  85.         final double[] state      = extractEquationData(0, y);
  86.         final double[] derivative = extractEquationData(0, yDot);
  87.         if (n < 2) {
  88.             return new ODEStateAndDerivative(t, state, derivative);
  89.         } else {
  90.             final double[][] secondaryState      = new double[n - 1][];
  91.             final double[][] secondaryDerivative = new double[n - 1][];
  92.             for (int index = 1; index < getNumberOfEquations(); ++index) {
  93.                 secondaryState[index - 1]      = extractEquationData(index, y);
  94.                 secondaryDerivative[index - 1] = extractEquationData(index, yDot);
  95.             }
  96.             return new ODEStateAndDerivative(t, state, derivative, secondaryState, secondaryDerivative);
  97.         }
  98.     }

  99.     /** Extract equation data from a complete state or derivative array.
  100.      * @param index index of the equation, must be between 0 included and
  101.      * {@link #getNumberOfEquations()} (excluded)
  102.      * @param complete complete state or derivative array from which
  103.      * equation data should be retrieved
  104.      * @return equation data
  105.      * @exception MathIllegalArgumentException if index is out of range
  106.      * @exception MathIllegalArgumentException if complete state has not enough elements
  107.      */
  108.     public double[] extractEquationData(final int index, final double[] complete)
  109.         throws MathIllegalArgumentException {
  110.         checkIndex(index);
  111.         final int begin     = start[index];
  112.         final int end       = start[index + 1];
  113.         if (complete.length < end) {
  114.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  115.                                                    complete.length, end);
  116.         }
  117.         final int dimension = end - begin;
  118.         final double[] equationData = new double[dimension];
  119.         System.arraycopy(complete, begin, equationData, 0, dimension);
  120.         return equationData;
  121.     }

  122.     /** Insert equation data into a complete state or derivative array.
  123.      * @param index index of the equation, must be between 0 included and
  124.      * {@link #getNumberOfEquations()} (excluded)
  125.      * @param equationData equation data to be inserted into the complete array
  126.      * @param complete placeholder where to put equation data (only the
  127.      * part corresponding to the equation will be overwritten)
  128.      * @exception MathIllegalArgumentException if either array has not enough elements
  129.      */
  130.     public void insertEquationData(final int index, double[] equationData, double[] complete)
  131.         throws MathIllegalArgumentException {
  132.         checkIndex(index);
  133.         final int begin     = start[index];
  134.         final int end       = start[index + 1];
  135.         final int dimension = end - begin;
  136.         if (complete.length < end) {
  137.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  138.                                                    complete.length, end);
  139.         }
  140.         if (equationData.length != dimension) {
  141.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  142.                                                    equationData.length, dimension);
  143.         }
  144.         System.arraycopy(equationData, 0, complete, begin, dimension);
  145.     }

  146.     /** Check equation index.
  147.      * @param index index of the equation, must be between 0 included and
  148.      * {@link #getNumberOfEquations()} (excluded)
  149.      * @exception MathIllegalArgumentException if index is out of range
  150.      */
  151.     private void checkIndex(final int index) throws MathIllegalArgumentException {
  152.         if (index < 0 || index > start.length - 2) {
  153.             throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
  154.                                                    index, 0, start.length - 2);
  155.         }
  156.     }

  157. }