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.bodies.CelestialBody;
27  import org.orekit.forces.AbstractForceModel;
28  import org.orekit.forces.ForceModel;
29  import org.orekit.forces.gravity.potential.CachedNormalizedSphericalHarmonicsProvider;
30  import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
31  import org.orekit.forces.gravity.potential.TideSystem;
32  import org.orekit.frames.Frame;
33  import org.orekit.propagation.FieldSpacecraftState;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.events.EventDetector;
36  import org.orekit.propagation.events.FieldEventDetector;
37  import org.orekit.time.TimeScales;
38  import org.orekit.time.UT1Scale;
39  import org.orekit.utils.Constants;
40  import org.orekit.utils.IERSConventions;
41  import org.orekit.utils.OrekitConfiguration;
42  import org.orekit.utils.ParameterDriver;
43  
44  /** Solid tides force model.
45   * @since 6.1
46   * @author Luc Maisonobe
47   */
48  public class SolidTides extends AbstractForceModel {
49  
50      /** Default step for tides field sampling (seconds). */
51      public static final double DEFAULT_STEP = 600.0;
52  
53      /** Default number of points tides field sampling. */
54      public static final int DEFAULT_POINTS = 12;
55  
56      /** Underlying attraction model. */
57      private final ForceModel attractionModel;
58  
59      /** Simple constructor.
60       * <p>
61       * This constructor uses pole tides, the default {@link #DEFAULT_STEP step} and default
62       * {@link #DEFAULT_POINTS number of points} for the tides field interpolation.
63       * </p>
64       * @param centralBodyFrame rotating body frame
65       * @param ae central body reference radius
66       * @param mu central body attraction coefficient
67       * @param centralTideSystem tide system used in the central attraction model
68       * @param conventions IERS conventions used for loading Love numbers
69       * @param ut1 UT1 time scale
70       * @param bodies tide generating bodies (typically Sun and Moon)
71       * @see #DEFAULT_STEP
72       * @see #DEFAULT_POINTS
73       * @see #SolidTides(Frame, double, double, TideSystem, boolean, double, int, IERSConventions, UT1Scale, CelestialBody...)
74       */
75      public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
76                        final TideSystem centralTideSystem,
77                        final IERSConventions conventions, final UT1Scale ut1,
78                        final CelestialBody... bodies) {
79          this(centralBodyFrame, ae, mu, centralTideSystem, true,
80               DEFAULT_STEP, DEFAULT_POINTS, conventions, ut1, bodies);
81      }
82  
83      /** Simple constructor.
84       * @param centralBodyFrame rotating body frame
85       * @param ae central body reference radius
86       * @param mu central body attraction coefficient
87       * @param centralTideSystem tide system used in the central attraction model
88       * @param poleTide if true, pole tide is computed
89       * @param step time step between sample points for interpolation
90       * @param nbPoints number of points to use for interpolation, if less than 2
91       * then no interpolation is performed (thus greatly increasing computation cost)
92       * @param conventions IERS conventions used for loading Love numbers
93       * @param ut1 UT1 time scale
94       * @param bodies tide generating bodies (typically Sun and Moon)
95       */
96      public SolidTides(final Frame centralBodyFrame, final double ae, final double mu,
97                        final TideSystem centralTideSystem, final boolean poleTide,
98                        final double step, final int nbPoints,
99                        final IERSConventions conventions, final UT1Scale ut1,
100                       final CelestialBody... bodies) {
101         final TimeScales timeScales = ut1.getEOPHistory().getTimeScales();
102         final SolidTidesField raw =
103                 new SolidTidesField(conventions.getLoveNumbers(),
104                                     conventions.getTideFrequencyDependenceFunction(ut1, timeScales),
105                                     conventions.getPermanentTide(),
106                                     poleTide ? conventions.getSolidPoleTide(ut1.getEOPHistory()) : null,
107                                              centralBodyFrame, ae, mu, centralTideSystem, bodies);
108         final NormalizedSphericalHarmonicsProvider provider;
109         if (nbPoints < 2) {
110             provider = raw;
111         } else {
112             provider =
113                 new CachedNormalizedSphericalHarmonicsProvider(raw, step, nbPoints,
114                                                                OrekitConfiguration.getCacheSlotsNumber(),
115                                                                7 * Constants.JULIAN_DAY,
116                                                                0.5 * Constants.JULIAN_DAY);
117         }
118         attractionModel = new HolmesFeatherstoneAttractionModel(centralBodyFrame, provider);
119     }
120 
121     /** {@inheritDoc} */
122     @Override
123     public boolean dependsOnPositionOnly() {
124         return attractionModel.dependsOnPositionOnly();
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
130         // delegate to underlying attraction model
131         return attractionModel.acceleration(s, parameters);
132     }
133 
134     /** {@inheritDoc} */
135     @Override
136     public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
137                                                                          final T[] parameters) {
138         // delegate to underlying attraction model
139         return attractionModel.acceleration(s, parameters);
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public Stream<EventDetector> getEventsDetectors() {
145         // delegate to underlying attraction model
146         return attractionModel.getEventsDetectors();
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
152         // delegate to underlying attraction model
153         return attractionModel.getFieldEventsDetectors(field);
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public List<ParameterDriver> getParametersDrivers() {
159         // delegate to underlying attraction model
160         return attractionModel.getParametersDrivers();
161     }
162 
163 }