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;
18
19 import java.util.List;
20
21 import org.hipparchus.util.FastMath;
22 import org.orekit.data.BodiesElements;
23 import org.orekit.data.FundamentalNutationArguments;
24 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
25 import org.orekit.forces.gravity.potential.OceanTidesWave;
26 import org.orekit.forces.gravity.potential.TideSystem;
27 import org.orekit.time.AbsoluteDate;
28 import org.orekit.time.TimeVectorFunction;
29
30 /** Gravity field corresponding to ocean tides.
31 * <p>
32 * This ocean tides force model implementation corresponds to the method described
33 * in <a href="http://www.iers.org/nn_11216/IERS/EN/Publications/TechnicalNotes/tn36.html">
34 * IERS conventions (2010)</a>, chapter 6, section 6.3.
35 * </p>
36 * <p>
37 * Note that this class is <em>not</em> thread-safe, and that tides computation
38 * are computer intensive if repeated. So this class is really expected to
39 * be wrapped within a {@link
40 * org.orekit.forces.gravity.potential.CachedNormalizedSphericalHarmonicsProvider}
41 * that will both ensure thread safety and improve performances using caching.
42 * </p>
43 * @see OceanTides
44 * @author Luc Maisonobe
45 * @since 6.1
46 */
47 class OceanTidesField implements NormalizedSphericalHarmonicsProvider {
48
49 /** Maximum degree. */
50 private final int degree;
51
52 /** Maximum order. */
53 private final int order;
54
55 /** Central body reference radius. */
56 private final double ae;
57
58 /** Central body attraction coefficient. */
59 private final double mu;
60
61 /** Tides model. */
62 private final List<OceanTidesWave> waves;
63
64 /** Object computing the fundamental arguments. */
65 private final FundamentalNutationArguments arguments;
66
67 /** Function computing pole tide terms (ΔC₂₁, ΔS₂₁). */
68 private final TimeVectorFunction poleTideFunction;
69
70 /** Simple constructor.
71 * @param ae central body reference radius
72 * @param mu central body attraction coefficient
73 * @param waves ocean tides waves
74 * @param arguments object computing the fundamental arguments
75 * @param poleTideFunction function computing ocean pole tide terms (ΔC₂₁, ΔS₂₁), may be null
76 */
77 OceanTidesField(final double ae, final double mu,
78 final List<OceanTidesWave> waves,
79 final FundamentalNutationArguments arguments,
80 final TimeVectorFunction poleTideFunction) {
81
82 // store mode parameters
83 this.ae = ae;
84 this.mu = mu;
85
86 // waves
87 this.waves = waves;
88 int m = 0;
89 int n = 0;
90 for (final OceanTidesWave wave : waves) {
91 m = FastMath.max(m, wave.getMaxDegree());
92 n = FastMath.max(n, wave.getMaxOrder());
93 }
94 degree = m;
95 order = n;
96
97 this.arguments = arguments;
98
99 // pole tide
100 this.poleTideFunction = poleTideFunction;
101
102 }
103
104 /** {@inheritDoc} */
105 @Override
106 public int getMaxDegree() {
107 return degree;
108 }
109
110 /** {@inheritDoc} */
111 @Override
112 public int getMaxOrder() {
113 return order;
114 }
115
116 /** {@inheritDoc} */
117 @Override
118 public double getMu() {
119 return mu;
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public double getAe() {
125 return ae;
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public AbsoluteDate getReferenceDate() {
131 return AbsoluteDate.ARBITRARY_EPOCH;
132 }
133
134 /** {@inheritDoc} */
135 @Override
136 public double getOffset(final AbsoluteDate date) {
137 return date.durationFrom(getReferenceDate());
138 }
139
140 /** {@inheritDoc} */
141 @Override
142 public TideSystem getTideSystem() {
143 // not really used here, but for consistency we can state that either
144 // we add the permanent tide or it was already in the central attraction
145 return TideSystem.ZERO_TIDE;
146 }
147
148 /** {@inheritDoc} */
149 @Override
150 public NormalizedSphericalHarmonics onDate(final AbsoluteDate date) {
151
152 // computed Cnm and Snm coefficients
153 final int rows = degree + 1;
154 final double[][] cnm = new double[rows][];
155 final double[][] snm = new double[rows][];
156 for (int i = 0; i <= degree; ++i) {
157 final int m = FastMath.min(i, order) + 1;
158 cnm[i] = new double[m];
159 snm[i] = new double[m];
160 }
161
162 final BodiesElements bodiesElements = arguments.evaluateAll(date);
163 for (final OceanTidesWave wave : waves) {
164 wave.addContribution(bodiesElements, cnm, snm);
165 }
166
167 if (poleTideFunction != null && degree > 1 && order > 0) {
168 // add pole tide
169 poleTide(date, cnm, snm);
170 }
171
172 return new TideHarmonics(date, cnm, snm);
173
174 }
175
176 /** Update coefficients applying pole tide.
177 * @param date current date
178 * @param cnm the Cnm coefficients. Modified in place.
179 * @param snm the Snm coefficients. Modified in place.
180 */
181 private void poleTide(final AbsoluteDate date, final double[][] cnm, final double[][] snm) {
182 final double[] deltaCS = poleTideFunction.value(date);
183 cnm[2][1] += deltaCS[0]; // ΔC₂₁
184 snm[2][1] += deltaCS[1]; // ΔS₂₁
185 }
186
187 /** The Tidal geopotential evaluated on a specific date. */
188 private static class TideHarmonics implements NormalizedSphericalHarmonics {
189
190 /** evaluation date. */
191 private final AbsoluteDate date;
192
193 /** Cached cnm. */
194 private final double[][] cnm;
195
196 /** Cached snm. */
197 private final double[][] snm;
198
199 /** Construct the tidal harmonics on the given date.
200 *
201 * @param date of evaluation
202 * @param cnm the Cnm coefficients. Not copied.
203 * @param snm the Snm coeffiecients. Not copied.
204 */
205 private TideHarmonics(final AbsoluteDate date,
206 final double[][] cnm,
207 final double[][] snm) {
208 this.date = date;
209 this.cnm = cnm;
210 this.snm = snm;
211 }
212
213 /** {@inheritDoc} */
214 @Override
215 public AbsoluteDate getDate() {
216 return date;
217 }
218
219 /** {@inheritDoc} */
220 @Override
221 public double getNormalizedCnm(final int n, final int m) {
222 return cnm[n][m];
223 }
224
225 /** {@inheritDoc} */
226 @Override
227 public double getNormalizedSnm(final int n, final int m) {
228 return snm[n][m];
229 }
230
231 }
232
233 }