Skip to content

Commit 6dc54f6

Browse files
committed
Add numerical integrator macro
TODO: Guard against NaNs
1 parent 327005a commit 6dc54f6

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

lib.ua

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,79 @@ PSet ← ⍚▽⋯⇡˜ⁿ2⧻⟜¤
471471
# Wrapping convolution producing the same shape as the largest input
472472
Wrap ← ⍥R=0↥⊃∩type(×√/×⊸△⍜∩fft×∩⌞⬚0↙↥◡∩△)
473473
└─╴
474+
475+
# Configuration parameters for the Ode‼ macro
476+
~OdeConfig {
477+
# Error bound
478+
ε ← 1e¯8
479+
# Initial step size
480+
H ← 0.01
481+
}
482+
483+
# Temporarily public until macro scoping bug is fixed
484+
# Import when using `Ode‼` or `Ode‼!`
485+
A‼ ←^ $"∩_(_)"+@₀⬚0⍜⧻↥₁⇌⊥10-2⊢˜⊓⊢⊏₁
486+
B‼ ↚^ $"∩_(_)"+@₀⬚0⍜⧻↥₁⇌⊥10⊢˜⊓⊢⊏₁
487+
488+
OdeImpl‼ ↚ (
489+
# Runge-Kutta-Fehlberg 4th-5th-order variable-step-size numerical integrator
490+
# From https://math.okstate.edu/people/yqwang/teaching/math4513_fall11/Notes/rungekutta.pdf
491+
⟜⊓⊃⋅⊙∘OdeConfig~H⊓A‼^0∘∩[]
492+
⍢⟜(
493+
⊙(◡(⊙⊓¤⊙⊓A‼^0¤[]
494+
{[0]
495+
[1/4 1/4]
496+
[3/8 3/32 9/32]
497+
[12/13 1932/2197 ¯7200/2197 7296/2197]
498+
[1 439/216 ¯8 3680/513 ¯845/4104]
499+
[1/2 ¯8/27 2 ¯3544/2565 1859/4104 ¯11/40]}
500+
501+
⊃∧◇(
502+
˜⊂¤×⊸⊃⋅⋅⋅∘(
503+
^0˜∩+⊙/+∪₂⌟˜∩×⊙∘°⊂⊙⊙⊙⊙⤙⊓A‼^0∘◌
504+
)
505+
)⋅⋅⋅∘
506+
507+
[[25/216 0 1408/2565 2197/4104 ¯1/5 0]
508+
[16/135 0 6656/12825 28561/56430 ¯9/50 2/55]]
509+
⊃(˜÷⍜°√/+/-)⊣ Mmp
510+
))
511+
512+
OdeConfig~ε ⊙⊙⊙⊙⊙⊙⤙₂⊓A‼^0∘⋅◌
513+
∪⌞⊙∘×⊃(×0.84√₄˜÷|⨬◌⊃(˜∘⊸˜∩+|∪₂˜∩˜⊂⋅⊙¤)≤)
514+
⊙⊙⊙⤚₂⋅⋅A‼^0∘
515+
)(⊙⊙⊙⊙⤙⊙⊙◌^1◡⋅B‼^1∘⊙⊙⊙⤚⋅⊙∘)
516+
˜∩˜⊂⊙¤⋅⊙⊙⋅A‼^0◌
517+
)
518+
519+
# More configurable version of `Ode‼`
520+
#
521+
# The first of the three functions can be used to set optional arguments, namely ε, the error bound for the integration.
522+
# The remaining two functions correspond to those of `Ode‼`.
523+
Ode‼! ← OdeImpl‼^1^2 OdeConfig!(^0($"_New"˜▽@⊙-1⊢⋅⊢)^!^0)
524+
# Numerical integrator
525+
#
526+
# Note: Due to a current bug in the interpreter, using this macro temporarily requires also importing the `A‼` macro from this library.
527+
#
528+
# Takes two functions and two values.
529+
# - The first function should take a time value and a state vector and output the derivative of the state vector.
530+
# - The second function should take anywhere from 1 to 4 arguments and return 0 or 1 for whether to continue simulating. Based on how many inputs the second function takes, it will be passed:
531+
# 1. The current time
532+
# 2. The current state vector
533+
# 3. The array of all past times
534+
# 4. The array of all past state vectors
535+
#
536+
# The two values should respectively be the initial time and the initial state vector.
537+
#
538+
# Example: Simulating a damped pendulum
539+
# This simulates the motion of a damped pendulum that begins vertical with an initial angular velocity of 12 radians per second.
540+
# ```uiua
541+
# g ← 9.81 # Gravity
542+
# L ← 1 # Pendulum length
543+
# μ ← 0.5 # Damping coefficient
544+
# Ode‼(⋅⊃[⊣|¯+˜∩×g μ÷L∿°⊟]|<10) 0 [0 12]
545+
# ```
546+
#
547+
# Uses Runge-Kutta-Fehlberg 4th-5th-order variable-step-size numerical integration.
548+
# T X ? T₀ X₀
549+
Ode‼ ← Ode‼!∘^0^1

0 commit comments

Comments
 (0)