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