1 /* Copyright 2002-2026 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 org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.util.MathArrays;
21 import org.orekit.bodies.CelestialBody;
22 import org.orekit.forces.ForceModel;
23 import org.orekit.forces.ForceModelModifier;
24 import org.orekit.forces.gravity.potential.CachedNormalizedSphericalHarmonicsProvider;
25 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
26 import org.orekit.forces.gravity.potential.TideSystem;
27 import org.orekit.frames.Frame;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.time.FieldAbsoluteDate;
30 import org.orekit.time.TimeVectorFunction;
31 import org.orekit.time.UT1Scale;
32 import org.orekit.utils.Constants;
33 import org.orekit.utils.IERSConventions;
34 import org.orekit.utils.LoveNumbers;
35 import org.orekit.utils.OrekitConfiguration;
36
37 /** Solid tides force model.
38 * @since 6.1
39 * @author Luc Maisonobe
40 */
41 public class SolidTides implements ForceModelModifier {
42
43 /**
44 * Default step for tides field sampling (seconds).
45 */
46 public static final double DEFAULT_STEP = 600.0;
47
48 /**
49 * Default number of points tides field sampling.
50 */
51 public static final int DEFAULT_POINTS = 12;
52
53 /**
54 * Zero frequency-dependent corrections function for bodies without
55 * frequency-dependent tidal data.
56 *
57 * @author Rafael Ayala
58 * @since 14.0
59 */
60 private static final TimeVectorFunction ZERO_FREQUENCY_FUNCTION = new TimeVectorFunction() {
61 @Override
62 public double[] value(final AbsoluteDate date) {
63 return new double[5];
64 }
65 @Override
66 public <T extends CalculusFieldElement<T>> T[] value(final FieldAbsoluteDate<T> date) {
67 return MathArrays.buildArray(date.getField(), 5);
68 }
69 };
70
71 /**
72 * Underlying attraction model.
73 */
74 private final ForceModel attractionModel;
75
76 /**
77 * Private constructor with the force model only.
78 * @param attractionModel underlying attraction model
79 * @since 14.0
80 */
81 private SolidTides(final ForceModel attractionModel) {
82 this.attractionModel = attractionModel;
83 }
84
85 /**
86 * Simple constructor.
87 * <p>
88 * This constructor uses pole tides, the default {@link #DEFAULT_STEP step} and default
89 * {@link #DEFAULT_POINTS number of points} for the tides field interpolation.
90 * </p>
91 *
92 * @param centralBodyFrame rotating body frame
93 * @param ae central body reference radius
94 * @param mu central body attraction coefficient
95 * @param centralTideSystem tide system used in the central attraction model
96 * @param conventions IERS conventions used for loading Love numbers
97 * @param ut1 UT1 time scale
98 * @param bodies tide generating bodies (typically Sun and Moon)
99 * @see #DEFAULT_STEP
100 * @see #DEFAULT_POINTS
101 * @see #SolidTides(Frame, double, double, TideSystem, boolean, double, int, IERSConventions, UT1Scale, CelestialBody...)
102 */
103 public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
104 final TideSystem centralTideSystem,
105 final IERSConventions conventions, final UT1Scale ut1,
106 final CelestialBody... bodies) {
107 this(centralBodyFrame, ae, mu, centralTideSystem, true,
108 DEFAULT_STEP, DEFAULT_POINTS, conventions, ut1, bodies);
109 }
110
111 /**
112 * Simple constructor.
113 *
114 * @param centralBodyFrame rotating body frame
115 * @param ae central body reference radius
116 * @param mu central body attraction coefficient
117 * @param centralTideSystem tide system used in the central attraction model
118 * @param poleTide if true, pole tide is computed
119 * @param step time step between sample points for interpolation
120 * @param nbPoints number of points to use for interpolation, if less than 2
121 * then no interpolation is performed (thus greatly increasing computation cost)
122 * @param conventions IERS conventions used for loading Love numbers
123 * @param ut1 UT1 time scale
124 * @param bodies tide generating bodies (typically Sun and Moon)
125 */
126 public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
127 final TideSystem centralTideSystem, final boolean poleTide,
128 final double step, final int nbPoints,
129 final IERSConventions conventions, final UT1Scale ut1,
130 final CelestialBody... bodies) {
131 this(buildAttractionModel(centralBodyFrame,
132 new SolidTidesField(conventions.getLoveNumbers(),
133 conventions.getTideFrequencyDependenceFunction(ut1, ut1.getEOPHistory().getTimeScales()),
134 conventions.getPermanentTide(),
135 poleTide ? conventions.getSolidPoleTide(ut1.getEOPHistory()) : null,
136 centralBodyFrame, ae, mu, centralTideSystem, bodies),
137 step, nbPoints));
138 }
139
140 /**
141 * Constructor with custom Love numbers for any central body.
142 * This constructor allows using body-specific Love numbers (e.g. for the Moon)
143 * instead of IERS Earth conventions. Note that frequency-dependent corrections and pole
144 * tide are not applied, and only the frequency-independent tidal deformation
145 * (IERS 2010 equations 6.6 and 6.7) is computed.
146 *
147 * @param centralBodyFrame rotating body frame
148 * @param ae central body reference radius
149 * @param mu central body attraction coefficient
150 * @param centralTideSystem tide system used in the central attraction model
151 * @param loveNumbers body-specific Love numbers
152 * @param step time step between sample points for interpolation
153 * @param nbPoints number of points to use for interpolation, if less than 2
154 * then no interpolation is performed (thus greatly increasing computation cost)
155 * @param bodies tide generating bodies (typically Sun and Moon)
156 * @author Rafael Ayala
157 * @since 14.0
158 */
159 public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
160 final TideSystem centralTideSystem,
161 final LoveNumbers loveNumbers,
162 final double step, final int nbPoints,
163 final CelestialBody... bodies) {
164 this(buildAttractionModel(centralBodyFrame,
165 new SolidTidesField(loveNumbers, ZERO_FREQUENCY_FUNCTION,
166 0.0, null,
167 centralBodyFrame, ae, mu, centralTideSystem, bodies),
168 step, nbPoints));
169 }
170
171 /**
172 * Constructor with custom Love numbers using default interpolation settings.
173 * <p>
174 * This constructor uses the default {@link #DEFAULT_STEP step} and default
175 * {@link #DEFAULT_POINTS number of points} for the tides field interpolation.
176 * </p>
177 *
178 * @param centralBodyFrame rotating body frame
179 * @param ae central body reference radius
180 * @param mu central body attraction coefficient
181 * @param centralTideSystem tide system used in the central attraction model
182 * @param loveNumbers body-specific Love numbers
183 * @param bodies tide generating bodies (typically Sun and Moon)
184 * @see #DEFAULT_STEP
185 * @see #DEFAULT_POINTS
186 * @see #SolidTides(Frame, double, double, TideSystem, LoveNumbers, double, int, CelestialBody...)
187 * @author Rafael Ayala
188 * @since 14.0
189 */
190 public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
191 final TideSystem centralTideSystem,
192 final LoveNumbers loveNumbers,
193 final CelestialBody... bodies) {
194 this(centralBodyFrame, ae, mu, centralTideSystem, loveNumbers,
195 DEFAULT_STEP, DEFAULT_POINTS, bodies);
196 }
197
198 /** Build the attraction model from a raw provider.
199 * @param centralBodyFrame rotating body frame
200 * @param rawProvider raw spherical harmonics provider
201 * @param step time step between sample points for interpolation
202 * @param nbPoints number of points to use for interpolation
203 * @return the attraction model
204 */
205 private static ForceModel buildAttractionModel(final Frame centralBodyFrame,
206 final NormalizedSphericalHarmonicsProvider rawProvider,
207 final double step, final int nbPoints) {
208 final NormalizedSphericalHarmonicsProvider provider;
209 if (nbPoints < 2) {
210 provider = rawProvider;
211 } else {
212 provider =
213 new CachedNormalizedSphericalHarmonicsProvider(rawProvider, step, nbPoints,
214 OrekitConfiguration.getCacheSlotsNumber(),
215 7 * Constants.JULIAN_DAY,
216 0.5 * Constants.JULIAN_DAY);
217 }
218 return new HolmesFeatherstoneAttractionModel(centralBodyFrame, provider);
219 }
220
221 @Override
222 public ForceModel getUnderlyingModel() {
223 return attractionModel;
224 }
225 }