1   /* Copyright 2002-2020 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.orekit.time.AbsoluteDate;
22  
23  /** Simple implementation of {@link RawSphericalHarmonicsProvider} for pulsating gravity fields.
24   * @author Luc Maisonobe
25   * @since 6.0
26   */
27  class PulsatingSphericalHarmonics implements RawSphericalHarmonicsProvider {
28  
29      /** Underlying part of the field. */
30      private final RawSphericalHarmonicsProvider provider;
31  
32      /** Pulsation (rad/s). */
33      private final double pulsation;
34  
35      /** Cosine component of the cosine coefficients. */
36      private final double[][] cosC;
37  
38      /** Sine component of the cosine coefficients. */
39      private final double[][] sinC;
40  
41      /** Cosine component of the sine coefficients. */
42      private final double[][] cosS;
43  
44      /** Sine component of the sine coefficients. */
45      private final double[][] sinS;
46  
47      /** Simple constructor.
48       * @param provider underlying part of the field
49       * @param period period of the pulsation (s)
50       * @param cosC cosine component of the cosine coefficients
51       * @param sinC sine component of the cosine coefficients
52       * @param cosS cosine component of the sine coefficients
53       * @param sinS sine component of the sine coefficients
54       */
55      PulsatingSphericalHarmonics(final RawSphericalHarmonicsProvider provider,
56                                       final double period,
57                                       final double[][] cosC, final double[][] sinC,
58                                       final double[][] cosS, final double[][] sinS) {
59          this.provider  = provider;
60          this.pulsation = MathUtils.TWO_PI / period;
61          this.cosC      = cosC;
62          this.sinC      = sinC;
63          this.cosS      = cosS;
64          this.sinS      = sinS;
65      }
66  
67      /** {@inheritDoc} */
68      public int getMaxDegree() {
69          return provider.getMaxDegree();
70      }
71  
72      /** {@inheritDoc} */
73      public int getMaxOrder() {
74          return provider.getMaxOrder();
75      }
76  
77      /** {@inheritDoc} */
78      public double getMu() {
79          return provider.getMu();
80      }
81  
82      /** {@inheritDoc} */
83      public double getAe() {
84          return provider.getAe();
85      }
86  
87      /** {@inheritDoc} */
88      public AbsoluteDate getReferenceDate() {
89          return provider.getReferenceDate();
90      }
91  
92      /** {@inheritDoc} */
93      public double getOffset(final AbsoluteDate date) {
94          return provider.getOffset(date);
95      }
96  
97      /** {@inheritDoc} */
98      public TideSystem getTideSystem() {
99          return provider.getTideSystem();
100     }
101 
102     @Override
103     public RawSphericalHarmonics onDate(final AbsoluteDate date) {
104         //raw (constant) harmonics
105         final RawSphericalHarmonics raw = provider.onDate(date);
106         //phase angle, will loose precision for large offsets
107         final double alpha = pulsation * getOffset(date);
108         //pre-compute transcendental functions
109         final double cAlpha = FastMath.cos(alpha);
110         final double sAlpha = FastMath.sin(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] * cAlpha + sinC[n][m] * sAlpha;
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] * cAlpha + sinS[n][m] * sAlpha;
141                 }
142 
143                 return snm;
144             }
145 
146         };
147     }
148 
149 }