1 /* 2 * Licensed to the Hipparchus project under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The Hipparchus project 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 * https://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 18 package org.hipparchus.ode.events; 19 20 import org.hipparchus.CalculusFieldElement; 21 import org.hipparchus.analysis.solvers.BracketedRealFieldUnivariateSolver; 22 import org.hipparchus.analysis.solvers.FieldBracketingNthOrderBrentSolver; 23 import org.hipparchus.ode.FieldODEStateAndDerivative; 24 25 /** Base class for #@link {@link FieldODEEventDetector}. 26 * @param <T> type of the detector 27 * @param <E> type of the field elements 28 * @since 3.0 29 */ 30 public abstract class AbstractFieldODEDetector<T extends AbstractFieldODEDetector<T, E>, E extends CalculusFieldElement<E>> 31 implements FieldODEEventDetector<E> { 32 33 /** Default maximum checking interval (s). */ 34 public static final double DEFAULT_MAXCHECK = 600; 35 36 /** Default convergence threshold (s). */ 37 public static final double DEFAULT_THRESHOLD = 1.e-6; 38 39 /** Default maximum number of iterations in the event time search. */ 40 public static final int DEFAULT_MAX_ITER = 100; 41 42 /** Max check interval. */ 43 private final FieldAdaptableInterval<E> maxCheck; 44 45 /** Maximum number of iterations in the event time search. */ 46 private final int maxIter; 47 48 /** Root-finding algorithm to use to detect state events. */ 49 private final BracketedRealFieldUnivariateSolver<E> solver; 50 51 /** Default handler for event overrides. */ 52 private final FieldODEEventHandler<E> handler; 53 54 /** Propagation direction. */ 55 private boolean forward; 56 57 /** Build a new instance. 58 * @param maxCheck maximum checking interval, must be strictly positive (s) 59 * @param maxIter maximum number of iterations in the event time search 60 * @param solver root-finding algorithm to use to detect state events 61 * @param handler event handler to call at event occurrences 62 */ 63 protected AbstractFieldODEDetector(final FieldAdaptableInterval<E> maxCheck, final int maxIter, 64 final BracketedRealFieldUnivariateSolver<E> solver, 65 final FieldODEEventHandler<E> handler) { 66 this.maxCheck = maxCheck; 67 this.maxIter = maxIter; 68 this.solver = solver; 69 this.handler = handler; 70 this.forward = true; 71 } 72 73 /** 74 * {@inheritDoc} 75 * 76 * <p> This implementation sets the direction of integration and initializes the event 77 * handler. If a subclass overrides this method it should call {@code 78 * super.init(s0, t)}. 79 */ 80 @Override 81 public void init(final FieldODEStateAndDerivative<E> s0, final E t) { 82 forward = t.subtract(s0.getTime()).getReal() >= 0; 83 getHandler().init(s0, t, this); 84 } 85 86 /** {@inheritDoc} */ 87 @Override 88 public abstract E g(FieldODEStateAndDerivative<E> s); 89 90 /** {@inheritDoc} */ 91 @Override 92 public FieldAdaptableInterval<E> getMaxCheckInterval() { 93 return maxCheck; 94 } 95 96 /** {@inheritDoc} */ 97 @Override 98 public int getMaxIterationCount() { 99 return maxIter; 100 } 101 102 /** {@inheritDoc} */ 103 @Override 104 public BracketedRealFieldUnivariateSolver<E> getSolver() { 105 return solver; 106 } 107 108 /** 109 * Setup the maximum checking interval. 110 * <p> 111 * This will override a maximum checking interval if it has been configured previously. 112 * </p> 113 * @param newMaxCheck maximum checking interval (s) 114 * @return a new detector with updated configuration (the instance is not changed) 115 */ 116 public T withMaxCheck(final E newMaxCheck) { 117 return withMaxCheck(s -> newMaxCheck.getReal()); 118 } 119 120 /** 121 * Setup the maximum checking interval. 122 * <p> 123 * This will override a maximum checking interval if it has been configured previously. 124 * </p> 125 * @param newMaxCheck maximum checking interval (s) 126 * @return a new detector with updated configuration (the instance is not changed) 127 * @since 3.0 128 */ 129 public T withMaxCheck(final FieldAdaptableInterval<E> newMaxCheck) { 130 return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler()); 131 } 132 133 /** 134 * Setup the maximum number of iterations in the event time search. 135 * <p> 136 * This will override a number of iterations if it has been configured previously. 137 * </p> 138 * @param newMaxIter maximum number of iterations in the event time search 139 * @return a new detector with updated configuration (the instance is not changed) 140 */ 141 public T withMaxIter(final int newMaxIter) { 142 return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler()); 143 } 144 145 /** 146 * Setup the convergence threshold. 147 * <p> 148 * This is equivalent to call {@code withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, 149 * newThreshold, zero, 5)}, so it will override a solver if one has been configured previously. 150 * </p> 151 * @param newThreshold convergence threshold 152 * @return a new detector with updated configuration (the instance is not changed) 153 * @see #withSolver(BracketedRealFieldUnivariateSolver) 154 */ 155 public T withThreshold(final E newThreshold) { 156 final E zero = newThreshold.getField().getZero(); 157 return withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, newThreshold, zero, 5)); 158 } 159 160 /** 161 * Setup the root-finding algorithm to use to detect state events. 162 * <p> 163 * This will override a solver if it has been configured previously. 164 * </p> 165 * @param newSolver root-finding algorithm to use to detect state events 166 * @return a new detector with updated configuration (the instance is not changed) 167 * @see #withThreshold(CalculusFieldElement) 168 */ 169 public T withSolver(final BracketedRealFieldUnivariateSolver<E> newSolver) { 170 return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler()); 171 } 172 173 /** 174 * Setup the event handler to call at event occurrences. 175 * <p> 176 * This will override a handler if it has been configured previously. 177 * </p> 178 * @param newHandler event handler to call at event occurrences 179 * @return a new detector with updated configuration (the instance is not changed) 180 */ 181 public T withHandler(final FieldODEEventHandler<E> newHandler) { 182 return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler); 183 } 184 185 /** {@inheritDoc} */ 186 @Override 187 public FieldODEEventHandler<E> getHandler() { 188 return handler; 189 } 190 191 /** Build a new instance. 192 * @param newMaxCheck maximum checking interval 193 * @param newMaxIter maximum number of iterations in the event time search 194 * @param newSolver root-finding algorithm to use to detect state events 195 * @param newHandler event handler to call at event occurrences 196 * @return a new instance of the appropriate sub-type 197 */ 198 protected abstract T create(FieldAdaptableInterval<E> newMaxCheck, int newMaxIter, 199 BracketedRealFieldUnivariateSolver<E> newSolver, 200 FieldODEEventHandler<E> newHandler); 201 202 /** Check if the current propagation is forward or backward. 203 * @return true if the current propagation is forward 204 */ 205 public boolean isForward() { 206 return forward; 207 } 208 209 }