diff --git a/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java b/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java
index 36bec620901515bb2b8bb13ebb2fc78db286f9a3..745bba459326ed0db9ad296369b893c86694a7f0 100644
--- a/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java
+++ b/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java
@@ -17,14 +17,12 @@
 package org.orekit.propagation;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
-import java.util.stream.Collectors;
 
 import org.hipparchus.CalculusFieldElement;
 import org.hipparchus.Field;
@@ -33,10 +31,9 @@ import org.orekit.errors.OrekitException;
 import org.orekit.errors.OrekitMessages;
 import org.orekit.frames.Frame;
 import org.orekit.propagation.sampling.FieldStepHandlerMultiplexer;
-import org.orekit.time.AbsoluteDate;
 import org.orekit.time.FieldAbsoluteDate;
 import org.orekit.utils.FieldArrayDictionary;
-import org.orekit.utils.TimeSpanMap;
+import org.orekit.utils.FieldTimeSpanMap;
 import org.orekit.utils.TimeStampedFieldPVCoordinates;
 
 /** Common handling of {@link Propagator} methods for analytical propagators.
@@ -59,13 +56,11 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
     /** Attitude provider. */
     private AttitudeProvider attitudeProvider;
 
-    /** Closed form generators.
-     * @since 11.1
-     */
-    private final List<FieldStackableGenerator<T>> closedFormGenerators;
+    /** Additional state providers. */
+    private final List<FieldAdditionalStateProvider<T>> additionalStateProviders;
 
-    /** States managed by no generators. */
-    private final Map<String, TimeSpanMap<T[]>> unmanagedStates;
+    /** States managed by neither additional equations nor state providers. */
+    private final Map<String, FieldTimeSpanMap<T[], T>> unmanagedStates;
 
     /** Field used.*/
     private final Field<T> field;
@@ -77,10 +72,10 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
      * @param field setting the field
      */
     protected FieldAbstractPropagator(final Field<T> field) {
-        this.field      = field;
-        multiplexer     = new FieldStepHandlerMultiplexer<>();
-        closedFormGenerators        = new ArrayList<>();
-        unmanagedStates = new HashMap<>();
+        this.field               = field;
+        multiplexer              = new FieldStepHandlerMultiplexer<>();
+        additionalStateProviders = new ArrayList<>();
+        unmanagedStates          = new HashMap<>();
     }
 
     /** Set a start date.
@@ -135,47 +130,29 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
     }
 
     /** {@inheritDoc} */
-    @Deprecated
-    @Override
     public void addAdditionalStateProvider(final FieldAdditionalStateProvider<T> additionalStateProvider) {
-        addClosedFormGenerator(new FieldAdditionalStateProviderAdapter<>(additionalStateProvider));
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("deprecation")
-    @Deprecated
-    @Override
-    public List<FieldAdditionalStateProvider<T>> getAdditionalStateProviders() {
-        return getClosedFormGenerators().
-                        stream().
-                        map(u -> new FieldClosedFormAdapter<>(u)).
-                        collect(Collectors.toList());
-    }
-
-    /** {@inheritDoc} */
-    public void addClosedFormGenerator(final FieldStackableGenerator<T> generator) {
 
         // check if the name is already used
-        if (isAdditionalStateManaged(generator.getName())) {
+        if (isAdditionalStateManaged(additionalStateProvider.getName())) {
             // this additional state is already registered, complain
             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
-                                      generator.getName());
+                                      additionalStateProvider.getName());
         }
 
         // this is really a new name, add it
-        closedFormGenerators.add(generator);
+        additionalStateProviders.add(additionalStateProvider);
 
     }
 
     /** {@inheritDoc} */
