1   /* Copyright 2002-2024 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.events;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.orekit.errors.OrekitException;
21  import org.orekit.errors.OrekitMessages;
22  import org.orekit.propagation.FieldSpacecraftState;
23  import org.orekit.propagation.events.handlers.FieldEventHandler;
24  import org.orekit.time.FieldAbsoluteDate;
25  
26  /** Common parts shared by several orbital events finders.
27   * @param <D> type of the detector
28   * @param <T> type of the field element
29   * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
30   * @author Luc Maisonobe
31   */
32  public abstract class FieldAbstractDetector<D extends FieldAbstractDetector<D, T>, T extends CalculusFieldElement<T>>
33      implements FieldEventDetector<T> {
34  
35      /** Default maximum checking interval (s). */
36      public static final double DEFAULT_MAXCHECK = 600;
37  
38      /** Default convergence threshold (s). */
39      public static final double DEFAULT_THRESHOLD = 1.e-6;
40  
41      /** Default cmaximum number of iterations in the event time search. */
42      public static final int DEFAULT_MAX_ITER = 100;
43  
44      /** Max check interval. */
45      private final FieldAdaptableInterval<T> maxCheck;
46  
47      /** Convergence threshold. */
48      private final T threshold;
49  
50      /** Maximum number of iterations in the event time search. */
51      private final int maxIter;
52  
53      /** Default handler for event overrides. */
54      private final FieldEventHandler<T> handler;
55  
56      /** Propagation direction. */
57      private boolean forward;
58  
59      /** Build a new instance.
60       * @param maxCheck maximum checking interval
61       * @param threshold convergence threshold (s)
62       * @param maxIter maximum number of iterations in the event time search
63       * @param handler event handler to call at event occurrences
64       */
65      protected FieldAbstractDetector(final FieldAdaptableInterval<T> maxCheck, final T threshold, final int maxIter,
66                                      final FieldEventHandler<T> handler) {
67          checkStrictlyPositive(threshold.getReal());
68          this.maxCheck  = maxCheck;
69          this.threshold = threshold;
70          this.maxIter   = maxIter;
71          this.handler   = handler;
72          this.forward   = true;
73      }
74  
75      /** Check value is strictly positive.
76       * @param value value to check
77       * @exception OrekitException if value is not strictly positive
78       * @since 11.2
79       */
80      private void checkStrictlyPositive(final double value) throws OrekitException {
81          if (value <= 0.0) {
82              throw new OrekitException(OrekitMessages.NOT_STRICTLY_POSITIVE, value);
83          }
84      }
85  
86      /** {@inheritDoc} */
87      public void init(final FieldSpacecraftState<T> s0,
88                       final FieldAbsoluteDate<T> t) {
89          forward = t.durationFrom(s0.getDate()).getReal() >= 0.0;
90          getHandler().init(s0, t, this);
91      }
92  
93      /** {@inheritDoc} */
94      public abstract T g(FieldSpacecraftState<T> s);
95  
96      /** {@inheritDoc} */
97      public FieldAdaptableInterval<T> getMaxCheckInterval() {
98          return maxCheck;
99      }
100 
101     /** {@inheritDoc} */
102     public int getMaxIterationCount() {
103         return maxIter;
104     }
105 
106     /** {@inheritDoc} */
107     public T getThreshold() {
108         return threshold;
109     }
110 
111     /**
112      * Setup the maximum checking interval.
113      * <p>
114      * This will override a maximum checking interval if it has been configured previously.
115      * </p>
116      * @param newMaxCheck maximum checking interval (s)
117      * @return a new detector with updated configuration (the instance is not changed)
118      * @since 12.0
119      */
120     public D withMaxCheck(final double newMaxCheck) {
121         return withMaxCheck(FieldAdaptableInterval.of(newMaxCheck));
122     }
123 
124     /**
125      * Setup the maximum checking interval.
126      * <p>
127      * This will override a maximum checking interval if it has been configured previously.
128      * </p>
129      * @param newMaxCheck maximum checking interval (s)
130      * @return a new detector with updated configuration (the instance is not changed)
131      * @since 12.0
132      */
133     public D withMaxCheck(final FieldAdaptableInterval<T> newMaxCheck) {
134         return create(newMaxCheck, getThreshold(), getMaxIterationCount(), getHandler());
135     }
136 
137     /**
138      * Setup the maximum number of iterations in the event time search.
139      * <p>
140      * This will override a number of iterations if it has been configured previously.
141      * </p>
142      * @param newMaxIter maximum number of iterations in the event time search
143      * @return a new detector with updated configuration (the instance is not changed)
144      * @since 6.1
145      */
146     public D withMaxIter(final int newMaxIter) {
147         return create(getMaxCheckInterval(), getThreshold(), newMaxIter,  getHandler());
148     }
149 
150     /**
151      * Setup the convergence threshold.
152      * <p>
153      * This will override a convergence threshold if it has been configured previously.
154      * </p>
155      * @param newThreshold convergence threshold (s)
156      * @return a new detector with updated configuration (the instance is not changed)
157      * @since 6.1
158      */
159     public D withThreshold(final T newThreshold) {
160         return create(getMaxCheckInterval(), newThreshold, getMaxIterationCount(),  getHandler());
161     }
162 
163     /**
164      * Setup the event handler to call at event occurrences.
165      * <p>
166      * This will override a handler if it has been configured previously.
167      * </p>
168      * @param newHandler event handler to call at event occurrences
169      * @return a new detector with updated configuration (the instance is not changed)
170      * @since 6.1
171      */
172     public D withHandler(final FieldEventHandler<T> newHandler) {
173         return create(getMaxCheckInterval(), getThreshold(), getMaxIterationCount(), newHandler);
174     }
175 
176     /** {@inheritDoc} */
177     public FieldEventHandler<T> getHandler() {
178         return handler;
179     }
180 
181     /** Build a new instance.
182      * @param newMaxCheck maximum checking interval
183      * @param newThreshold convergence threshold (s)
184      * @param newMaxIter maximum number of iterations in the event time search
185      * @param newHandler event handler to call at event occurrences
186      * @return a new instance of the appropriate sub-type
187      */
188     protected abstract D create(FieldAdaptableInterval<T> newMaxCheck, T newThreshold,
189                                 int newMaxIter, FieldEventHandler<T> newHandler);
190 
191     /** Check if the current propagation is forward or backward.
192      * @return true if the current propagation is forward
193      * @since 7.2
194      */
195     public boolean isForward() {
196         return forward;
197     }
198 
199 }