1 /* 2 * Licensed to the Apache Software Foundation (ASF) 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 ASF 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 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 23 package org.hipparchus.ode.events; 24 25 import org.hipparchus.exception.MathRuntimeException; 26 27 /** Enumerate for {@link EventSlopeFilter filtering events}. 28 * 29 */ 30 31 public enum FilterType { 32 33 /** Constant for triggering only decreasing events. 34 * <p>When this filter is used, the wrapped {@link ODEEventHandler 35 * event handler} {@link ODEEventHandler#eventOccurred(org.hipparchus.ode.ODEStateAndDerivative, 36 * ODEEventDetector, boolean) eventOccurred} method will be called <em>only</em> with 37 * its {@code increasing} argument set to false.</p> 38 */ 39 TRIGGER_ONLY_DECREASING_EVENTS { 40 41 /** {@inheritDoc} */ 42 @Override 43 protected boolean isTriggeredOnIncreasing() { 44 return false; 45 } 46 47 /** {@inheritDoc} 48 * <p> 49 * states scheduling for computing h(t,y) as an altered version of g(t, y) 50 * <ul> 51 * <li>0 are triggered events for which a zero is produced (here decreasing events)</li> 52 * <li>X are ignored events for which zero is masked (here increasing events)</li> 53 * </ul> 54 * </p> 55 * <pre> 56 * g(t) 57 * ___ ___ ___ 58 * / \ / \ / \ 59 * / \ / \ / \ 60 * / g>0 \ / g>0 \ / g>0 \ 61 * / \ / \ / \ 62 * ----- X --------- 0 --------- X --------- 0 --------- X --------- 0 --- 63 * / \ / \ / \ 64 * / \ g<0 / \ g<0 / \ g<0 65 * / \ / \ / \ / 66 * ___/ \___/ \___/ \___/ 67 * </pre> 68 * <pre> 69 * h(t,y)) as an alteration of g(t,y) 70 * ___ ___ ___ 71 * \ / \ / \ / \ 72 * \ / \ h=+g / \ / \ 73 * \ / \ h=min(-s,-g,+g) / \ / \ 74 * \_/ \ / \_/ \ 75 * ------ ---------- 0 ----------_---------- 0 --------------------- 0 --- 76 * \ / \ / \ 77 * h=max(+s,-g,+g) \ / \ / h=max(+s,-g,+g) \ 78 * \ / \ / h=-g \ / 79 * \___/ \___/ \___/ 80 * </pre> 81 * <p> 82 * As shown by the figure above, several expressions are used to compute h, 83 * depending on the current state: 84 * <ul> 85 * <li>h = max(+s,-g,+g)</li> 86 * <li>h = +g</li> 87 * <li>h = min(-s,-g,+g)</li> 88 * <li>h = -g</li> 89 * </ul> 90 * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}. 91 * </p> 92 */ 93 @Override 94 protected Transformer selectTransformer(final Transformer previous, 95 final double g, final boolean forward) { 96 if (forward) { 97 switch (previous) { 98 case UNINITIALIZED : 99 // we are initializing the first point 100 if (g > 0) { 101 // initialize as if previous root (i.e. backward one) was an ignored increasing event 102 return Transformer.MAX; 103 } else if (g < 0) { 104 // initialize as if previous root (i.e. backward one) was a triggered decreasing event 105 return Transformer.PLUS; 106 } else { 107 // we are exactly at a root, we don't know if it is an increasing 108 // or a decreasing event, we remain in uninitialized state 109 return Transformer.UNINITIALIZED; 110 } 111 case PLUS : 112 if (g >= 0) { 113 // we have crossed the zero line on an ignored increasing event, 114 // we must change the transformer 115 return Transformer.MIN; 116 } else { 117 // we are still in the same status 118 return previous; 119 } 120 case MINUS : 121 if (g >= 0) { 122 // we have crossed the zero line on an ignored increasing event, 123 // we must change the transformer 124 return Transformer.MAX; 125 } else { 126 // we are still in the same status 127 return previous; 128 } 129 case MIN : 130 if (g <= 0) { 131 // we have crossed the zero line on a triggered decreasing event, 132 // we must change the transformer 133 return Transformer.MINUS; 134 } else { 135 // we are still in the same status 136 return previous; 137 } 138 case MAX : 139 if (g <= 0) { 140 // we have crossed the zero line on a triggered decreasing event, 141 // we must change the transformer 142 return Transformer.PLUS; 143 } else { 144 // we are still in the same status 145 return previous; 146 } 147 default : 148 // this should never happen 149 throw MathRuntimeException.createInternalError(); 150 } 151 } else { 152 switch (previous) { 153 case UNINITIALIZED : 154 // we are initializing the first point 155 if (g > 0) { 156 // initialize as if previous root (i.e. forward one) was a triggered decreasing event 157 return Transformer.MINUS; 158 } else if (g < 0) { 159 // initialize as if previous root (i.e. forward one) was an ignored increasing event 160 return Transformer.MIN; 161 } else { 162 // we are exactly at a root, we don't know if it is an increasing 163 // or a decreasing event, we remain in uninitialized state 164 return Transformer.UNINITIALIZED; 165 } 166 case PLUS : 167 if (g <= 0) { 168 // we have crossed the zero line on an ignored increasing event, 169 // we must change the transformer 170 return Transformer.MAX; 171 } else { 172 // we are still in the same status 173 return previous; 174 } 175 case MINUS : 176 if (g <= 0) { 177 // we have crossed the zero line on an ignored increasing event, 178 // we must change the transformer 179 return Transformer.MIN; 180 } else { 181 // we are still in the same status 182 return previous; 183 } 184 case MIN : 185 if (g >= 0) { 186 // we have crossed the zero line on a triggered decreasing event, 187 // we must change the transformer 188 return Transformer.PLUS; 189 } else { 190 // we are still in the same status 191 return previous; 192 } 193 case MAX : 194 if (g >= 0) { 195 // we have crossed the zero line on a triggered decreasing event, 196 // we must change the transformer 197 return Transformer.MINUS; 198 } else { 199 // we are still in the same status 200 return previous; 201 } 202 default : 203 // this should never happen 204 throw MathRuntimeException.createInternalError(); 205 } 206 } 207 } 208 209 }, 210 211 /** Constant for triggering only increasing events. 212 * <p>When this filter is used, the wrapped {@link ODEEventHandler 213 * event handler} {@link ODEEventHandler#eventOccurred(org.hipparchus.ode.ODEStateAndDerivative, 214 * ODEEventDetector, boolean) eventOccurred} method will be called <em>only</em> with 215 * its {@code increasing} argument set to true.</p> 216 */ 217 TRIGGER_ONLY_INCREASING_EVENTS { 218 219 /** {@inheritDoc} */ 220 @Override 221 protected boolean isTriggeredOnIncreasing() { 222 return true; 223 } 224 225 /** {@inheritDoc} 226 * <p> 227 * states scheduling for computing h(t,y) as an altered version of g(t, y) 228 * <ul> 229 * <li>0 are triggered events for which a zero is produced (here increasing events)</li> 230 * <li>X are ignored events for which zero is masked (here decreasing events)</li> 231 * </ul> 232 * </p> 233 * <pre> 234 * g(t) 235 * ___ ___ ___ 236 * / \ / \ / \ 237 * / \ / \ / \ 238 * / g>0 \ / g>0 \ / g>0 \ 239 * / \ / \ / \ 240 * ----- 0 --------- X --------- 0 --------- X --------- 0 --------- X --- 241 * / \ / \ / \ 242 * / \ g<0 / \ g<0 / \ g<0 243 * / \ / \ / \ / 244 * ___/ \___/ \___/ \___/ 245 * </pre> 246 * <pre> 247 * h(t,y)) as an alteration of g(t,y) 248 * ___ ___ 249 * \ / \ / \ 250 * \ h=-g / \ / \ h=-g 251 * \ h=min(-s,-g,+g) / \ / \ h=min(-s,-g,+g) 252 * \ / \_/ \ 253 * ------0 ----------_---------- 0 --------------------- 0 --------- _ --- 254 * \ / \ / \ / \ 255 * \ / \ / h=max(+s,-g,+g) \ / \ 256 * \ / \ / h=+g \ / \ / 257 * \___/ \___/ \___/ \___/ 258 * </pre> 259 * <p> 260 * As shown by the figure above, several expressions are used to compute h, 261 * depending on the current state: 262 * <ul> 263 * <li>h = max(+s,-g,+g)</li> 264 * <li>h = +g</li> 265 * <li>h = min(-s,-g,+g)</li> 266 * <li>h = -g</li> 267 * </ul> 268 * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}. 269 * </p> 270 */ 271 @Override 272 protected Transformer selectTransformer(final Transformer previous, 273 final double g, final boolean forward) { 274 if (forward) { 275 switch (previous) { 276 case UNINITIALIZED : 277 // we are initializing the first point 278 if (g > 0) { 279 // initialize as if previous root (i.e. backward one) was a triggered increasing event 280 return Transformer.PLUS; 281 } else if (g < 0) { 282 // initialize as if previous root (i.e. backward one) was an ignored decreasing event 283 return Transformer.MIN; 284 } else { 285 // we are exactly at a root, we don't know if it is an increasing 286 // or a decreasing event, we remain in uninitialized state 287 return Transformer.UNINITIALIZED; 288 } 289 case PLUS : 290 if (g <= 0) { 291 // we have crossed the zero line on an ignored decreasing event, 292 // we must change the transformer 293 return Transformer.MAX; 294 } else { 295 // we are still in the same status 296 return previous; 297 } 298 case MINUS : 299 if (g <= 0) { 300 // we have crossed the zero line on an ignored decreasing event, 301 // we must change the transformer 302 return Transformer.MIN; 303 } else { 304 // we are still in the same status 305 return previous; 306 } 307 case MIN : 308 if (g >= 0) { 309 // we have crossed the zero line on a triggered increasing event, 310 // we must change the transformer 311 return Transformer.PLUS; 312 } else { 313 // we are still in the same status 314 return previous; 315 } 316 case MAX : 317 if (g >= 0) { 318 // we have crossed the zero line on a triggered increasing event, 319 // we must change the transformer 320 return Transformer.MINUS; 321 } else { 322 // we are still in the same status 323 return previous; 324 } 325 default : 326 // this should never happen 327 throw MathRuntimeException.createInternalError(); 328 } 329 } else { 330 switch (previous) { 331 case UNINITIALIZED : 332 // we are initializing the first point 333 if (g > 0) { 334 // initialize as if previous root (i.e. forward one) was an ignored decreasing event 335 return Transformer.MAX; 336 } else if (g < 0) { 337 // initialize as if previous root (i.e. forward one) was a triggered increasing event 338 return Transformer.MINUS; 339 } else { 340 // we are exactly at a root, we don't know if it is an increasing 341 // or a decreasing event, we remain in uninitialized state 342 return Transformer.UNINITIALIZED; 343 } 344 case PLUS : 345 if (g >= 0) { 346 // we have crossed the zero line on an ignored decreasing event, 347 // we must change the transformer 348 return Transformer.MIN; 349 } else { 350 // we are still in the same status 351 return previous; 352 } 353 case MINUS : 354 if (g >= 0) { 355 // we have crossed the zero line on an ignored decreasing event, 356 // we must change the transformer 357 return Transformer.MAX; 358 } else { 359 // we are still in the same status 360 return previous; 361 } 362 case MIN : 363 if (g <= 0) { 364 // we have crossed the zero line on a triggered increasing event, 365 // we must change the transformer 366 return Transformer.MINUS; 367 } else { 368 // we are still in the same status 369 return previous; 370 } 371 case MAX : 372 if (g <= 0) { 373 // we have crossed the zero line on a triggered increasing event, 374 // we must change the transformer 375 return Transformer.PLUS; 376 } else { 377 // we are still in the same status 378 return previous; 379 } 380 default : 381 // this should never happen 382 throw MathRuntimeException.createInternalError(); 383 } 384 } 385 } 386 387 }; 388 389 /** Check if triggered events are increasing events. 390 * @return true if triggered events are increasing events 391 */ 392 protected abstract boolean isTriggeredOnIncreasing(); 393 394 /** Get next function transformer in the specified direction. 395 * @param previous transformer active on the previous point with respect 396 * to integration direction (may be null if no previous point is known) 397 * @param g current value of the g function 398 * @param forward true if integration goes forward 399 * @return next transformer transformer 400 */ 401 protected abstract Transformer selectTransformer(Transformer previous, 402 double g, boolean forward); 403 404 }