FourierTimeSeries.java

  1. /* Copyright 2022-2025 Thales Alenia Space
  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.models.earth.ionosphere.nequick;

  18. import org.hipparchus.util.FastMath;
  19. import org.hipparchus.util.SinCos;
  20. import org.orekit.time.DateTimeComponents;

  21. /**
  22.  * Fourier time series for the NeQuick model.
  23.  * @see NeQuickModel#computeFourierTimeSeries(DateTimeComponents, double)
  24.  * @author Luc Maisonobe
  25.  * @since 13.0.1
  26.  */
  27. public class FourierTimeSeries {

  28.     /** Date. */
  29.     private final DateTimeComponents dateTime;

  30.     /** Effective ionisation level. */
  31.     private final double az;

  32.     /** Effective sunspot number (Eq. 19). */
  33.     private final double azr;

  34.     /** Fourier time series for foF2. */
  35.     private final double[] cf2;

  36.     /** Fourier time series for M(3000)F2. */
  37.     private final double[] cm3;

  38.     /**
  39.      * Simple constructor.
  40.      * @param dateTime   current date time components
  41.      * @param az         effective ionisation level
  42.      * @param flattenF2  F2 coefficients used by the F2 layer (flatten array)
  43.      * @param flattenFm3 Fm3 coefficients used by the M(3000)F2 layer (flatten array)
  44.      */
  45.     FourierTimeSeries(final DateTimeComponents dateTime, final double az,
  46.                       final double[] flattenF2, final double[] flattenFm3) {

  47.         this.dateTime = dateTime;
  48.         this.az       = az;

  49.         // Effective sunspot number (Eq. 19)
  50.         this.azr = FastMath.sqrt(167273.0 + (az - 63.7) * 1123.6) - 408.99;

  51.         // Hours
  52.         final double hours = dateTime.getTime().getSecondsInUTCDay() / 3600.0;

  53.         // Time argument (Eq. 49)
  54.         final double t = FastMath.toRadians(15 * hours) - FastMath.PI;

  55.         // Compute Fourier time series for foF2 and M(3000)F2
  56.         final double[] scT = sinCos(t, 6);
  57.         this.cf2 = computeCF2(flattenF2, scT);
  58.         this.cm3 = computeCm3(flattenFm3, scT);

  59.     }

  60.     /** Get date time components.
  61.      * @return date time components
  62.      */
  63.     public DateTimeComponents getDateTime() {
  64.         return dateTime;
  65.     }

  66.     /** Get effective ionisation level.
  67.      * @return effective ionisation level
  68.      */
  69.     public double getAz() {
  70.         return az;
  71.     }

  72.     /** Get effective sunspot number.
  73.      * @return effective sunspot number
  74.      */
  75.     public double getAzr() {
  76.         return azr;
  77.     }

  78.     /** Get Fourier time series for foF2.
  79.      * <p>
  80.      * Beware that for efficiency purposes, this method returns
  81.      * a reference to an internal array; this is the reason why
  82.      * this method visibility is limited to package level.
  83.      * </p>
  84.      * @return Fourier time series for foF2 (reference to an internal array)
  85.      */
  86.     double[] getCf2Reference() {
  87.         return cf2;
  88.     }

  89.     /** Get Fourier time series for M(3000)F2.
  90.      * <p>
  91.      * Beware that for efficiency purposes, this method returns
  92.      * a reference to an internal array; this is the reason why
  93.      * this method visibility is limited to package level.
  94.      * </p>
  95.      * @return Fourier time series for M(3000)F2 (reference to an internal array)
  96.      */
  97.     double[] getCm3Reference() {
  98.         return cm3;
  99.     }

  100.     /** Computes cf2 coefficients.
  101.      * @param flattenF2 F2 coefficients used by the F2 layer (flatten array)
  102.      * @param scT       sines/cosines array of time argument
  103.      * @return the cf2 coefficients array
  104.      */
  105.     private double[] computeCF2(final double[] flattenF2, final double[] scT) {

  106.         // interpolation coefficients for effective spot number
  107.         final double azr01   = azr * 0.01;
  108.         final double omazr01 = 1 - azr01;

  109.         // Eq. 44 and Eq. 50 merged into one loop
  110.         final double[] array   = new double[76];
  111.         int            index = 0;
  112.         for (int i = 0; i < array.length; i++) {
  113.             array[i] =
  114.                     omazr01 * flattenF2[index] + azr01 * flattenF2[index + 1] +
  115.                    (omazr01 * flattenF2[index + 2] + azr01 * flattenF2[index + 3]) * scT[0] +
  116.                    (omazr01 * flattenF2[index + 4] + azr01 * flattenF2[index + 5]) * scT[1] +
  117.                    (omazr01 * flattenF2[index + 6] + azr01 * flattenF2[index + 7]) * scT[2] +
  118.                    (omazr01 * flattenF2[index + 8] + azr01 * flattenF2[index + 9]) * scT[3] +
  119.                    (omazr01 * flattenF2[index + 10] + azr01 * flattenF2[index + 11]) * scT[4] +
  120.                    (omazr01 * flattenF2[index + 12] + azr01 * flattenF2[index + 13]) * scT[5] +
  121.                    (omazr01 * flattenF2[index + 14] + azr01 * flattenF2[index + 15]) * scT[6] +
  122.                    (omazr01 * flattenF2[index + 16] + azr01 * flattenF2[index + 17]) * scT[7] +
  123.                    (omazr01 * flattenF2[index + 18] + azr01 * flattenF2[index + 19]) * scT[8] +
  124.                    (omazr01 * flattenF2[index + 20] + azr01 * flattenF2[index + 21]) * scT[9] +
  125.                    (omazr01 * flattenF2[index + 22] + azr01 * flattenF2[index + 23]) * scT[10] +
  126.                    (omazr01 * flattenF2[index + 24] + azr01 * flattenF2[index + 25]) * scT[11];
  127.             index += 26;
  128.         }
  129.         return array;
  130.     }

  131.     /** Computes Cm3 coefficients.
  132.      * @param flattenFm3 Fm3 coefficients used by the M(3000)F2 layer (flatten array)
  133.      * @param scT        sines/cosines array of time argument
  134.      * @return the Cm3 coefficients array
  135.      */
  136.     private double[] computeCm3(final double[] flattenFm3, final double[] scT) {

  137.         // interpolation coefficients for effective spot number
  138.         final double azr01   = azr * 0.01;
  139.         final double omazr01 = 1 - azr01;

  140.         // Eq. 44 and Eq. 51 merged into one loop
  141.         final double[] array   = new double[49];
  142.         int            index = 0;
  143.         for (int i = 0; i < array.length; i++) {
  144.             array[i] =
  145.                     omazr01 * flattenFm3[index] + azr01 * flattenFm3[index + 1] +
  146.                    (omazr01 * flattenFm3[index + 2] + azr01 * flattenFm3[index + 3]) * scT[0] +
  147.                    (omazr01 * flattenFm3[index + 4] + azr01 * flattenFm3[index + 5]) * scT[1] +
  148.                    (omazr01 * flattenFm3[index + 6] + azr01 * flattenFm3[index + 7]) * scT[2] +
  149.                    (omazr01 * flattenFm3[index + 8] + azr01 * flattenFm3[index + 9]) * scT[3] +
  150.                    (omazr01 * flattenFm3[index + 10] + azr01 * flattenFm3[index + 11]) * scT[4] +
  151.                    (omazr01 * flattenFm3[index + 12] + azr01 * flattenFm3[index + 13]) * scT[5] +
  152.                    (omazr01 * flattenFm3[index + 14] + azr01 * flattenFm3[index + 15]) * scT[6] +
  153.                    (omazr01 * flattenFm3[index + 16] + azr01 * flattenFm3[index + 17]) * scT[7];
  154.             index += 18;
  155.         }
  156.         return array;
  157.     }

  158.     /** Compute sines and cosines.
  159.      * @param a argument
  160.      * @param n number of terms
  161.      * @return sin(a), cos(a), sin(2a), cos(2a) … sin(n a), cos(n a) array
  162.      */
  163.     static double[] sinCos(final double a, final int n) {

  164.         final SinCos sc0 = FastMath.sinCos(a);
  165.         SinCos sci = sc0;
  166.         final double[] sc = new double[2 * n];
  167.         int isc = 0;
  168.         sc[isc++] = sci.sin();
  169.         sc[isc++] = sci.cos();
  170.         for (int i = 1; i < n; i++) {
  171.             sci = SinCos.sum(sc0, sci);
  172.             sc[isc++] = sci.sin();
  173.             sc[isc++] = sci.cos();
  174.         }

  175.         return sc;

  176.     }

  177. }