FieldCjSjCoefficient.java

  1. /* Copyright 2002-2022 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS 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. package org.orekit.propagation.semianalytical.dsst.utilities;

  18. import java.util.ArrayList;
  19. import java.util.List;

  20. import org.hipparchus.Field;
  21. import org.hipparchus.CalculusFieldElement;
  22. import org.hipparchus.complex.Complex;
  23. import org.hipparchus.exception.NullArgumentException;

  24. /** Compute the S<sub>j</sub>(k, h) and the C<sub>j</sub>(k, h) series
  25.  *  and their partial derivatives with respect to k and h.
  26.  *  <p>
  27.  *  Those series are given in Danielson paper by expression 2.5.3-(5):
  28.  *
  29.  *  <p> C<sub>j</sub>(k, h) + i S<sub>j</sub>(k, h) = (k+ih)<sup>j</sup>
  30.  *
  31.  *  <p>
  32.  *  The C<sub>j</sub>(k, h) and the S<sub>j</sub>(k, h) elements are store as an
  33.  *  {@link ArrayList} of {@link Complex} number, the C<sub>j</sub>(k, h) being
  34.  *  represented by the real and the S<sub>j</sub>(k, h) by the imaginary part.
  35.  */
  36. public class FieldCjSjCoefficient <T extends CalculusFieldElement<T>> {

  37.     /** Zero for initialization. /*/
  38.     private final T zero;

  39.     /** Last computed order j. */
  40.     private int jLast;

  41.     /** Complex base (k + ih) of the C<sub>j</sub>, S<sub>j</sub> series. */
  42.     private final FieldComplex<T> kih;

  43.     /** List of computed elements. */
  44.     private final List<FieldComplex<T>> cjsj;

  45.     /** C<sub>j</sub>(k, h) and S<sub>j</sub>(k, h) constructor.
  46.      * @param k k value
  47.      * @param h h value
  48.      * @param field field for fieldElements
  49.      */
  50.     public FieldCjSjCoefficient(final T k, final T h, final Field<T> field) {
  51.         zero = field.getZero();
  52.         kih  = new FieldComplex<>(k, h);
  53.         cjsj = new ArrayList<FieldComplex<T>>();
  54.         cjsj.add(new FieldComplex<>(zero.add(1.), zero));
  55.         cjsj.add(kih);
  56.         jLast = 1;
  57.     }

  58.     /** Get the C<sub>j</sub> coefficient.
  59.      * @param j order
  60.      * @return C<sub>j</sub>
  61.      */
  62.     public T getCj(final int j) {
  63.         if (j > jLast) {
  64.             // Update to order j
  65.             updateCjSj(j);
  66.         }
  67.         return cjsj.get(j).getReal();
  68.     }

  69.     /** Get the S<sub>j</sub> coefficient.
  70.      * @param j order
  71.      * @return S<sub>j</sub>
  72.      */
  73.     public T getSj(final int j) {
  74.         if (j > jLast) {
  75.             // Update to order j
  76.             updateCjSj(j);
  77.         }
  78.         return cjsj.get(j).getImaginary();
  79.     }

  80.     /** Get the dC<sub>j</sub> / dk coefficient.
  81.      * @param j order
  82.      * @return dC<sub>j</sub> / d<sub>k</sub>
  83.      */
  84.     public T getDcjDk(final int j) {
  85.         return j == 0 ? zero : getCj(j - 1).multiply(j);
  86.     }

  87.     /** Get the dS<sub>j</sub> / dk coefficient.
  88.      * @param j order
  89.      * @return dS<sub>j</sub> / d<sub>k</sub>
  90.      */
  91.     public T getDsjDk(final int j) {
  92.         return j == 0 ? zero : getSj(j - 1).multiply(j);
  93.     }

  94.     /** Get the dC<sub>j</sub> / dh coefficient.
  95.      * @param j order
  96.      * @return dC<sub>i</sub> / d<sub>k</sub>
  97.      */
  98.     public T getDcjDh(final int j) {
  99.         return j == 0 ? zero : getSj(j - 1).multiply(-j);
  100.     }

  101.     /** Get the dS<sub>j</sub> / dh coefficient.
  102.      * @param j order
  103.      * @return dS<sub>j</sub> / d<sub>h</sub>
  104.      */
  105.     public T getDsjDh(final int j) {
  106.         return j == 0 ? zero : getCj(j - 1).multiply(j);
  107.     }

  108.     /** Update the cjsj up to order j.
  109.      * @param j order
  110.      */
  111.     private void updateCjSj(final int j) {
  112.         FieldComplex<T> last = cjsj.get(cjsj.size() - 1);
  113.         for (int i = jLast; i < j; i++) {
  114.             final FieldComplex<T> next = last.multiply(kih);
  115.             cjsj.add(next);
  116.             last = next;
  117.         }
  118.         jLast = j;
  119.     }

  120.     private static class FieldComplex <T extends CalculusFieldElement<T>> {

  121.         /** The imaginary part. */
  122.         private final T imaginary;

  123.         /** The real part. */
  124.         private final T real;

  125.         /**
  126.          * Create a complex number given the real and imaginary parts.
  127.          *
  128.          * @param real Real part.
  129.          * @param imaginary Imaginary part.
  130.          */
  131.         FieldComplex(final T real, final T imaginary) {
  132.             this.real = real;
  133.             this.imaginary = imaginary;
  134.         }

  135.         /**
  136.          * Access the real part.
  137.          *
  138.          * @return the real part.
  139.          */
  140.         public T getReal() {
  141.             return real;
  142.         }

  143.         /**
  144.          * Access the imaginary part.
  145.          *
  146.          * @return the imaginary part.
  147.          */
  148.         public T getImaginary() {
  149.             return imaginary;
  150.         }

  151.         /**
  152.          * Create a complex number given the real and imaginary parts.
  153.          *
  154.          * @param realPart Real part.
  155.          * @param imaginaryPart Imaginary part.
  156.          * @return a new complex number instance.
  157.          *
  158.          * @see #valueOf(double, double)
  159.          */
  160.         protected FieldComplex<T> createComplex(final T realPart, final T imaginaryPart) {
  161.             return new FieldComplex<>(realPart, imaginaryPart);
  162.         }

  163.         /**
  164.          * Returns a {@code Complex} whose value is {@code this * factor}.
  165.          * Implements preliminary checks for {@code NaN} and infinity followed by
  166.          * the definitional formula:
  167.          * <p>
  168.          *   {@code (a + bi)(c + di) = (ac - bd) + (ad + bc)i}
  169.          * </p>
  170.          * <p>
  171.          * Returns finite values in components of the result per the definitional
  172.          * formula in all remaining cases.</p>
  173.          *
  174.          * @param  factor value to be multiplied by this {@code Complex}.
  175.          * @return {@code this * factor}.
  176.          * @throws NullArgumentException if {@code factor} is {@code null}.
  177.          */
  178.         public FieldComplex<T> multiply(final FieldComplex<T> factor) throws NullArgumentException {
  179.             return createComplex(real.multiply(factor.real).subtract(imaginary.multiply(factor.imaginary)),
  180.                                  real.multiply(factor.imaginary).add(imaginary.multiply(factor.real)));
  181.         }
  182.     }
  183. }