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.forces.gravity;
18  
19  import org.hipparchus.util.FastMath;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Test;
23  import org.orekit.Utils;
24  import org.orekit.data.DataContext;
25  import org.orekit.forces.gravity.potential.AstronomicalAmplitudeReader;
26  import org.orekit.forces.gravity.potential.FESCHatEpsilonReader;
27  import org.orekit.forces.gravity.potential.GravityFieldFactory;
28  import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider.NormalizedSphericalHarmonics;
29  import org.orekit.forces.gravity.potential.OceanLoadDeformationCoefficients;
30  import org.orekit.forces.gravity.potential.OceanTidesWave;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.time.TimeScale;
33  import org.orekit.time.TimeScalesFactory;
34  import org.orekit.time.UT1Scale;
35  import org.orekit.utils.Constants;
36  import org.orekit.utils.IERSConventions;
37  
38  import java.util.ArrayList;
39  import java.util.List;
40  import java.util.Map;
41  
42  public class OceanTidesFieldTest {
43  
44      @Test
45      void testDeltaCnmSnm() {
46  
47          // this is an arbitrarily truncated model, limited to 4x4 and with only a few waves
48          List<OceanTidesWave> waves = getWaves(4, 4, 55565, 56554, 85455, 135655, 273555);
49  
50          UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
51          TimeScale utc = TimeScalesFactory.getUTC();
52  
53          AbsoluteDate date = new AbsoluteDate(2003, 5, 6, 13, 43, 32.125, utc);
54          OceanTidesField tidesField =
55                  new OceanTidesField(Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS, Constants.EIGEN5C_EARTH_MU,
56                                      waves,
57                                      IERSConventions.IERS_2010.getNutationArguments(ut1),
58                                      null);
59          NormalizedSphericalHarmonics harmonics = tidesField.onDate(date);
60          double[][] refDeltaCnm = new double[][] {
61              {           0.0,                    0.0,                   0.0,                      0.0,                     0.0           },
62              {           0.0,                    0.0,                   0.0,                      0.0,                     0.0           },
63              { -4.812565797928061E-11,  -4.1748378190052583E-11, 7.013273986245356E-11,           0.0,                     0.0           },
64              { -2.5341227608443308E-11,  9.76515813742254E-11,  -1.21931214469994E-10,    1.3179722429471184E-10,          0.0           },
65              { -2.7496974839179478E-11,  8.419627031293907E-11,  6.56546217101275E-11,   -3.375298928713117E-11,  -7.588006744166988E-11 }
66          };
67          double[][] refDeltaSnm = new double[][] {
68              {           0.0,                    0.0,                   0.0,                      0.0,                     0.0           },
69              {           0.0,                    0.0,                   0.0,                      0.0,                     0.0           },
70              { -1.168129177701461E-10,   5.646187590518608E-12,  1.742233297668071E-10,           0.0,                     0.0           },
71              { -6.586546350227345E-11,  -8.032186864783105E-11, -3.118910148495339E-11,   1.0566857199592183E-10,          0.0           },
72              {  7.665313525684617E-11,   7.37884528812169E-11,  -1.3085142873419844E-10, -1.5813709543115768E-10,  1.770903634801541E-10 }
73          };
74          for (int n = 0; n < refDeltaCnm.length; ++n) {
75              double threshold = 4.0e-17;
76              for (int m = 0; m <= n; ++m) {
77                  Assertions.assertEquals(refDeltaCnm[n][m], harmonics.getNormalizedCnm(n, m), threshold);
78                  Assertions.assertEquals(refDeltaSnm[n][m], harmonics.getNormalizedSnm(n, m), threshold);
79              }
80          }
81      }
82  
83      private List<OceanTidesWave> getWaves(int degree, int order, int... doodson)
84          {
85  
86          // load a complete model
87          AstronomicalAmplitudeReader aaReader =
88                  new AstronomicalAmplitudeReader("hf-fes2004.dat", 5, 2, 3, 1.0);
89          DataContext.getDefault().getDataProvidersManager().feed(aaReader.getSupportedNames(), aaReader);
90          Map<Integer, Double> map = aaReader.getAstronomicalAmplitudesMap();
91          GravityFieldFactory.addOceanTidesReader(new FESCHatEpsilonReader("fes2004-7x7.dat",
92                                                                           0.01, FastMath.toRadians(1.0),
93                                                                           OceanLoadDeformationCoefficients.IERS_2010,
94                                                                           map));
95          List<OceanTidesWave> complete =  GravityFieldFactory.getOceanTidesWaves(degree, order);
96          double[][][] triangular = new double[degree + 1][][];
97          for (int i = 0; i <= degree; ++i) {
98              triangular[i] = new double[FastMath.min(i, order) + 1][4];
99          };
100 
101         // filter waves
102         List<OceanTidesWave> filtered = new ArrayList<OceanTidesWave>(doodson.length);
103         for (final int d : doodson) {
104             for (final OceanTidesWave wave : complete) {
105                 if (wave.getDoodson() == d) {
106                     filtered.add(wave);
107                 }
108             }
109         }
110 
111         return filtered;
112 
113     }
114 
115     @BeforeEach
116     public void setUp() {
117         Utils.setDataRoot("regular-data:tides");
118     }
119 
120 }