1   /* Copyright 2002-2021 CS GROUP
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.forces.gravity.potential;
18  
19  import org.hipparchus.util.FastMath;
20  import org.hipparchus.util.MathUtils;
21  import org.hipparchus.util.SinCos;
22  import org.orekit.time.AbsoluteDate;
23  
24  /** Simple implementation of {@link RawSphericalHarmonicsProvider} for pulsating gravity fields.
25   * @author Luc Maisonobe
26   * @since 6.0
27   */
28  class PulsatingSphericalHarmonics implements RawSphericalHarmonicsProvider {
29  
30      /** Underlying part of the field. */
31      private final RawSphericalHarmonicsProvider provider;
32  
33      /** Pulsation (rad/s). */
34      private final double pulsation;
35  
36      /** Cosine component of the cosine coefficients. */
37      private final double[][] cosC;
38  
39      /** Sine component of the cosine coefficients. */
40      private final double[][] sinC;
41  
42      /** Cosine component of the sine coefficients. */
43      private final double[][] cosS;
44  
45      /** Sine component of the sine coefficients. */
46      private final double[][] sinS;
47  
48      /** Simple constructor.
49       * @param provider underlying part of the field
50       * @param period period of the pulsation (s)
51       * @param cosC cosine component of the cosine coefficients
52       * @param sinC sine component of the cosine coefficients
53       * @param cosS cosine component of the sine coefficients
54       * @param sinS sine component of the sine coefficients
55       */
56      PulsatingSphericalHarmonics(final RawSphericalHarmonicsProvider provider,
57                                       final double period,
58                                       final double[][] cosC, final double[][] sinC,
59                                       final double[][] cosS, final double[][] sinS) {
60          this.provider  = provider;
61          this.pulsation = MathUtils.TWO_PI / period;
62          this.cosC      = cosC;
63          this.sinC      = sinC;
64          this.cosS      = cosS;
65          this.sinS      = sinS;
66      }
67  
68      /** {@inheritDoc} */
69      public int getMaxDegree() {
70          return provider.getMaxDegree();
71      }
72  
73      /** {@inheritDoc} */
74      public int getMaxOrder() {
75          return provider.getMaxOrder();
76      }
77  
78      /** {@inheritDoc} */
79      public double getMu() {
80          return provider.getMu();
81      }
82  
83      /** {@inheritDoc} */
84      public double getAe() {
85          return provider.getAe();
86      }
87  
88      /** {@inheritDoc} */
89      public AbsoluteDate getReferenceDate() {
90          return provider.getReferenceDate();
91      }
92  
93      /** {@inheritDoc} */
94      public double getOffset(final AbsoluteDate date) {
95          return provider.getOffset(date);
96      }
97  
98      /** {@inheritDoc} */
99      public TideSystem getTideSystem() {
100         return provider.getTideSystem();
101     }
102 
103     @Override
104     public RawSphericalHarmonics onDate(final AbsoluteDate date) {
105         //raw (constant) harmonics
106         final RawSphericalHarmonics raw = provider.onDate(date);
107         //phase angle, will loose precision for large offsets
108         final double alpha = pulsation * getOffset(date);
109         //pre-compute transcendental functions
110         final SinCos scAlpha = FastMath.sinCos(alpha);
111         return new RawSphericalHarmonics() {
112 
113             @Override
114             public AbsoluteDate getDate() {
115                 return date;
116             }
117 
118             /** {@inheritDoc} */
119             public double getRawCnm(final int n, final int m) {
120 
121                 // retrieve the underlying part of the coefficient
122                 double cnm = raw.getRawCnm(n, m);
123 
124                 if (n < cosC.length && m < cosC[n].length) {
125                     // add pulsation
126                     cnm += cosC[n][m] * scAlpha.cos() + sinC[n][m] * scAlpha.sin();
127                 }
128 
129                 return cnm;
130             }
131 
132             /** {@inheritDoc} */
133             public double getRawSnm(final int n, final int m) {
134 
135                 // retrieve the constant part of the coefficient
136                 double snm = raw.getRawSnm(n, m);
137 
138                 if (n < cosS.length && m < cosS[n].length) {
139                     // add pulsation
140                     snm += cosS[n][m] * scAlpha.cos() + sinS[n][m] * scAlpha.sin();
141                 }
142 
143                 return snm;
144             }
145 
146         };
147     }
148 
149 }