FieldCjSjCoefficient.java

  1. /* Copyright 2002-2025 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 org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.complex.Complex;
  21. import org.hipparchus.exception.NullArgumentException;

  22. import java.util.ArrayList;
  23. import java.util.List;

  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.  * @param <T> type of the field elements
  36.  */
  37. public class FieldCjSjCoefficient <T extends CalculusFieldElement<T>> {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  152.         /**
  153.          * Create a complex number given the real and imaginary parts.
  154.          *
  155.          * @param realPart Real part.
  156.          * @param imaginaryPart Imaginary part.
  157.          * @return a new complex number instance.
  158.          *
  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. }