001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.math4.legacy.ode.events; 019 020import org.apache.commons.math4.legacy.exception.MathInternalError; 021 022/** Enumerate for {@link EventFilter filtering events}. 023 * 024 * @since 3.2 025 */ 026 027public enum FilterType { 028 029 /** Constant for triggering only decreasing events. 030 * <p>When this filter is used, the wrapped {@link EventHandler 031 * event handler} {@link EventHandler#eventOccurred(double, double[], 032 * boolean) eventOccurred} method will be called <em>only</em> with 033 * its {@code increasing} argument set to false.</p> 034 */ 035 TRIGGER_ONLY_DECREASING_EVENTS { 036 037 /** {@inheritDoc} */ 038 @Override 039 protected boolean getTriggeredIncreasing() { 040 return false; 041 } 042 043 /** {@inheritDoc} 044 * <p> 045 * states scheduling for computing h(t,y) as an altered version of g(t, y) 046 * <ul> 047 * <li>0 are triggered events for which a zero is produced (here decreasing events)</li> 048 * <li>X are ignored events for which zero is masked (here increasing events)</li> 049 * </ul> 050 * </p> 051 * <pre> 052 * g(t) 053 * ___ ___ ___ 054 * / \ / \ / \ 055 * / \ / \ / \ 056 * / g>0 \ / g>0 \ / g>0 \ 057 * / \ / \ / \ 058 * ----- X --------- 0 --------- X --------- 0 --------- X --------- 0 --- 059 * / \ / \ / \ 060 * / \ g<0 / \ g<0 / \ g<0 061 * / \ / \ / \ / 062 * ___/ \___/ \___/ \___/ 063 * </pre> 064 * <pre> 065 * h(t,y)) as an alteration of g(t,y) 066 * ___ ___ ___ 067 * \ / \ / \ / \ 068 * \ / \ h=+g / \ / \ 069 * \ / \ h=min(-s,-g,+g) / \ / \ 070 * \_/ \ / \_/ \ 071 * ------ ---------- 0 ----------_---------- 0 --------------------- 0 --- 072 * \ / \ / \ 073 * h=max(+s,-g,+g) \ / \ / h=max(+s,-g,+g) \ 074 * \ / \ / h=-g \ / 075 * \___/ \___/ \___/ 076 * </pre> 077 * <p> 078 * As shown by the figure above, several expressions are used to compute h, 079 * depending on the current state: 080 * <ul> 081 * <li>h = max(+s,-g,+g)</li> 082 * <li>h = +g</li> 083 * <li>h = min(-s,-g,+g)</li> 084 * <li>h = -g</li> 085 * </ul> 086 * where s is a tiny positive value: {@link org.apache.commons.numbers.core.Precision#SAFE_MIN}. 087 * </p> 088 */ 089 @Override 090 protected Transformer selectTransformer(final Transformer previous, 091 final double g, final boolean forward) { 092 if (forward) { 093 switch (previous) { 094 case UNINITIALIZED : 095 // we are initializing the first point 096 if (g > 0) { 097 // initialize as if previous root (i.e. backward one) was an ignored increasing event 098 return Transformer.MAX; 099 } else if (g < 0) { 100 // initialize as if previous root (i.e. backward one) was a triggered decreasing event 101 return Transformer.PLUS; 102 } else { 103 // we are exactly at a root, we don't know if it is an increasing 104 // or a decreasing event, we remain in uninitialized state 105 return Transformer.UNINITIALIZED; 106 } 107 case PLUS : 108 if (g >= 0) { 109 // we have crossed the zero line on an ignored increasing event, 110 // we must change the transformer 111 return Transformer.MIN; 112 } else { 113 // we are still in the same status 114 return previous; 115 } 116 case MINUS : 117 if (g >= 0) { 118 // we have crossed the zero line on an ignored increasing event, 119 // we must change the transformer 120 return Transformer.MAX; 121 } else { 122 // we are still in the same status 123 return previous; 124 } 125 case MIN : 126 if (g <= 0) { 127 // we have crossed the zero line on a triggered decreasing event, 128 // we must change the transformer 129 return Transformer.MINUS; 130 } else { 131 // we are still in the same status 132 return previous; 133 } 134 case MAX : 135 if (g <= 0) { 136 // we have crossed the zero line on a triggered decreasing event, 137 // we must change the transformer 138 return Transformer.PLUS; 139 } else { 140 // we are still in the same status 141 return previous; 142 } 143 default : 144 // this should never happen 145 throw new MathInternalError(); 146 } 147 } else { 148 switch (previous) { 149 case UNINITIALIZED : 150 // we are initializing the first point 151 if (g > 0) { 152 // initialize as if previous root (i.e. forward one) was a triggered decreasing event 153 return Transformer.MINUS; 154 } else if (g < 0) { 155 // initialize as if previous root (i.e. forward one) was an ignored increasing event 156 return Transformer.MIN; 157 } else { 158 // we are exactly at a root, we don't know if it is an increasing 159 // or a decreasing event, we remain in uninitialized state 160 return Transformer.UNINITIALIZED; 161 } 162 case PLUS : 163 if (g <= 0) { 164 // we have crossed the zero line on an ignored increasing event, 165 // we must change the transformer 166 return Transformer.MAX; 167 } else { 168 // we are still in the same status 169 return previous; 170 } 171 case MINUS : 172 if (g <= 0) { 173 // we have crossed the zero line on an ignored increasing event, 174 // we must change the transformer 175 return Transformer.MIN; 176 } else { 177 // we are still in the same status 178 return previous; 179 } 180 case MIN : 181 if (g >= 0) { 182 // we have crossed the zero line on a triggered decreasing event, 183 // we must change the transformer 184 return Transformer.PLUS; 185 } else { 186 // we are still in the same status 187 return previous; 188 } 189 case MAX : 190 if (g >= 0) { 191 // we have crossed the zero line on a triggered decreasing event, 192 // we must change the transformer 193 return Transformer.MINUS; 194 } else { 195 // we are still in the same status 196 return previous; 197 } 198 default : 199 // this should never happen 200 throw new MathInternalError(); 201 } 202 } 203 } 204 }, 205 206 /** Constant for triggering only increasing events. 207 * <p>When this filter is used, the wrapped {@link EventHandler 208 * event handler} {@link EventHandler#eventOccurred(double, double[], 209 * boolean) eventOccurred} method will be called <em>only</em> with 210 * its {@code increasing} argument set to true.</p> 211 */ 212 TRIGGER_ONLY_INCREASING_EVENTS { 213 214 /** {@inheritDoc} */ 215 @Override 216 protected boolean getTriggeredIncreasing() { 217 return true; 218 } 219 220 /** {@inheritDoc} 221 * <p> 222 * states scheduling for computing h(t,y) as an altered version of g(t, y) 223 * <ul> 224 * <li>0 are triggered events for which a zero is produced (here increasing events)</li> 225 * <li>X are ignored events for which zero is masked (here decreasing events)</li> 226 * </ul> 227 * </p> 228 * <pre> 229 * g(t) 230 * ___ ___ ___ 231 * / \ / \ / \ 232 * / \ / \ / \ 233 * / g>0 \ / g>0 \ / g>0 \ 234 * / \ / \ / \ 235 * ----- 0 --------- X --------- 0 --------- X --------- 0 --------- X --- 236 * / \ / \ / \ 237 * / \ g<0 / \ g<0 / \ g<0 238 * / \ / \ / \ / 239 * ___/ \___/ \___/ \___/ 240 * </pre> 241 * <pre> 242 * h(t,y)) as an alteration of g(t,y) 243 * ___ ___ 244 * \ / \ / \ 245 * \ h=-g / \ / \ h=-g 246 * \ h=min(-s,-g,+g) / \ / \ h=min(-s,-g,+g) 247 * \ / \_/ \ 248 * ------0 ----------_---------- 0 --------------------- 0 --------- _ --- 249 * \ / \ / \ / \ 250 * \ / \ / h=max(+s,-g,+g) \ / \ 251 * \ / \ / h=+g \ / \ / 252 * \___/ \___/ \___/ \___/ 253 * </pre> 254 * <p> 255 * As shown by the figure above, several expressions are used to compute h, 256 * depending on the current state: 257 * <ul> 258 * <li>h = max(+s,-g,+g)</li> 259 * <li>h = +g</li> 260 * <li>h = min(-s,-g,+g)</li> 261 * <li>h = -g</li> 262 * </ul> 263 * where s is a tiny positive value: {@link org.apache.commons.numbers.core.Precision#SAFE_MIN}. 264 * </p> 265 */ 266 @Override 267 protected Transformer selectTransformer(final Transformer previous, 268 final double g, final boolean forward) { 269 if (forward) { 270 switch (previous) { 271 case UNINITIALIZED : 272 // we are initializing the first point 273 if (g > 0) { 274 // initialize as if previous root (i.e. backward one) was a triggered increasing event 275 return Transformer.PLUS; 276 } else if (g < 0) { 277 // initialize as if previous root (i.e. backward one) was an ignored decreasing event 278 return Transformer.MIN; 279 } else { 280 // we are exactly at a root, we don't know if it is an increasing 281 // or a decreasing event, we remain in uninitialized state 282 return Transformer.UNINITIALIZED; 283 } 284 case PLUS : 285 if (g <= 0) { 286 // we have crossed the zero line on an ignored decreasing event, 287 // we must change the transformer 288 return Transformer.MAX; 289 } else { 290 // we are still in the same status 291 return previous; 292 } 293 case MINUS : 294 if (g <= 0) { 295 // we have crossed the zero line on an ignored decreasing event, 296 // we must change the transformer 297 return Transformer.MIN; 298 } else { 299 // we are still in the same status 300 return previous; 301 } 302 case MIN : 303 if (g >= 0) { 304 // we have crossed the zero line on a triggered increasing event, 305 // we must change the transformer 306 return Transformer.PLUS; 307 } else { 308 // we are still in the same status 309 return previous; 310 } 311 case MAX : 312 if (g >= 0) { 313 // we have crossed the zero line on a triggered increasing event, 314 // we must change the transformer 315 return Transformer.MINUS; 316 } else { 317 // we are still in the same status 318 return previous; 319 } 320 default : 321 // this should never happen 322 throw new MathInternalError(); 323 } 324 } else { 325 switch (previous) { 326 case UNINITIALIZED : 327 // we are initializing the first point 328 if (g > 0) { 329 // initialize as if previous root (i.e. forward one) was an ignored decreasing event 330 return Transformer.MAX; 331 } else if (g < 0) { 332 // initialize as if previous root (i.e. forward one) was a triggered increasing event 333 return Transformer.MINUS; 334 } else { 335 // we are exactly at a root, we don't know if it is an increasing 336 // or a decreasing event, we remain in uninitialized state 337 return Transformer.UNINITIALIZED; 338 } 339 case PLUS : 340 if (g >= 0) { 341 // we have crossed the zero line on an ignored decreasing event, 342 // we must change the transformer 343 return Transformer.MIN; 344 } else { 345 // we are still in the same status 346 return previous; 347 } 348 case MINUS : 349 if (g >= 0) { 350 // we have crossed the zero line on an ignored decreasing event, 351 // we must change the transformer 352 return Transformer.MAX; 353 } else { 354 // we are still in the same status 355 return previous; 356 } 357 case MIN : 358 if (g <= 0) { 359 // we have crossed the zero line on a triggered increasing event, 360 // we must change the transformer 361 return Transformer.MINUS; 362 } else { 363 // we are still in the same status 364 return previous; 365 } 366 case MAX : 367 if (g <= 0) { 368 // we have crossed the zero line on a triggered increasing event, 369 // we must change the transformer 370 return Transformer.PLUS; 371 } else { 372 // we are still in the same status 373 return previous; 374 } 375 default : 376 // this should never happen 377 throw new MathInternalError(); 378 } 379 } 380 } 381 }; 382 383 /** Get the increasing status of triggered events. 384 * @return true if triggered events are increasing events 385 */ 386 protected abstract boolean getTriggeredIncreasing(); 387 388 /** Get next function transformer in the specified direction. 389 * @param previous transformer active on the previous point with respect 390 * to integration direction (may be null if no previous point is known) 391 * @param g current value of the g function 392 * @param forward true if integration goes forward 393 * @return next transformer transformer 394 */ 395 protected abstract Transformer selectTransformer(Transformer previous, 396 double g, boolean forward); 397}