-    public List<FieldStackableGenerator<T>> getClosedFormGenerators() {
-        return Collections.unmodifiableList(closedFormGenerators);
+    public List<FieldAdditionalStateProvider<T>> getAdditionalStateProviders() {
+        return Collections.unmodifiableList(additionalStateProviders);
     }
 
     /** Update state by adding unmanaged states.
      * @param original original state
      * @return updated state, with unmanaged states included
-     * @see #updateAdditionalStates(FieldSpacecraftState)
+     * @see #updateAdditionalStates(SpacecraftState)
      */
     protected FieldSpacecraftState<T> updateUnmanagedStates(final FieldSpacecraftState<T> original) {
 
@@ -184,59 +161,45 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
         FieldSpacecraftState<T> updated = original;
 
         // update the states not managed by providers
-        for (final Map.Entry<String, TimeSpanMap<T[]>> entry : unmanagedStates.entrySet()) {
+        for (final Map.Entry<String, FieldTimeSpanMap<T[], T>> entry : unmanagedStates.entrySet()) {
             updated = updated.addAdditionalState(entry.getKey(),
-                                                 entry.getValue().get(original.getDate().toAbsoluteDate()));
+                                                 entry.getValue().get(original.getDate()));
         }
 
         return updated;
 
     }
 
-    /** Get all generators.
-     * @return all generators
-     * @since 11.1
-     */
-    protected Collection<FieldStackableGenerator<T>> getAllGenerators() {
-        return closedFormGenerators;
-    }
-
     /** Update state by adding all additional states.
      * @param original original state
      * @return updated state, with all additional states included
-     * (including {@link #updateUnmanagedStates(FieldSpacecraftState) unmanaged} states)
-     * @see #addClosedFormGenerator(FieldStackableGenerator)
-     * @see #updateUnmanagedStates(FieldSpacecraftState)
+     * @see #addAdditionalStateProvider(FieldAdditionalStateProvider)
      */
     protected FieldSpacecraftState<T> updateAdditionalStates(final FieldSpacecraftState<T> original) {
 
         // start with original state and unmanaged states
         FieldSpacecraftState<T> updated = updateUnmanagedStates(original);
 
-        // set up queue for generators
-        final Queue<FieldStackableGenerator<T>> pending = new LinkedList<>(getAllGenerators());
+        // set up queue for providers
+        final Queue<FieldAdditionalStateProvider<T>> pending = new LinkedList<>(getAdditionalStateProviders());
 
-        // update the additional states managed by generators, taking care of dependencies
+        // update the additional states managed by providers, taking care of dependencies
         int yieldCount = 0;
         while (!pending.isEmpty()) {
-            final FieldStackableGenerator<T> generator = pending.remove();
-            if (generator.yield(updated)) {
+            final FieldAdditionalStateProvider<T> provider = pending.remove();
+            if (provider.yield(updated)) {
                 // this generator has to wait for another one,
                 // we put it again in the pending queue
-                pending.add(generator);
+                pending.add(provider);
                 if (++yieldCount >= pending.size()) {
-                    // all pending generators yielded!, they probably need data not yet initialized
+                    // all pending providers yielded!, they probably need data not yet initialized
                     // we let the propagation proceed, if these data are really needed right now
                     // an appropriate exception will be triggered when caller tries to access them
                     break;
                 }
             } else {
-                // we can use this generator right now
-                if (generator.isClosedForm()) {
-                    updated = updated.addAdditionalState(generator.getName(), generator.generate(updated));
-                } else {
-                    updated = updated.addAdditionalStateDerivative(generator.getName(), generator.generate(updated));
-                }
+                // we can use this provider right now
+                updated    = updated.addAdditionalState(provider.getName(), provider.getAdditionalState(updated));
                 yieldCount = 0;
             }
         }
@@ -247,7 +210,7 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
 
     /** {@inheritDoc} */
     public boolean isAdditionalStateManaged(final String name) {
-        for (final FieldStackableGenerator<T> provider : closedFormGenerators) {
+        for (final FieldAdditionalStateProvider<T> provider : additionalStateProviders) {
             if (provider.getName().equals(name)) {
                 return true;
             }
@@ -257,9 +220,9 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
 
     /** {@inheritDoc} */
     public String[] getManagedAdditionalStates() {
-        final String[] managed = new String[closedFormGenerators.size()];
+        final String[] managed = new String[additionalStateProviders.size()];
         for (int i = 0; i < managed.length; ++i) {
-            managed[i] = closedFormGenerators.get(i).getName();
+            managed[i] = additionalStateProviders.get(i).getName();
         }
         return managed;
     }
@@ -292,7 +255,9 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
                 if (!isAdditionalStateManaged(initial.getKey())) {
                     // this additional state is in the initial state, but is unknown to the propagator
                     // we store it in a way event handlers may change it
-                    unmanagedStates.put(initial.getKey(), new TimeSpanMap<>(initial.getValue()));
+                    unmanagedStates.put(initial.getKey(),
+                                        new FieldTimeSpanMap<>(initial.getValue(),
+                                                               initialState.getDate().getField()));
                 }
             }
         }
@@ -302,10 +267,10 @@ public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>>
      * @param state new state
      */
     protected void stateChanged(final FieldSpacecraftState<T> state) {
-        final AbsoluteDate date    = state.getDate().toAbsoluteDate();
-        final boolean      forward = date.durationFrom(getStartDate().toAbsoluteDate()) >= 0.0;
+        final FieldAbsoluteDate<T> date    = state.getDate();
+        final boolean              forward = date.durationFrom(getStartDate()).getReal() >= 0.0;
         for (final  FieldArrayDictionary<T>.Entry changed : state.getAdditionalStatesValues().getData()) {
-            final TimeSpanMap<T[]> tsm = unmanagedStates.get(changed.getKey());
+            final FieldTimeSpanMap<T[], T> tsm = unmanagedStates.get(changed.getKey());
             if (tsm != null) {
                 // this is an unmanaged state
                 if (forward) {
diff --git a/src/main/java/org/orekit/propagation/FieldAdditionalStateProvider.java b/src/main/java/org/orekit/propagation/FieldAdditionalStateProvider.java
index a23906e81877a52efe4a23162f41ceb53d3bf62c..9c0da756d297a5ecdb6951e604df5117f376b875 100644
--- a/src/main/java/org/orekit/propagation/FieldAdditionalStateProvider.java
+++ b/src/main/java/org/orekit/propagation/FieldAdditionalStateProvider.java
@@ -20,17 +20,57 @@ import org.hipparchus.CalculusFieldElement;
 
 /** This interface represents providers for additional state data beyond {@link SpacecraftState}.
  * <p>
- * This interface is the analytical (read already integrated) counterpart of
- * the {@link org.orekit.propagation.integration.AdditionalEquations} interface.
- * It allows to append various additional state parameters to any {@link
- * org.orekit.propagation.AbstractPropagator abstract propagator}.
+ * {@link FieldPropagator Propagators} generate {@link fieldSpacecraftState states} that contain at
+ * least orbit, attitude, and mass. These states may however also contain {@link
+ * FieldSpacecraftState#addAdditionalState(String, CalculusFieldElement...) additional states}. Instances of classes
+ * implementing this interface are intended to be registered to propagators so they can add these
+ * additional states incrementally after having computed the basic components
+ * (orbit, attitude and mass).
  * </p>
- * @see org.orekit.propagation.AbstractPropagator
- * @see org.orekit.propagation.integration.AdditionalEquations
+ * <p>
+ * Some additional states may depend on previous additional states to
+ * be already available the before they can be computed. It may even be impossible to compute some
+ * of these additional states at some time if they depend on conditions that are fulfilled only
+ * after propagation as started or some event has occurred. As the propagator builds the complete
+ * state incrementally, looping over the registered providers, it must call their {@link
+ * #getAdditionalState(FieldSpacecraftState) getAdditionalState} methods in an order that fulfill these dependencies that
+ * may be time-dependent and are not related to the order in which the providers are registered to
+ * the propagator. This reordering is performed each time the complete state is built, using a yield
+ * mechanism. The propagator first push all providers in a stack and then empty the stack, one provider
+ * at a time, taking care to select only providers that do <em>not</em> {@link
+ * #yield(SpacecraftState) yield} when asked. Consider for example a case where providers A, B and C
+ * have been registered and provider B needs in fact the additional state generated by state C. Then
+ * when a complete state is built, the propagator puts the three providers, and then starts the incremental
+ * generation of additional states. It first checks provider A which does not yield so it is popped from
+ * the stack and the additional state it generates is added. Then provider B is checked, but it yields
+ * because state from provider C is not yet available. So propagator checks provider C which does not
+ * yield, so it is popped out of the stack and applied. At this stage, provider B is the only remaining one
+ * in the stack, so it is checked again, but this time it does not yield because the state from provider
+ * C is available as it has just been added, so provider B is popped from the stack and applied. The stack
+ * is now empty and the propagator can return the completed state.
+ * </p>
+ * <p>
+ * It is possible that at some stages in the propagation, a subset of the providers registered to a
+ * propagator all yied and cannot {@link #getAdditionalState(FieldSpacecraftState) retrieve} their additional
+ * state. This happens for example during the initialization phase of a propagator that
+ * compute State Transition Matrices or Jacobian matrices. These features are managed as secondary equations
+ * in the ODE integrator, and initialized after the primary equations (which correspond to orbit) have
+ * been initialized. So when the primary equation are initialized, the providers that depend on the secondary
+ * state will all yield. This behavior is expected. Another case occurs when users set up additional states
+ * that induces dependency loop (state A depending on state B which depends on state C which depends on
+ * state A). In this case, the three corresponding providers will wait for each other and indefinitely yield.
+ * This second case is a deadlock and results from a design error of the additional states management at
+ * application level. The propagator cannot know it in advance if as subset of providers that all yield is
+ * normal or not. So at propagator level, when either situation is detected, the propagator just give up and
+ * returns the most complete state it was able to compute, without generating any error. Errors will indeed
+ * not be triggered in the first case (once the primary equations have been initialized, the secondary
+ * equations will be initialized too), and they will be triggered in the second case as soon as user attempts
+ * to retrieve an additional state that was not added.
+ * </p>
+ * @see org.orekit.propagation.FieldPropagator
+ * @see org.orekit.propagation.integration.FieldAdditionalEquations
  * @author Luc Maisonobe
- * @deprecated as of 11.1, replaced by {@link FieldStackableGenerator}
  */
-@Deprecated
 public interface FieldAdditionalStateProvider<T extends CalculusFieldElement<T>> {
 
     /** Get the name of the additional state.
@@ -38,6 +78,32 @@ public interface FieldAdditionalStateProvider<T extends CalculusFieldElement<T>>
      */
     String getName();
 
+    /** Check if this provider should yield so another provider has an opportunity to add missing parts.
+     * <p>
+     * Decision to yield is often based on an additional state being {@link FieldSpacecraftState#hasAdditionalState(String)
+     * already available} in the provided {@code state} (but it could theoretically also depend on
+     * an additional state derivative being {@link FieldSpacecraftState#hasAdditionalStateDerivative(String)
+     * already available}, or any other criterion). If for example a provider needs the state transition
+     * matrix, it could implement this method as:
+     * </p>
+     * <pre>{@code
+     * public boolean yield(final FieldSpacecraftState state) {
+     *     return !state.getAdditionalStates().containsKey("STM");
+     * }
+     * }</pre>
+     * <p>
+     * The default implementation returns {@code false}, meaning that state data can be
+     * {@link #getAdditionalState(FieldSpacecraftState) generated} immediately.
+     * </p>
+     * @param state state to handle
+     * @return true if this provider should yield so another provider has an opportunity to add missing parts
+     * as the state is incrementally built up
+     * @since 11.1
+     */
+    default boolean yield(FieldSpacecraftState<T> state) {
+        return false;
+    }
+
     /** Get the additional state.
      * @param state spacecraft state to which additional state should correspond
      * @return additional state corresponding to spacecraft state
diff --git a/src/main/java/org/orekit/propagation/FieldAdditionalStateProviderAdapter.java b/src/main/java/org/orekit/propagation/FieldAdditionalStateProviderAdapter.java
deleted file mode 100644
index 966e75e9e0f965b34de74d1a34aac90e82be677e..0000000000000000000000000000000000000000
--- a/src/main/java/org/orekit/propagation/FieldAdditionalStateProviderAdapter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation;
-
-import org.hipparchus.CalculusFieldElement;
-
-/** Adapter from {@link FieldAdditionalStateProvider} to {@link FieldStackableGenerator}.
- * @param <T> type of the field elements
- * @since 11.1
- * @deprecated this adapter is temporary and will be removed when {@link FieldAdditionalStateProvider} is removed
- */
-public class FieldAdditionalStateProviderAdapter<T extends CalculusFieldElement<T>> implements FieldStackableGenerator<T> {
-
-    /** Underlying provider. */
-    private final FieldAdditionalStateProvider<T> provider;
-
-    /** Simple constructor.
-     * @param provider underlying provider
-     */
-    public FieldAdditionalStateProviderAdapter(final FieldAdditionalStateProvider<T> provider) {
-        this.provider = provider;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getName() {
-        return provider.getName();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public T[] generate(final FieldSpacecraftState<T> state) {
-        return provider.getAdditionalState(state);
-    }
-
-}
diff --git a/src/main/java/org/orekit/propagation/FieldClosedFormAdapter.java b/src/main/java/org/orekit/propagation/FieldClosedFormAdapter.java
deleted file mode 100644
index a956cebc8b614b35af7051e3f140091d3a26a970..0000000000000000000000000000000000000000
--- a/src/main/java/org/orekit/propagation/FieldClosedFormAdapter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation;
-
-import org.hipparchus.CalculusFieldElement;
-
-/** Adapter from {@link FieldStackableGenerator} to {@link FieldAdditionalStateProvider}.
- * @param <T> type of the field elements
- * @since 11.1
- * @deprecated this adapter is temporary and will be removed when {@link FieldAdditionalStateProvider} is removed
- */
-public class FieldClosedFormAdapter<T extends CalculusFieldElement<T>> implements FieldAdditionalStateProvider<T> {
-
-    /** Underlying generator. */
-    private final FieldStackableGenerator<T> generator;
-
-    /** Simple constructor.
-     * @param generator underlying generator
-     */
-    public FieldClosedFormAdapter(final FieldStackableGenerator<T> generator) {
-        this.generator = generator;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getName() {
-        return generator.getName();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public T[] getAdditionalState(final FieldSpacecraftState<T> state) {
-        return generator.generate(state);
-    }
-
-}
diff --git a/src/main/java/org/orekit/propagation/FieldPropagator.java b/src/main/java/org/orekit/propagation/FieldPropagator.java
index 5f5e0789a2a73af083b4f861090ec3e444bd925f..db14c32c700e205091f658d4923b9916e6916995 100644
--- a/src/main/java/org/orekit/propagation/FieldPropagator.java
+++ b/src/main/java/org/orekit/propagation/FieldPropagator.java
@@ -18,7 +18,6 @@ package org.orekit.propagation;
 
 import java.util.Collection;
 import java.util.List;
-import java.util.stream.Collectors;
 
 import org.hipparchus.CalculusFieldElement;
 import org.orekit.attitudes.AttitudeProvider;
@@ -142,39 +141,14 @@ public interface FieldPropagator<T extends CalculusFieldElement<T>> extends Fiel
 
     /** Add a set of user-specified state parameters to be computed along with the orbit propagation.
      * @param additionalStateProvider provider for additional state
-     * @deprecated as of 11.1, replaced by {@link #addClosedFormGenerator(FieldStackableGenerator)}
      */
-    @Deprecated
     void addAdditionalStateProvider(FieldAdditionalStateProvider<T> additionalStateProvider);
 
     /** Get an unmodifiable list of providers for additional state.
      * @return providers for the additional states
-     * @deprecated as of 11.1, replaced by {@link #getClosedFormGenerators()}
      */
-    @Deprecated
     List<FieldAdditionalStateProvider<T>> getAdditionalStateProviders();
 
-    /** Add a generator for user-specified state parameters to be computed along with the orbit propagation.
-     * @param generator generator for additional state
-     * @since 11.1
-     */
-    @SuppressWarnings("deprecation")
-    default void addClosedFormGenerator(FieldStackableGenerator<T> generator) {
-        addAdditionalStateProvider(new FieldClosedFormAdapter<>(generator));
-    }
-
-    /** Get an unmodifiable list of generators for additional states.
-     * @return generators for the additional states
-     * @since 11.1
-     */
-    @SuppressWarnings("deprecation")
-    default List<FieldStackableGenerator<T>> getClosedFormGenerators() {
-        return getAdditionalStateProviders().
-                        stream().
-                        map(asp -> new FieldAdditionalStateProviderAdapter<>(asp)).
-                        collect(Collectors.toList());
-    }
-
     /** Check if an additional state is managed.
      * <p>
      * Managed states are states for which the propagators know how to compute
diff --git a/src/main/java/org/orekit/propagation/FieldStackableGenerator.java b/src/main/java/org/orekit/propagation/FieldStackableGenerator.java
deleted file mode 100644
index cf9261bd5f2a3a47b357ac7f1f46218e264a35cf..0000000000000000000000000000000000000000
--- a/src/main/java/org/orekit/propagation/FieldStackableGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation;
-
-import org.hipparchus.CalculusFieldElement;
-
-/** This interface represents one element of a stack used to build up {@link FieldSpacecraftState states}
- * incrementally.
- * <p>
- * {@link FieldPropagator Propagators} generate {@link FieldSpacecraftState states} that contain at
- * least orbit, attitude, and mass. These states may however also contain {@link
- * FieldSpacecraftState#addAdditionalState(String, CalculusFieldElement...) additional states} and {@link
- * FieldSpacecraftState#addAdditionalStateDerivative(String, CalculusFieldElement...) derivatives}. Instances of classes
- * implementing this interface are intended to be registered to propagators so they can add these
- * additional states and derivatives incrementally after having computed the basic components
- * (orbit, attitude and mass).
- * </p>
- * <p>
- * Some additional states or derivatives may depend on previous additional states or derivatives
- * to be already available the before they can be computed. As an example, lets consider Jacobians
- * computation. We may managed the state transition matrix ∂y/∂y₀ as one additional state and
- * each column of the Jacobian matrix ∂y/∂pₘ corresponding to the partial derivatives of state
- * with respect to propagation parameter pₘ (drag coefficient, thrust, coefficient of a parametric
- * acceleration…) as separate additional states. Then the generators managing the time derivatives
- * d(∂y/∂pₘ)/dt depend on the already integrated state transition matrix ∂y/∂y₀ to be available.
- * The propagator builds the complete state incrementally, looping over the registered generators,
- * calling their {@link #generate(FieldSpacecraftState) generate} method and pushing the generated data
- * into the state before iterating to next generator. At each iteration, it uses the {@link
- * #yield(FieldSpacecraftState) yield} method of the candidate generator to check if its {@link
- * #generate(FieldSpacecraftState) generate} method can be called at this iteration or if it should be
- * postponed later in the loop. This allows to satisfy dependencies requirements easily.
- * </p>
- * <p>
- * It is possible that at some stages in the propagation, a subset of the generators registered to a
- * propagator all yied and cannot {@link #generate(FieldSpacecraftState) generate} their additional
- * state or derivative. This happens for example when some additional states are must be integrated.
- * They are managed as secondary equations in the ODE integrator, and initialized after the primary
- * equations (which correspond to orbit) have been initialized. So when the primary
- * equation are initialized, the generators that depend on the secondary state will all yield. This
- * behavior is expected. Another case occurs when users set up additional states that induces
- * dependency loop (state A depending on state B which depends on state C which depends on state A).
- * In this case, the three corresponding generators will wait for each other and indefinitely yield.
- * This second case is not normal. The propagator cannot know it in advance if as subset of generators
- * that all yield is normal or not. So at propagator level, when such a situation is detected, the
- * propagator just give up and returns the most complete state it was able to compute, without
- * generating any error. Errors will indeed not be triggered in the first case (because once the
- * primary equations have been initialized, the secondary equations will be initialized too), and
- * they will be triggered in the second case as soon as user attempts to retrieve an additional
- * state or derivative that was not added.
- * </p>
- * @param <T> type of the field elements
- * @see FieldPropagator
- * @author Luc Maisonobe
- * @since 11.1
- */
-public interface FieldStackableGenerator<T extends CalculusFieldElement<T>> {
-
-    /** Get the name of the additional state or derivative {@link #generate(SpacecraftState) generated}
-     * by the instance.
-     * @return name of the additional state or derivative
-     */
-    String getName();
-
-    /** Check if the generated data is a closed form state or a derivative that needs to be integrated.
-     * @return true if the array {@link #generate(FieldSpacecraftState) generate} returns should be
-     * {@link FieldSpacecraftState#addAdditionalState(String, CalculusFieldElement...) added as a state}, and false if it should be
-     * {@link FieldSpacecraftState#addAdditionalStateDerivative(String, CalculusFieldElement...) added as a derivative}.
-     */
-    default boolean isClosedForm() {
-        return true;
-    }
-
-    /** Check if this generator should yield so another generator has an opportunity to add missing parts.
-     * <p>
-     * Decision to yield is often based on an additional state being {@link FieldSpacecraftState#hasAdditionalState(String)
-     * already available} in the provided {@code state} (but it could theoretically also depend on
-     * an additional state derivative being {@link FieldSpacecraftState#hasAdditionalStateDerivative(String)
-     * already available}, or any other criterion). If for example a generator needs the state transition
-     * matrix, it could implement this method as:
-     * </p>
-     * <pre>{@code
-     * public boolean yield(final FieldSpacecraftState<T> state) {
-     *     return !state.getAdditionalStates().containsKey("STM");
-     * }
-     * }</pre>
-     * <p>
-     * The default implementation returns {@code false}, meaning that state or derivative data can be
-     * {@link #generate(FieldSpacecraftState) generated} immediately.
-     * </p>
-     * @param state state to handle
-     * @return true if this generator should yield so another generator has an opportunity to add missing parts
-     * as the state is incrementally built up
-     */
-    default boolean yield(FieldSpacecraftState<T> state) {
-        return false;
-    }
-
-    /** Generate an additional state or derivative.
-     * @param state original state to use
-     * @return generated state or derivative
-     * @see #isClosedForm()
-     */
-    T[] generate(FieldSpacecraftState<T> state);
-
-}
diff --git a/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java b/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java
index ad9598d635a1a89a511ad84cd41612b90f384fe2..3a3b1cda40f056c61d8bce0cd0ae9d658f99abc5 100644
--- a/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java
+++ b/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java
@@ -37,8 +37,8 @@ import org.orekit.frames.Frame;
 import org.orekit.orbits.FieldOrbit;
 import org.orekit.propagation.BoundedPropagator;
 import org.orekit.propagation.FieldAbstractPropagator;
+import org.orekit.propagation.FieldAdditionalStateProvider;
 import org.orekit.propagation.FieldBoundedPropagator;
-import org.orekit.propagation.FieldStackableGenerator;
 import org.orekit.propagation.FieldEphemerisGenerator;
 import org.orekit.propagation.FieldSpacecraftState;
 import org.orekit.propagation.events.FieldEventDetector;
@@ -443,12 +443,12 @@ public abstract class FieldAbstractAnalyticalPropagator<T extends CalculusFieldE
             }
 
             try {
-                // copy the same additional state generators as the original propagator
-                for (FieldStackableGenerator<T> generator : FieldAbstractAnalyticalPropagator.this.getClosedFormGenerators()) {
-                    addClosedFormGenerator(generator);
+                // copy the same additional state providers as the original propagator
+                for (FieldAdditionalStateProvider<T> provider : FieldAbstractAnalyticalPropagator.this.getAdditionalStateProviders()) {
+                    addAdditionalStateProvider(provider);
                 }
             } catch (OrekitException oe) {
-                // as the generators are already compatible with each other,
+                // as the providers are already compatible with each other,
                 // this should never happen
                 throw new OrekitInternalError(null);
             }
diff --git a/src/main/java/org/orekit/propagation/integration/FieldAbstractIntegratedPropagator.java b/src/main/java/org/orekit/propagation/integration/FieldAbstractIntegratedPropagator.java
index 619c9d795d7ba99450af26725094305801459181..5388401419817df66fdf85bc794283efa206422d 100644
--- a/src/main/java/org/orekit/propagation/integration/FieldAbstractIntegratedPropagator.java
+++ b/src/main/java/org/orekit/propagation/integration/FieldAbstractIntegratedPropagator.java
@@ -17,9 +17,12 @@
 package org.orekit.propagation.integration;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.hipparchus.CalculusFieldElement;
 import org.hipparchus.Field;
@@ -51,7 +54,6 @@ import org.orekit.propagation.FieldAbstractPropagator;
 import org.orekit.propagation.FieldBoundedPropagator;
 import org.orekit.propagation.FieldEphemerisGenerator;
 import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.propagation.FieldStackableGenerator;
 import org.orekit.propagation.PropagationType;
 import org.orekit.propagation.events.FieldEventDetector;
 import org.orekit.propagation.sampling.FieldOrekitStepHandler;
@@ -67,6 +69,11 @@ import org.orekit.utils.FieldArrayDictionary;
  */
 public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldElement<T>> extends FieldAbstractPropagator<T> {
 
+    /** Internal name used for complete secondary state dimension.
+     * @since 11.1
+     */
+    private static final String SECONDARY_DIMENSION = "Orekit-secondary-dimension";
+
     /** Event detectors not related to force models. */
     private final List<FieldEventDetector<T>> detectors;
 
@@ -76,10 +83,13 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
     /** Integrator selected by the user for the orbital extrapolation process. */
     private final FieldODEIntegrator<T> integrator;
 
-    /** Integrable generators.
+    /** Offsets of secondary states managed by {@link AdditionalEquations}.
      * @since 11.1
      */
-    private final List<FieldIntegrableGenerator<T>> integrableGenerators;
+    private final Map<String, Integer> secondaryOffsets;
+
+    /** Additional equations. */
+    private List<FieldAdditionalEquations<T>> additionalEquations;
 
     /** Counter for differential equations calls. */
     private int calls;
@@ -105,12 +115,13 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
      */
     protected FieldAbstractIntegratedPropagator(final Field<T> field, final FieldODEIntegrator<T> integrator, final PropagationType propagationType) {
         super(field);
-        detectors            = new ArrayList<>();
-        ephemerisGenerators  = new ArrayList<>();
-        integrableGenerators = new ArrayList<>();
-        this.integrator      = integrator;
-        this.propagationType = propagationType;
-        this.resetAtEnd      = true;
+        detectors             = new ArrayList<>();
+        ephemerisGenerators   = new ArrayList<>();
+        additionalEquations   = new ArrayList<>();
+        this.secondaryOffsets = new HashMap<>();
+        this.integrator       = integrator;
+        this.propagationType  = propagationType;
+        this.resetAtEnd       = true;
     }
 
     /** Allow/disallow resetting the initial state at end of propagation.
@@ -227,8 +238,8 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
         }
 
         // then look at states we integrate ourselves
-        for (final FieldIntegrableGenerator<T> generator : integrableGenerators) {
-            if (generator.getName().equals(name)) {
+        for (final FieldAdditionalEquations<T> equation : additionalEquations) {
+            if (equation.getName().equals(name)) {
                 return true;
             }
         }
@@ -240,56 +251,46 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
     @Override
     public String[] getManagedAdditionalStates() {
         final String[] alreadyIntegrated = super.getManagedAdditionalStates();
-        final String[] managed = new String[alreadyIntegrated.length + integrableGenerators.size()];
+        final String[] managed = new String[alreadyIntegrated.length + additionalEquations.size()];
         System.arraycopy(alreadyIntegrated, 0, managed, 0, alreadyIntegrated.length);
-        for (int i = 0; i < integrableGenerators.size(); ++i) {
-            managed[i + alreadyIntegrated.length] = integrableGenerators.get(i).getName();
+        for (int i = 0; i < additionalEquations.size(); ++i) {
+            managed[i + alreadyIntegrated.length] = additionalEquations.get(i).getName();
         }
         return managed;
     }
 
     /** Add a set of user-specified equations to be integrated along with the orbit propagation.
      * @param additional additional equations
-     * @deprecated as of 11.1, replaced by {@link #addIntegrableGenerator(FieldIntegrableGenerator)}
      */
-    @Deprecated
     public void addAdditionalEquations(final FieldAdditionalEquations<T> additional) {
-        addIntegrableGenerator(new FieldAdditionalEquationAdapter<>(additional));
-    }
-
-    /** Add an generator for user-specified state parameters to be integrated along with the orbit propagation.
-     * @param generator generator for additional state
-     * @see #addClosedFormGenerator(FieldStackableGenerator)
-     * @since 11.1
-     */
-    public void addIntegrableGenerator(final FieldIntegrableGenerator<T> generator) {
 
         // check if the name is already used
-        if (isAdditionalStateManaged(generator.getName())) {
+        if (isAdditionalStateManaged(additional.getName())) {
             // this set of equations is already registered, complain
             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
-                                      generator.getName());
+                                      additional.getName());
         }
 
         // this is really a new set of equations, add it
-        integrableGenerators.add(generator);
+        // FIXME: the following if statement should be removed in 12.0
+        // when the dummy default implementation of AdditionalEquations.getDimension() is removed
+        if (additional.getDimension() < 0) {
+            // the additional equation does not implement getDimension by itself, we wrap it
+            additionalEquations.add(new AdditionalEquationsWrapper(additional));
+        } else {
+            additionalEquations.add(additional);
+        }
+
+        secondaryOffsets.clear();
 
     }
 
-    /** Get an unmodifiable list of generators for additional state.
-     * @return generators for the additional states
+    /** Get an unmodifiable list of equations for additional state.
+     * @return equations for the additional states
      * @since 11.1
      */
-    public List<FieldIntegrableGenerator<T>> getIntegrableGenerators() {
-        return Collections.unmodifiableList(integrableGenerators);
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected Collection<FieldStackableGenerator<T>> getAllGenerators() {
-        final List<FieldStackableGenerator<T>> allGenerators = new ArrayList<>(super.getAllGenerators());
-        allGenerators.addAll(integrableGenerators);
-        return allGenerators;
+    public List<FieldAdditionalEquations<T>> getAdditionalEquations() {
+        return Collections.unmodifiableList(additionalEquations);
     }
 
     /** {@inheritDoc} */
@@ -454,10 +455,16 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
                                                         mathFinalState.getPrimaryState(),
                                                         mathFinalState.getPrimaryDerivative(),
                                                         propagationType);
-            for (int i = 0; i < integrableGenerators.size(); ++i) {
-                final T[] secondary = mathFinalState.getSecondaryState(i + 1);
-                finalState = finalState.addAdditionalState(integrableGenerators.get(i).getName(),
-                                                           secondary);
+            if (!additionalEquations.isEmpty()) {
+                final T[] secondary = mathFinalState.getSecondaryState(1);
+                int offset = 0;
+                for (FieldAdditionalEquations<T> equations : additionalEquations) {
+                    finalState = finalState.addAdditionalState(equations.getName(),
+                                                               Arrays.copyOfRange(secondary,
+                                                                                  offset,
+                                                                                  offset + equations.getDimension()));
+                    offset += equations.getDimension();
+                }
             }
             finalState = updateAdditionalStates(finalState);
 
@@ -488,28 +495,69 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
      * @param initialState initial state in flight dynamics world
      * @return initial state in mathematics world
      */
-    @SuppressWarnings("deprecation")
     private FieldODEState<T> createInitialState(final FieldSpacecraftState<T> initialState) {
 
         // retrieve initial state
         final T[] primary  = MathArrays.buildArray(initialState.getA().getField(), getBasicDimension());
         stateMapper.mapStateToArray(initialState, primary, null);
 
-        // secondary part of the ODE
-        final T[][] secondary = MathArrays.buildArray(initialState.getA().getField(), integrableGenerators.size(), -1);
-        for (int i = 0; i < integrableGenerators.size(); ++i) {
-            final FieldIntegrableGenerator<T> generator = integrableGenerators.get(i);
-            final T[] addState = getInitialState().getAdditionalState(generator.getName());
-            secondary[i] = MathArrays.buildArray(initialState.getA().getField(), addState.length);
-            for (int j = 0; j < addState.length; j++) {
-                secondary[i][j] = addState[j];
-            }
-            if (generator instanceof FieldAdditionalEquationAdapter) {
-                ((FieldAdditionalEquationAdapter<T>) generator).setDimension(secondary[i].length);
+        if (secondaryOffsets.isEmpty()) {
+            // compute dimension of the secondary state
+            int offset = 0;
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                secondaryOffsets.put(equations.getName(), offset);
+                offset += equations.getDimension();
             }
+            secondaryOffsets.put(SECONDARY_DIMENSION, offset);
         }
 
-        return new FieldODEState<>(initialState.getA().getField().getZero(), primary, secondary);
+        return new FieldODEState<>(initialState.getA().getField().getZero(), primary, secondary(initialState));
+
+    }
+
+    /** Create secondary state.
+     * @param state spacecraft state
+     * @return secondary state
+     * @since 11.1
+     */
+    private T[][] secondary(final FieldSpacecraftState<T> state) {
+
+        if (secondaryOffsets.isEmpty()) {
+            return null;
+        }
+
+        final T[][] secondary = MathArrays.buildArray(state.getDate().getField(), 1, secondaryOffsets.get(SECONDARY_DIMENSION));
+        for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+            final String name       = equations.getName();
+            final int    offset     = secondaryOffsets.get(name);
+            final T[]    additional = state.getAdditionalState(name);
+            System.arraycopy(additional, 0, secondary[0], offset, additional.length);
+        }
+
+        return secondary;
+
+    }
+
+    /** Create secondary state derivative.
+     * @param state spacecraft state
+     * @return secondary state derivative
+     * @since 11.1
+     */
+    private T[][] secondaryDerivative(final FieldSpacecraftState<T> state) {
+
+        if (secondaryOffsets.isEmpty()) {
+            return null;
+        }
+
+        final T[][] secondaryDerivative = MathArrays.buildArray(state.getDate().getField(), 1, secondaryOffsets.get(SECONDARY_DIMENSION));
+        for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+            final String name       = equations.getName();
+            final int    offset     = secondaryOffsets.get(name);
+            final T[]    additionalDerivative = state.getAdditionalStateDerivative(name);
+            System.arraycopy(additionalDerivative, 0, secondaryDerivative[0], offset, additionalDerivative.length);
+        }
+
+        return secondaryDerivative;
 
     }
 
@@ -525,12 +573,8 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
                 new FieldExpandableODE<>(new ConvertedMainStateEquations(getMainStateEquations(integ)));
 
         // secondary part of the ODE
-        for (int i = 0; i < integrableGenerators.size(); ++i) {
-            final FieldIntegrableGenerator<T> generator = integrableGenerators.get(i);
-            final FieldSecondaryODE<T>        secondary =
-                    new ConvertedSecondaryStateEquations(generator,
-                                                         mathInitialState.getSecondaryStateDimension(i + 1));
-            ode.addSecondaryEquations(secondary);
+        if (!additionalEquations.isEmpty()) {
+            ode.addSecondaryEquations(new ConvertedSecondaryStateEquations());
         }
 
         return ode;
@@ -578,24 +622,27 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
      * @return space flight dynamics state
      */
     private FieldSpacecraftState<T> convert(final FieldODEStateAndDerivative<T> os) {
-        try {
 
-            FieldSpacecraftState<T> s =
-                    stateMapper.mapArrayToState(os.getTime(),
-                                                os.getPrimaryState(),
-                                                os.getPrimaryDerivative(),
-                                                propagationType);
-            for (int i = 0; i < integrableGenerators.size(); ++i) {
-                final T[] secondary = os.getSecondaryState(i + 1);
-                s = s.addAdditionalState(integrableGenerators.get(i).getName(), secondary);
+        FieldSpacecraftState<T> s =
+                        stateMapper.mapArrayToState(os.getTime(),
+                                                    os.getPrimaryState(),
+                                                    os.getPrimaryDerivative(),
+                                                    propagationType);
+        if (os.getNumberOfSecondaryStates() > 0) {
+            final T[] secondary           = os.getSecondaryState(1);
+            final T[] secondaryDerivative = os.getSecondaryDerivative(1);
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                final String name      = equations.getName();
+                final int    offset    = secondaryOffsets.get(name);
+                final int    dimension = equations.getDimension();
+                s = s.addAdditionalState(name, Arrays.copyOfRange(secondary, offset, offset + dimension));
+                s = s.addAdditionalStateDerivative(name, Arrays.copyOfRange(secondaryDerivative, offset, offset + dimension));
             }
-            s = updateAdditionalStates(s);
+        }
+        s = updateAdditionalStates(s);
 
-            return s;
+        return s;
 
-        } catch (OrekitException oe) {
-            throw new OrekitException(oe);
-        }
     }
 
     /** Convert a state from space flight dynamics world to mathematical world.
@@ -610,15 +657,12 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
         stateMapper.mapStateToArray(state, primary, primaryDot);
 
         // secondary part of the ODE
-        final T[][] secondary    = MathArrays.buildArray(getField(), integrableGenerators.size(), -1);
-        for (int i = 0; i < integrableGenerators.size(); ++i) {
-            final FieldIntegrableGenerator<T> generator = integrableGenerators.get(i);
-            secondary[i] = state.getAdditionalState(generator.getName());
-        }
+        final T[][] secondary           = secondary(state);
+        final T[][] secondaryDerivative = secondaryDerivative(state);
 
         return new FieldODEStateAndDerivative<>(stateMapper.mapDateToDouble(state.getDate()),
                                                 primary, primaryDot,
-                                                secondary, null);
+                                                secondary, secondaryDerivative);
 
     }
 
@@ -692,26 +736,19 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
     /** Differential equations for the secondary state (Jacobians, user variables ...), with converted API. */
     private class ConvertedSecondaryStateEquations implements FieldSecondaryODE<T> {
 
-        /** Integrable generator. */
-        private final FieldIntegrableGenerator<T> generator;
-
-        /** Dimension of the additional state. */
-        private final int dimension;
+        /** Dimension of the combined additional states. */
+        private final int combinedDimension;
 
         /** Simple constructor.
-         * @param generator differential equations in the form of an integrable generator
-         * @param dimension dimension of the additional state
          */
-        ConvertedSecondaryStateEquations(final FieldIntegrableGenerator<T> generator,
-                                         final int dimension) {
-            this.generator = generator;
-            this.dimension = dimension;
+        ConvertedSecondaryStateEquations() {
+            this.combinedDimension = secondaryOffsets.get(SECONDARY_DIMENSION);
         }
 
         /** {@inheritDoc} */
         @Override
         public int getDimension() {
-            return dimension;
+            return combinedDimension;
         }
 
         /** {@inheritDoc} */
@@ -719,11 +756,13 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
         public void init(final T t0, final T[] primary0,
                          final T[] secondary0, final T finalTime) {
             // update space dynamics view
-            FieldSpacecraftState<T> initialState = stateMapper.mapArrayToState(t0, primary0, null, PropagationType.MEAN);
-            initialState = initialState.addAdditionalState(generator.getName(), secondary0);
-            initialState = updateAdditionalStates(initialState);
+            final FieldSpacecraftState<T> initialState = convert(t0, primary0, null, secondary0);
+
             final FieldAbsoluteDate<T> target = stateMapper.mapDoubleToDate(finalTime);
-            generator.init(initialState, target);
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                equations.init(initialState, target);
+            }
+
         }
 
         /** {@inheritDoc} */
@@ -732,11 +771,44 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
                                       final T[] primaryDot, final T[] secondary) {
 
             // update space dynamics view
-            FieldSpacecraftState<T> currentState = stateMapper.mapArrayToState(t, primary, primaryDot, PropagationType.MEAN);
-            currentState = currentState.addAdditionalState(generator.getName(), secondary);
-            currentState = updateAdditionalStates(currentState);
+            // the integrable generators generate method will be called here,
+            // according to the generators yield order
+            final FieldSpacecraftState<T> currentState = convert(t, primary, primaryDot, secondary);
+
+            // gather the derivatives from all integrable generators
+            final T[] secondaryDot = MathArrays.buildArray(t.getField(), combinedDimension);
+            // FIXME: use yield to compute derivatives in dependencies order
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                final String name      = equations.getName();
+                final int    offset    = secondaryOffsets.get(name);
+                final int    dimension = equations.getDimension();
+                System.arraycopy(equations.derivatives(currentState), 0, secondaryDot, offset, dimension);
+            }
+
+            return secondaryDot;
+
+        }
 
-            return currentState.getAdditionalStateDerivative(generator.getName());
+        /** Convert mathematical view to space view.
+         * @param t current value of the independent <I>time</I> variable
+         * @param primary array containing the current value of the primary state vector
+         * @param primaryDot array containing the derivative of the primary state vector
+         * @param secondary array containing the current value of the secondary state vector
+         * @return space view of the state
+         */
+        private FieldSpacecraftState<T> convert(final T t, final T[] primary,
+                                                final T[] primaryDot, final T[] secondary) {
+
+            FieldSpacecraftState<T> initialState = stateMapper.mapArrayToState(t, primary, primaryDot, PropagationType.MEAN);
+
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                final String name      = equations.getName();
+                final int    offset    = secondaryOffsets.get(name);
+                final int    dimension = equations.getDimension();
+                initialState = initialState.addAdditionalState(name, Arrays.copyOfRange(secondary, offset, offset + dimension));
+            }
+
+            return updateAdditionalStates(initialState);
 
         }
 
@@ -800,13 +872,12 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
             stateMapper.mapStateToArray(newState, primary, null);
 
             // secondary part
-            final T[][] secondary = MathArrays.buildArray(getField(), integrableGenerators.size(), -1);
-
-            for (int i = 0; i < integrableGenerators.size(); ++i) {
-                final FieldIntegrableGenerator<T> generator = integrableGenerators.get(i);
-                final T[] si = newState.getAdditionalState(generator.getName());
-                secondary[i] = MathArrays.buildArray(getField(), si.length);
-                System.arraycopy(si, 0, secondary[i], 0, si.length);
+            final T[][] secondary = MathArrays.buildArray(getField(), 1, additionalEquations.size());
+            for (final FieldAdditionalEquations<T> equations : additionalEquations) {
+                final String name      = equations.getName();
+                final int    offset    = secondaryOffsets.get(name);
+                final int    dimension = equations.getDimension();
+                System.arraycopy(newState.getAdditionalState(name), 0, secondary[0], offset, dimension);
             }
 
             return new FieldODEState<>(newState.getDate().durationFrom(getStartDate()),
@@ -983,15 +1054,15 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
             }
 
             // get the names of additional states managed by differential equations
-            final String[] names = new String[integrableGenerators.size()];
+            final String[] names = new String[additionalEquations.size()];
             for (int i = 0; i < names.length; ++i) {
-                names[i] = integrableGenerators.get(i).getName();
+                names[i] = additionalEquations.get(i).getName();
             }
 
             // create the ephemeris
             ephemeris = new FieldIntegratedEphemeris<>(startDate, minDate, maxDate,
                                                        stateMapper, propagationType, model,
-                                                       unmanaged, getClosedFormGenerators(), names);
+                                                       unmanaged, getAdditionalStateProviders(), names);
 
         }
 
@@ -1052,4 +1123,62 @@ public abstract class FieldAbstractIntegratedPropagator<T extends CalculusFieldE
 
     }
 
+    /** Temporary wrapper for {@link AdditionalEquations} that do not implement getDimension().
+     * @since 11.1
+     * @deprecated introduced in 11.1 as a temporary workaround for missing getDimension, must be removed in 12.0
+     */
+    @Deprecated
+    private class AdditionalEquationsWrapper implements FieldAdditionalEquations<T> {
+
+        /** Wrapped equations. */
+        private final FieldAdditionalEquations<T> equations;
+
+        /** Dimension. */
+        private int dimension;
+
+        /** Simple constructor.
+         * @param equations wrapped equations
+         */
+        AdditionalEquationsWrapper(final FieldAdditionalEquations<T> equations) {
+            this.equations = equations;
+            this.dimension = -1;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public String getName() {
+            return equations.getName();
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public int getDimension() {
+            if (dimension < 0) {
+                // retrieve the dimension the first time we need it
+                dimension = getInitialState().getAdditionalState(getName()).length;
+            }
+            return dimension;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public boolean yield(final FieldSpacecraftState<T> state) {
+            return equations.yield(state);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target) {
+            equations.init(initialState, target);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public T[] derivatives(final FieldSpacecraftState<T> s) {
+            final T[] pDot = MathArrays.buildArray(s.getDate().getField(), getDimension());
+            computeDerivatives(s, pDot);
+            return pDot;
+        }
+    }
+
 }
diff --git a/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquationAdapter.java b/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquationAdapter.java
deleted file mode 100644
index ec70ae03cb37767397ac8e57a215bf015eda9594..0000000000000000000000000000000000000000
--- a/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquationAdapter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation.integration;
-
-import org.hipparchus.CalculusFieldElement;
-import org.hipparchus.util.MathArrays;
-import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.time.FieldAbsoluteDate;
-
-/** Adapter from {@link FieldAdditionalEquations} to {@link FieldIntegrableGeneratorTest}.
- * @param <T> the type of the field elements
- * @since 11.1
- * @deprecated this adapter is temporary and will be removed when {@link FieldAdditionalEquations} is removed
- */
-public class FieldAdditionalEquationAdapter<T extends CalculusFieldElement<T>> implements FieldIntegrableGenerator<T> {
-
-    /** Underlying equations. */
-    private final FieldAdditionalEquations<T> equations;
-
-    /** Dimension of the equations. */
-    private int dimension;
-
-    /** Simple constructor.
-     * @param equations underlying equations
-     */
-    public FieldAdditionalEquationAdapter(final FieldAdditionalEquations<T> equations) {
-        this.equations = equations;
-    }
-
-    /** Set the dimension.
-     * @param dimension dimension of the equations
-     */
-    void setDimension(final int dimension) {
-        this.dimension = dimension;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String getName() {
-        return equations.getName();
-    }
-
-    /** {@inheritDoc}
-     * <p>
-     * In order to compute the derivative of state {@link #getName()},
-     * we must have the state itself, so we yield if it is not available.
-     * </p>
-     */
-    @Override
-    public  boolean yield(final FieldSpacecraftState<T> state) {
-        return !state.hasAdditionalState(getName());
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target) {
-        equations.init(initialState, target);
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public T[] generate(final FieldSpacecraftState<T> state) {
-        final T[] yDot = MathArrays.buildArray(state.getDate().getField(), dimension);
-        equations.computeDerivatives(state, yDot);
-        return yDot;
-    }
-
-}
diff --git a/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquations.java b/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquations.java
index 8de70df5846cfda36f06fafee0350db1e3f0bb71..e4ff7466753a480c2f6f928033cc538d9625cfd9 100644
--- a/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquations.java
+++ b/src/main/java/org/orekit/propagation/integration/FieldAdditionalEquations.java
@@ -17,7 +17,9 @@
 package org.orekit.propagation.integration;
 
 import org.hipparchus.CalculusFieldElement;
+import org.hipparchus.util.MathArrays;
 import org.orekit.propagation.FieldSpacecraftState;
+import org.orekit.propagation.SpacecraftState;
 import org.orekit.time.FieldAbsoluteDate;
 
 /** This interface allows users to add their own differential equations to a numerical propagator.
@@ -66,6 +68,41 @@ public interface FieldAdditionalEquations<T extends CalculusFieldElement<T>> {
      */
     String getName();
 
+    /** Get the dimension of the generated derivative.
+     * @return dimension of the generated
+     */
+    default int getDimension() {
+        // FIXME: as of 11.1 there is a default implementation that intentionally returns a wrong (negative) size
+        // the default implementation should be removed in 12.0
+        return -1;
+    }
+
+    /** Check if this provider should yield so another provider has an opportunity to add missing parts.
+     * <p>
+     * Decision to yield is often based on an additional state being {@link SpacecraftState#hasAdditionalState(String)
+     * already available} in the provided {@code state} (but it could theoretically also depend on
+     * an additional state derivative being {@link SpacecraftState#hasAdditionalStateDerivative(String)
+     * already available}, or any other criterion). If for example a provider needs the state transition
+     * matrix, it could implement this method as:
+     * </p>
+     * <pre>{@code
+     * public boolean yield(final SpacecraftState state) {
+     *     return !state.getAdditionalStates().containsKey("STM");
+     * }
+     * }</pre>
+     * <p>
+     * The default implementation returns {@code false}, meaning that derivative data can be
+     * {@link #derivatives(SpacecraftState) computed} immediately.
+     * </p>
+     * @param state state to handle
+     * @return true if this provider should yield so another provider has an opportunity to add missing parts
+     * as the state is incrementally built up
+     * @since 11.1
+     */
+    default boolean yield(FieldSpacecraftState<T> state) {
+        return false;
+    }
+
     /**
      * Initialize the equations at the start of propagation.
      *
@@ -101,7 +138,27 @@ public interface FieldAdditionalEquations<T extends CalculusFieldElement<T>> {
      * should be put
      * @return cumulative effect of the equations on the main state (may be null if
      * equations do not change main state at all)
+     * @deprecated as of 11.1, replaced by {@link #derivatives(FieldSpacecraftState)}
+     */
+    @Deprecated
+    default T[] computeDerivatives(FieldSpacecraftState<T> s,  T[] pDot) {
+        return null;
+    }
+
+    /** Compute the derivatives related to the additional state parameters.
+     * @param s current state information: date, kinematics, attitude, and
+     * additional states this equations depend on (according to the
+     * {@link #yield(SpacecraftState) yield} method)
+     * @return computed derivatives
+     * @since 11.1
      */
-    T[] computeDerivatives(FieldSpacecraftState<T> s,  T[] pDot);
+    default T[] derivatives(FieldSpacecraftState<T> s) {
+        // FIXME: as of 11.1 there is a default implementation that delegates
+        // to computeDerivatives. This default implementation should be removed when
+        // computeDerivatives is removed in 12.0
+        final T[] pDot = MathArrays.buildArray(s.getDate().getField(), getDimension());
+        computeDerivatives(s, pDot);
+        return pDot;
+    }
 
 }
diff --git a/src/main/java/org/orekit/propagation/integration/FieldIntegrableGenerator.java b/src/main/java/org/orekit/propagation/integration/FieldIntegrableGenerator.java
deleted file mode 100644
index 04989429b3cac7b55cb3d8b29f5d56b733dff759..0000000000000000000000000000000000000000
--- a/src/main/java/org/orekit/propagation/integration/FieldIntegrableGenerator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation.integration;
-
-import org.hipparchus.CalculusFieldElement;
-import org.orekit.propagation.FieldStackableGenerator;
-import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.time.FieldAbsoluteDate;
-
-/** {@link FieldStackableGenerator Stackable generator} relying on integration.
- * @see org.orekit.propagation.Propagator
- * @param <T> the type of the field elements
- * @author Luc Maisonobe
- * @since 11.1
- */
-public interface FieldIntegrableGenerator<T extends CalculusFieldElement<T>> extends FieldStackableGenerator<T> {
-
-    /** {@inheritDoc}
-     * {@link FieldIntegrableGeneratorTest Integrable generator} are not closed form,
-     * so this method returns {@code false}.
-     */
-    @Override
-    default boolean isClosedForm() {
-        return false;
-    }
-
-    /** Initialize the generator at the start of propagation.
-     * @param initialState initial state information at the start of propagation
-     * @param target       date of propagation
-     */
-    default void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target) {
-        // nothing by default
-    }
-
-}
diff --git a/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java b/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
index 9a435d2746db6be8d4a3f3a414f7e393feb68599..0ca187c1b572d934fe3c931830b8bfd8b2917c78 100644
--- a/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
+++ b/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
@@ -19,7 +19,6 @@ package org.orekit.propagation.integration;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 import org.hipparchus.CalculusFieldElement;
 import org.hipparchus.ode.FieldDenseOutputModel;
@@ -28,9 +27,9 @@ import org.orekit.errors.OrekitException;
 import org.orekit.errors.OrekitMessages;
 import org.orekit.frames.Frame;
 import org.orekit.orbits.FieldOrbit;
+import org.orekit.propagation.FieldAdditionalStateProvider;
 import org.orekit.propagation.FieldBoundedPropagator;
 import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.propagation.FieldStackableGenerator;
 import org.orekit.propagation.PropagationType;
 import org.orekit.propagation.analytical.FieldAbstractAnalyticalPropagator;
 import org.orekit.time.FieldAbsoluteDate;
@@ -114,7 +113,6 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
      * FieldAbsoluteDate, FieldAbsoluteDate, FieldStateMapper, PropagationType, FieldDenseOutputModel,
      * List, Map, String[])
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     public FieldIntegratedEphemeris(final FieldAbsoluteDate<T> startDate,
                                final FieldAbsoluteDate<T> minDate, final FieldAbsoluteDate<T> maxDate,
@@ -125,7 +123,7 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
                                final String[] equations) {
         this(startDate, minDate, maxDate, mapper, type, model,
              new FieldArrayDictionary<>(startDate.getField(), unmanaged),
-             providers.stream().map(asp -> new org.orekit.propagation.FieldAdditionalStateProviderAdapter<>(asp)).collect(Collectors.toList()), equations);
+             providers, equations);
     }
 
     /** Creates a new instance of IntegratedEphemeris.
@@ -136,7 +134,7 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
      * @param type type of orbit to output (mean or osculating)
      * @param model underlying raw mathematical model
      * @param unmanaged unmanaged additional states that must be simply copied
-     * @param generators generators for pre-integrated states
+     * @param providers generators for pre-integrated states
      * @param equations names of additional equations
      * @since 11.1
      */
@@ -145,7 +143,7 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
                                     final FieldStateMapper<T> mapper, final PropagationType type,
                                     final FieldDenseOutputModel<T> model,
                                     final FieldArrayDictionary<T> unmanaged,
-                                    final List<FieldStackableGenerator<T>> generators,
+                                    final List<FieldAdditionalStateProvider<T>> providers,
                                     final String[] equations) {
 
         super(startDate.getField(), mapper.getAttitudeProvider());
@@ -158,14 +156,14 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
         this.model     = model;
         this.unmanaged = unmanaged;
 
-        // set up the pre-integrated generators
-        for (final FieldStackableGenerator<T> generator : generators) {
-            addClosedFormGenerator(generator);
+        // set up the pre-integrated providers
+        for (final FieldAdditionalStateProvider<T> provider : providers) {
+            addAdditionalStateProvider(provider);
         }
 
         // set up providers to map the final elements of the model array to additional states
         for (int i = 0; i < equations.length; ++i) {
-            addClosedFormGenerator(new LocalGenerator(equations[i], i));
+            addAdditionalStateProvider(new LocalGenerator(equations[i], i));
         }
 
     }
@@ -265,7 +263,7 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
     }
 
     /** Local generator for additional state data. */
-    private class LocalGenerator implements FieldStackableGenerator<T> {
+    private class LocalGenerator implements FieldAdditionalStateProvider<T> {
 
         /** Name of the additional state. */
         private final String name;
@@ -290,7 +288,7 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
 
         /** {@inheritDoc} */
         @Override
-        public T[] generate(final FieldSpacecraftState<T> state) {
+        public T[] getAdditionalState(final FieldSpacecraftState<T> state) {
 
             // extract the part of the interpolated array corresponding to the additional state
             return getInterpolatedState(state.getDate()).getSecondaryState(index + 1);
diff --git a/src/test/java/org/orekit/propagation/integration/FieldAdditionalEquationsTest.java b/src/test/java/org/orekit/propagation/integration/FieldAdditionalEquationsTest.java
index d14adc4d2b76862ecb67fc893d5d9804a4aa3353..17f85f1681a54ce8645ed29041cc9aea6686bd3e 100644
--- a/src/test/java/org/orekit/propagation/integration/FieldAdditionalEquationsTest.java
+++ b/src/test/java/org/orekit/propagation/integration/FieldAdditionalEquationsTest.java
@@ -16,8 +16,8 @@
  */
 package org.orekit.propagation.integration;
 
-import org.hipparchus.Field;
 import org.hipparchus.CalculusFieldElement;
+import org.hipparchus.Field;
 import org.hipparchus.geometry.euclidean.threed.Vector3D;
 import org.hipparchus.ode.nonstiff.AdaptiveStepsizeFieldIntegrator;
 import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
@@ -38,11 +38,11 @@ import org.orekit.propagation.FieldSpacecraftState;
 import org.orekit.propagation.SpacecraftState;
 import org.orekit.propagation.numerical.FieldNumericalPropagator;
 import org.orekit.propagation.numerical.NumericalPropagator;
+import org.orekit.propagation.semianalytical.dsst.FieldDSSTPropagator;
 import org.orekit.time.AbsoluteDate;
 import org.orekit.time.FieldAbsoluteDate;
 import org.orekit.utils.PVCoordinates;
 
-@Deprecated
 public class FieldAdditionalEquationsTest {
 
     private double                       mu;
@@ -57,11 +57,77 @@ public class FieldAdditionalEquationsTest {
         doTestInitNumerical(Decimal64Field.getInstance());
     }
 
+    /** Test for issue #401
+     *  with a DSST propagator */
+    @Test
+    public void testInitDSST() {
+        doTestInitDSST(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testResetStateT() {
+        doTestResetState(Decimal64Field.getInstance());
+    }
+
     private <T extends CalculusFieldElement<T>> void doTestInitNumerical(Field<T> field) {
         // setup
         final double reference = 1.25;
-        InitCheckerEquations<T> checker = new InitCheckerEquations<>(reference);
-        Assert.assertFalse(checker.wasCalled());
+        final double rate      = 1.5;
+        final double dt        = 600.0;
+        Linear<T> linear = new Linear<>("linear", reference, rate);
+        Assert.assertFalse(linear.wasCalled());
+
+        // action
+        AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 200,
+                                                                                              tolerance[0], tolerance[1]);
+        integrator.setInitialStepSize(60);
+        FieldNumericalPropagator<T> propagatorNumerical = new FieldNumericalPropagator<>(field, integrator);
+        propagatorNumerical.setInitialState(new FieldSpacecraftState<>(field, initialState).
+                                            addAdditionalState(linear.getName(), field.getZero().newInstance(reference)));
+        propagatorNumerical.addAdditionalEquations(linear);
+        FieldSpacecraftState<T> finalState = propagatorNumerical.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(dt));
+
+        // verify
+        Assert.assertTrue(linear.wasCalled());
+        Assert.assertEquals(reference + dt * rate, finalState.getAdditionalState(linear.getName())[0].getReal(), 1.0e-10);
+
+    }
+
+    private <T extends CalculusFieldElement<T>> void doTestInitDSST(Field<T> field) {
+        // setup
+        final double reference = 3.5;
+        final double rate      = 1.5;
+        final double dt        = 600.0;
+        Linear<T> linear = new Linear<>("linear", reference, rate);
+        Assert.assertFalse(linear.wasCalled());
+
+        // action
+        AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 200,
+                                                                                              tolerance[0], tolerance[1]);
+        integrator.setInitialStepSize(60);
+        FieldDSSTPropagator<T> propagatorDSST = new FieldDSSTPropagator<>(field, integrator);
+        propagatorDSST.setInitialState(new FieldSpacecraftState<>(field, initialState).
+                                       addAdditionalState(linear.getName(), field.getZero().newInstance(reference)));
+        propagatorDSST.addAdditionalEquations(linear);
+        FieldSpacecraftState<T> finalState = propagatorDSST.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(dt));
+
+        // verify
+        Assert.assertTrue(linear.wasCalled());
+        Assert.assertEquals(reference + dt * rate, finalState.getAdditionalState(linear.getName())[0].getReal(), 1.0e-10);
+
+    }
+
+    private <T extends CalculusFieldElement<T>> void doTestResetState(Field<T> field) {
+        // setup
+        final double reference1 = 3.5;
+        final double rate1      = 1.5;
+        Linear<T> linear1 = new Linear<>("linear-1", reference1, rate1);
+        Assert.assertFalse(linear1.wasCalled());
+        final double reference2 = 4.5;
+        final double rate2      = 1.25;
+        Linear<T> linear2 = new Linear<>("linear-2", reference2, rate2);
+        Assert.assertFalse(linear2.wasCalled());
+        final double dt = 600;
 
         // action
         AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 200,
@@ -69,12 +135,17 @@ public class FieldAdditionalEquationsTest {
         integrator.setInitialStepSize(60);
         FieldNumericalPropagator<T> propagatorNumerical = new FieldNumericalPropagator<>(field, integrator);
         propagatorNumerical.setInitialState(new FieldSpacecraftState<>(field, initialState).
-                                            addAdditionalState(checker.getName(), field.getZero().add(reference)));
-        propagatorNumerical.addAdditionalEquations(checker);
-        propagatorNumerical.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(600));
+                                            addAdditionalState(linear1.getName(), field.getZero().newInstance(reference1)).
+                                            addAdditionalState(linear2.getName(), field.getZero().newInstance(reference2)));
+        propagatorNumerical.addAdditionalEquations(linear1);
+        propagatorNumerical.addAdditionalEquations(linear2);
+        FieldSpacecraftState<T> finalState = propagatorNumerical.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(dt));
 
         // verify
-        Assert.assertTrue(checker.wasCalled());
+        Assert.assertTrue(linear1.wasCalled());
+        Assert.assertTrue(linear2.wasCalled());
+        Assert.assertEquals(reference1 + dt * rate1, finalState.getAdditionalState(linear1.getName())[0].getReal(), 1.0e-10);
+        Assert.assertEquals(reference2 + dt * rate2, finalState.getAdditionalState(linear2.getName())[0].getReal(), 1.0e-10);
 
     }
 
@@ -99,33 +170,41 @@ public class FieldAdditionalEquationsTest {
         tolerance    = null;
     }
 
-    public static class InitCheckerEquations<T extends CalculusFieldElement<T>> implements FieldAdditionalEquations<T> {
+    public static class Linear<T extends CalculusFieldElement<T>> implements FieldAdditionalEquations<T> {
 
-        private double expected;
+        private String  name;
+        private double  expectedAtInit;
+        private double  rate;
         private boolean called;
 
-        public InitCheckerEquations(final double expected) {
-            this.expected = expected;
-            this.called   = false;
+        public Linear(final String name, final double expectedAtInit, final double rate) {
+            this.name           = name;
+            this.expectedAtInit = expectedAtInit;
+            this.rate           = rate;
+            this.called         = false;
         }
 
         @Override
-        public void init(FieldSpacecraftState<T> initiaState, FieldAbsoluteDate<T> target)
-            {
-            Assert.assertEquals(expected, initiaState.getAdditionalState(getName())[0].getReal(), 1.0e-15);
+        public void init(FieldSpacecraftState<T> initiaState, FieldAbsoluteDate<T> target) {
+            Assert.assertEquals(expectedAtInit, initiaState.getAdditionalState(getName())[0].getReal(), 1.0e-15);
             called = true;
         }
 
         @Override
-        public T[] computeDerivatives(FieldSpacecraftState<T> s, T[] pDot)
-            {
-            pDot[0] = s.getDate().getField().getZero().add(1.5);
-            return MathArrays.buildArray(s.getDate().getField(), 7);
+        public T[] derivatives(FieldSpacecraftState<T> s) {
+            final T[] pDot = MathArrays.buildArray(s.getDate().getField(), 1);
+            pDot[0] = s.getDate().getField().getZero().newInstance(rate);
+            return pDot;
+        }
+
+        @Override
+        public int getDimension() {
+            return 1;
         }
 
         @Override
         public String getName() {
-            return "linear";
+            return name;
         }
 
         public boolean wasCalled() {
diff --git a/src/test/java/org/orekit/propagation/integration/FieldIntegrableGeneratorTest.java b/src/test/java/org/orekit/propagation/integration/FieldIntegrableGeneratorTest.java
deleted file mode 100644
index 1f72286e354e198273f98f6601e9ed400c6cd386..0000000000000000000000000000000000000000
--- a/src/test/java/org/orekit/propagation/integration/FieldIntegrableGeneratorTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Copyright 2002-2021 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.orekit.propagation.integration;
-
-import org.hipparchus.CalculusFieldElement;
-import org.hipparchus.Field;
-import org.hipparchus.geometry.euclidean.threed.Vector3D;
-import org.hipparchus.ode.nonstiff.AdaptiveStepsizeFieldIntegrator;
-import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
-import org.hipparchus.util.Decimal64Field;
-import org.hipparchus.util.MathArrays;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.orekit.Utils;
-import org.orekit.forces.gravity.potential.GravityFieldFactory;
-import org.orekit.forces.gravity.potential.SHMFormatReader;
-import org.orekit.frames.FramesFactory;
-import org.orekit.orbits.EquinoctialOrbit;
-import org.orekit.orbits.Orbit;
-import org.orekit.orbits.OrbitType;
-import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.propagation.SpacecraftState;
-import org.orekit.propagation.numerical.FieldNumericalPropagator;
-import org.orekit.propagation.numerical.NumericalPropagator;
-import org.orekit.propagation.semianalytical.dsst.FieldDSSTPropagator;
-import org.orekit.time.AbsoluteDate;
-import org.orekit.time.FieldAbsoluteDate;
-import org.orekit.utils.PVCoordinates;
-
-public class FieldIntegrableGeneratorTest {
-
-    private double                       mu;
-    private AbsoluteDate                 initDate;
-    private SpacecraftState              initialState;
-    private double[][]                   tolerance;
-
-    /** Test for issue #401
-     *  with a numerical propagator */
-    @Test
-    public void testInitNumerical() {
-        doTestInitNumerical(Decimal64Field.getInstance());
-    }
-
-    private <T extends CalculusFieldElement<T>> void doTestInitNumerical(Field<T> field) {
-        // setup
-        final double reference = 1.25;
-        InitCheckerEquations<T> checker = new InitCheckerEquations<>(reference);
-        Assert.assertFalse(checker.wasCalled());
-
-        // action
-        AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 200,
-                                                                                              tolerance[0], tolerance[1]);
-        integrator.setInitialStepSize(60);
-        FieldNumericalPropagator<T> propagatorNumerical = new FieldNumericalPropagator<>(field, integrator);
-        propagatorNumerical.setInitialState(new FieldSpacecraftState<>(field, initialState).
-                                            addAdditionalState(checker.getName(), field.getZero().newInstance(reference)));
-        propagatorNumerical.addIntegrableGenerator(checker);
-        propagatorNumerical.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(600));
-
-        // verify
-        Assert.assertTrue(checker.wasCalled());
-
-    }
-
-    /** Test for issue #401
-     *  with a DSST propagator */
-    @Test
-    public void testInitDSST() {
-        doTestIniDSST(Decimal64Field.getInstance());
-    }
-
-    private <T extends CalculusFieldElement<T>> void doTestIniDSST(Field<T> field) {
-        // setup
-        final double reference = 3.5;
-        InitCheckerEquations<T> checker = new InitCheckerEquations<>(reference);
-        Assert.assertFalse(checker.wasCalled());
-
-        // action
-        AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 200,
-                                                                                              tolerance[0], tolerance[1]);
-        integrator.setInitialStepSize(60);
-        FieldDSSTPropagator<T> propagatorDSST = new FieldDSSTPropagator<>(field, integrator);
-        propagatorDSST.setInitialState(new FieldSpacecraftState<>(field, initialState).
-                                       addAdditionalState(checker.getName(), field.getZero().newInstance(reference)));
-        propagatorDSST.addIntegrableGenerator(checker);
-        propagatorDSST.propagate(new FieldAbsoluteDate<>(field, initDate).shiftedBy(600));
-
-        // verify
-        Assert.assertTrue(checker.wasCalled());
-
-    }
-
-    @Before
-    public void setUp() {
-        Utils.setDataRoot("regular-data:potential/shm-format");
-        GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("^eigen_cg03c_coef$", false));
-        mu  = GravityFieldFactory.getUnnormalizedProvider(0, 0).getMu();
-        final Vector3D position = new Vector3D(7.0e6, 1.0e6, 4.0e6);
-        final Vector3D velocity = new Vector3D(-500.0, 8000.0, 1000.0);
-        initDate = AbsoluteDate.J2000_EPOCH;
-        final Orbit orbit = new EquinoctialOrbit(new PVCoordinates(position,  velocity),
-                                                 FramesFactory.getEME2000(), initDate, mu);
-        initialState = new SpacecraftState(orbit);
-        tolerance = NumericalPropagator.tolerances(0.001, orbit, OrbitType.EQUINOCTIAL);
-    }
-
-    @After
-    public void tearDown() {
-        initDate     = null;
-        initialState = null;
-        tolerance    = null;
-    }
-
-    public static class InitCheckerEquations<T extends CalculusFieldElement<T>> implements FieldIntegrableGenerator<T> {
-
-        private double expected;
-        private boolean called;
-
-        public InitCheckerEquations(final double expected) {
-            this.expected = expected;
-            this.called   = false;
-        }
-
-        @Override
-        public void init(FieldSpacecraftState<T> initiaState, FieldAbsoluteDate<T> target) {
-            Assert.assertEquals(expected, initiaState.getAdditionalState(getName())[0].getReal(), 1.0e-15);
-            called = true;
-        }
-
-        @Override
-        public T[] generate(FieldSpacecraftState<T> s)  {
-            final T[] pDot = MathArrays.buildArray(s.getDate().getField(), 1);
-            pDot[0] = s.getDate().getField().getZero().newInstance(1.5);
-            return pDot;
-        }
-
-        @Override
-        public String getName() {
-            return "linear";
-        }
-
-        public boolean wasCalled() {
-            return called;
-        }
-
-    }
-
-}
diff --git a/src/test/java/org/orekit/propagation/integration/FieldIntegratedEphemerisTest.java b/src/test/java/org/orekit/propagation/integration/FieldIntegratedEphemerisTest.java
index 6876b75ecc296279ac6bf9e3915046a5602047d7..f50146fc41cbfc33ed6920296fd3b518d8554b87 100644
--- a/src/test/java/org/orekit/propagation/integration/FieldIntegratedEphemerisTest.java
+++ b/src/test/java/org/orekit/propagation/integration/FieldIntegratedEphemerisTest.java
@@ -40,10 +40,10 @@ import org.orekit.frames.FramesFactory;
 import org.orekit.orbits.FieldEquinoctialOrbit;
 import org.orekit.orbits.FieldOrbit;
 import org.orekit.orbits.OrbitType;
+import org.orekit.propagation.FieldAdditionalStateProvider;
 import org.orekit.propagation.FieldBoundedPropagator;
 import org.orekit.propagation.FieldEphemerisGenerator;
 import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.propagation.FieldStackableGenerator;
 import org.orekit.propagation.analytical.FieldKeplerianPropagator;
 import org.orekit.propagation.events.FieldDateDetector;
 import org.orekit.propagation.numerical.FieldNumericalPropagator;
@@ -144,7 +144,7 @@ public class FieldIntegratedEphemerisTest {
         numericalPropagator.propagate(finalDate);
         Assert.assertTrue(numericalPropagator.getCalls() < 3200);
         FieldBoundedPropagator<T> ephemeris = generator.getGeneratedEphemeris();
-        ephemeris.addClosedFormGenerator(new FieldStackableGenerator<T>() {
+        ephemeris.addAdditionalStateProvider(new FieldAdditionalStateProvider<T>() {
 
             @Override
             public String getName() {
@@ -152,7 +152,7 @@ public class FieldIntegratedEphemerisTest {
             }
 
             @Override
-            public T[] generate(FieldSpacecraftState<T> state) {
+            public T[] getAdditionalState(FieldSpacecraftState<T> state) {
                 T[] array = MathArrays.buildArray(state.getDate().getField(), 1);
                 array[0] = state.getDate().durationFrom(initialOrbit.getDate());
                 return array;
diff --git a/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java b/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
index 4acafde50b452a71a1cadd21739bc0b9f5426927..8185c40a20ae4d1385367ed88bed4255b9811ecd 100644
--- a/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
+++ b/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
@@ -65,7 +65,7 @@ import org.orekit.orbits.PositionAngle;
 import org.orekit.propagation.FieldBoundedPropagator;
 import org.orekit.propagation.FieldEphemerisGenerator;
 import org.orekit.propagation.FieldSpacecraftState;
-import org.orekit.propagation.FieldStackableGenerator;
+import org.orekit.propagation.FieldAdditionalStateProvider;
 import org.orekit.propagation.events.FieldAbstractDetector;
 import org.orekit.propagation.events.FieldApsideDetector;
 import org.orekit.propagation.events.FieldDateDetector;
@@ -74,7 +74,7 @@ import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
 import org.orekit.propagation.events.handlers.FieldEventHandler;
 import org.orekit.propagation.events.handlers.FieldStopOnEvent;
 import org.orekit.propagation.integration.FieldAbstractIntegratedPropagator;
-import org.orekit.propagation.integration.FieldIntegrableGenerator;
+import org.orekit.propagation.integration.FieldAdditionalEquations;
 import org.orekit.propagation.sampling.FieldOrekitStepHandler;
 import org.orekit.propagation.sampling.FieldOrekitStepInterpolator;
 import org.orekit.time.FieldAbsoluteDate;
@@ -872,26 +872,34 @@ public class FieldNumericalPropagatorTest {
         propagator.setOrbitType(type);
         propagator.setInitialState(initialState);
 
-        propagator.addIntegrableGenerator(new FieldIntegrableGenerator<T>() {
+        propagator.addAdditionalEquations(new FieldAdditionalEquations<T>() {
 
             public String getName() {
                 return "linear";
             }
 
-            public T[] generate(FieldSpacecraftState<T> s) {
+            public int getDimension() {
+                return 1;
+            }
+
+            public T[] derivatives(FieldSpacecraftState<T> s) {
                 T[] pDot = MathArrays.buildArray(field, 1);
                 pDot[0] = field.getOne();
                 return pDot;
             }
         });
         try {
-            propagator.addIntegrableGenerator(new FieldIntegrableGenerator<T>() {
+            propagator.addAdditionalEquations(new FieldAdditionalEquations<T>() {
 
                 public String getName() {
                     return "linear";
                 }
 
-                public T[] generate(FieldSpacecraftState<T> s) {
+                public int getDimension() {
+                    return 1;
+                }
+
+                public T[] derivatives(FieldSpacecraftState<T> s) {
                     T[] pDot = MathArrays.buildArray(field, 1);
                     pDot[0] = field.getOne();
                     return pDot;
@@ -902,12 +910,12 @@ public class FieldNumericalPropagatorTest {
             Assert.assertEquals(oe.getSpecifier(), OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE);
         }
         try {
-            propagator.addClosedFormGenerator(new FieldStackableGenerator<T>() {
+            propagator.addAdditionalStateProvider(new FieldAdditionalStateProvider<T>() {
                public String getName() {
                     return "linear";
                 }
 
-                public T[] generate(FieldSpacecraftState<T> state) {
+                public T[] getAdditionalState(FieldSpacecraftState<T> state) {
                     return null;
                 }
             });
@@ -915,12 +923,12 @@ public class FieldNumericalPropagatorTest {
         } catch (OrekitException oe) {
             Assert.assertEquals(oe.getSpecifier(), OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE);
         }
-        propagator.addClosedFormGenerator(new FieldStackableGenerator<T>() {
+        propagator.addAdditionalStateProvider(new FieldAdditionalStateProvider<T>() {
             public String getName() {
                 return "constant";
             }
 
-            public T[] generate(FieldSpacecraftState<T> state) {
+            public T[] getAdditionalState(FieldSpacecraftState<T> state) {
                 T[] ret = MathArrays.buildArray(field, 1);
                 ret[0] = zero.add(1.0);
                 return ret;
@@ -980,13 +988,17 @@ public class FieldNumericalPropagatorTest {
         FieldNumericalPropagator<T> propagator = createPropagator(field);
 
 
-        propagator.addIntegrableGenerator(new FieldIntegrableGenerator<T>() {
+        propagator.addAdditionalEquations(new FieldAdditionalEquations<T>() {
 
             public String getName() {
                 return "linear";
             }
 
-            public T[] generate(FieldSpacecraftState<T> s) {
+            public int getDimension() {
+                return 1;
+            }
+
+            public T[] derivatives(FieldSpacecraftState<T> s) {
                 T[] pDot = MathArrays.buildArray(field, 1);
                 pDot[0] = field.getOne();
                 return pDot;
@@ -1133,21 +1145,24 @@ public class FieldNumericalPropagatorTest {
         FieldNumericalPropagator<T> propagator = createPropagator(field);
         FieldAbsoluteDate<T> initDate = propagator.getInitialState().getDate();
 
-        propagator.addClosedFormGenerator(new FieldStackableGenerator<T>() {
+        propagator.addAdditionalStateProvider(new FieldAdditionalStateProvider<T>() {
             public String getName() {
                 return "squaredA";
             }
-            public T[] generate(FieldSpacecraftState<T> state) {
+            public T[] getAdditionalState(FieldSpacecraftState<T> state) {
                 T[] a = MathArrays.buildArray(field, 1);
                 a[0] = state.getA().multiply(state.getA());
                 return a;
             }
         });
-        propagator.addIntegrableGenerator(new FieldIntegrableGenerator<T>() {
+        propagator.addAdditionalEquations(new FieldAdditionalEquations<T>() {
             public String getName() {
                 return "extra";
             }
-            public T[] generate(FieldSpacecraftState<T> s) {
+            public int getDimension() {
+                return 1;
+            }
+            public T[] derivatives(FieldSpacecraftState<T> s) {
                 T[] pDot = MathArrays.buildArray(field, 1);
                 pDot[0] = field.getZero().newInstance(rate);
                 return pDot;