1   /* Copyright 2002-2022 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  
20  import java.lang.reflect.Field;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.hipparchus.exception.Localizable;
25  import org.hipparchus.util.FastMath;
26  import org.hipparchus.util.MathUtils;
27  import org.hipparchus.util.Precision;
28  import org.junit.Assert;
29  import org.junit.Test;
30  import org.orekit.Utils;
31  import org.orekit.data.DataContext;
32  import org.orekit.errors.OrekitException;
33  import org.orekit.errors.OrekitMessages;
34  import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider.NormalizedSphericalHarmonics;
35  import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
36  import org.orekit.time.AbsoluteDate;
37  import org.orekit.time.ChronologicalComparator;
38  import org.orekit.time.TimeScale;
39  import org.orekit.time.TimeScalesFactory;
40  import org.orekit.utils.Constants;
41  import org.orekit.utils.TimeSpanMap;
42  
43  public class ICGEMFormatReaderTest {
44  
45      @Test
46      public void testReadLimits() {
47          Utils.setDataRoot("potential");
48          GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("g007_eigen_05c_coef", false));
49          UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(3, 2);
50          UnnormalizedSphericalHarmonics harmonics = provider.onDate(new AbsoluteDate(2004, 10, 1, 12, 0, 0.0, TimeScalesFactory.getTT()));
51          Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
52          try {
53              harmonics.getUnnormalizedCnm(3, 3);
54              Assert.fail("an exception should have been thrown");
55          } catch (OrekitException oe) {
56              // expected
57          } catch (Exception e) {
58              Assert.fail("wrong exception caught: " + e.getLocalizedMessage());
59          }
60          try {
61              harmonics.getUnnormalizedCnm(4, 2);
62              Assert.fail("an exception should have been thrown");
63          } catch (OrekitException oe) {
64              // expected
65          } catch (Exception e) {
66              Assert.fail("wrong exception caught: " + e.getLocalizedMessage());
67          }
68          harmonics.getUnnormalizedCnm(3, 2);
69          Assert.assertEquals(3, provider.getMaxDegree());
70          Assert.assertEquals(2, provider.getMaxOrder());
71      }
72  
73      @Test
74      public void testRegular05cNormalized() {
75          Utils.setDataRoot("potential");
76          GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("g007_eigen_05c_coef", false));
77          NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(5, 5);
78          Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
79          AbsoluteDate refDate = new AbsoluteDate("2004-10-01T12:00:00", TimeScalesFactory.getTT());
80          AbsoluteDate date = new AbsoluteDate("2013-01-08T10:46:53", TimeScalesFactory.getTT());
81          NormalizedSphericalHarmonics harmonics = provider.onDate(date);
82  
83          double offset     = date.durationFrom(refDate);
84          double offsetYear = offset / Constants.JULIAN_YEAR;
85          Assert.assertEquals(0.957212879862e-06 + offsetYear * 0.490000000000e-11,
86                              harmonics.getNormalizedCnm(3, 0), 1.0e-15);
87          Assert.assertEquals( 0.174804558032e-06, harmonics.getNormalizedCnm(5, 5), 1.0e-15);
88          Assert.assertEquals( 0.0,                harmonics.getNormalizedSnm(4, 0), 1.0e-15);
89          Assert.assertEquals( 0.308816581016e-06, harmonics.getNormalizedSnm(4, 4), 1.0e-15);
90          Assert.assertEquals(0.3986004415E+15, provider.getMu(), 1.0e-20);
91          Assert.assertEquals(0.6378136460E+07, provider.getAe(), 1.0e-20);
92      }
93  
94      @Deprecated
95      @Test
96      public void testDeprecated() throws OrekitException {
97          Utils.setDataRoot("potential");
98          GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("g007_eigen_05c_coef", false));
99          NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(5, 5);
100         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
101         AbsoluteDate refDate = new AbsoluteDate("2004-10-01T12:00:00", TimeScalesFactory.getTT());
102         Assert.assertEquals(refDate, provider.getReferenceDate());
103         AbsoluteDate date = new AbsoluteDate("2013-01-08T10:46:53", TimeScalesFactory.getTT());
104         Assert.assertEquals(date.durationFrom(refDate), provider.getOffset(date), Precision.SAFE_MIN);
105     }
106 
107     @Test
108     public void testMoonGravityField() {
109         Utils.setDataRoot("potential");
110         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("GrazLGM300c.truncated", false));
111         NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(12, 12);
112         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
113         Assert.assertEquals(4.9028010560e+12, provider.getMu(), 1.0e-20);
114         Assert.assertEquals(1.7380000000e+06, provider.getAe(), 1.0e-20);
115     }
116 
117     @Test
118     public void testVenusGravityField() {
119         Utils.setDataRoot("potential");
120         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("shgj180ua01.truncated", false));
121         NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(12, 12);
122         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
123         Assert.assertEquals(3.248585920790e+14, provider.getMu(), 1.0e-20);
124         Assert.assertEquals(6.0510e+06,         provider.getAe(), 1.0e-20);
125     }
126 
127     @Test
128     public void testMarsGravityField() {
129         Utils.setDataRoot("potential");
130         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("jgm85f01.truncated", false));
131         NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(12, 12);
132         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
133         Assert.assertEquals(4.28283763830e+13, provider.getMu(), 1.0e-20);
134         Assert.assertEquals(3.39420e+06,       provider.getAe(), 1.0e-20);
135     }
136 
137     @Test
138     public void testRegular05cUnnormalized() {
139         Utils.setDataRoot("potential");
140         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("g007_eigen_05c_coef", false));
141         UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(5, 5);
142         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
143         AbsoluteDate date = new AbsoluteDate("2013-01-08T10:46:53", TimeScalesFactory.getTT());
144         UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
145         int maxUlps = 2;
146         checkValue(harmonics.getUnnormalizedCnm(3, 0),
147                    date, 3, 0, 2004, 10, 1, 0.957212879862e-06, 0.490000000000e-11, 0, 0, 0, 0,
148                    maxUlps);
149         checkValue(harmonics.getUnnormalizedCnm(5, 5),
150                    date, 5, 5, 2004, 10, 1, 0.174804558032e-06, 0, 0, 0, 0, 0,
151                    maxUlps);
152         checkValue(harmonics.getUnnormalizedSnm(4, 0),
153                    date, 4, 0, 2004, 10, 1, 0, 0, 0, 0, 0, 0,
154                    maxUlps);
155         checkValue(harmonics.getUnnormalizedSnm(4, 4),
156                    date, 4, 4, 2004, 10, 1, 0.308816581016e-06, 0, 0, 0, 0, 0,
157                    maxUlps);
158         Assert.assertEquals(0.3986004415E+15, provider.getMu(), 1.0e-20);
159         Assert.assertEquals(0.6378136460E+07, provider.getAe(), 1.0e-20);
160     }
161 
162     @Test
163     public void testEigen06() {
164         Utils.setDataRoot("potential");
165         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s-truncated", false));
166         UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(5, 5);
167         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
168         AbsoluteDate date = new AbsoluteDate("2013-01-08T10:46:53", TimeScalesFactory.getTT());
169         UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
170         int maxUlps = 3;
171         checkValue(harmonics.getUnnormalizedCnm(3, 0),
172                    date, 3, 0, 2005, 1, 1, 9.57211326674e-07, -8.37191630994e-12,
173                    -1.76087178236e-11, 9.47617140143e-11, 1.06252954726e-11, -9.12524501214e-12,
174                    maxUlps);
175         checkValue(harmonics.getUnnormalizedCnm(5, 5),
176                    date, 5, 5, 2005, 1, 1, 1.74807033099e-07, -1.33498578664e-12,
177                    -2.76043013690e-12, -8.28591865697e-12, 1.57898939101e-12, 2.90931436419e-12,
178                    maxUlps);
179         checkValue(harmonics.getUnnormalizedSnm(4, 0),
180                    date, 4, 0, 2005, 1, 1, 0, 0, 0, 0, 0, 0,
181                    maxUlps);
182         checkValue(harmonics.getUnnormalizedSnm(4, 4),
183                    date, 4, 4, 2005, 1, 1, 3.08820169866e-07, 4.35447782358e-13,
184                    -1.21823769110e-11, 3.89722186321e-11, 7.28153817742e-12, -7.64506592459e-12,
185                    maxUlps);
186         Assert.assertEquals(0.3986004415E+15, provider.getMu(), 1.0e-20);
187         Assert.assertEquals(0.6378136460E+07, provider.getAe(), 1.0e-20);
188     }
189 
190     @Test
191     public void testEigen06S4() throws OrekitException {
192         Utils.setDataRoot("potential");
193         TimeScale tt = DataContext.getDefault().getTimeScales().getTT();
194         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("EIGEN-6S4-v2-truncated", true, tt));
195         UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(3, 3);
196         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
197 
198         try {
199             Field rawProviderField = WrappingUnnormalizedProvider.class.getDeclaredField("rawProvider");
200             rawProviderField.setAccessible(true);
201             PiecewiseSphericalHarmonics psh = (PiecewiseSphericalHarmonics) rawProviderField.get(provider);
202             Field piecesField = PiecewiseSphericalHarmonics.class.getDeclaredField("pieces");
203             piecesField.setAccessible(true);
204             @SuppressWarnings("unchecked")
205             TimeSpanMap<PiecewisePart> pieces = (TimeSpanMap<PiecewisePart>) piecesField.get(psh);
206 
207             List<AbsoluteDate> ref = new ArrayList<>();
208             ref.add(new AbsoluteDate(1950, 1, 1, 0, 0, 0.0, tt));
209             for (int year = 1986; year <= 2014; year++) {
210                 if (year != 2005 && year != 2010 && year != 2011) {
211                     ref.add(new AbsoluteDate(year, 1, 1, 0, 0, 0.0, tt));
212                 }
213             }
214             ref.add(new AbsoluteDate(1985,  1,  9, 17, 51, 0.0, tt));
215             ref.add(new AbsoluteDate(2002,  8, 15,  8, 17, 0.0, tt));
216             ref.add(new AbsoluteDate(2004, 12, 26,  1,  0, 0.0, tt));
217             ref.add(new AbsoluteDate(2010,  2, 27,  7, 35, 0.0, tt));
218             ref.add(new AbsoluteDate(2011,  3, 11,  5, 15, 0.0, tt));
219             ref.add(new AbsoluteDate(2014,  6, 15,  9, 17, 0.0, tt));
220             ref.add(new AbsoluteDate(2050,  1,  1,  0,  0, 0.0, tt));
221             ref.sort(new ChronologicalComparator());
222             Assert.assertEquals(35, pieces.getSpansNumber());
223             TimeSpanMap.Transition<PiecewisePart> transition = pieces.getFirstTransition();
224             for (final AbsoluteDate expected : ref) {
225                 Assert.assertEquals(expected, transition.getDate());
226                 transition = transition.next();
227             }
228             Assert.assertNull(transition);
229 
230         } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
231             Assert.fail(e.getLocalizedMessage());
232         }
233 
234         AbsoluteDate date = new AbsoluteDate("2013-01-08T10:46:53", TimeScalesFactory.getTT());
235         UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
236         int maxUlps = 2;
237         checkValue(harmonics.getUnnormalizedCnm(3, 0),
238                    date, 3, 0, 2013, 1, 1, 0, 0, 0.0,
239                    9.57111813364E-07, 7.88508311993E-11,
240                    -7.48797671617E-12, 1.07165711711E-10, -1.77995489691E-11, 8.19305927733E-12,
241                    maxUlps);
242         checkValue(harmonics.getUnnormalizedCnm(3, 2),
243                    date, 3, 2, 2013, 1, 1, 0, 0, 0.0,
244                    9.04721171104E-07, 3.61186647604E-11,
245                    2.80429063599E-11, 2.70919929040E-11, -6.91647796355E-12, 2.03433003058E-11,
246                    maxUlps);
247         checkValue(harmonics.getUnnormalizedSnm(3, 2),
248                    date, 3, 2, 2013, 1, 1, 0, 0, 0.0,
249                    -6.18912728852E-07, -1.81446053580E-10,
250                    -2.59785683825E-11, -2.89784167157E-11, 1.89089403607E-11, -3.61256979359E-11,
251                    maxUlps);
252         checkValue(harmonics.getUnnormalizedSnm(3, 3),
253                    date, 3, 3, 2013, 1, 1, 0, 0, 0.0,
254                    1.41428736507E-06, 3.11677919895E-10,
255                    -8.67871982998E-11, 1.53591055907E-10, -4.45522488259E-11, 8.52872405198E-11,
256                    maxUlps);
257         Assert.assertEquals(0.3986004415E+15, provider.getMu(), 1.0e-20);
258         Assert.assertEquals(0.6378136460E+07, provider.getAe(), 1.0e-20);
259     }
260 
261     @Test
262     public void testEigen06S4SplitBetween() throws OrekitException {
263         Utils.setDataRoot("potential");
264         TimeScale tai = DataContext.getDefault().getTimeScales().getTAI();
265         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("eigen-6s4-split-between", true, tai));
266         UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(1, 1);
267         Assert.assertEquals(TideSystem.TIDE_FREE, provider.getTideSystem());
268 
269         try {
270             Field rawProviderField = WrappingUnnormalizedProvider.class.getDeclaredField("rawProvider");
271             rawProviderField.setAccessible(true);
272             PiecewiseSphericalHarmonics psh = (PiecewiseSphericalHarmonics) rawProviderField.get(provider);
273             Field piecesField = PiecewiseSphericalHarmonics.class.getDeclaredField("pieces");
274             piecesField.setAccessible(true);
275             @SuppressWarnings("unchecked")
276             TimeSpanMap<PiecewisePart> pieces = (TimeSpanMap<PiecewisePart>) piecesField.get(psh);
277 
278             List<AbsoluteDate> ref = new ArrayList<>();
279             ref.add(new AbsoluteDate(1950,  1,  1,  0,  0, 0.0, tai));
280             ref.add(new AbsoluteDate(2002,  8, 15,  8, 17, 0.0, tai));
281             ref.add(new AbsoluteDate(2003,  1,  1,  0,  0, 0.0, tai));
282             ref.add(new AbsoluteDate(2002,  1,  1,  0,  0, 0.0, tai));
283             ref.add(new AbsoluteDate(2002,  6,  1,  0,  0, 0.0, tai));
284             ref.add(new AbsoluteDate(2004,  1,  1,  0,  0, 0.0, tai));
285             ref.sort(new ChronologicalComparator());
286             Assert.assertEquals(7, pieces.getSpansNumber());
287             TimeSpanMap.Transition<PiecewisePart> transition = pieces.getFirstTransition();
288             for (final AbsoluteDate expected : ref) {
289                 Assert.assertEquals(expected, transition.getDate());
290                 transition = transition.next();
291             }
292             Assert.assertNull(transition);
293 
294             AbsoluteDate previous = null;
295             for (final AbsoluteDate current : ref) {
296                 if (previous != null) {
297                     UnnormalizedSphericalHarmonics sh = provider.onDate(previous.shiftedBy(0.5 * current.durationFrom(previous)));
298                     Assert.assertEquals(1.0, sh.getUnnormalizedCnm(0, 0), 1.0e-15);
299                     Assert.assertEquals(0.0, sh.getUnnormalizedSnm(0, 0), 1.0e-15);
300                 }
301                 previous = current;
302             }
303         } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
304             Assert.fail(e.getLocalizedMessage());
305         }
306 
307     }
308 
309     @Test
310     public void testCorruptedFile01() {
311         doTestCorruptedFile("corrupted-01-g007_eigen_coef", 5, 5,
312                             OrekitMessages.UNEXPECTED_FILE_FORMAT_ERROR_FOR_LOADER, -1);
313     }
314 
315     @Test
316     public void testCorruptedFile02() {
317         doTestCorruptedFile("corrupted-02-g007_eigen_coef", 5, 5,
318                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 45);
319     }
320 
321     @Test
322     public void testCorruptedFile03() {
323         doTestCorruptedFile("corrupted-03-g007_eigen_coef", 5, 5,
324                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 46);
325     }
326 
327     @Test
328     public void testCorruptedFile04() {
329         doTestCorruptedFile("corrupted-04-g007_eigen_coef", 5, 5,
330                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 51);
331     }
332 
333     @Test
334     public void testCorruptedFile05() {
335         doTestCorruptedFile("corrupted-05-g007_eigen_coef", 5, 5,
336                             OrekitMessages.MISSING_GRAVITY_FIELD_COEFFICIENT_IN_FILE, -1);
337     }
338 
339     @Test
340     public void testCorruptedFile06() {
341         doTestCorruptedFile("corrupted-06-g007_eigen_coef", 5, 5,
342                             OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD, -1);
343     }
344 
345     @Test
346     public void testCorruptedFile07() {
347         doTestCorruptedFile("corrupted-07-g007_eigen_coef", 5, 5,
348                             OrekitMessages.DUPLICATED_GRAVITY_FIELD_COEFFICIENT_IN_FILE, -1);
349     }
350 
351     @Test
352     public void testCorruptedFile08() {
353         doTestCorruptedFile("corrupted-08-g007_eigen_coef", 5, 5,
354                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 107);
355     }
356 
357     @Test
358     public void testCorruptedFile09() {
359         doTestCorruptedFile("corrupted-09-g007_eigen_coef", 5, 5,
360                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 113);
361     }
362 
363     @Test
364     public void testCorruptedFile10() {
365         doTestCorruptedFile("corrupted-10-eigen-6s4", 3, 3,
366                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 77);
367     }
368 
369     @Test
370     public void testCorruptedFile11() {
371         doTestCorruptedFile("corrupted-11-eigen-6s4", 3, 3,
372                             OrekitMessages.DUPLICATED_GRAVITY_FIELD_COEFFICIENT_IN_FILE, -1);
373     }
374 
375     @Test
376     public void testCorruptedFile12() {
377         doTestCorruptedFile("corrupted-12-eigen-6s4", 3, 3,
378                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 53);
379     }
380 
381     @Test
382     public void testCorruptedFile13() throws OrekitException {
383         doTestCorruptedFile("corrupted-13-eigen-6s4", 1, 1,
384                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 27);
385     }
386 
387     @Test
388     public void testInvalidFormat() {
389         doTestCorruptedFile("dummy_invalid_format_icgem", 3, 3,
390                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 2);
391     }
392 
393     @Test
394     public void testUnsupportedFormat() {
395         doTestCorruptedFile("dummy_unsupported_format_icgem", 3, 3,
396                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 2);
397     }
398 
399     @Test
400     public void testInvalidProductType() {
401         doTestCorruptedFile("dummy_invalid_product_type_icgem", 3, 3,
402                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 3);
403     }
404 
405     @Test
406     public void testInvalidError() {
407         doTestCorruptedFile("dummy_invalid_error_icgem", 3, 3,
408                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 8);
409     }
410 
411     @Test
412     public void testInvalidNorm() {
413         doTestCorruptedFile("dummy_invalid_norm_icgem", 3, 3,
414                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 9);
415     }
416 
417     @Test
418     public void testInvalidTide() {
419         doTestCorruptedFile("dummy_invalid_tide_icgem", 3, 3,
420                             OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, 10);
421     }
422 
423     private void doTestCorruptedFile(final String name, final int degree, final int order,
424                                      final Localizable specifier, int lineError) {
425         Utils.setDataRoot("potential");
426         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader(name, false));
427         try {
428             GravityFieldFactory.getUnnormalizedProvider(degree, order);
429             Assert.fail("an exception should have been thrown");
430         } catch (OrekitException oe) {
431             Assert.assertEquals(specifier, oe.getSpecifier());
432             if (specifier.equals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE)) {
433                 Assert.assertEquals(lineError, ((Integer) oe.getParts()[0]).intValue());
434             }
435         }
436     }
437 
438 
439     @Test
440     public void testZeroTide() {
441         Utils.setDataRoot("potential");
442         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("dummy_zero_tide_icgem", false));
443         Assert.assertEquals(TideSystem.ZERO_TIDE,
444                             GravityFieldFactory.getUnnormalizedProvider(3, 3).getTideSystem());
445     }
446 
447     @Test
448     public void testUnknownTide() {
449         Utils.setDataRoot("potential");
450         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("dummy_unknown_tide_icgem", false));
451         Assert.assertEquals(TideSystem.UNKNOWN,
452                             GravityFieldFactory.getUnnormalizedProvider(3, 3).getTideSystem());
453     }
454 
455     /** Check numbers in the format 1.0d0 can be parsed. */
456     @Test
457     public void testLowercaseD() {
458         Utils.setDataRoot("potential");
459         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("dummy_small_d_icgem", false));
460         Assert.assertEquals(10.0,
461                 GravityFieldFactory
462                         .getUnnormalizedProvider(3, 3)
463                         .onDate(AbsoluteDate.J2000_EPOCH)
464                         .getUnnormalizedCnm(2, 2),
465                 0.0);
466     }
467 
468     /** check files without 1,0 and 1,1 can be parsed. */
469     @Test
470     public void testMissingDegree1() {
471         Utils.setDataRoot("potential");
472         GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("dummy_missing_degree_1", false));
473         UnnormalizedSphericalHarmonics harmonics = GravityFieldFactory
474                 .getUnnormalizedProvider(2, 2)
475                 .onDate(AbsoluteDate.J2000_EPOCH);
476         //check coefficients not in the file are initialized correctly
477         Assert.assertEquals(0.0, harmonics.getUnnormalizedCnm(1, 0), 0.0);
478         Assert.assertEquals(0.0, harmonics.getUnnormalizedCnm(1, 1), 0.0);
479         //check a coefficient is read correctly
480         Assert.assertEquals(10.0, harmonics.getUnnormalizedCnm(2, 2), 0.0);
481     }
482 
483     private void checkValue(final double value,
484                             final AbsoluteDate date, final int n, final int m,
485                             final int refYear, final int refMonth, final int refDay,
486                             final double constant, final double trend,
487                             final double cosYear, final double sinYear,
488                             final double cosHalfYear, final double sinHalfYear,
489                             final int maxUlps) {
490         checkValue(value, date, n, m,
491                    refYear, refMonth, refDay, 12, 0, 0.0,
492                    constant, trend,
493                    cosYear, sinYear, cosHalfYear, sinHalfYear,
494                    maxUlps);
495     }
496 
497     private void checkValue(final double value,
498                             final AbsoluteDate date, final int n, final int m,
499                             final int refYear, final int refMonth, final int refDay,
500                             final int refHour, final int refMin, final double refSec,
501                             final double constant, final double trend,
502                             final double cosYear, final double sinYear,
503                             final double cosHalfYear, final double sinHalfYear,
504                             final int maxUlps) {
505         double factor = GravityFieldFactory.getUnnormalizationFactors(n, m)[n][m];
506         AbsoluteDate refDate = new AbsoluteDate(refYear, refMonth, refDay, refHour, refMin, refSec,
507                                                 TimeScalesFactory.getTT());
508         double dtYear = date.durationFrom(refDate) / Constants.JULIAN_YEAR;
509         double unNormalized = factor * (constant +
510                                         trend       * dtYear +
511                                         cosYear     * FastMath.cos(MathUtils.TWO_PI * dtYear) +
512                                         sinYear     * FastMath.sin(MathUtils.TWO_PI * dtYear) +
513                                         cosHalfYear * FastMath.cos(MathUtils.TWO_PI * dtYear * 2) +
514                                         sinHalfYear * FastMath.sin(MathUtils.TWO_PI * dtYear * 2));
515         double epsilon = maxUlps * FastMath.ulp(unNormalized);
516         Assert.assertEquals(unNormalized, value, epsilon);
517     }
518 
519 }