IsotropicRadiationClassicalConvention.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.  * <p>This model uses the classical thermo-optical coefficients
  35.  * Ca for absorption, Cs for specular reflection and Kd for diffuse
  36.  * reflection. The equation Ca + Cs + Cd = 1 always holds.
  37.  * </p>
  38.  * <p>
  39.  * A less standard set of coefficients α = Ca for absorption and
  40.  * τ = Cs/(1-Ca) for specular reflection is implemented in the sister
  41.  * class {@link IsotropicRadiationCNES95Convention}.
  42.  * </p>
  43.  *
  44.  * @see org.orekit.forces.BoxAndSolarArraySpacecraft
  45.  * @see org.orekit.forces.drag.IsotropicDrag
  46.  * @see IsotropicRadiationCNES95Convention
  47.  * @author Luc Maisonobe
  48.  * @since 7.1
  49.  */
  50. public class IsotropicRadiationClassicalConvention implements RadiationSensitive {

  51.     /** Parameters scaling factor.
  52.      * <p>
  53.      * We use a power of 2 to avoid numeric noise introduction
  54.      * in the multiplications/divisions sequences.
  55.      * </p>
  56.      */
  57.     private final double SCALE = FastMath.scalb(1.0, -3);

  58.     /** Driver for absorption coefficient. */
  59.     private final ParameterDriver absorptionParameterDriver;

  60.     /** Driver for specular reflection coefficient. */
  61.     private final ParameterDriver reflectionParameterDriver;

  62.     /** Cross section (m²). */
  63.     private final double crossSection;

  64.     /** Factory for the DerivativeStructure instances. */
  65.     private final DSFactory factory;

  66.     /** Simple constructor.
  67.      * @param crossSection Surface (m²)
  68.      * @param ca absorption coefficient Ca between 0.0 an 1.0
  69.      * @param cs specular reflection coefficient Cs between 0.0 an 1.0
  70.      */
  71.     public IsotropicRadiationClassicalConvention(final double crossSection, final double ca, final double cs) {
  72.         try {
  73.             absorptionParameterDriver = new ParameterDriver(RadiationSensitive.ABSORPTION_COEFFICIENT,
  74.                                                             ca, SCALE, 0.0, 1.0);
  75.             reflectionParameterDriver = new ParameterDriver(RadiationSensitive.REFLECTION_COEFFICIENT,
  76.                                                             cs, SCALE, 0.0, 1.0);
  77.             factory = new DSFactory(1, 1);
  78.         } catch (OrekitException oe) {
  79.             // this should never occur as valueChanged above never throws an exception
  80.             throw new OrekitInternalError(oe);
  81.         }
  82.         this.crossSection = crossSection;
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public ParameterDriver[] getRadiationParametersDrivers() {
  87.         return new ParameterDriver[] {
  88.             absorptionParameterDriver, reflectionParameterDriver
  89.         };
  90.     }

  91.     /** {@inheritDoc} */
  92.     @Override
  93.     public Vector3D radiationPressureAcceleration(final AbsoluteDate date, final Frame frame, final Vector3D position,
  94.                                                   final Rotation rotation, final double mass, final Vector3D flux,
  95.                                                   final double[] parameters) {
  96.         final double ca = parameters[0];
  97.         final double cs = parameters[1];
  98.         final double kP = crossSection * (1 + 4 * (1.0 - ca - cs) / 9.0);
  99.         return new Vector3D(kP / mass, flux);
  100.     }

  101.     /** {@inheritDoc} */
  102.     @Override
  103.     public <T extends RealFieldElement<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.         throws OrekitException {
  110.         final T ca = parameters[0];
  111.         final T cs = parameters[1];
  112.         final T kP = ca.add(cs).negate().add(1).multiply(4.0 / 9.0).add(1).multiply(crossSection);
  113.         return new FieldVector3D<>(mass.reciprocal().multiply(kP), flux);
  114.     }

  115.     /** {@inheritDoc} */
  116.     @Override
  117.     public FieldVector3D<DerivativeStructure> radiationPressureAcceleration(final AbsoluteDate date, final Frame frame, final Vector3D position,
  118.                                                                             final Rotation rotation, final double mass,
  119.                                                                             final Vector3D flux, final double[] parameters,
  120.                                                                             final String paramName)
  121.         throws OrekitException {

  122.         final DerivativeStructure caDS;
  123.         final DerivativeStructure csDS;
  124.         if (ABSORPTION_COEFFICIENT.equals(paramName)) {
  125.             caDS = factory.variable(0, parameters[0]);
  126.             csDS = factory.constant(parameters[1]);
  127.         } else if (REFLECTION_COEFFICIENT.equals(paramName)) {
  128.             caDS = factory.constant(parameters[0]);
  129.             csDS = factory.variable(0, parameters[1]);
  130.         } else {
  131.             throw new OrekitException(OrekitMessages.UNSUPPORTED_PARAMETER_NAME, paramName,
  132.                                       ABSORPTION_COEFFICIENT + ", " + REFLECTION_COEFFICIENT);
  133.         }

  134.         final DerivativeStructure kP =
  135.                 caDS.add(csDS).subtract(1).multiply(-4.0 / 9.0).add(1).multiply(crossSection);
  136.         return new FieldVector3D<>(kP.divide(mass), flux);

  137.     }

  138. }