FESCnmSnmReader.java

  1. /* Copyright 2002-2021 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. import java.io.BufferedReader;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.InputStreamReader;
  22. import java.nio.charset.StandardCharsets;
  23. import java.util.regex.Matcher;
  24. import java.util.regex.Pattern;

  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.errors.OrekitMessages;

  27. /** Reader for ocean tides files following the fes2004_Cnm-Snm.dat format.
  28.  * @since 6.1
  29.  * @author Luc Maisonobe
  30.  */
  31. public class FESCnmSnmReader extends OceanTidesReader {

  32.     /** Default pattern for fields with unknown type (non-space characters). */
  33.     private static final String  UNKNOWN_TYPE_PATTERN = "\\S+";

  34.     /** Pattern for fields with integer type. */
  35.     private static final String  INTEGER_TYPE_PATTERN = "[-+]?\\p{Digit}+";

  36.     /** Pattern for fields with real type. */
  37.     private static final String  REAL_TYPE_PATTERN = "[-+]?(?:(?:\\p{Digit}+(?:\\.\\p{Digit}*)?)|(?:\\.\\p{Digit}+))(?:[eE][-+]?\\p{Digit}+)?";

  38.     /** Pattern for fields with Doodson number. */
  39.     private static final String  DOODSON_TYPE_PATTERN = "\\p{Digit}{2,3}[.,]\\p{Digit}{3}";

  40.     /** Pattern for regular data. */
  41.     private static final Pattern PATTERN = Pattern.compile("[.,]");

  42.     /** Scale of the Cnm, Snm parameters. */
  43.     private final double scale;

  44.     /** Simple constructor.
  45.      * @param supportedNames regular expression for supported files names
  46.      * @param scale scale of the Cnm, Snm parameters
  47.      */
  48.     public FESCnmSnmReader(final String supportedNames, final double scale) {
  49.         super(supportedNames);
  50.         this.scale = scale;
  51.     }

  52.     /** {@inheritDoc} */
  53.     @Override
  54.     public void loadData(final InputStream input, final String name)
  55.         throws IOException {

  56.         // FES ocean tides models have the following form:
  57.         //    Coefficients to compute variations in normalized Stokes coefficients (unit = 10^-12)
  58.         //    Ocean tide model: FES2004 normalized model (fev. 2004) up to (100,100)
  59.         //    (long period from FES2002 up to (50,50) + equilibrium Om1/Om2, atmospheric tide NOT included)
  60.         //    Doodson Darw  l   m    DelC+     DelS+       DelC-     DelS-
  61.         //     55.565 Om1   2   0   6.58128  -0.00000    -0.00000  -0.00000
  62.         //     55.575 Om2   2   0  -0.06330   0.00000     0.00000   0.00000
  63.         //     56.554 Sa    1   0  -0.00000  -0.00000    -0.00000  -0.00000
  64.         //     56.554 Sa    2   0   0.56720   0.01099    -0.00000  -0.00000
  65.         //     56.554 Sa    3   0   0.00908  -0.00050    -0.00000  -0.00000
  66.         final String[] fieldsPatterns = new String[] {
  67.             DOODSON_TYPE_PATTERN,
  68.             UNKNOWN_TYPE_PATTERN,
  69.             INTEGER_TYPE_PATTERN,
  70.             INTEGER_TYPE_PATTERN,
  71.             REAL_TYPE_PATTERN,
  72.             REAL_TYPE_PATTERN,
  73.             REAL_TYPE_PATTERN,
  74.             REAL_TYPE_PATTERN
  75.         };
  76.         final StringBuilder builder = new StringBuilder("^\\p{Space}*");
  77.         for (int i = 0; i < fieldsPatterns.length; ++i) {
  78.             builder.append("(");
  79.             builder.append(fieldsPatterns[i]);
  80.             builder.append(")");
  81.             builder.append((i < fieldsPatterns.length - 1) ? "\\p{Space}+" : "\\p{Space}*$");
  82.         }
  83.         final Pattern regularLinePattern = Pattern.compile(builder.toString());

  84.         // parse the file
  85.         startParse(name);
  86.         try (BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
  87.             int lineNumber      = 0;
  88.             boolean dataStarted = false;
  89.             for (String line = r.readLine(); line != null; line = r.readLine()) {
  90.                 ++lineNumber;
  91.                 final Matcher regularMatcher = regularLinePattern.matcher(line);
  92.                 if (regularMatcher.matches()) {
  93.                     // we have found a regular data line

  94.                     // parse Doodson, degree and order fields
  95.                     final int doodson = Integer.parseInt(PATTERN.matcher(regularMatcher.group(1)).replaceAll(""));
  96.                     final int n       = Integer.parseInt(regularMatcher.group(3));
  97.                     final int m       = Integer.parseInt(regularMatcher.group(4));

  98.                     if (canAdd(n, m)) {

  99.                         // parse coefficients
  100.                         final double cPlus  = scale * Double.parseDouble(regularMatcher.group(5));
  101.                         final double sPlus  = scale * Double.parseDouble(regularMatcher.group(6));
  102.                         final double cMinus = scale * Double.parseDouble(regularMatcher.group(7));
  103.                         final double sMinus = scale * Double.parseDouble(regularMatcher.group(8));

  104.                         // store parsed fields
  105.                         addWaveCoefficients(doodson, n, m, cPlus,  sPlus, cMinus, sMinus, lineNumber, line);
  106.                         dataStarted = true;

  107.                     }

  108.                 } else if (dataStarted) {
  109.                     // once the first data line has been encountered,
  110.                     // all remaining lines should also be data lines
  111.                     throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
  112.                                               lineNumber, name, line);
  113.                 }
  114.             }
  115.         }
  116.         endParse();

  117.     }

  118. }