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.radiation;
18  
19  import java.util.Collections;
20  import java.util.List;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
24  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25  import org.hipparchus.geometry.euclidean.threed.Rotation;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.FastMath;
28  import org.orekit.frames.Frame;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.time.FieldAbsoluteDate;
31  import org.orekit.utils.ParameterDriver;
32  
33  /** This class represents the features of a simplified spacecraft.
34   * <p>This model uses a single coefficient cr, considered to be
35   * a {@link RadiationSensitive#REFLECTION_COEFFICIENT}.
36   * </p>
37   *
38   * @see org.orekit.forces.BoxAndSolarArraySpacecraft
39   * @see org.orekit.forces.drag.IsotropicDrag
40   * @see IsotropicRadiationCNES95Convention
41   * @author Luc Maisonobe
42   * @since 7.1
43   */
44  public class IsotropicRadiationSingleCoefficient implements RadiationSensitive {
45  
46      /** Parameters scaling factor.
47       * <p>
48       * We use a power of 2 to avoid numeric noise introduction
49       * in the multiplications/divisions sequences.
50       * </p>
51       */
52      private final double SCALE = FastMath.scalb(1.0, -3);
53  
54      /** Driver for reflection coefficient. */
55      private final ParameterDriver reflectionParameterDriver;
56  
57      /** Cross section (m²). */
58      private final double crossSection;
59  
60      /** Constructor with reflection coefficient min/max set to ±∞.
61       * @param crossSection Surface (m²)
62       * @param cr reflection coefficient
63       */
64      public IsotropicRadiationSingleCoefficient(final double crossSection, final double cr) {
65          this(crossSection, cr, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
66      }
67  
68      /** Constructor with reflection coefficient min/max set by user.
69      * @param crossSection Surface (m²)
70      * @param cr reflection coefficient
71      * @param crMin Minimum value of reflection coefficient
72      * @param crMax Maximum value of reflection coefficient
73      */
74      public IsotropicRadiationSingleCoefficient(final double crossSection, final double cr,
75                                                 final double crMin, final double crMax) {
76          // in some corner cases (unknown spacecraft, fuel leaks, active piloting ...)
77          // the single coefficient may be arbitrary, and even negative
78          reflectionParameterDriver = new ParameterDriver(RadiationSensitive.REFLECTION_COEFFICIENT,
79                                                          cr, SCALE,
80                                                          crMin, crMax);
81  
82          this.crossSection = crossSection;
83  
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      public List<ParameterDriver> getRadiationParametersDrivers() {
89          return Collections.singletonList(reflectionParameterDriver);
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public Vector3D radiationPressureAcceleration(final AbsoluteDate date, final Frame frame, final Vector3D position,
95                                                    final Rotation rotation, final double mass, final Vector3D flux,
96                                                    final double[] parameters) {
97          final double cr = parameters[0];
98          return new Vector3D(crossSection * cr / mass, flux);
99      }
100 
101     /** {@inheritDoc} */
102     @Override
103     public <T extends CalculusFieldElement<T>> FieldVector3D<T>
104         radiationPressureAcceleration(final FieldAbsoluteDate<T> date, final Frame frame,
105                                       final FieldVector3D<T> position,
106                                       final FieldRotation<T> rotation, final T mass,
107                                       final FieldVector3D<T> flux,
108                                       final T[] parameters) {
109         final T cr = parameters[0];
110         return new FieldVector3D<>(mass.reciprocal().multiply(crossSection).multiply(cr), flux);
111 
112     }
113 }