1   /* Copyright 2010-2011 Centre National d'Études Spatiales
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.Collections;
20  import java.util.List;
21  import java.util.stream.Stream;
22  
23  import org.hipparchus.Field;
24  import org.hipparchus.CalculusFieldElement;
25  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.FastMath;
28  import org.orekit.forces.AbstractForceModel;
29  import org.orekit.propagation.FieldSpacecraftState;
30  import org.orekit.propagation.SpacecraftState;
31  import org.orekit.propagation.events.EventDetector;
32  import org.orekit.propagation.events.FieldEventDetector;
33  import org.orekit.propagation.numerical.FieldTimeDerivativesEquations;
34  import org.orekit.propagation.numerical.TimeDerivativesEquations;
35  import org.orekit.utils.ParameterDriver;
36  
37  /** Force model for Newtonian central body attraction.
38   * @author Luc Maisonobe
39   */
40  public class NewtonianAttraction extends AbstractForceModel {
41  
42      /** Name of the single parameter of this model: the central attraction coefficient. */
43      public static final String CENTRAL_ATTRACTION_COEFFICIENT = "central attraction coefficient";
44  
45      /** Central attraction scaling factor.
46       * <p>
47       * We use a power of 2 to avoid numeric noise introduction
48       * in the multiplications/divisions sequences.
49       * </p>
50       */
51      private static final double MU_SCALE = FastMath.scalb(1.0, 32);
52  
53      /** Driver for gravitational parameter. */
54      private final ParameterDriver gmParameterDriver;
55  
56     /** Simple constructor.
57       * @param mu central attraction coefficient (m^3/s^2)
58       */
59      public NewtonianAttraction(final double mu) {
60          gmParameterDriver = new ParameterDriver(NewtonianAttraction.CENTRAL_ATTRACTION_COEFFICIENT,
61                                                  mu, MU_SCALE,
62                                                  0.0, Double.POSITIVE_INFINITY);
63      }
64  
65      /** {@inheritDoc} */
66      @Override
67      public boolean dependsOnPositionOnly() {
68          return true;
69      }
70  
71      /** Get the central attraction coefficient μ.
72       * @return mu central attraction coefficient (m³/s²)
73       */
74      public double getMu() {
75          return gmParameterDriver.getValue();
76      }
77  
78      /** Get the central attraction coefficient μ.
79       * @param <T> the type of the field element
80       * @param field field to which the state belongs
81       * @return mu central attraction coefficient (m³/s²)
82       */
83      public <T extends CalculusFieldElement<T>> T getMu(final Field<T> field) {
84          final T zero = field.getZero();
85          return zero.add(gmParameterDriver.getValue());
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      public void addContribution(final SpacecraftState s, final TimeDerivativesEquations adder) {
91          adder.addKeplerContribution(getMu());
92      }
93  
94      /** {@inheritDoc} */
95      @Override
96      public <T extends CalculusFieldElement<T>> void addContribution(final FieldSpacecraftState<T> s,
97                                                                  final FieldTimeDerivativesEquations<T> adder) {
98          final Field<T> field = s.getDate().getField();
99          adder.addKeplerContribution(getMu(field));
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
105         final double mu = parameters[0];
106         final double r2 = s.getPVCoordinates().getPosition().getNormSq();
107         return new Vector3D(-mu / (FastMath.sqrt(r2) * r2), s.getPVCoordinates().getPosition());
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
113                                                                          final T[] parameters) {
114         final T mu = parameters[0];
115         final T r2 = s.getPVCoordinates().getPosition().getNormSq();
116         return new FieldVector3D<>(r2.sqrt().multiply(r2).reciprocal().multiply(mu).negate(), s.getPVCoordinates().getPosition());
117     }
118 
119     /** {@inheritDoc} */
120     @Override
121     public Stream<EventDetector> getEventsDetectors() {
122         return Stream.empty();
123     }
124 
125     /** {@inheritDoc} */
126     @Override
127     public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
128         return Stream.empty();
129     }
130 
131     /** {@inheritDoc} */
132     @Override
133     public List<ParameterDriver> getParametersDrivers() {
134         return Collections.singletonList(gmParameterDriver);
135     }
136 
137 }
138