OceanTidesWave.java

/* Copyright 2002-2022 CS GROUP
 * 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.forces.gravity.potential;

import org.hipparchus.util.FastMath;
import org.hipparchus.util.SinCos;
import org.orekit.data.BodiesElements;

/** Container for ocen tides coefficients for one tide wave.
 * @see org.orekit.forces.gravity.OceanTides
 * @author Luc Maisonobe
 * @since 6.1
 * @see OceanTidesReader
 */
public class OceanTidesWave {

    /** Waves of degree 0 and 1 do not affect spacecrafts. */
    private static final int START_DEGREE = 2;

    /** Maximum supported degree. */
    private final int degree;

    /** Maximum supported order. */
    private final int order;

    /** Doodson number for the wave. */
    private final int doodson;

    /** Coefficient for γ = GMST + π tide parameter. */
    private final int cGamma;

    /** Coefficient for mean anomaly of the Moon. */
    private final int cL;

    /** Coefficient for mean anomaly of the Sun. */
    private final int cLPrime;

    /** Coefficient for L - Ω where L is the mean longitude of the Moon. */
    private final int cF;

    /** Coefficient for mean elongation of the Moon from the Sun. */
    private final int cD;

    /** Coefficient for mean longitude of the ascending node of the Moon. */
    private final int cOmega;

    /** C<sub>n,m</sub><sup>+</sup> coefficients. */
    private final double[][] cPlus;

    /** S<sub>n,m</sub><sup>+</sup> coefficients. */
    private final double[][] sPlus;

    /** C<sub>n,m</sub><sup>-</sup> coefficients. */
    private final double[][] cMinus;

    /** S<sub>n,m</sub><sup>-</sup> coefficients. */
    private final double[][] sMinus;

    /** Simple constructor.
     * @param doodson Doodson number for the wave
     * @param degree max degree present in the coefficients array
     * @param order max order present in the coefficients array
     * @param coefficients C<sub>n,m</sub><sup>+</sup>, S<sub>n,m</sub><sup>+</sup>,
     * C<sub>n,m</sub><sup>-</sup> and S<sub>n,m</sub><sup>-</sup> coefficients
     */
    public OceanTidesWave(final int doodson, final int degree, final int order,
                          final double[][][] coefficients) {

        this.doodson = doodson;

        // compute Doodson arguments from Doodson number
        final int cPs     = ( doodson           % 10) - 5;
        final int cNPrime = ((doodson / 10)     % 10) - 5;
        final int cP      = ((doodson / 100)    % 10) - 5;
        final int cH      = ((doodson / 1000)   % 10) - 5;
        final int cS      = ((doodson / 10000)  % 10) - 5;
        final int cTau    =  (doodson / 100000) % 10;

        // compute Delaunay arguments from Doodson arguments
        this.cGamma  =  cTau;
        this.cL      = -cP;
        this.cLPrime = -cPs;
        this.cF      = -cTau + cS + cH + cP + cPs;
        this.cD      = -cH - cPs;
        this.cOmega  = -cTau + cS + cH + cP - cNPrime + cPs;

        this.degree   = degree;
        this.order    = order;

        // distribute the coefficients
        final int rows = degree + 1;
        this.cPlus     = new double[rows][];
        this.sPlus     = new double[rows][];
        this.cMinus    = new double[rows][];
        this.sMinus    = new double[rows][];
        for (int i = 0; i <= degree; ++i) {
            final int m = FastMath.min(i, order) + 1;
            final double[][] row = coefficients[i];
            cPlus[i]  = new double[m];
            sPlus[i]  = new double[m];
            cMinus[i] = new double[m];
            sMinus[i] = new double[m];
            for (int j = 0; j < m; ++j) {
                cPlus[i][j]  = row[j][0];
                sPlus[i][j]  = row[j][1];
                cMinus[i][j] = row[j][2];
                sMinus[i][j] = row[j][3];
            }
        }

    }

    /** Get the maximum supported degree.
     * @return maximum supported degree
     */
    public int getMaxDegree() {
        return degree;
    }

    /** Get the maximum supported order.
     * @return maximum supported order
     */
    public int getMaxOrder() {
        return order;
    }

    /** Get the Doodson number for the wave.
     * @return Doodson number for the wave
     */
    public int getDoodson() {
        return doodson;
    }

    /** Add the contribution of the wave to Stokes coefficients.
     * @param elements nutation elements
     * @param cnm spherical harmonic cosine coefficients table to add contribution too
     * @param snm spherical harmonic sine coefficients table to add contribution too
     */
    public void addContribution(final BodiesElements elements,
                                final double[][] cnm, final double[][] snm) {

        final double thetaF = cGamma * elements.getGamma() +
                              cL * elements.getL() + cLPrime * elements.getLPrime() + cF * elements.getF() +
                              cD * elements.getD() + cOmega * elements.getOmega();
        final SinCos sc = FastMath.sinCos(thetaF);

        for (int i = START_DEGREE; i <= degree; ++i) {
            for (int j = 0; j <= FastMath.min(i, order); ++j) {
                // from IERS conventions 2010, section 6.3, equation 6.15
                cnm[i][j] += (cPlus[i][j] + cMinus[i][j]) * sc.cos() + (sPlus[i][j] + sMinus[i][j]) * sc.sin();
                snm[i][j] += (sPlus[i][j] - sMinus[i][j]) * sc.cos() - (cPlus[i][j] - cMinus[i][j]) * sc.sin();
            }
        }

    }

}