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