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.potential;
18  
19  import org.hipparchus.util.FastMath;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  import org.orekit.Utils;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider.NormalizedSphericalHarmonics;
25  import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.time.TimeScalesFactory;
28  import org.orekit.utils.Constants;
29  
30  public class SHMFormatReaderTest {
31  
32      @Test
33      void testReadLimits() {
34          Utils.setDataRoot("potential");
35          GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("eigen_cg03c_coef", false));
36          UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(3, 2);
37          UnnormalizedSphericalHarmonics harmonics = provider.onDate(new AbsoluteDate(1997, 1, 1, 12, 0, 0.0, TimeScalesFactory.getTT()));
38          try {
39              harmonics.getUnnormalizedCnm(3, 3);
40              Assertions.fail("an exception should have been thrown");
41          } catch (OrekitException oe) {
42              // expected
43          } catch (Exception e) {
44              Assertions.fail("wrong exception caught: " + e.getLocalizedMessage());
45          }
46          try {
47              harmonics.getUnnormalizedCnm(4, 2);
48              Assertions.fail("an exception should have been thrown");
49          } catch (OrekitException oe) {
50              // expected
51          } catch (Exception e) {
52              Assertions.fail("wrong exception caught: " + e.getLocalizedMessage());
53          }
54          harmonics.getUnnormalizedCnm(3, 2);
55          Assertions.assertEquals(3, provider.getMaxDegree());
56          Assertions.assertEquals(2, provider.getMaxOrder());
57      }
58  
59      @Test
60      void testRegular03cNormalized() {
61          Utils.setDataRoot("potential");
62          GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("eigen_cg03c_coef", false));
63          NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(5, 5);
64          Assertions.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
65  
66          AbsoluteDate refDate = new AbsoluteDate("1997-01-01T12:00:00", TimeScalesFactory.getTT());
67          AbsoluteDate date = new AbsoluteDate("2011-05-01T01:02:03", TimeScalesFactory.getTT());
68  
69          NormalizedSphericalHarmonics harmonics = provider.onDate(date);
70          double offset     = date.durationFrom(refDate);
71          double offsetYear = offset / Constants.JULIAN_YEAR;
72          Assertions.assertEquals(0.957201462136e-06 + offsetYear * 0.490000000000e-11,
73                              harmonics.getNormalizedCnm(3, 0), 1.0e-15);
74          Assertions.assertEquals( 0.174786174485e-06, harmonics.getNormalizedCnm(5, 5), 1.0e-15);
75          Assertions.assertEquals( 0.0,                harmonics.getNormalizedSnm(4, 0), 1.0e-15);
76          Assertions.assertEquals( 0.308834784975e-06, harmonics.getNormalizedSnm(4, 4), 1.0e-15);
77          Assertions.assertEquals(0.3986004415E+15 , provider.getMu(),  0);
78          Assertions.assertEquals(0.6378136460E+07 , provider.getAe(),  0);
79  
80      }
81  
82      @Test
83      void testRegular03cUnnormalized() {
84          Utils.setDataRoot("potential");
85          GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("eigen_cg03c_coef", false));
86          UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(5, 5);
87          Assertions.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
88  
89          AbsoluteDate date = new AbsoluteDate("2011-05-01T01:02:03", TimeScalesFactory.getTT());
90  
91          UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
92          int maxUlps = 2;
93          checkValue(harmonics.getUnnormalizedCnm(3, 0), date, 3, 0,
94                     1997, 1, 1, 0.957201462136e-06, 0.490000000000e-11, maxUlps);
95          checkValue(harmonics.getUnnormalizedCnm(5, 5), date, 5, 5,
96                     1997, 1, 1, 0.174786174485e-06, 0.0, maxUlps);
97          checkValue(harmonics.getUnnormalizedSnm(4, 0), date, 4, 0,
98                     1997, 1, 1, 0, 0, maxUlps);
99          checkValue(harmonics.getUnnormalizedSnm(4, 4), date, 4, 4,
100                    1997, 1, 1, 0.308834784975e-06, 0, maxUlps);
101         Assertions.assertEquals(0.3986004415E+15 , provider.getMu(),  0);
102         Assertions.assertEquals(0.6378136460E+07 , provider.getAe(),  0);
103 
104     }
105 
106     @Test
107     void testReadCompressed01c() {
108         Utils.setDataRoot("potential");
109         GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("compressed-eigen-cg01c_coef", false));
110         UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(5, 5);
111         Assertions.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
112 
113         AbsoluteDate date = new AbsoluteDate("2011-05-01T01:02:03", TimeScalesFactory.getTT());
114 
115         UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
116         int maxUlps = 2;
117         checkValue(harmonics.getUnnormalizedCnm(3, 0), date, 3, 0,
118                    1997, 1, 1, 0.957187536534E-06, 0.490000000000E-11, maxUlps);
119         checkValue(harmonics.getUnnormalizedCnm(5, 5), date, 5, 5,
120                    1997, 1, 1, 0.174787189024E-06, 0.0, maxUlps);
121         checkValue(harmonics.getUnnormalizedSnm(4, 0), date, 4, 0,
122                    1997, 1, 1, 0, 0, maxUlps);
123         checkValue(harmonics.getUnnormalizedSnm(4, 4), date, 4, 4,
124                    1997, 1, 1, 0.308834848269E-06, 0, maxUlps);
125         Assertions.assertEquals(0.3986004415E+15 , provider.getMu(),  0);
126         Assertions.assertEquals(0.6378136460E+07 , provider.getAe(),  0);
127 
128     }
129 
130     @Test
131     void testCorruptedFile1() {
132         Assertions.assertThrows(OrekitException.class, () -> {
133             Utils.setDataRoot("potential");
134             GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("corrupted-1-eigen_coef", false));
135             GravityFieldFactory.getUnnormalizedProvider(5, 5);
136         });
137     }
138 
139     @Test
140     void testCorruptedFile2() {
141         Assertions.assertThrows(OrekitException.class, () -> {
142             Utils.setDataRoot("potential");
143             GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("corrupted-2-eigen_coef", false));
144             GravityFieldFactory.getUnnormalizedProvider(5, 5);
145         });
146     }
147 
148     @Test
149     void testCorruptedFile3() {
150         Assertions.assertThrows(OrekitException.class, () -> {
151             Utils.setDataRoot("potential");
152             GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("corrupted-3-eigen_coef", false));
153             GravityFieldFactory.getUnnormalizedProvider(5, 5);
154         });
155     }
156 
157     @Test
158     void testCorruptedFile4() {
159         Assertions.assertThrows(OrekitException.class, () -> {
160             Utils.setDataRoot("potential");
161             GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("corrupted-4-eigen_coef", false));
162             GravityFieldFactory.getUnnormalizedProvider(5, 5);
163         });
164     }
165 
166     @Test
167     void testZeroTide() {
168         Utils.setDataRoot("potential");
169         GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("dummy_unknown_tide_shm", false));
170         Assertions.assertEquals(TideSystem.UNKNOWN,
171                             GravityFieldFactory.getUnnormalizedProvider(5, 5).getTideSystem());
172     }
173 
174     private void checkValue(final double value,
175                             final AbsoluteDate date, final int n, final int m,
176                             final int refYear, final int refMonth, final int refDay,
177                             final double constant, final double trend,
178                             final int maxUlps)
179         {
180         double factor = GravityFieldFactory.getUnnormalizationFactors(n, m)[n][m];
181         AbsoluteDate refDate = new AbsoluteDate(refYear, refMonth, refDay, 12, 0, 0, TimeScalesFactory.getTT());
182         double dtYear = date.durationFrom(refDate) / Constants.JULIAN_YEAR;
183         double normalized = factor * (constant + trend * dtYear);
184         double epsilon = maxUlps * FastMath.ulp(normalized);
185         Assertions.assertEquals(normalized, value, epsilon);
186     }
187 
188 }