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 import java.util.stream.Stream;
21
22 import org.hipparchus.Field;
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.orekit.annotation.DefaultDataContext;
27 import org.orekit.data.DataContext;
28 import org.orekit.forces.AbstractForceModel;
29 import org.orekit.forces.ForceModel;
30 import org.orekit.forces.gravity.potential.CachedNormalizedSphericalHarmonicsProvider;
31 import org.orekit.forces.gravity.potential.GravityFields;
32 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
33 import org.orekit.forces.gravity.potential.OceanTidesWave;
34 import org.orekit.frames.Frame;
35 import org.orekit.propagation.FieldSpacecraftState;
36 import org.orekit.propagation.SpacecraftState;
37 import org.orekit.propagation.events.EventDetector;
38 import org.orekit.propagation.events.FieldEventDetector;
39 import org.orekit.time.TimeScales;
40 import org.orekit.time.UT1Scale;
41 import org.orekit.utils.Constants;
42 import org.orekit.utils.IERSConventions;
43 import org.orekit.utils.OrekitConfiguration;
44 import org.orekit.utils.ParameterDriver;
45
46 /** Ocean tides force model.
47 * @since 6.1
48 * @author Luc Maisonobe
49 */
50 public class OceanTides extends AbstractForceModel {
51
52 /** Default step for tides field sampling (seconds). */
53 public static final double DEFAULT_STEP = 600.0;
54
55 /** Default number of points tides field sampling. */
56 public static final int DEFAULT_POINTS = 12;
57
58 /** Underlying attraction model. */
59 private final ForceModel attractionModel;
60
61 /** Simple constructor.
62 * <p>
63 * This constructor uses pole tides, the default {@link #DEFAULT_STEP step} and default
64 * {@link #DEFAULT_POINTS number of points} for the tides field interpolation.
65 * </p>
66 *
67 * <p>This constructor uses the {@link DataContext#getDefault() default data context}.
68 *
69 * @param centralBodyFrame rotating body frame
70 * @param ae central body reference radius
71 * @param mu central body attraction coefficient
72 * @param degree degree of the tide model to load
73 * @param order order of the tide model to load
74 * @param conventions IERS conventions used for loading ocean pole tide
75 * @param ut1 UT1 time scale
76 * @see #DEFAULT_STEP
77 * @see #DEFAULT_POINTS
78 * @see #OceanTides(Frame, double, double, boolean, double, int, int, int, IERSConventions, UT1Scale)
79 * @see GravityFields#getOceanTidesWaves(int, int)
80 * @see #OceanTides(Frame, double, double, boolean, double, int, int, int,
81 * IERSConventions, UT1Scale, GravityFields)
82 */
83 @DefaultDataContext
84 public OceanTides(final Frame centralBodyFrame, final double ae, final double mu,
85 final int degree, final int order,
86 final IERSConventions conventions, final UT1Scale ut1) {
87 this(centralBodyFrame, ae, mu, true,
88 DEFAULT_STEP, DEFAULT_POINTS, degree, order,
89 conventions, ut1);
90 }
91
92 /** Simple constructor.
93 *
94 * <p>This constructor uses the {@link DataContext#getDefault() default data context}.
95 *
96 * @param centralBodyFrame rotating body frame
97 * @param ae central body reference radius
98 * @param mu central body attraction coefficient
99 * @param poleTide if true, pole tide is computed
100 * @param step time step between sample points for interpolation
101 * @param nbPoints number of points to use for interpolation, if less than 2
102 * then no interpolation is performed (thus greatly increasing computation cost)
103 * @param degree degree of the tide model to load
104 * @param order order of the tide model to load
105 * @param conventions IERS conventions used for loading ocean pole tide
106 * @param ut1 UT1 time scale
107 * @see GravityFields#getOceanTidesWaves(int, int)
108 * @see #OceanTides(Frame, double, double, boolean, double, int, int, int,
109 * IERSConventions, UT1Scale, GravityFields)
110 */
111 @DefaultDataContext
112 public OceanTides(final Frame centralBodyFrame, final double ae, final double mu,
113 final boolean poleTide, final double step, final int nbPoints,
114 final int degree, final int order,
115 final IERSConventions conventions, final UT1Scale ut1) {
116 this(centralBodyFrame, ae, mu, poleTide, step, nbPoints, degree, order,
117 conventions, ut1, DataContext.getDefault().getGravityFields());
118 }
119
120 /** Simple constructor.
121 * @param centralBodyFrame rotating body frame
122 * @param ae central body reference radius
123 * @param mu central body attraction coefficient
124 * @param poleTide if true, pole tide is computed
125 * @param step time step between sample points for interpolation
126 * @param nbPoints number of points to use for interpolation, if less than 2
127 * then no interpolation is performed (thus greatly increasing computation cost)
128 * @param degree degree of the tide model to load
129 * @param order order of the tide model to load
130 * @param conventions IERS conventions used for loading ocean pole tide
131 * @param ut1 UT1 time scale
132 * @param gravityFields used to compute ocean tides.
133 * @see GravityFields#getOceanTidesWaves(int, int)
134 * @since 10.1
135 */
136 public OceanTides(final Frame centralBodyFrame, final double ae, final double mu,
137 final boolean poleTide, final double step, final int nbPoints,
138 final int degree, final int order,
139 final IERSConventions conventions, final UT1Scale ut1,
140 final GravityFields gravityFields) {
141
142 // load the ocean tides model
143 final List<OceanTidesWave> waves = gravityFields.getOceanTidesWaves(degree, order);
144
145 final TimeScales timeScales = ut1.getEOPHistory().getTimeScales();
146 final OceanTidesField raw =
147 new OceanTidesField(ae, mu, waves,
148 conventions.getNutationArguments(ut1, timeScales),
149 poleTide ? conventions.getOceanPoleTide(ut1.getEOPHistory()) : null);
150
151 final NormalizedSphericalHarmonicsProvider provider;
152 if (nbPoints < 2) {
153 provider = raw;
154 } else {
155 provider =
156 new CachedNormalizedSphericalHarmonicsProvider(raw, step, nbPoints,
157 OrekitConfiguration.getCacheSlotsNumber(),
158 7 * Constants.JULIAN_DAY,
159 0.5 * Constants.JULIAN_DAY);
160 }
161
162 attractionModel = new HolmesFeatherstoneAttractionModel(centralBodyFrame, provider);
163
164 }
165
166 /** {@inheritDoc} */
167 @Override
168 public boolean dependsOnPositionOnly() {
169 return attractionModel.dependsOnPositionOnly();
170 }
171
172 /** {@inheritDoc} */
173 @Override
174 public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
175 // delegate to underlying model
176 return attractionModel.acceleration(s, parameters);
177 }
178
179 /** {@inheritDoc} */
180 @Override
181 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
182 final T[] parameters) {
183 // delegate to underlying model
184 return attractionModel.acceleration(s, parameters);
185 }
186
187
188 /** {@inheritDoc} */
189 @Override
190 public Stream<EventDetector> getEventsDetectors() {
191 // delegate to underlying attraction model
192 return attractionModel.getEventsDetectors();
193 }
194
195 /** {@inheritDoc} */
196 @Override
197 public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
198 // delegate to underlying attraction model
199 return attractionModel.getFieldEventsDetectors(field);
200 }
201
202 /** {@inheritDoc} */
203 @Override
204 public List<ParameterDriver> getParametersDrivers() {
205 // delegate to underlying attraction model
206 return attractionModel.getParametersDrivers();
207 }
208
209 }