1   /* Copyright 2022-2025 Thales Alenia Space
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.weather;
18  
19  import org.hipparchus.util.FastMath;
20  import org.orekit.utils.Constants;
21  
22  import java.util.Map;
23  
24  /** Grid entry in Global Pressure Temperature models, evaluated at some date.
25   * @author Luc Maisonobe
26   * @since 13.0
27   */
28  class EvaluatedGridEntry {
29  
30      /** Standard gravity constant [m/s²]. */
31      private static final double G = Constants.G0_STANDARD_GRAVITY;
32  
33      /** Molar mass of dry air in kg/mol. */
34      private static final double DMTR = 28.965e-3;
35  
36      /** Universal gas constant in J/K/mol. */
37      private static final double RG = 8.3143;
38  
39      /** Underlying fixed grid entry. */
40      private final GridEntry entry;
41  
42      /** Corrected height. */
43      private final double correctedHeight;
44  
45      /** Virtual temperature factor. */
46      private final double factor;
47  
48      /** Evaluated seasonal models. */
49      private final Map<SeasonalModelType, Double> evaluatedModels;
50  
51      /** Build an entry from its components.
52       * @param entry underlying fixed entry
53       * @param altitude altitude
54       * @param evaluatedModels evaluated models
55       */
56      EvaluatedGridEntry(final GridEntry entry, final double altitude,
57                         final Map<SeasonalModelType, Double> evaluatedModels) {
58          this.entry           = entry;
59          this.evaluatedModels = evaluatedModels;
60          this.correctedHeight = altitude - entry.getUndulation() - entry.getHs();
61          final double t0 = getEvaluatedModel(SeasonalModelType.TEMPERATURE);
62          final double qv = getEvaluatedModel(SeasonalModelType.QV) * 0.001;
63          final double tv = t0 * (1 + 0.6077 * qv);
64          this.factor     = -correctedHeight * G * DMTR / (RG * tv);
65      }
66  
67      /** Get underlying fixed entry.
68       * @return underlying fixed entry
69       */
70      public GridEntry getEntry() {
71          return entry;
72      }
73  
74      /** Get evaluated model.
75       * @param type model type
76       * @return evaluated model type
77       */
78      public double getEvaluatedModel(final SeasonalModelType type) {
79          return evaluatedModels.get(type);
80      }
81  
82      /** Get temperature.
83       * @return temperature
84       */
85      public double getTemperature() {
86          final double t0   = getEvaluatedModel(SeasonalModelType.TEMPERATURE);
87          final double dtdh = getEvaluatedModel(SeasonalModelType.DT) * 0.001;
88          return t0 + dtdh * correctedHeight;
89      }
90  
91      /** Get pressure.
92       * @return pressure
93       */
94      public double getPressure() {
95          final double p0 = getEvaluatedModel(SeasonalModelType.PRESSURE) * 0.01;
96          return p0 * FastMath.exp(factor);
97      }
98  
99      /** Get water vapor pressure.
100      * <p>
101      * This applies only to GPT2w and GPT3 as GPT2 does not have water vapor decrease factor λ
102      * </p>
103      * @return water vapor pressure
104      */
105     public double getWaterVaporPressure() {
106         final double p0     = getEvaluatedModel(SeasonalModelType.PRESSURE) * 0.01;
107         final double qv     = getEvaluatedModel(SeasonalModelType.QV) * 0.001;
108         final double e0     = qv * p0 / (0.622 + 0.378 * qv);
109         final double lambda = getEvaluatedModel(SeasonalModelType.LAMBDA);
110         return e0 * FastMath.exp(factor * (1 + lambda));
111     }
112 
113 }