1 /* Copyright 2002-2025 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 TideSystem getTideSystem() {
137 // not really used here, but for consistency we can state that either
138 // we add the permanent tide or it was already in the central attraction
139 return TideSystem.ZERO_TIDE;
140 }
141
142 /** {@inheritDoc} */
143 @Override
144 public NormalizedSphericalHarmonics onDate(final AbsoluteDate date) {
145
146 // computed Cnm and Snm coefficients
147 final int rows = degree + 1;
148 final double[][] cnm = new double[rows][];
149 final double[][] snm = new double[rows][];
150 for (int i = 0; i <= degree; ++i) {
151 final int m = FastMath.min(i, order) + 1;
152 cnm[i] = new double[m];
153 snm[i] = new double[m];
154 }
155
156 final BodiesElements bodiesElements = arguments.evaluateAll(date);
157 for (final OceanTidesWave wave : waves) {
158 wave.addContribution(bodiesElements, cnm, snm);
159 }
160
161 if (poleTideFunction != null && degree > 1 && order > 0) {
162 // add pole tide
163 poleTide(date, cnm, snm);
164 }
165
166 return new TideHarmonics(date, cnm, snm);
167
168 }
169
170 /** Update coefficients applying pole tide.
171 * @param date current date
172 * @param cnm the Cnm coefficients. Modified in place.
173 * @param snm the Snm coefficients. Modified in place.
174 */
175 private void poleTide(final AbsoluteDate date, final double[][] cnm, final double[][] snm) {
176 final double[] deltaCS = poleTideFunction.value(date);
177 cnm[2][1] += deltaCS[0]; // ΔC₂₁
178 snm[2][1] += deltaCS[1]; // ΔS₂₁
179 }
180
181 /** The Tidal geopotential evaluated on a specific date. */
182 private static class TideHarmonics implements NormalizedSphericalHarmonics {
183
184 /** evaluation date. */
185 private final AbsoluteDate date;
186
187 /** Cached cnm. */
188 private final double[][] cnm;
189
190 /** Cached snm. */
191 private final double[][] snm;
192
193 /** Construct the tidal harmonics on the given date.
194 *
195 * @param date of evaluation
196 * @param cnm the Cnm coefficients. Not copied.
197 * @param snm the Snm coeffiecients. Not copied.
198 */
199 private TideHarmonics(final AbsoluteDate date,
200 final double[][] cnm,
201 final double[][] snm) {
202 this.date = date;
203 this.cnm = cnm;
204 this.snm = snm;
205 }
206
207 /** {@inheritDoc} */
208 @Override
209 public AbsoluteDate getDate() {
210 return date;
211 }
212
213 /** {@inheritDoc} */
214 @Override
215 public double getNormalizedCnm(final int n, final int m) {
216 return cnm[n][m];
217 }
218
219 /** {@inheritDoc} */
220 @Override
221 public double getNormalizedSnm(final int n, final int m) {
222 return snm[n][m];
223 }
224
225 }
226
227 }