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.weather.water;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.analysis.interpolation.SplineInterpolator;
21  import org.hipparchus.analysis.polynomials.PolynomialSplineFunction;
22  import org.hipparchus.util.FastMath;
23  
24  /** Steam table from US National Bureau of Standards (NBS) and National Research Council (NRC) of Canada.
25   * <p>
26   * The table is an extract from table 1 in <a href="https://www.thermopedia.com/content/1150/">Thermopedia</a>,
27   * using only the pressure column and truncated to 99°C (the original table goes up to 373.976°C). According to
28   * <a href="https://www.thermopedia.com/access/">the access page</a>, this data is available for free.
29   * </p>
30   * @see <a href="https://dx.doi.org/10.1615/AtoZ.s.steam_tables">Thermopedia Steam Tables</a>
31   *
32   * @author Luc Maisonobe
33   * @since 12.1
34   */
35  public class NbsNrcSteamTable implements WaterVaporPressureProvider {
36  
37      /** Celsius temperature offset. */
38      private static final double CELSIUS = 273.15;
39  
40      /** Minimum temperature of the model, at the triple point of water, i.e. 273.16K (which is 0.01°C). */
41      private static final double MIN_T = CELSIUS + 0.01;
42  
43      /** Saturation pressure model. */
44      private static final PolynomialSplineFunction MODEL;
45  
46      static {
47  
48          // saturation pressure in SI units (Pa)
49          final double[] pressure = {
50              00611.73,    657.16,    706.05,    758.13,    813.59,    872.60,    935.37,   1002.09,   1072.97,   1148.25,
51              01228.10,   1312.90,   1402.70,   1497.90,   1598.80,   1705.60,   1818.50,   1938.00,   2064.40,   2197.90,
52              02338.80,   2487.70,   2644.70,   2810.40,   2985.00,   3169.10,   3362.90,   3567.00,   3781.80,   4007.80,
53              04245.50,   4495.30,   4757.80,   5033.50,   5322.90,   5626.70,   5945.40,   6279.50,   6629.80,   6996.90,
54              07381.40,   7784.00,   8205.40,   8646.40,   9107.60,   9589.80,  10093.80,  10620.50,  11170.60,  11744.90,
55              12344.00,  12970.00,  13623.00,  14303.00,  15012.00,  15752.00,  16522.00,  17324.00,  18159.00,  19028.00,
56              19932.00,  20873.00,  21851.00,  22868.00,  23925.00,  25022.00,  26163.00,  27347.00,  28576.00,  29852.00,
57              31176.00,  32549.00,  33972.00,  35448.00,  36978.00,  38563.00,  40205.00,  41905.00,  43665.00,  45487.00,
58              47373.00,  49324.00,  51342.00,  53428.00,  55585.00,  57815.00,  60119.00,  62499.00,  64958.00,  67496.00,
59              70117.00,  72823.00,  75614.00,  78495.00,  81465.00,  84529.00,  87688.00,  90945.00,  94301.00,  97759.00
60          };
61  
62          // the table first entry is at 0.01°C, not 0.00°C, but remaining entries are 1°C, 2°C, … 99°C
63          final double[] temperature = new double[pressure.length];
64          for (int i = 0; i < temperature.length; ++i) {
65              temperature[i] = (i == 0) ? MIN_T : (CELSIUS + i);
66          }
67  
68          MODEL = new SplineInterpolator().interpolate(temperature, pressure);
69  
70      }
71  
72      /** {@inheritDoc} */
73      @Override
74      public double waterVaporPressure(final double p, final double t, final double rh) {
75          return MODEL.value(FastMath.max(t, MIN_T)) * rh;
76      }
77  
78      /** {@inheritDoc} */
79      @Override
80      public <T extends CalculusFieldElement<T>> T waterVaporPressure(final T p, final T t, final T rh) {
81          return MODEL.value(FastMath.max(t, MIN_T)).multiply(rh);
82      }
83  
84  }