AbstractIndirectShooting.java

  1. /* Copyright 2022-2024 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.control.indirect.shooting;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.analysis.differentiation.Gradient;
  21. import org.hipparchus.ode.FieldODEIntegrator;
  22. import org.hipparchus.ode.ODEIntegrator;
  23. import org.orekit.control.indirect.shooting.propagation.ShootingPropagationSettings;
  24. import org.orekit.forces.ForceModel;
  25. import org.orekit.forces.gravity.NewtonianAttraction;
  26. import org.orekit.orbits.FieldOrbit;
  27. import org.orekit.orbits.Orbit;
  28. import org.orekit.propagation.FieldSpacecraftState;
  29. import org.orekit.propagation.SpacecraftState;
  30. import org.orekit.propagation.conversion.FieldODEIntegratorBuilder;
  31. import org.orekit.propagation.conversion.ODEIntegratorBuilder;
  32. import org.orekit.propagation.integration.AdditionalDerivativesProvider;
  33. import org.orekit.propagation.integration.FieldAdditionalDerivativesProvider;
  34. import org.orekit.propagation.numerical.FieldNumericalPropagator;
  35. import org.orekit.propagation.numerical.NumericalPropagator;

  36. /**
  37.  * Abstract class for indirect shooting methods with numerical propagation.
  38.  *
  39.  * @author Romain Serra
  40.  * @since 12.2
  41.  */
  42. public abstract class AbstractIndirectShooting {

  43.     /** Default value for convergence tolerance on mass adjoint variable. */
  44.     public static final double DEFAULT_TOLERANCE_MASS_ADJOINT = 1e-10;

  45.     /** Propagation settings. */
  46.     private final ShootingPropagationSettings propagationSettings;

  47.     /**
  48.      * Constructor.
  49.      * @param propagationSettings propagation settings
  50.      */
  51.     protected AbstractIndirectShooting(final ShootingPropagationSettings propagationSettings) {
  52.         this.propagationSettings = propagationSettings;
  53.     }

  54.     /**
  55.      * Getter for the propagation settings.
  56.      * @return propagation settings
  57.      */
  58.     public ShootingPropagationSettings getPropagationSettings() {
  59.         return propagationSettings;
  60.     }

  61.     /**
  62.      * Solve for the boundary conditions, given an initial mass and an initial guess for the adjoint variables.
  63.      * @param initialMass initial mass
  64.      * @param initialGuess initial guess
  65.      * @return boundary problem solution
  66.      */
  67.     public abstract ShootingBoundaryOutput solve(double initialMass, double[] initialGuess);

  68.     /**
  69.      * Create numerical propagator.
  70.      * @param initialState initial state
  71.      * @return numerical propagator
  72.      */
  73.     protected NumericalPropagator buildPropagator(final SpacecraftState initialState) {
  74.         final ODEIntegrator integrator = buildIntegrator(initialState);
  75.         final NumericalPropagator propagator =
  76.               new NumericalPropagator(integrator, propagationSettings.getAttitudeProvider());
  77.         propagator.setIgnoreCentralAttraction(true);
  78.         propagator.setInitialState(initialState);
  79.         propagator.setIgnoreCentralAttraction(false);
  80.         propagator.removeForceModels();
  81.         if (initialState.isOrbitDefined()) {
  82.             propagator.setOrbitType(initialState.getOrbit().getType());
  83.         } else {
  84.             if (propagationSettings.getForceModels().stream().noneMatch(NewtonianAttraction.class::isInstance)) {
  85.                 propagator.setIgnoreCentralAttraction(true);
  86.             }
  87.             propagator.setOrbitType(null);
  88.         }
  89.         for (final ForceModel forceModel: propagationSettings.getForceModels()) {
  90.             propagator.addForceModel(forceModel);
  91.         }
  92.         final AdditionalDerivativesProvider derivativesProvider = propagationSettings.getAdjointDynamicsProvider()
  93.                 .buildAdditionalDerivativesProvider();
  94.         propagator.addAdditionalDerivativesProvider(derivativesProvider);
  95.         return propagator;
  96.     }

  97.     /**
  98.      * Create integrator.
  99.      * @param initialState initial state
  100.      * @return integrator
  101.      */
  102.     private ODEIntegrator buildIntegrator(final SpacecraftState initialState) {
  103.         final ODEIntegratorBuilder integratorBuilder = propagationSettings.getIntegrationSettings().getIntegratorBuilder();
  104.         if (initialState.isOrbitDefined()) {
  105.             final Orbit orbit = initialState.getOrbit();
  106.             return integratorBuilder.buildIntegrator(orbit, orbit.getType());
  107.         } else {
  108.             return integratorBuilder.buildIntegrator(initialState.getAbsPVA());
  109.         }
  110.     }

  111.     /**
  112.      * Create Gradient numerical propagator.
  113.      * @param initialState initial state
  114.      * @return numerical propagator.
  115.      */
  116.     protected FieldNumericalPropagator<Gradient> buildFieldPropagator(final FieldSpacecraftState<Gradient> initialState) {
  117.         final Field<Gradient> field = initialState.getDate().getField();
  118.         final FieldODEIntegrator<Gradient> integrator = buildFieldIntegrator(initialState);
  119.         final FieldNumericalPropagator<Gradient> propagator =
  120.               new FieldNumericalPropagator<>(field, integrator, propagationSettings.getAttitudeProvider());
  121.         propagator.setIgnoreCentralAttraction(true);
  122.         propagator.removeForceModels();
  123.         propagator.setInitialState(initialState);
  124.         propagator.setIgnoreCentralAttraction(false);
  125.         if (initialState.isOrbitDefined()) {
  126.             propagator.setOrbitType(initialState.getOrbit().getType());
  127.         } else {
  128.             propagator.setOrbitType(null);
  129.             if (propagationSettings.getForceModels().stream().noneMatch(NewtonianAttraction.class::isInstance)) {
  130.                 propagator.setIgnoreCentralAttraction(true);
  131.             }
  132.         }
  133.         for (final ForceModel forceModel: propagationSettings.getForceModels()) {
  134.             propagator.addForceModel(forceModel);
  135.         }
  136.         final FieldAdditionalDerivativesProvider<Gradient> derivativesProvider = propagationSettings.getAdjointDynamicsProvider()
  137.             .buildFieldAdditionalDerivativesProvider(field);
  138.         propagator.addAdditionalDerivativesProvider(derivativesProvider);
  139.         return propagator;
  140.     }

  141.     /**
  142.      * Create Field integrator.
  143.      * @param initialState initial state
  144.      * @param <T> field type
  145.      * @return integrator.
  146.      */
  147.     private <T extends CalculusFieldElement<T>> FieldODEIntegrator<T> buildFieldIntegrator(final FieldSpacecraftState<T> initialState) {
  148.         final FieldODEIntegratorBuilder<T> integratorBuilder = propagationSettings.getIntegrationSettings()
  149.             .getFieldIntegratorBuilder(initialState.getMass().getField());
  150.         if (initialState.isOrbitDefined()) {
  151.             final FieldOrbit<T> orbit = initialState.getOrbit();
  152.             return integratorBuilder.buildIntegrator(orbit, orbit.getType());
  153.         } else {
  154.             return integratorBuilder.buildIntegrator(initialState.getAbsPVA());
  155.         }
  156.     }
  157. }