ViennaOne.java

  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.models.earth.troposphere;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.util.FastMath;
  21. import org.hipparchus.util.MathArrays;
  22. import org.hipparchus.util.MathUtils;
  23. import org.orekit.bodies.FieldGeodeticPoint;
  24. import org.orekit.bodies.GeodeticPoint;
  25. import org.orekit.time.AbsoluteDate;
  26. import org.orekit.time.FieldAbsoluteDate;
  27. import org.orekit.time.TimeScale;
  28. import org.orekit.utils.FieldTrackingCoordinates;
  29. import org.orekit.utils.TrackingCoordinates;

  30. /** The Vienna 1 tropospheric delay model for radio techniques.
  31.  * The Vienna model data are given with a time interval of 6 hours
  32.  * as well as on a global 2.5° * 2.0° grid.
  33.  * This version considered the height correction for the hydrostatic part
  34.  * developed by Niell, 1996.
  35.  *
  36.  * @see "Boehm, J., Werl, B., and Schuh, H., (2006),
  37.  *       Troposhere mapping functions for GPS and very long baseline
  38.  *       interferometry from European Centre for Medium-Range Weather
  39.  *       Forecasts operational analysis data, J. Geophy. Res., Vol. 111,
  40.  *       B02406, doi:10.1029/2005JB003629"
  41.  * @since 12.1
  42.  * @author Bryan Cazabonne
  43.  * @author Luc Maisonobe
  44.  */
  45. public class ViennaOne extends AbstractVienna {

  46.     /** Build a new instance.
  47.      * @param aProvider provider for a<sub>h</sub> and a<sub>w</sub> coefficients
  48.      * @param gProvider provider for {@link AzimuthalGradientCoefficients} and {@link FieldAzimuthalGradientCoefficients}
  49.      * @param zenithDelayProvider provider for zenith delays
  50.      * @param utc                 UTC time scale
  51.      */
  52.     public ViennaOne(final ViennaAProvider aProvider,
  53.                      final AzimuthalGradientProvider gProvider,
  54.                      final TroposphericModel zenithDelayProvider,
  55.                      final TimeScale utc) {
  56.         super(aProvider, gProvider, zenithDelayProvider, utc);
  57.     }

  58.     /** {@inheritDoc} */
  59.     @Override
  60.     public double[] mappingFactors(final TrackingCoordinates trackingCoordinates,
  61.                                    final GeodeticPoint point,
  62.                                    final AbsoluteDate date) {

  63.         // a coefficients
  64.         final ViennaACoefficients a = getAProvider().getA(point, date);

  65.         // Day of year computation
  66.         final double dofyear = getDayOfYear(date);

  67.         // General constants | Hydrostatic part
  68.         final double bh  = 0.0029;
  69.         final double c0h = 0.062;
  70.         final double c10h;
  71.         final double c11h;
  72.         final double psi;

  73.         // Latitude of the station
  74.         final double latitude = point.getLatitude();

  75.         // sin(latitude) > 0 -> northern hemisphere
  76.         if (FastMath.sin(latitude) > 0) {
  77.             c10h = 0.001;
  78.             c11h = 0.005;
  79.             psi  = 0;
  80.         } else {
  81.             c10h = 0.002;
  82.             c11h = 0.007;
  83.             psi  = FastMath.PI;
  84.         }

  85.         // Temporal factor
  86.         double t0 = 28;
  87.         if (latitude < 0) {
  88.             // southern hemisphere: t0 = 28 + an integer half of year
  89.             t0 += 183;
  90.         }
  91.         // Compute hydrostatique coefficient c
  92.         final double coef = psi + ((dofyear - t0) / 365) * MathUtils.TWO_PI;
  93.         final double ch = c0h + ((FastMath.cos(coef) + 1) * (c11h / 2) + c10h) * (1 - FastMath.cos(latitude));

  94.         // General constants | Wet part
  95.         final double bw = 0.00146;
  96.         final double cw = 0.04391;

  97.         final double[] function = new double[2];
  98.         function[0] = TroposphericModelUtils.mappingFunction(a.getAh(), bh, ch,
  99.                                                              trackingCoordinates.getElevation());
  100.         function[1] = TroposphericModelUtils.mappingFunction(a.getAw(), bw, cw,
  101.                                                              trackingCoordinates.getElevation());

  102.         // Apply height correction
  103.         final double correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
  104.                                                                                  point.getAltitude());
  105.         function[0] = function[0] + correction;

  106.         return function;
  107.     }

  108.     /** {@inheritDoc} */
  109.     @Override
  110.     public <T extends CalculusFieldElement<T>> T[] mappingFactors(final FieldTrackingCoordinates<T> trackingCoordinates,
  111.                                                                   final FieldGeodeticPoint<T> point,
  112.                                                                   final FieldAbsoluteDate<T> date) {

  113.         final Field<T> field = date.getField();
  114.         final T zero = field.getZero();

  115.         // a coefficients
  116.         final FieldViennaACoefficients<T> a = getAProvider().getA(point, date);

  117.         // Day of year computation
  118.         final T dofyear = getDayOfYear(date);

  119.         // General constants | Hydrostatic part
  120.         final T bh  = zero.newInstance(0.0029);
  121.         final T c0h = zero.newInstance(0.062);
  122.         final T c10h;
  123.         final T c11h;
  124.         final T psi;

  125.         // Latitude and longitude of the station
  126.         final T latitude = point.getLatitude();

  127.         // sin(latitude) > 0 -> northern hemisphere
  128.         if (FastMath.sin(latitude.getReal()) > 0) {
  129.             c10h = zero.newInstance(0.001);
  130.             c11h = zero.newInstance(0.005);
  131.             psi  = zero;
  132.         } else {
  133.             c10h = zero.newInstance(0.002);
  134.             c11h = zero.newInstance(0.007);
  135.             psi  = zero.getPi();
  136.         }

  137.         // Compute hydrostatique coefficient c
  138.         // Temporal factor
  139.         double t0 = 28;
  140.         if (latitude.getReal() < 0) {
  141.             // southern hemisphere: t0 = 28 + an integer half of year
  142.             t0 += 183;
  143.         }
  144.         final T coef = psi.add(dofyear.subtract(t0).divide(365).multiply(MathUtils.TWO_PI));
  145.         final T ch = c11h.divide(2.0).multiply(FastMath.cos(coef).add(1.0)).add(c10h).multiply(FastMath.cos(latitude).negate().add(1.)).add(c0h);

  146.         // General constants | Wet part
  147.         final T bw = zero.newInstance(0.00146);
  148.         final T cw = zero.newInstance(0.04391);

  149.         final T[] function = MathArrays.buildArray(field, 2);
  150.         function[0] = TroposphericModelUtils.mappingFunction(a.getAh(), bh, ch,
  151.                                                              trackingCoordinates.getElevation());
  152.         function[1] = TroposphericModelUtils.mappingFunction(a.getAw(), bw, cw,
  153.                                                              trackingCoordinates.getElevation());

  154.         // Apply height correction
  155.         final T correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
  156.                                                                             point.getAltitude(),
  157.                                                                             field);
  158.         function[0] = function[0].add(correction);

  159.         return function;
  160.     }

  161. }