FieldFourierTimeSeries.java
- /* Copyright 2022-2025 Thales Alenia Space
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.models.earth.ionosphere.nequick;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.util.FastMath;
- import org.hipparchus.util.FieldSinCos;
- import org.hipparchus.util.MathArrays;
- import org.orekit.time.DateTimeComponents;
- /**
- * Fourier time series for the NeQuick model.
- * @see NeQuickModel#computeFourierTimeSeries(DateTimeComponents, double)
- * @author Luc Maisonobe
- * @since 13.0.1
- * @param <T> type of the field elements
- */
- public class FieldFourierTimeSeries<T extends CalculusFieldElement<T>> {
- /** Date. */
- private final DateTimeComponents dateTime;
- /** Effective ionisation level. */
- private final T az;
- /** Effective sunspot number (Eq. 19). */
- private final T azr;
- /** Fourier time series for foF2. */
- private final T[] cf2;
- /** Fourier time series for M(3000)F2. */
- private final T[] cm3;
- /**
- * Simple constructor.
- * @param dateTime current date time components
- * @param az effective ionisation level
- * @param flattenF2 F2 coefficients used by the F2 layer (flatten array)
- * @param flattenFm3 Fm3 coefficients used by the M(3000)F2 layer (flatten array)
- */
- FieldFourierTimeSeries(final DateTimeComponents dateTime, final T az,
- final double[] flattenF2, final double[] flattenFm3) {
- this.dateTime = dateTime;
- this.az = az;
- // Effective sunspot number (Eq. 19)
- this.azr = FastMath.sqrt(az.subtract(63.7).multiply(1123.6).add(167273.0)).subtract(408.99);
- // Hours
- final double hours = dateTime.getTime().getSecondsInUTCDay() / 3600.0;
- // Time argument (Eq. 49)
- final double t = FastMath.toRadians(15 * hours) - FastMath.PI;
- // Compute Fourier time series for foF2 and M(3000)F2
- final T[] scT = sinCos(az.newInstance(t), 6);
- this.cf2 = computeCF2(flattenF2, scT);
- this.cm3 = computeCm3(flattenFm3, scT);
- }
- /** Get date time components.
- * @return date time components
- */
- public DateTimeComponents getDateTime() {
- return dateTime;
- }
- /** Get effective ionisation level.
- * @return effective ionisation level
- */
- public T getAz() {
- return az;
- }
- /** Get effective sunspot number.
- * @return effective sunspot number
- */
- public T getAzr() {
- return azr;
- }
- /** Get Fourier time series for foF2.
- * <p>
- * Beware that for efficiency purposes, this method returns
- * a reference to an internal array; this is the reason why
- * this method visibility is limited to package level.
- * </p>
- * @return Fourier time series for foF2 (reference to an internal array)
- */
- T[] getCf2Reference() {
- return cf2;
- }
- /** Get Fourier time series for M(3000)F2.
- * <p>
- * Beware that for efficiency purposes, this method returns
- * a reference to an internal array; this is the reason why
- * this method visibility is limited to package level.
- * </p>
- * @return Fourier time series for M(3000)F2 (reference to an internal array)
- */
- T[] getCm3Reference() {
- return cm3;
- }
- /** Computes cf2 coefficients.
- * @param flattenF2 F2 coefficients used by the F2 layer (flatten array)
- * @param scT sines/cosines array of time argument
- * @return the cf2 coefficients array
- */
- private T[] computeCF2(final double[] flattenF2, final T[] scT) {
- // interpolation coefficients for effective spot number
- final T azr01 = azr.multiply(0.01);
- final T omazr01 = azr01.negate().add(1);
- // Eq. 44 and Eq. 50 merged into one loop
- final T[] array = MathArrays.buildArray(azr.getField(), 76);
- int index = 0;
- for (int i = 0; i < array.length; i++) {
- // CHECKSTYLE: stop Indentation check
- array[i] = omazr01.multiply(flattenF2[index ]).add(azr01.multiply(flattenF2[index + 1])).
- add(omazr01.multiply(flattenF2[index + 2]).add(azr01.multiply(flattenF2[index + 3])).multiply(scT[ 0])).
- add(omazr01.multiply(flattenF2[index + 4]).add(azr01.multiply(flattenF2[index + 5])).multiply(scT[ 1])).
- add(omazr01.multiply(flattenF2[index + 6]).add(azr01.multiply(flattenF2[index + 7])).multiply(scT[ 2])).
- add(omazr01.multiply(flattenF2[index + 8]).add(azr01.multiply(flattenF2[index + 9])).multiply(scT[ 3])).
- add(omazr01.multiply(flattenF2[index + 10]).add(azr01.multiply(flattenF2[index + 11])).multiply(scT[ 4])).
- add(omazr01.multiply(flattenF2[index + 12]).add(azr01.multiply(flattenF2[index + 13])).multiply(scT[ 5])).
- add(omazr01.multiply(flattenF2[index + 14]).add(azr01.multiply(flattenF2[index + 15])).multiply(scT[ 6])).
- add(omazr01.multiply(flattenF2[index + 16]).add(azr01.multiply(flattenF2[index + 17])).multiply(scT[ 7])).
- add(omazr01.multiply(flattenF2[index + 18]).add(azr01.multiply(flattenF2[index + 19])).multiply(scT[ 8])).
- add(omazr01.multiply(flattenF2[index + 20]).add(azr01.multiply(flattenF2[index + 21])).multiply(scT[ 9])).
- add(omazr01.multiply(flattenF2[index + 22]).add(azr01.multiply(flattenF2[index + 23])).multiply(scT[10])).
- add(omazr01.multiply(flattenF2[index + 24]).add(azr01.multiply(flattenF2[index + 25])).multiply(scT[11]));
- index += 26;
- // CHECKSTYLE: resume Indentation check
- }
- return array;
- }
- /** Computes Cm3 coefficients.
- * @param flattenFm3 Fm3 coefficients used by the M(3000)F2 layer (flatten array)
- * @param scT sines/cosines array of time argument
- * @return the Cm3 coefficients array
- */
- private T[] computeCm3(final double[] flattenFm3, final T[] scT) {
- // interpolation coefficients for effective spot number
- final T azr01 = azr.multiply(0.01);
- final T omazr01 = azr01.negate().add(1);
- // Eq. 44 and Eq. 51 merged into one loop
- final T[] array = MathArrays.buildArray(azr.getField(), 49);
- int index = 0;
- for (int i = 0; i < array.length; i++) {
- array[i] = omazr01.multiply(flattenFm3[index ]).add(azr01.multiply(flattenFm3[index + 1])).
- add(omazr01.multiply(flattenFm3[index + 2]).add(azr01.multiply(flattenFm3[index + 3])).multiply(scT[ 0])).
- add(omazr01.multiply(flattenFm3[index + 4]).add(azr01.multiply(flattenFm3[index + 5])).multiply(scT[ 1])).
- add(omazr01.multiply(flattenFm3[index + 6]).add(azr01.multiply(flattenFm3[index + 7])).multiply(scT[ 2])).
- add(omazr01.multiply(flattenFm3[index + 8]).add(azr01.multiply(flattenFm3[index + 9])).multiply(scT[ 3])).
- add(omazr01.multiply(flattenFm3[index + 10]).add(azr01.multiply(flattenFm3[index + 11])).multiply(scT[ 4])).
- add(omazr01.multiply(flattenFm3[index + 12]).add(azr01.multiply(flattenFm3[index + 13])).multiply(scT[ 5])).
- add(omazr01.multiply(flattenFm3[index + 14]).add(azr01.multiply(flattenFm3[index + 15])).multiply(scT[ 6])).
- add(omazr01.multiply(flattenFm3[index + 16]).add(azr01.multiply(flattenFm3[index + 17])).multiply(scT[ 7]));
- index += 18;
- }
- return array;
- }
- /** Compute sines and cosines.
- * @param <T> type of the field elements
- * @param a argument
- * @param n number of terms
- * @return sin(a), cos(a), sin(2a), cos(2a) … sin(n a), cos(n a) array
- */
- static <T extends CalculusFieldElement<T>> T[] sinCos(final T a, final int n) {
- final FieldSinCos<T> sc0 = FastMath.sinCos(a);
- FieldSinCos<T> sci = sc0;
- final T[] sc = MathArrays.buildArray(a.getField(), 2 * n);
- int isc = 0;
- sc[isc++] = sci.sin();
- sc[isc++] = sci.cos();
- for (int i = 1; i < n; i++) {
- sci = FieldSinCos.sum(sc0, sci);
- sc[isc++] = sci.sin();
- sc[isc++] = sci.cos();
- }
- return sc;
- }
- }