1   /* Copyright 2013 Applied Defense Solutions, Inc.
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;
18  
19  import org.hipparchus.util.FastMath;
20  import org.orekit.models.AtmosphericRefractionModel;
21  
22  /** Implementation of refraction model for Earth standard atmosphere.
23   * <p>Refraction angle is 0 at zenith, about 1 arcminute at 45°, and 34 arcminutes at the
24   *  horizon for optical wavelengths.</p>
25   * <p>Refraction angle is computed according to Saemundssen formula quoted by Meeus.
26   *  For reference, see <b>Astronomical Algorithms</b> (1998), 2nd ed,
27   *  (ISBN 0-943396-61-1), chap. 15.</p>
28   * <p>This formula is about 30 arcseconds of accuracy very close to the horizon, as
29   *  variable atmospheric effects become very important.</p>
30   * <p>Local pressure and temperature can be set to correct refraction at the viewpoint.</p>
31   * @since 6.1
32   */
33  public class EarthStandardAtmosphereRefraction implements AtmosphericRefractionModel {
34  
35  
36      /** Default correction factor value. */
37      public static final double DEFAULT_CORRECTION_FACTOR = 1.0;
38  
39      /** Default local pressure at viewpoint (Pa). */
40      public static final double DEFAULT_PRESSURE = 101000.0;
41  
42      /** Default local temperature at viewpoint (K). */
43      public static final double DEFAULT_TEMPERATURE = 283.0;
44  
45      /** NIST standard atmospheric pressure (Pa). */
46      public static final double STANDARD_ATM_PRESSURE = 101325.0;
47  
48      /** NIST standard atmospheric temperature (K). */
49      public static final double STANDARD_ATM_TEMPERATURE = 293.15;
50  
51      /** Elevation min value to compute refraction (under the horizon). */
52      private static final double MIN_ELEVATION = -2.0;
53  
54      /** Elevation max value to compute refraction (zenithal). */
55      private static final double MAX_ELEVATION = 89.89;
56  
57      /** Serializable UID. */
58      private static final long serialVersionUID = 6001744143210742620L;
59  
60      /** Refraction correction from local pressure and temperature. */
61      private double correfrac;
62  
63      /** Local pressure. */
64      private double pressure;
65  
66      /** Local temperature. */
67      private double temperature;
68  
69      /**
70       * Creates a new default instance.
71       */
72      public EarthStandardAtmosphereRefraction() {
73          correfrac   = DEFAULT_CORRECTION_FACTOR;
74          pressure    = DEFAULT_PRESSURE;
75          temperature = DEFAULT_TEMPERATURE;
76      }
77  
78      /**
79       * Creates an instance given a specific pressure and temperature.
80       * @param pressure in Pascals (Pa)
81       * @param temperature in Kelvin (K)
82       */
83      public EarthStandardAtmosphereRefraction(final double pressure, final double temperature) {
84          setTemperature(temperature);
85          setPressure(pressure);
86      }
87  
88      /** Get the local pressure at the evaluation location.
89       * @return the pressure (Pa)
90       */
91      public double getPressure() {
92          return pressure;
93      }
94  
95      /** Set the local pressure at the evaluation location
96       * <p>Otherwise the default value for the local pressure is set to {@link #DEFAULT_PRESSURE}.</p>
97       * @param pressure the pressure to set (Pa)
98       */
99      public void setPressure(final double pressure) {
100         this.pressure = pressure;
101         this.correfrac = (pressure / DEFAULT_PRESSURE) * (DEFAULT_TEMPERATURE / temperature);
102     }
103 
104     /** Get the local temperature at the evaluation location.
105      * @return the temperature (K)
106      */
107     public double getTemperature() {
108         return temperature;
109     }
110 
111     /** Set the local temperature at the evaluation location
112      * <p>Otherwise the default value for the local temperature is set to {@link #DEFAULT_TEMPERATURE}.</p>
113      * @param temperature the temperature to set (K)
114      */
115     public void setTemperature(final double temperature) {
116         this.temperature = temperature;
117         this.correfrac = (pressure / DEFAULT_PRESSURE) * (DEFAULT_TEMPERATURE / temperature);
118     }
119 
120     @Override
121     /** {@inheritDoc} */
122     public double getRefraction(final double trueElevation) {
123         double refraction = 0.0;
124         final double eld = FastMath.toDegrees(trueElevation);
125         if (eld > MIN_ELEVATION && eld < MAX_ELEVATION) {
126             final double tmp = eld + 10.3 / (eld + 5.11);
127             final double ref = 1.02 / FastMath.tan(FastMath.toRadians(tmp)) / 60.;
128             refraction = FastMath.toRadians(correfrac * ref);
129         }
130         return refraction;
131     }
132 }