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.drag;
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.analysis.differentiation.DerivativeStructure;
25  import org.hipparchus.analysis.differentiation.Gradient;
26  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27  import org.hipparchus.geometry.euclidean.threed.Vector3D;
28  import org.orekit.frames.Frame;
29  import org.orekit.models.earth.atmosphere.Atmosphere;
30  import org.orekit.propagation.FieldSpacecraftState;
31  import org.orekit.propagation.SpacecraftState;
32  import org.orekit.propagation.events.EventDetector;
33  import org.orekit.propagation.events.FieldEventDetector;
34  import org.orekit.time.AbsoluteDate;
35  import org.orekit.time.FieldAbsoluteDate;
36  import org.orekit.utils.ParameterDriver;
37  
38  
39  /** Atmospheric drag force model.
40   *
41   * The drag acceleration is computed as follows :
42   *
43   * γ = (1/2 * ρ * V² * S / Mass) * DragCoefVector
44   *
45   * With DragCoefVector = {C<sub>x</sub>, C<sub>y</sub>, C<sub>z</sub>} and S given by the user through the interface
46   * {@link DragSensitive}
47   *
48   * @author &Eacute;douard Delente
49   * @author Fabien Maussion
50   * @author V&eacute;ronique Pommier-Maurussane
51   * @author Pascal Parraud
52   */
53  
54  public class DragForce extends AbstractDragForceModel {
55  
56      /** Atmospheric model. */
57      private final Atmosphere atmosphere;
58  
59      /** Spacecraft. */
60      private final DragSensitive spacecraft;
61  
62      /** Simple constructor.
63       * @param atmosphere atmospheric model
64       * @param spacecraft the object physical and geometrical information
65       */
66      public DragForce(final Atmosphere atmosphere, final DragSensitive spacecraft) {
67          super(atmosphere);
68          this.atmosphere = atmosphere;
69          this.spacecraft = spacecraft;
70      }
71  
72      /** {@inheritDoc} */
73      @Override
74      public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
75  
76          final AbsoluteDate date     = s.getDate();
77          final Frame        frame    = s.getFrame();
78          final Vector3D     position = s.getPVCoordinates().getPosition();
79  
80          final double rho    = atmosphere.getDensity(date, position, frame);
81          final Vector3D vAtm = atmosphere.getVelocity(date, position, frame);
82          final Vector3D relativeVelocity = vAtm.subtract(s.getPVCoordinates().getVelocity());
83  
84          return spacecraft.dragAcceleration(date, frame, position, s.getAttitude().getRotation(),
85                                             s.getMass(), rho, relativeVelocity, parameters);
86  
87      }
88  
89      /** {@inheritDoc} */
90      @SuppressWarnings("unchecked")
91      @Override
92      public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
93                                                                           final T[] parameters) {
94  
95          final FieldAbsoluteDate<T> date     = s.getDate();
96          final Frame                frame    = s.getFrame();
97          final FieldVector3D<T>     position = s.getPVCoordinates().getPosition();
98  
99          // Density and its derivatives
100         final T rho;
101 
102         // Check for faster computation dedicated to derivatives with respect to state
103         // Using finite differences instead of automatic differentiation as it seems to be much
104         // faster for the drag's derivatives' computation
105         if (isGradientStateDerivative(s)) {
106             rho =  (T) this.getGradientDensityWrtStateUsingFiniteDifferences(date.toAbsoluteDate(), frame, (FieldVector3D<Gradient>) position);
107         } else if (isDSStateDerivative(s)) {
108             rho = (T) this.getDSDensityWrtStateUsingFiniteDifferences(date.toAbsoluteDate(), frame, (FieldVector3D<DerivativeStructure>) position);
109         } else {
110             rho = atmosphere.getDensity(date, position, frame);
111         }
112 
113         // Spacecraft relative velocity with respect to the atmosphere
114         final FieldVector3D<T> vAtm = atmosphere.getVelocity(date, position, frame);
115         final FieldVector3D<T> relativeVelocity = vAtm.subtract(s.getPVCoordinates().getVelocity());
116 
117         // Drag acceleration along with its derivatives
118         return spacecraft.dragAcceleration(date, frame, position, s.getAttitude().getRotation(),
119                                            s.getMass(), rho, relativeVelocity, parameters);
120 
121     }
122 
123     /** {@inheritDoc} */
124     @Override
125     public List<ParameterDriver> getParametersDrivers() {
126         return spacecraft.getDragParametersDrivers();
127     }
128 
129     /** {@inheritDoc} */
130     @Override
131     public Stream<EventDetector> getEventsDetectors() {
132         return Stream.empty();
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
138         return Stream.empty();
139     }
140 
141     /** Get the atmospheric model.
142      * @return atmosphere model
143      */
144     public Atmosphere getAtmosphere() {
145         return atmosphere;
146     }
147 
148     /** Get spacecraft that are sensitive to atmospheric drag forces.
149      * @return drag sensitive spacecraft model
150      */
151     public DragSensitive getSpacecraft() {
152         return spacecraft;
153     }
154 }