FieldEquationsMapper.java

  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.  *      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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.ode;

  22. import java.io.Serializable;

  23. import org.hipparchus.CalculusFieldElement;
  24. import org.hipparchus.exception.LocalizedCoreFormats;
  25. import org.hipparchus.exception.MathIllegalArgumentException;
  26. import org.hipparchus.util.MathArrays;
  27. import org.hipparchus.util.MathUtils;

  28. /**
  29.  * Class mapping the part of a complete state or derivative that pertains
  30.  * to a set of differential equations.
  31.  * <p>
  32.  * Instances of this class are guaranteed to be immutable.
  33.  * </p>
  34.  * @see FieldExpandableODE
  35.  * @param <T> the type of the field elements
  36.  */
  37. public class FieldEquationsMapper<T extends CalculusFieldElement<T>> implements Serializable {

  38.     /** Serializable UID. */
  39.     private static final long serialVersionUID = 20151114L;

  40.     /** Start indices of the components. */
  41.     private final int[] start;

  42.     /** Create a mapper by adding a new equation to another mapper.
  43.      * <p>
  44.      * The new equation will have index {@code mapper.}{@link #getNumberOfEquations()},
  45.      * or 0 if {@code mapper} is null.
  46.      * </p>
  47.      * @param mapper former mapper, with one equation less (null for first equation)
  48.      * @param dimension dimension of the equation state vector
  49.      */
  50.     FieldEquationsMapper(final FieldEquationsMapper<T> mapper, final int dimension) {
  51.         final int index = (mapper == null) ? 0 : mapper.getNumberOfEquations();
  52.         this.start = new int[index + 2];
  53.         if (mapper == null) {
  54.             start[0] = 0;
  55.         } else {
  56.             System.arraycopy(mapper.start, 0, start, 0, index + 1);
  57.         }
  58.         start[index + 1] = start[index] + dimension;
  59.     }

  60.     /** Get the number of equations mapped.
  61.      * @return number of equations mapped
  62.      */
  63.     public int getNumberOfEquations() {
  64.         return start.length - 1;
  65.     }

  66.     /** Return the dimension of the complete set of equations.
  67.      * <p>
  68.      * The complete set of equations correspond to the primary set plus all secondary sets.
  69.      * </p>
  70.      * @return dimension of the complete set of equations
  71.      */
  72.     public int getTotalDimension() {
  73.         return start[start.length - 1];
  74.     }

  75.     /** Map flat arrays to a state and derivative.
  76.      * @param t time
  77.      * @param y state array to map, including primary and secondary components
  78.      * @param yDot state derivative array to map, including primary and secondary components
  79.      * @return mapped state
  80.      * @exception MathIllegalArgumentException if an array does not match total dimension
  81.      */
  82.     public FieldODEStateAndDerivative<T> mapStateAndDerivative(final T t, final T[] y, final T[] yDot)
  83.         throws MathIllegalArgumentException {

  84.         if (y.length != getTotalDimension()) {
  85.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  86.                                                    y.length, getTotalDimension());
  87.         }

  88.         if (yDot.length != getTotalDimension()) {
  89.             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  90.                                                    yDot.length, getTotalDimension());
  91.         }

  92.         final int n = getNumberOfEquations();
  93.         final T[] state      = extractEquationData(0, y);
  94.         final T[] derivative = extractEquationData(0, yDot);
  95.         if (n < 2) {
  96.             return new FieldODEStateAndDerivative<T>(t, state, derivative);
  97.         } else {
  98.             final T[][] secondaryState      = MathArrays.buildArray(t.getField(), n - 1, -1);
  99.             final T[][] secondaryDerivative = MathArrays.buildArray(t.getField(), n - 1, -1);
  100.             for (int index = 1; index < getNumberOfEquations(); ++index) {
  101.                 secondaryState[index - 1]      = extractEquationData(index, y);
  102.                 secondaryDerivative[index - 1] = extractEquationData(index, yDot);
  103.             }
  104.             return new FieldODEStateAndDerivative<T>(t, state, derivative, secondaryState, secondaryDerivative);
  105.         }
  106.     }

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

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

  154.     /** Check equation index.
  155.      * @param index index of the equation, must be between 0 included and
  156.      * {@link #getNumberOfEquations()} (excluded)
  157.      * @exception MathIllegalArgumentException if index is out of range
  158.      */
  159.     private void checkIndex(final int index) throws MathIllegalArgumentException {
  160.         MathUtils.checkRangeInclusive(index, 0, start.length - 2);
  161.     }

  162. }