IsotropicRadiationCNES95Convention.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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. import org.hipparchus.RealFieldElement;
  19. import org.hipparchus.analysis.differentiation.DSFactory;
  20. import org.hipparchus.analysis.differentiation.DerivativeStructure;
  21. import org.hipparchus.geometry.euclidean.threed.FieldRotation;
  22. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  23. import org.hipparchus.geometry.euclidean.threed.Rotation;
  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.hipparchus.util.FastMath;
  26. import org.orekit.errors.OrekitException;
  27. import org.orekit.errors.OrekitInternalError;
  28. import org.orekit.errors.OrekitMessages;
  29. import org.orekit.frames.Frame;
  30. import org.orekit.time.AbsoluteDate;
  31. import org.orekit.time.FieldAbsoluteDate;
  32. import org.orekit.utils.ParameterDriver;

  33. /** This class represents the features of a simplified spacecraft.
  34.  *
  35.  * <p>This model uses the coefficients described in the collective
  36.  * book edited by CNES in 1995: Spaceflight Dynamics (part I), in
  37.  * section 5.2.2.1.3.1 (page 296 of the English edition). The absorption
  38.  * coefficient is called α and the specular reflection coefficient is
  39.  * called τ. A comment in section 5.2.2.1.3.2 of the same book reads:
  40.  * <pre>
  41.  * Some authors prefer to express thermo-optical properties for surfaces
  42.  * using the following coefficients: Ka = α, Ks = (1-α)τ, Kd = (1-α)(1-τ)
  43.  * </pre>
  44.  * <p> Ka is the same absorption coefficient, and Ks is also called specular
  45.  * reflection coefficient, which leads to a confusion. In fact, as the Ka,
  46.  * Ks and Kd coefficients are the most frequently used ones (using the
  47.  * names Ca, Cs and Cd), when speaking about reflection coefficients, it
  48.  * is more often Cd that is considered rather than τ.
  49.  *
  50.  * <p>
  51.  * The classical set of coefficients Ca, Cs, and Cd are implemented in the
  52.  * sister class {@link IsotropicRadiationClassicalConvention}, which should
  53.  * probably be preferred to this legacy class.
  54.  * </p>
  55.  *
  56.  * @see org.orekit.forces.BoxAndSolarArraySpacecraft
  57.  * @see org.orekit.forces.drag.IsotropicDrag
  58.  * @see IsotropicRadiationClassicalConvention
  59.  * @author Luc Maisonobe
  60.  * @since 7.1
  61.  */
  62. public class IsotropicRadiationCNES95Convention implements RadiationSensitive {

  63.     /** Parameters scaling factor.
  64.      * <p>
  65.      * We use a power of 2 to avoid numeric noise introduction
  66.      * in the multiplications/divisions sequences.
  67.      * </p>
  68.      */
  69.     private final double SCALE = FastMath.scalb(1.0, -3);

  70.     /** Driver for absorption coefficient. */
  71.     private final ParameterDriver absorptionParameterDriver;

  72.     /** Driver for specular reflection coefficient. */
  73.     private final ParameterDriver reflectionParameterDriver;

  74.     /** Cross section (m²). */
  75.     private final double crossSection;

  76.     /** Factory for the DerivativeStructure instances. */
  77.     private final DSFactory factory;

  78.     /** Simple constructor.
  79.      * @param crossSection Surface (m²)
  80.      * @param alpha absorption coefficient α between 0.0 an 1.0
  81.      * @param tau specular reflection coefficient τ between 0.0 an 1.0
  82.      */
  83.     public IsotropicRadiationCNES95Convention(final double crossSection, final double alpha, final double tau) {
  84.         try {
  85.             absorptionParameterDriver = new ParameterDriver(RadiationSensitive.ABSORPTION_COEFFICIENT,
  86.                                                             alpha, SCALE, 0.0, 1.0);
  87.             reflectionParameterDriver = new ParameterDriver(RadiationSensitive.REFLECTION_COEFFICIENT,
  88.                                                             tau, SCALE, 0.0, 1.0);
  89.             factory = new DSFactory(1, 1);
  90.         } catch (OrekitException oe) {
  91.             // this should never occur as valueChanged above never throws an exception
  92.             throw new OrekitInternalError(oe);
  93.         }
  94.         this.crossSection = crossSection;
  95.     }

  96.     /** {@inheritDoc} */
  97.     @Override
  98.     public ParameterDriver[] getRadiationParametersDrivers() {
  99.         return new ParameterDriver[] {
  100.             absorptionParameterDriver, reflectionParameterDriver
  101.         };
  102.     }

  103.     /** {@inheritDoc} */
  104.     @Override
  105.     public Vector3D radiationPressureAcceleration(final AbsoluteDate date, final Frame frame, final Vector3D position,
  106.                                                   final Rotation rotation, final double mass, final Vector3D flux,
  107.                                                   final double[] parameters) {
  108.         final double alpha = parameters[0];
  109.         final double tau   = parameters[1];
  110.         final double kP = crossSection * (1 + 4 * (1.0 - alpha) * (1.0 - tau) / 9.0);
  111.         return new Vector3D(kP / mass, flux);
  112.     }

  113.     /** {@inheritDoc} */
  114.     @Override
  115.     public <T extends RealFieldElement<T>> FieldVector3D<T>
  116.         radiationPressureAcceleration(final FieldAbsoluteDate<T> date, final Frame frame,
  117.                                       final FieldVector3D<T> position,
  118.                                       final FieldRotation<T> rotation, final T mass,
  119.                                       final FieldVector3D<T> flux,
  120.                                       final T[] parameters)
  121.         throws OrekitException {
  122.         final T alpha = parameters[0];
  123.         final T tau   = parameters[1];
  124.         final T kP    = alpha.negate().add(1).multiply(tau.negate().add(1)).multiply(4.0 / 9.0).add(1).multiply(crossSection);
  125.         return new FieldVector3D<>(mass.reciprocal().multiply(kP), flux);
  126.     }

  127.     /** {@inheritDoc} */
  128.     @Override
  129.     public FieldVector3D<DerivativeStructure> radiationPressureAcceleration(final AbsoluteDate date, final Frame frame, final Vector3D position,
  130.                                                                             final Rotation rotation, final double mass,
  131.                                                                             final Vector3D flux, final double[] parameters,
  132.                                                                             final String paramName)
  133.         throws OrekitException {

  134.         final DerivativeStructure absorptionCoeffDS;
  135.         final DerivativeStructure specularReflectionCoeffDS;
  136.         if (ABSORPTION_COEFFICIENT.equals(paramName)) {
  137.             absorptionCoeffDS         = factory.variable(0, parameters[0]);
  138.             specularReflectionCoeffDS = factory.constant(parameters[1]);
  139.         } else if (REFLECTION_COEFFICIENT.equals(paramName)) {
  140.             absorptionCoeffDS         = factory.constant(parameters[0]);
  141.             specularReflectionCoeffDS = factory.variable(0, parameters[1]);
  142.         } else {
  143.             throw new OrekitException(OrekitMessages.UNSUPPORTED_PARAMETER_NAME, paramName,
  144.                                       ABSORPTION_COEFFICIENT + ", " + REFLECTION_COEFFICIENT);
  145.         }

  146.         final DerivativeStructure kP =
  147.                 absorptionCoeffDS.subtract(1).multiply(specularReflectionCoeffDS.subtract(1)).multiply(4.0 / 9.0).add(1).multiply(crossSection);
  148.         return new FieldVector3D<>(kP.divide(mass), flux);

  149.     }

  150. }