1   /* Copyright 2002-2024 Thales Alenia Space
2    * Licensed to CS Communication & Systèmes (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  
19  import java.util.Collections;
20  import java.util.List;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.orekit.bodies.FieldGeodeticPoint;
24  import org.orekit.bodies.GeodeticPoint;
25  import org.orekit.models.earth.weather.FieldPressureTemperatureHumidity;
26  import org.orekit.models.earth.weather.PressureTemperatureHumidity;
27  import org.orekit.time.AbsoluteDate;
28  import org.orekit.time.FieldAbsoluteDate;
29  import org.orekit.utils.Constants;
30  import org.orekit.utils.FieldTrackingCoordinates;
31  import org.orekit.utils.ParameterDriver;
32  import org.orekit.utils.TrackingCoordinates;
33  
34  /** The Askne Nordius model.
35   * <p>
36   * The hydrostatic part is equivalent to Saastamoinen, whereas the wet part takes
37   * into account {@link PressureTemperatureHumidity#getTm() mean temperature weighted
38   * with water vapor pressure} and {@link PressureTemperatureHumidity#getLambda() water
39   * vapor decrease factor}.
40   * </p>
41   * @author Luc Maisonobe
42   * @see "J. Askne and H. Nordius, Estimation of tropospheric delay for microwaves
43   *      from surface weather data, Radio Science, volume 22, number 3, pages 379-386,
44   *      May-June 1987"
45   * @see "Landskron D (2017) Modeling tropospheric delays for space geodetic
46   *      techniques. Dissertation, Department of Geodesy and Geoinformation, TU Wien, Supervisor: J. Böhm.
47   *      http://repositum.tuwien.ac.at/urn:nbn:at:at-ubtuw:1-100249"
48   * @since 12.1
49   */
50  public class AskneNordiusModel implements TroposphericModel {
51  
52      /** Lowest acceptable elevation angle [rad]. */
53      public static final double LOW_ELEVATION_THRESHOLD = 0.05;
54  
55      /** Base delay coefficient (from Saastamoninen model). */
56      private static final double L0 = 2.2768e-5;
57  
58      /** Askne-Nordius coefficient k'₂. */
59      private static final double K_PRIME_2 = 16.5203;
60  
61      /** Askne-Nordius coefficient k₃. */
62      private static final double K_3 = 377600;
63  
64      /** Gas constant for dry components. */
65      private static final double RD = 287.0464;
66  
67      /** Unit consversion factor. */
68      private static final double FACTOR = 1.0e-6;
69  
70      /** Mapping function. */
71      private final TroposphereMappingFunction mappingFunction;
72  
73      /** Create a new Askne Nordius model.
74       * @param mappingFunction mapping function
75       */
76      public AskneNordiusModel(final TroposphereMappingFunction mappingFunction) {
77          this.mappingFunction = mappingFunction;
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public TroposphericDelay pathDelay(final TrackingCoordinates trackingCoordinates, final GeodeticPoint point,
83                                         final PressureTemperatureHumidity weather,
84                                         final double[] parameters, final AbsoluteDate date) {
85  
86          final double[] mf = mappingFunction.mappingFactors(trackingCoordinates, point, weather, date);
87  
88          // calculate the path delay
89          final double zh     = L0 * weather.getPressure();
90          final double zw     = FACTOR * (K_PRIME_2 + K_3 / weather.getTm()) *
91                                RD * weather.getWaterVaporPressure() /
92                                (Constants.G0_STANDARD_GRAVITY * (weather.getLambda() + 1.0));
93          final double sh     = zh * mf[0];
94          final double sw     = zw * mf[1];
95          return new TroposphericDelay(zh, zw, sh, sw);
96  
97      }
98  
99      /** {@inheritDoc} */
100     @Override
101     public <T extends CalculusFieldElement<T>> FieldTroposphericDelay<T> pathDelay(final FieldTrackingCoordinates<T> trackingCoordinates,
102                                                                                    final FieldGeodeticPoint<T> point,
103                                                                                    final FieldPressureTemperatureHumidity<T> weather,
104                                                                                    final T[] parameters, final FieldAbsoluteDate<T> date) {
105 
106         final T[] mf = mappingFunction.mappingFactors(trackingCoordinates, point, weather, date);
107 
108         // calculate the path delay in m
109         final T zh     = weather.getPressure().multiply(L0);
110         final T zw     = weather.getTm().reciprocal().multiply(K_3).add(K_PRIME_2).
111                          multiply(weather.getWaterVaporPressure().multiply(RD)).
112                          divide(weather.getLambda().add(1.0).multiply(Constants.G0_STANDARD_GRAVITY)).
113                          multiply(FACTOR);
114         final T sh     = zh.multiply(mf[0]);
115         final T sw     = zw.multiply(mf[1]);
116         return new FieldTroposphericDelay<>(zh, zw, sh, sw);
117 
118     }
119 
120     /** {@inheritDoc} */
121     @Override
122     public List<ParameterDriver> getParametersDrivers() {
123         return Collections.emptyList();
124     }
125 
126 }