Gravity.java

  1. /* Copyright 2022-2025 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.iturp834;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.analysis.interpolation.GridAxis;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.bodies.FieldGeodeticPoint;
  22. import org.orekit.bodies.GeodeticPoint;
  23. import org.orekit.utils.units.Unit;

  24. /** Utility class for ITU-R P.834 gravity parameters.
  25.  * <p>
  26.  * This class implements the gravity parts of the model,
  27.  * i.e. equations 27g and 27j in section 6 of the recommendation.
  28.  * </p>
  29.  * @see ITURP834PathDelay
  30.  * @see ITURP834MappingFunction
  31.  * @see ITURP834WeatherParametersProvider
  32.  * @author Luc Maisonobe
  33.  * @see <a href="https://www.itu.int/rec/R-REC-P.834/en">P.834 : Effects of tropospheric refraction on radiowave propagation</a>
  34.  * @since 13.0
  35.  */
  36. class Gravity {

  37.     /** Name of height reference level. */
  38.     public static final String AVERAGE_HEIGHT_REFERENCE_LEVEL_NAME = "hreflev.dat";

  39.     /** Unit per km. */
  40.     private static final Unit UNIT_PER_KM = Unit.parse("km⁻¹");

  41.     /** Gravity factor for equation 27g. */
  42.     private static final double G_27G = 9.806;

  43.     /** Gravity latitude correction factor for equation 27g. */
  44.     private static final double GL_27G = 0.002637;

  45.     /** Gravity altitude correction factor for equation 27g. */
  46.     private static final double GH_27G = UNIT_PER_KM.toSI(0.00031);

  47.     /** Gravity factor for equation 27j. */
  48.     private static final double G_27J = 9.784;

  49.     /** Gravity latitude correction factor for equation 27j. */
  50.     private static final double GL_27J = 0.00266;

  51.     /** Gravity altitude correction factor for equation 27j. */
  52.     private static final double GH_27J = UNIT_PER_KM.toSI(0.00028);

  53.     /** Gravity at Earth surface. */
  54.     private static final ConstantGrid GS =
  55.         new ConstantGrid(Unit.METRE, AVERAGE_HEIGHT_REFERENCE_LEVEL_NAME).
  56.                 apply((lat, lon, h) -> G_27G * (1 - GL_27G * FastMath.cos(2 * lat) - GH_27G * h));

  57.     /** Private constructor for a utility class.
  58.      */
  59.     private Gravity() {
  60.         // nothing to do
  61.     }

  62.     /** Get gravity at surface.
  63.      * @param location point location on Earth
  64.      * @return gravity model over one cell
  65.      */
  66.     public static GridCell getGravityAtSurface(final GeodeticPoint location) {
  67.         return GS.getCell(location, 0.0);
  68.     }

  69.     /** Get gravity at surface.
  70.      * @param <T> type of the field elements
  71.      * @param location point location on Earth
  72.      * @return gravity model over one cell
  73.      */
  74.     public static <T extends CalculusFieldElement<T>> FieldGridCell<T> getGravityAtSurface(final FieldGeodeticPoint<T> location) {
  75.         return GS.getCell(location, null);
  76.     }

  77.     /** Get gravity at point altitude.
  78.      * @param location point location on Earth
  79.      * @return gravity model over one cell
  80.      */
  81.     public static GridCell getGravityAtAltitude(final GeodeticPoint location) {
  82.         final GridAxis latitudeAxis  = GS.getLatitudeAxis();
  83.         final int      southIndex    = latitudeAxis.interpolationIndex(location.getLatitude());
  84.         final double   northLatitude = latitudeAxis.node(southIndex + 1);
  85.         final double   southLatitude = latitudeAxis.node(southIndex);
  86.         final GridAxis longitudeAxis = GS.getLongitudeAxis();
  87.         final int      westIndex     = longitudeAxis.interpolationIndex(location.getLongitude());
  88.         final double   westLongitude = longitudeAxis.node(westIndex);
  89.         final double   mga           = -GH_27J * location.getAltitude();
  90.         final double   gNorth        = (mga + 1 - GL_27J * FastMath.cos(2 * northLatitude)) * G_27J;
  91.         final double   gSouth        = (mga + 1 - GL_27J * FastMath.cos(2 * southLatitude)) * G_27J;
  92.         return new GridCell(location.getLatitude()  - southLatitude,
  93.                             location.getLongitude() - westLongitude,
  94.                             GS.getSizeLat(), GS.getSizeLon(),
  95.                             gNorth, gSouth, gSouth, gNorth);
  96.     }

  97.     /** Get gravity at point altitude.
  98.      * @param <T> type of the field elements
  99.      * @param location point location on Earth
  100.      * @return gravity model over one cell
  101.      */
  102.     public static <T extends CalculusFieldElement<T>> FieldGridCell<T> getGravityAtAltitude(
  103.         final FieldGeodeticPoint<T> location) {
  104.         final GridAxis latitudeAxis  = GS.getLatitudeAxis();
  105.         final int      southIndex    = latitudeAxis.interpolationIndex(location.getLatitude().getReal());
  106.         final double   northLatitude = latitudeAxis.node(southIndex + 1);
  107.         final double   southLatitude = latitudeAxis.node(southIndex);
  108.         final GridAxis longitudeAxis = GS.getLongitudeAxis();
  109.         final int      westIndex     = longitudeAxis.interpolationIndex(location.getLongitude().getReal());
  110.         final double   westLongitude = longitudeAxis.node(westIndex);
  111.         final T        mga           = location.getAltitude().multiply(GH_27J).negate();
  112.         final T        gNorth        = mga.add(1 - GL_27J * FastMath.cos(2 * northLatitude)).multiply(G_27J);
  113.         final T        gSouth        = mga.add(1 - GL_27J * FastMath.cos(2 * southLatitude)).multiply(G_27J);
  114.         return new FieldGridCell<>(location.getLatitude().subtract(southLatitude),
  115.                                    location.getLongitude().subtract(westLongitude),
  116.                                    GS.getSizeLat(), GS.getSizeLon(), gNorth,
  117.                                    gSouth, gSouth, gNorth);
  118.     }

  119. }