1   /* Copyright 2002-2019 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (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.data;
18  
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.regex.Matcher;
30  import java.util.regex.Pattern;
31  
32  import org.hipparchus.RealFieldElement;
33  import org.hipparchus.exception.DummyLocalizable;
34  import org.hipparchus.util.FastMath;
35  import org.orekit.errors.OrekitException;
36  import org.orekit.errors.OrekitInternalError;
37  import org.orekit.errors.OrekitMessages;
38  import org.orekit.time.AbsoluteDate;
39  import org.orekit.time.FieldAbsoluteDate;
40  import org.orekit.time.TimeScalarFunction;
41  import org.orekit.time.TimeScale;
42  import org.orekit.utils.Constants;
43  import org.orekit.utils.IERSConventions;
44  
45  /**
46   * Class computing the fundamental arguments for nutation and tides.
47   * <p>
48   * The fundamental arguments are split in two sets:
49   * </p>
50   * <ul>
51   *   <li>the Delaunay arguments for Moon and Sun effects</li>
52   *   <li>the planetary arguments for other planets</li>
53   * </ul>
54   *
55   * @author Luc Maisonobe
56   * @see SeriesTerm
57   * @see PoissonSeries
58   * @see BodiesElements
59   */
60  public class FundamentalNutationArguments implements Serializable {
61  
62      /** Serializable UID. */
63      private static final long serialVersionUID = 20131209L;
64  
65      /** IERS conventions to use. */
66      private final IERSConventions conventions;
67  
68      /** Time scale for GMST computation. */
69      private final TimeScale timeScale;
70  
71      /** Function computing Greenwich Mean Sidereal Time. */
72      private final transient TimeScalarFunction gmstFunction;
73  
74      /** Function computing Greenwich Mean Sidereal Time rate. */
75      private final transient TimeScalarFunction gmstRateFunction;
76  
77      // luni-solar Delaunay arguments
78  
79      /** Coefficients for mean anomaly of the Moon. */
80      private final double[] lCoefficients;
81  
82      /** Coefficients for mean anomaly of the Sun. */
83      private final double[] lPrimeCoefficients;
84  
85      /** Coefficients for L - Ω where L is the mean longitude of the Moon. */
86      private final double[] fCoefficients;
87  
88      /** Coefficients for mean elongation of the Moon from the Sun. */
89      private final double[] dCoefficients;
90  
91      /** Coefficients for mean longitude of the ascending node of the Moon. */
92      private final double[] omegaCoefficients;
93  
94      // planetary nutation arguments
95  
96      /** Coefficients for mean Mercury longitude. */
97      private final double[] lMeCoefficients;
98  
99      /** Coefficients for mean Venus longitude. */
100     private final double[] lVeCoefficients;
101 
102     /** Coefficients for mean Earth longitude. */
103     private final double[] lECoefficients;
104 
105     /** Coefficients for mean Mars longitude. */
106     private final double[] lMaCoefficients;
107 
108     /** Coefficients for mean Jupiter longitude. */
109     private final double[] lJCoefficients;
110 
111     /** Coefficients for mean Saturn longitude. */
112     private final double[] lSaCoefficients;
113 
114     /** Coefficients for mean Uranus longitude. */
115     private final double[] lUCoefficients;
116 
117     /** Coefficients for mean Neptune longitude. */
118     private final double[] lNeCoefficients;
119 
120     /** Coefficients for general accumulated precession. */
121     private final double[] paCoefficients;
122 
123     /** Build a model of fundamental arguments from an IERS table file.
124      * @param conventions IERS conventions to use
125      * @param timeScale time scale for GMST computation
126      * (may be null if tide parameter γ = GMST + π is not needed)
127      * @param stream stream containing the IERS table
128      * @param name name of the resource file (for error messages only)
129      */
130     public FundamentalNutationArguments(final IERSConventions conventions,
131                                         final TimeScale timeScale,
132                                         final InputStream stream, final String name) {
133         this(conventions, timeScale, parseCoefficients(stream, name));
134     }
135 
136     /** Build a model of fundamental arguments from an IERS table file.
137      * @param conventions IERS conventions to use
138      * @param timeScale time scale for GMST computation
139      * (may be null if tide parameter γ = GMST + π is not needed)
140      * @param coefficients list of coefficients arrays (all 14 arrays must be provided,
141      * the 5 Delaunay first and the 9 planetary afterwards)
142      * @since 6.1
143      */
144     public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale,
145                                         final List<double[]> coefficients) {
146         this.conventions        = conventions;
147         this.timeScale          = timeScale;
148         this.gmstFunction       = (timeScale == null) ? null : conventions.getGMSTFunction(timeScale);
149         this.gmstRateFunction   = (timeScale == null) ? null : conventions.getGMSTRateFunction(timeScale);
150         this.lCoefficients      = coefficients.get( 0);
151         this.lPrimeCoefficients = coefficients.get( 1);
152         this.fCoefficients      = coefficients.get( 2);
153         this.dCoefficients      = coefficients.get( 3);
154         this.omegaCoefficients  = coefficients.get( 4);
155         this.lMeCoefficients    = coefficients.get( 5);
156         this.lVeCoefficients    = coefficients.get( 6);
157         this.lECoefficients     = coefficients.get( 7);
158         this.lMaCoefficients    = coefficients.get( 8);
159         this.lJCoefficients     = coefficients.get( 9);
160         this.lSaCoefficients    = coefficients.get(10);
161         this.lUCoefficients     = coefficients.get(11);
162         this.lNeCoefficients    = coefficients.get(12);
163         this.paCoefficients     = coefficients.get(13);
164     }
165 
166     /** Parse coefficients.
167      * @param stream stream containing the IERS table
168      * @param name name of the resource file (for error messages only)
169      * @return list of coefficients arrays
170      */
171     private static List<double[]> parseCoefficients(final InputStream stream, final String name) {
172 
173         if (stream == null) {
174             throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
175         }
176 
177         try {
178 
179             final DefinitionParser definitionParser = new DefinitionParser();
180 
181             // setup the reader
182             final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
183             int lineNumber = 0;
184 
185             // look for the reference date and the 14 polynomials
186             final int n = FundamentalName.values().length;
187             final Map<FundamentalName, double[]> polynomials = new HashMap<FundamentalName, double[]>(n);
188             for (String line = reader.readLine(); line != null; line = reader.readLine()) {
189                 lineNumber++;
190                 if (definitionParser.parseDefinition(line, lineNumber, name)) {
191                     polynomials.put(definitionParser.getParsedName(),
192                                     definitionParser.getParsedPolynomial());
193                 }
194             }
195 
196             final List<double[]> coefficients = new ArrayList<double[]>(n);
197             coefficients.add(getCoefficients(FundamentalName.L,       polynomials, name));
198             coefficients.add(getCoefficients(FundamentalName.L_PRIME, polynomials, name));
199             coefficients.add(getCoefficients(FundamentalName.F,       polynomials, name));
200             coefficients.add(getCoefficients(FundamentalName.D,       polynomials, name));
201             coefficients.add(getCoefficients(FundamentalName.OMEGA,   polynomials, name));
202             if (polynomials.containsKey(FundamentalName.L_ME)) {
203                 // IERS conventions 2003 and later provide planetary nutation arguments
204                 coefficients.add(getCoefficients(FundamentalName.L_ME,    polynomials, name));
205                 coefficients.add(getCoefficients(FundamentalName.L_VE,    polynomials, name));
206                 coefficients.add(getCoefficients(FundamentalName.L_E,     polynomials, name));
207                 coefficients.add(getCoefficients(FundamentalName.L_MA,    polynomials, name));
208                 coefficients.add(getCoefficients(FundamentalName.L_J,     polynomials, name));
209                 coefficients.add(getCoefficients(FundamentalName.L_SA,    polynomials, name));
210                 coefficients.add(getCoefficients(FundamentalName.L_U,     polynomials, name));
211                 coefficients.add(getCoefficients(FundamentalName.L_NE,    polynomials, name));
212                 coefficients.add(getCoefficients(FundamentalName.PA,      polynomials, name));
213             } else {
214                 // IERS conventions 1996 and earlier don't provide planetary nutation arguments
215                 final double[] zero = new double[] {
216                     0.0
217                 };
218                 while (coefficients.size() < n) {
219                     coefficients.add(zero);
220                 }
221             }
222 
223             return coefficients;
224 
225         } catch (IOException ioe) {
226             throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage()));
227         }
228 
229     }
230 
231     /** Get the coefficients for a fundamental argument.
232      * @param argument fundamental argument
233      * @param polynomials map of the polynomials
234      * @param fileName name of the file from which the coefficients have been read
235      * @return polynomials coefficients (ordered from high degrees to low degrees)
236      */
237     private static double[] getCoefficients(final FundamentalName argument,
238                                             final Map<FundamentalName, double[]> polynomials,
239                                             final String fileName) {
240         if (!polynomials.containsKey(argument)) {
241             throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, fileName);
242         }
243         return polynomials.get(argument);
244     }
245 
246     /** Evaluate a polynomial.
247      * @param tc offset in Julian centuries
248      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
249      * @return value of the polynomial
250      */
251     private double value(final double tc, final double[] coefficients) {
252         double value = 0;
253         for (int i = coefficients.length - 1; i >= 0; --i) {
254             value = coefficients[i] + tc * value;
255         }
256         return value;
257     }
258 
259     /** Evaluate a polynomial time derivative.
260      * @param tc offset in Julian centuries
261      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
262      * @return time derivative of the polynomial
263      */
264     private double derivative(final double tc, final double[] coefficients) {
265         double derivative = 0;
266         for (int i = coefficients.length - 1; i > 0; --i) {
267             derivative = i * coefficients[i] + tc * derivative;
268         }
269         return derivative / Constants.JULIAN_CENTURY;
270     }
271 
272     /** Evaluate a polynomial.
273      * @param tc offset in Julian centuries
274      * @param <T> type of the field elements
275      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
276      * @return value of the polynomial
277      */
278     private <T extends RealFieldElement<T>> T value(final T tc, final double[] coefficients) {
279         T value = tc.getField().getZero();
280         for (int i = coefficients.length - 1; i >= 0; --i) {
281             value = tc.multiply(value).add(coefficients[i]);
282         }
283         return value;
284     }
285 
286     /** Evaluate a polynomial time derivative.
287      * @param tc offset in Julian centuries
288      * @param <T> type of the field elements
289      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
290      * @return time derivative of the polynomial
291      */
292     private <T extends RealFieldElement<T>> T derivative(final T tc, final double[] coefficients) {
293         T derivative = tc.getField().getZero();
294         for (int i = coefficients.length - 1; i > 0; --i) {
295             derivative = tc.multiply(derivative).add(i * coefficients[i]);
296         }
297         return derivative.divide(Constants.JULIAN_CENTURY);
298     }
299 
300     /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
301      * @param date current date
302      * @return all fundamental arguments for the current date (Delaunay plus planetary)
303      */
304     public BodiesElements evaluateAll(final AbsoluteDate date) {
305 
306         final double tc       = conventions.evaluateTC(date);
307         final double gamma    = gmstFunction == null ?
308                                 Double.NaN : gmstFunction.value(date) + FastMath.PI;
309         final double gammaDot = gmstRateFunction == null ?
310                                 Double.NaN : gmstRateFunction.value(date);
311 
312         return new BodiesElements(date, tc, gamma, gammaDot,
313                                   value(tc, lCoefficients),           // mean anomaly of the Moon
314                                   derivative(tc, lCoefficients),      // mean anomaly of the Moon time derivative
315                                   value(tc, lPrimeCoefficients),      // mean anomaly of the Sun
316                                   derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
317                                   value(tc, fCoefficients),           // L - Ω where L is the mean longitude of the Moon
318                                   derivative(tc, fCoefficients),      // L - Ω where L is the mean longitude of the Moon time derivative
319                                   value(tc, dCoefficients),           // mean elongation of the Moon from the Sun
320                                   derivative(tc, dCoefficients),      // mean elongation of the Moon from the Sun time derivative
321                                   value(tc, omegaCoefficients),       // mean longitude of the ascending node of the Moon
322                                   derivative(tc, omegaCoefficients),  // mean longitude of the ascending node of the Moon time derivative
323                                   value(tc, lMeCoefficients),         // mean Mercury longitude
324                                   derivative(tc, lMeCoefficients),    // mean Mercury longitude time derivative
325                                   value(tc, lVeCoefficients),         // mean Venus longitude
326                                   derivative(tc, lVeCoefficients),    // mean Venus longitude time derivative
327                                   value(tc, lECoefficients),          // mean Earth longitude
328                                   derivative(tc, lECoefficients),     // mean Earth longitude time derivative
329                                   value(tc, lMaCoefficients),         // mean Mars longitude
330                                   derivative(tc, lMaCoefficients),    // mean Mars longitude time derivative
331                                   value(tc, lJCoefficients),          // mean Jupiter longitude
332                                   derivative(tc, lJCoefficients),     // mean Jupiter longitude time derivative
333                                   value(tc, lSaCoefficients),         // mean Saturn longitude
334                                   derivative(tc, lSaCoefficients),    // mean Saturn longitude time derivative
335                                   value(tc, lUCoefficients),          // mean Uranus longitude
336                                   derivative(tc, lUCoefficients),     // mean Uranus longitude time derivative
337                                   value(tc, lNeCoefficients),         // mean Neptune longitude
338                                   derivative(tc, lNeCoefficients),    // mean Neptune longitude time derivative
339                                   value(tc, paCoefficients),          // general accumulated precession in longitude
340                                   derivative(tc, paCoefficients));    // general accumulated precession in longitude time derivative
341 
342     }
343 
344     /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
345      * @param date current date
346      * @param <T> type of the field elements
347      * @return all fundamental arguments for the current date (Delaunay plus planetary)
348      */
349     public <T extends RealFieldElement<T>> FieldBodiesElements<T> evaluateAll(final FieldAbsoluteDate<T> date) {
350 
351         final T tc       = conventions.evaluateTC(date);
352         final T gamma    = gmstFunction == null ?
353                            tc.getField().getZero().add(Double.NaN) : gmstFunction.value(date).add(FastMath.PI);
354         final T gammaDot = gmstRateFunction == null ?
355                            tc.getField().getZero().add(Double.NaN) : gmstRateFunction.value(date);
356 
357         return new FieldBodiesElements<>(date, tc, gamma, gammaDot,
358                                          value(tc, lCoefficients),           // mean anomaly of the Moon
359                                          derivative(tc, lCoefficients),      // mean anomaly of the Moon time derivative
360                                          value(tc, lPrimeCoefficients),      // mean anomaly of the Sun
361                                          derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
362                                          value(tc, fCoefficients),           // L - Ω where L is the mean longitude of the Moon
363                                          derivative(tc, fCoefficients),      // L - Ω where L is the mean longitude of the Moon time derivative
364                                          value(tc, dCoefficients),           // mean elongation of the Moon from the Sun
365                                          derivative(tc, dCoefficients),      // mean elongation of the Moon from the Sun time derivative
366                                          value(tc, omegaCoefficients),       // mean longitude of the ascending node of the Moon
367                                          derivative(tc, omegaCoefficients),  // mean longitude of the ascending node of the Moon time derivative
368                                          value(tc, lMeCoefficients),         // mean Mercury longitude
369                                          derivative(tc, lMeCoefficients),    // mean Mercury longitude time derivative
370                                          value(tc, lVeCoefficients),         // mean Venus longitude
371                                          derivative(tc, lVeCoefficients),    // mean Venus longitude time derivative
372                                          value(tc, lECoefficients),          // mean Earth longitude
373                                          derivative(tc, lECoefficients),     // mean Earth longitude time derivative
374                                          value(tc, lMaCoefficients),         // mean Mars longitude
375                                          derivative(tc, lMaCoefficients),    // mean Mars longitude time derivative
376                                          value(tc, lJCoefficients),          // mean Jupiter longitude
377                                          derivative(tc, lJCoefficients),     // mean Jupiter longitude time derivative
378                                          value(tc, lSaCoefficients),         // mean Saturn longitude
379                                          derivative(tc, lSaCoefficients),    // mean Saturn longitude time derivative
380                                          value(tc, lUCoefficients),          // mean Uranus longitude
381                                          derivative(tc, lUCoefficients),     // mean Uranus longitude time derivative
382                                          value(tc, lNeCoefficients),         // mean Neptune longitude
383                                          derivative(tc, lNeCoefficients),    // mean Neptune longitude time derivative
384                                          value(tc, paCoefficients),          // general accumulated precession in longitude
385                                          derivative(tc, paCoefficients));    // general accumulated precession in longitude time derivative
386 
387     }
388 
389     /** Replace the instance with a data transfer object for serialization.
390      * <p>
391      * This intermediate class serializes only the frame key.
392      * </p>
393      * @return data transfer object that will be serialized
394      */
395     private Object writeReplace() {
396         return new DataTransferObject(conventions, timeScale,
397                                       Arrays.asList(lCoefficients, lPrimeCoefficients, fCoefficients,
398                                                     dCoefficients, omegaCoefficients,
399                                                     lMeCoefficients, lVeCoefficients, lECoefficients,
400                                                     lMaCoefficients, lJCoefficients, lSaCoefficients,
401                                                     lUCoefficients, lNeCoefficients, paCoefficients));
402     }
403 
404     /** Internal class used only for serialization. */
405     private static class DataTransferObject implements Serializable {
406 
407         /** Serializable UID. */
408         private static final long serialVersionUID = 20131209L;
409 
410         /** IERS conventions to use. */
411         private final IERSConventions conventions;
412 
413         /** Time scale for GMST computation. */
414         private final TimeScale timeScale;
415 
416         /** All coefficients. */
417         private final List<double[]> coefficients;
418 
419         /** Simple constructor.
420          * @param conventions IERS conventions to use
421          * @param timeScale time scale for GMST computation
422          * @param coefficients all coefficients
423          */
424         DataTransferObject(final IERSConventions conventions, final TimeScale timeScale,
425                                   final List<double[]> coefficients) {
426             this.conventions  = conventions;
427             this.timeScale    = timeScale;
428             this.coefficients = coefficients;
429         }
430 
431         /** Replace the deserialized data transfer object with a {@link TIRFProvider}.
432          * @return replacement {@link TIRFProvider}
433          */
434         private Object readResolve() {
435             try {
436                 // retrieve a managed frame
437                 return new FundamentalNutationArguments(conventions, timeScale, coefficients);
438             } catch (OrekitException oe) {
439                 throw new OrekitInternalError(oe);
440             }
441         }
442 
443     }
444 
445     /** Enumerate for the fundamental names. */
446     private enum FundamentalName {
447 
448         /** Constant for Mean anomaly of the Moon. */
449         L() {
450             /** {@inheritDoc} */
451             public String getArgumentName() {
452                 return "l";
453             }
454         },
455 
456         /** Constant for Mean anomaly of the Sun. */
457         L_PRIME() {
458             /** {@inheritDoc} */
459             public String getArgumentName() {
460                 return "l'";
461             }
462         },
463 
464         /** Constant for L - Ω where L is the mean longitude of the Moon. */
465         F() {
466             /** {@inheritDoc} */
467             public String getArgumentName() {
468                 return "F";
469             }
470         },
471 
472         /** Constant for mean elongation of the Moon from the Sun. */
473         D() {
474             /** {@inheritDoc} */
475             public String getArgumentName() {
476                 return "D";
477             }
478         },
479 
480         /** Constant for longitude of the ascending node of the Moon. */
481         OMEGA() {
482             /** {@inheritDoc} */
483             public String getArgumentName() {
484                 return "\u03a9";
485             }
486         },
487 
488         /** Constant for mean Mercury longitude. */
489         L_ME() {
490             /** {@inheritDoc} */
491             public String getArgumentName() {
492                 return "LMe";
493             }
494         },
495 
496         /** Constant for mean Venus longitude. */
497         L_VE() {
498             /** {@inheritDoc} */
499             public String getArgumentName() {
500                 return "LVe";
501             }
502         },
503 
504         /** Constant for mean Earth longitude. */
505         L_E() {
506             /** {@inheritDoc} */
507             public String getArgumentName() {
508                 return "LE";
509             }
510         },
511 
512         /** Constant for mean Mars longitude. */
513         L_MA() {
514             /** {@inheritDoc} */
515             public String getArgumentName() {
516                 return "LMa";
517             }
518         },
519 
520         /** Constant for mean Jupiter longitude. */
521         L_J() {
522             /** {@inheritDoc} */
523             public String getArgumentName() {
524                 return "LJ";
525             }
526         },
527 
528         /** Constant for mean Saturn longitude. */
529         L_SA() {
530             /** {@inheritDoc} */
531             public String getArgumentName() {
532                 return "LSa";
533             }
534         },
535 
536         /** Constant for mean Uranus longitude. */
537         L_U() {
538             /** {@inheritDoc} */
539             public String getArgumentName() {
540                 return "LU";
541             }
542         },
543 
544         /** Constant for mean Neptune longitude. */
545         L_NE() {
546             /** {@inheritDoc} */
547             public String getArgumentName() {
548                 return "LNe";
549             }
550         },
551 
552         /** Constant for general accumulated precession in longitude. */
553         PA() {
554             /** {@inheritDoc} */
555             public String getArgumentName() {
556                 return "pA";
557             }
558         };
559 
560         /** Get the fundamental name.
561          * @return fundamental name
562          */
563         public abstract String getArgumentName();
564 
565     }
566 
567     /** Local parser for argument definition lines. */
568     private static class DefinitionParser {
569 
570         /** Regular expression pattern for definitions. */
571         private final Pattern pattern;
572 
573         /** Parser for polynomials. */
574         private PolynomialParser polynomialParser;
575 
576         /** Last parsed fundamental name. */
577         private FundamentalName parsedName;
578 
579         /** Last parsed polynomial. */
580         private double[] parsedPolynomial;
581 
582         /** Simple constructor. */
583         DefinitionParser() {
584 
585             // the luni-solar Delaunay arguments polynomial parts should read something like:
586             // F5 ≡ Ω = 125.04455501° − 6962890.5431″t + 7.4722″t² + 0.007702″t³ − 0.00005939″t⁴
587             // whereas the planetary arguments polynomial parts should read something like:
588             // F14 ≡ pA  = 0.02438175 × t + 0.00000538691 × t²
589             final String unicodeIdenticalTo = "\u2261";
590 
591             // pattern for the global line
592             final StringBuilder builder = new StringBuilder();
593             for (final FundamentalName fn : FundamentalName.values()) {
594                 if (builder.length() > 0) {
595                     builder.append('|');
596                 }
597                 builder.append(fn.getArgumentName());
598             }
599             final String fundamentalName = "\\p{Space}*((?:" + builder.toString() + ")+)";
600             pattern = Pattern.compile("\\p{Space}*F\\p{Digit}+\\p{Space}*" + unicodeIdenticalTo +
601                                       fundamentalName + "\\p{Space}*=\\p{Space}*(.*)");
602 
603             polynomialParser = new PolynomialParser('t', PolynomialParser.Unit.NO_UNITS);
604 
605         }
606 
607         /** Parse a definition line.
608          * @param line line to parse
609          * @param lineNumber line number
610          * @param fileName name of the file
611          * @return true if a definition has been parsed
612          */
613         public boolean parseDefinition(final String line, final int lineNumber, final String fileName) {
614 
615             parsedName       = null;
616             parsedPolynomial = null;
617 
618             final Matcher matcher = pattern.matcher(line);
619             if (matcher.matches()) {
620                 for (FundamentalName fn : FundamentalName.values()) {
621                     if (fn.getArgumentName().equals(matcher.group(1))) {
622                         parsedName = fn;
623                     }
624                 }
625 
626                 // parse the polynomial
627                 parsedPolynomial = polynomialParser.parse(matcher.group(2));
628 
629                 return true;
630 
631             } else {
632                 return false;
633             }
634 
635         }
636 
637         /** Get the last parsed fundamental name.
638          * @return last parsed fundamental name
639          */
640         public FundamentalName getParsedName() {
641             return parsedName;
642         }
643 
644         /** Get the last parsed polynomial.
645          * @return last parsed polynomial
646          */
647         public double[] getParsedPolynomial() {
648             return parsedPolynomial.clone();
649         }
650 
651     }
652 
653 }