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_MAX_CHECK = AbstractODEDetector.DEFAULT_MAX_CHECK; 35 36 /** Default convergence threshold (s). */ 37 public static final double DEFAULT_THRESHOLD = AbstractODEDetector.DEFAULT_THRESHOLD; 38 39 /** Default maximum number of iterations in the event time search. */ 40 public static final int DEFAULT_MAX_ITER = AbstractODEDetector.DEFAULT_MAX_ITER; 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 FieldODEEventDetector.super.init(s0, t); 83 forward = t.subtract(s0.getTime()).getReal() >= 0; 84 } 85 86 /** {@inheritDoc} */ 87 @Override 88 public FieldAdaptableInterval<E> getMaxCheckInterval() { 89 return maxCheck; 90 } 91 92 /** {@inheritDoc} */ 93 @Override 94 public int getMaxIterationCount() { 95 return maxIter; 96 } 97 98 /** {@inheritDoc} */ 99 @Override 100 public BracketedRealFieldUnivariateSolver<E> getSolver() { 101 return solver; 102 } 103 104 /** 105 * Setup the maximum checking interval. 106 * <p> 107 * This will override a maximum checking interval if it has been configured previously. 108 * </p> 109 * @param newMaxCheck maximum checking interval (s) 110 * @return a new detector with updated configuration (the instance is not changed) 111 */ 112 public T withMaxCheck(final E newMaxCheck) { 113 return withMaxCheck(FieldAdaptableInterval.of(newMaxCheck.getReal())); 114 } 115 116 /** 117 * Setup the maximum checking interval. 118 * <p> 119 * This will override a maximum checking interval if it has been configured previously. 120 * </p> 121 * @param newMaxCheck maximum checking interval (s) 122 * @return a new detector with updated configuration (the instance is not changed) 123 * @since 3.0 124 */ 125 public T withMaxCheck(final FieldAdaptableInterval<E> newMaxCheck) { 126 return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler()); 127 } 128 129 /** 130 * Setup the maximum number of iterations in the event time search. 131 * <p> 132 * This will override a number of iterations if it has been configured previously. 133 * </p> 134 * @param newMaxIter maximum number of iterations in the event time search 135 * @return a new detector with updated configuration (the instance is not changed) 136 */ 137 public T withMaxIter(final int newMaxIter) { 138 return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler()); 139 } 140 141 /** 142 * Setup the convergence threshold. 143 * <p> 144 * This is equivalent to call {@code withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, 145 * newThreshold, zero, 5)}, so it will override a solver if one has been configured previously. 146 * </p> 147 * @param newThreshold convergence threshold 148 * @return a new detector with updated configuration (the instance is not changed) 149 * @see #withSolver(BracketedRealFieldUnivariateSolver) 150 */ 151 public T withThreshold(final E newThreshold) { 152 final E zero = newThreshold.getField().getZero(); 153 return withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, newThreshold, zero, 5)); 154 } 155 156 /** 157 * Setup the root-finding algorithm to use to detect state events. 158 * <p> 159 * This will override a solver if it has been configured previously. 160 * </p> 161 * @param newSolver root-finding algorithm to use to detect state events 162 * @return a new detector with updated configuration (the instance is not changed) 163 * @see #withThreshold(CalculusFieldElement) 164 */ 165 public T withSolver(final BracketedRealFieldUnivariateSolver<E> newSolver) { 166 return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler()); 167 } 168 169 /** 170 * Setup the event handler to call at event occurrences. 171 * <p> 172 * This will override a handler if it has been configured previously. 173 * </p> 174 * @param newHandler event handler to call at event occurrences 175 * @return a new detector with updated configuration (the instance is not changed) 176 */ 177 public T withHandler(final FieldODEEventHandler<E> newHandler) { 178 return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler); 179 } 180 181 /** {@inheritDoc} */ 182 @Override 183 public FieldODEEventHandler<E> getHandler() { 184 return handler; 185 } 186 187 /** Build a new instance. 188 * @param newMaxCheck maximum checking interval 189 * @param newMaxIter maximum number of iterations in the event time search 190 * @param newSolver root-finding algorithm to use to detect state events 191 * @param newHandler event handler to call at event occurrences 192 * @return a new instance of the appropriate sub-type 193 */ 194 protected abstract T create(FieldAdaptableInterval<E> newMaxCheck, int newMaxIter, 195 BracketedRealFieldUnivariateSolver<E> newSolver, 196 FieldODEEventHandler<E> newHandler); 197 198 /** Check if the current propagation is forward or backward. 199 * @return true if the current propagation is forward 200 */ 201 public boolean isForward() { 202 return forward; 203 } 204 205 }