1   /* Copyright 2022-2026 Romain Serra
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.geometry.euclidean.threed.FieldVector3D;
21  import org.hipparchus.geometry.euclidean.threed.Vector3D;
22  import org.hipparchus.util.FastMath;
23  import org.orekit.forces.ForceModel;
24  import org.orekit.frames.Frame;
25  import org.orekit.time.AbsoluteDate;
26  import org.orekit.time.FieldAbsoluteDate;
27  import org.orekit.time.TimeInterval;
28  import org.orekit.utils.ExtendedPositionProvider;
29  import org.orekit.utils.drivers.ParameterDriver;
30  import org.orekit.utils.TimeStampedPVCoordinates;
31  import org.orekit.utils.TimeStampedFieldPVCoordinates;
32  
33  import java.util.Collections;
34  import java.util.List;
35  
36  /** Abstract class for non-central body attraction force model.
37   *
38   * @author Romain Serra
39   */
40  public abstract class AbstractBodyAttraction implements ForceModel {
41  
42      /** Suffix for parameter name for attraction coefficient enabling Jacobian processing. */
43      public static final String ATTRACTION_COEFFICIENT_SUFFIX = " 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      /** The position provider for the body to consider. */
54      private final ExtendedPositionProvider positionProvider;
55  
56      /** Drivers for body attraction coefficient. */
57      private final ParameterDriver gmParameterDriver;
58  
59      /** Name of body. */
60      private final String name;
61  
62      /** Simple constructor.
63       * @param positionProvider provider for the body to consider
64       * @param name body name
65       * @param mu body gravitational constant
66       */
67      protected AbstractBodyAttraction(final ExtendedPositionProvider positionProvider, final String name,
68                                       final double mu) {
69          this.positionProvider = positionProvider;
70          this.name = name;
71          this.gmParameterDriver = new ParameterDriver(name + ATTRACTION_COEFFICIENT_SUFFIX, FastMath.abs(mu),
72                                                       MU_SCALE, 0.0, Double.POSITIVE_INFINITY, TimeInterval.UNLIMITED);
73      }
74  
75      /** Getter for the body's name.
76       * @return the body's name
77       */
78      public String getBodyName() {
79          return name;
80      }
81  
82      /**
83       * Get the body's position vector.
84       * @param date date
85       * @param frame frame
86       * @return position
87       * @since 12.2
88       */
89      protected Vector3D getBodyPosition(final AbsoluteDate date, final Frame frame) {
90          return positionProvider.getPosition(date, frame);
91      }
92  
93      /**
94       * Get the body's position vector.
95       * @param date date
96       * @param frame frame
97       * @param <T> field type
98       * @return position
99       * @since 12.2
100      */
101     protected <T extends CalculusFieldElement<T>> FieldVector3D<T> getBodyPosition(final FieldAbsoluteDate<T> date,
102                                                                                    final Frame frame) {
103         return positionProvider.getPosition(date, frame);
104     }
105 
106     /**
107      * Get the body's position-velocity-acceleration vector.
108      * @param date date
109      * @param frame frame
110      * @return PV
111      * @since 12.2
112      */
113     protected TimeStampedPVCoordinates getBodyPVCoordinates(final AbsoluteDate date, final Frame frame) {
114         return positionProvider.getPVCoordinates(date, frame);
115     }
116 
117     /**
118      * Get the body's position-velocity-acceleration vector.
119      * @param date date
120      * @param frame frame
121      * @param <T> field type
122      * @return PV
123      * @since 12.2
124      */
125     protected <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> getBodyPVCoordinates(final FieldAbsoluteDate<T> date,
126                                                                                                         final Frame frame) {
127         return positionProvider.getPVCoordinates(date, frame);
128     }
129 
130     /** {@inheritDoc} */
131     @Override
132     public boolean dependsOnPositionOnly() {
133         return true;
134     }
135 
136     /** {@inheritDoc} */
137     @Override
138     public List<ParameterDriver> getParametersDrivers() {
139         return Collections.singletonList(gmParameterDriver);
140     }
141 }