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