NbsNrcSteamTable.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.weather.water;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.analysis.interpolation.SplineInterpolator;
  20. import org.hipparchus.analysis.polynomials.PolynomialSplineFunction;
  21. import org.hipparchus.util.FastMath;

  22. /** Steam table from US National Bureau of Standards (NBS) and National Research Council (NRC) of Canada.
  23.  * <p>
  24.  * The table is an extract from table 1 in <a href="https://www.thermopedia.com/content/1150/">Thermopedia</a>,
  25.  * using only the pressure column and truncated to 99°C (the original table goes up to 373.976°C). According to
  26.  * <a href="https://www.thermopedia.com/access/">the access page</a>, this data is available for free.
  27.  * </p>
  28.  * @see <a href="https://dx.doi.org/10.1615/AtoZ.s.steam_tables">Thermopedia Steam Tables</a>
  29.  *
  30.  * @author Luc Maisonobe
  31.  * @since 12.1
  32.  */
  33. public class NbsNrcSteamTable implements WaterVaporPressureProvider {

  34.     /** Celsius temperature offset. */
  35.     private static final double CELSIUS = 273.15;

  36.     /** Minimum temperature of the model, at the triple point of water, i.e. 273.16K (which is 0.01°C). */
  37.     private static final double MIN_T = CELSIUS + 0.01;

  38.     /** Saturation pressure model. */
  39.     private static final PolynomialSplineFunction MODEL;

  40.     static {

  41.         // saturation pressure in SI units (Pa)
  42.         final double[] pressure = {
  43.             00611.73,    657.16,    706.05,    758.13,    813.59,    872.60,    935.37,   1002.09,   1072.97,   1148.25,
  44.             01228.10,   1312.90,   1402.70,   1497.90,   1598.80,   1705.60,   1818.50,   1938.00,   2064.40,   2197.90,
  45.             02338.80,   2487.70,   2644.70,   2810.40,   2985.00,   3169.10,   3362.90,   3567.00,   3781.80,   4007.80,
  46.             04245.50,   4495.30,   4757.80,   5033.50,   5322.90,   5626.70,   5945.40,   6279.50,   6629.80,   6996.90,
  47.             07381.40,   7784.00,   8205.40,   8646.40,   9107.60,   9589.80,  10093.80,  10620.50,  11170.60,  11744.90,
  48.             12344.00,  12970.00,  13623.00,  14303.00,  15012.00,  15752.00,  16522.00,  17324.00,  18159.00,  19028.00,
  49.             19932.00,  20873.00,  21851.00,  22868.00,  23925.00,  25022.00,  26163.00,  27347.00,  28576.00,  29852.00,
  50.             31176.00,  32549.00,  33972.00,  35448.00,  36978.00,  38563.00,  40205.00,  41905.00,  43665.00,  45487.00,
  51.             47373.00,  49324.00,  51342.00,  53428.00,  55585.00,  57815.00,  60119.00,  62499.00,  64958.00,  67496.00,
  52.             70117.00,  72823.00,  75614.00,  78495.00,  81465.00,  84529.00,  87688.00,  90945.00,  94301.00,  97759.00
  53.         };

  54.         // the table first entry is at 0.01°C, not 0.00°C, but remaining entries are 1°C, 2°C, … 99°C
  55.         final double[] temperature = new double[pressure.length];
  56.         for (int i = 0; i < temperature.length; ++i) {
  57.             temperature[i] = (i == 0) ? MIN_T : (CELSIUS + i);
  58.         }

  59.         MODEL = new SplineInterpolator().interpolate(temperature, pressure);

  60.     }

  61.     /** {@inheritDoc} */
  62.     @Override
  63.     public double waterVaporPressure(final double p, final double t, final double rh) {
  64.         return MODEL.value(FastMath.max(t, MIN_T)) * rh;
  65.     }

  66.     /** {@inheritDoc} */
  67.     @Override
  68.     public <T extends CalculusFieldElement<T>> T waterVaporPressure(final T p, final T t, final T rh) {
  69.         return MODEL.value(FastMath.max(t, MIN_T)).multiply(rh);
  70.     }

  71. }