194194 (; recf, recf2, mα, mσ, mτ) = cache
195195
196196 gen_prob = ! (
197- (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number) ||
198- (length (W. dW) == 1 )
197+ (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number)
199198 )
200- gen_prob && ( vec_χ = 2 .* floor .( false .* W . dW .+ 1 // 2 .+ oftype (W. dW, rand (W . rng, length (W . dW)))) .- true )
199+ vec_χ = gen_prob ? init_χ! ( similar (W. dW), W) : nothing
201200
202201 alg = unwrap_alg (integrator, true )
203202 alg. eigen_est === nothing ? maxeig! (integrator, cache) : alg. eigen_est (integrator)
265264 # Now uᵢ₋₂ = uₛ₋₂, uᵢ₋₁ = uₛ₋₁, uᵢ = uₛ
266265 # Similarly tᵢ₋₂ = tₛ₋₂, tᵢ₋₁ = tₛ₋₁, tᵢ = tₛ
267266
268- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
267+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
269268 Gₛ = integrator. f. g (uᵢ₋₁, p, tᵢ₋₁)
270269 u += Gₛ .* W. dW
271270 Gₛ = integrator. f. g (uᵢ, p, tᵢ)
300299 for i in 1 : length (W. dW)
301300 WikJ = W. dW[i]
302301 WikJ2 = vec_χ[i]
303- WikRange = 1 // 2 .* (W. dW .* WikJ .- (1 : length (W. dW) .== i) .* abs (dt)) # .- (1:length(W.dW) .> i) .* dt .* vec_χ .+ (1:length(W.dW) .< i) .* dt .* WikJ2)
302+ WikRange = 1 // 2 .* (
303+ W. dW .* WikJ .- (1 : length (W. dW) .== i) .* abs (dt) .-
304+ (1 : length (W. dW) .> i) .* abs (dt) .* vec_χ .+
305+ (1 : length (W. dW) .< i) .* abs (dt) .* WikJ2
306+ )
304307 uₓ = Gₛ * WikRange
305308 WikRange = 1 // 2 .* (1 : length (W. dW) .== i)
306309 uᵢ₋₂ = uᵢ + uₓ
332335 (; recf, recf2, mα, mσ, mτ) = cache. constantcache
333336 ccache = cache. constantcache
334337 gen_prob = ! (
335- (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number) ||
336- (length (W. dW) == 1 )
338+ (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number)
337339 )
338340
339341 alg = unwrap_alg (integrator, true )
362364
363365 sqrt_dt = sqrt (abs (dt))
364366 if gen_prob
365- vec_χ .= 1 // 2 .+ oftype (W. dW, rand (W. rng, length (W. dW)))
366- @. . vec_χ = 2 * floor (vec_χ) - 1
367+ init_χ! (vec_χ, W)
367368 end
368369
369370 μ = recf[start] # here κ = 0
418419 # Now uᵢ₋₂ = uₛ₋₂, uᵢ₋₁ = uₛ₋₁, uᵢ = uₛ
419420 # Similarly tᵢ₋₂ = tₛ₋₂, tᵢ₋₁ = tₛ₋₁, tᵢ = tₛ
420421
421- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
422+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
422423 integrator. f. g (Gₛ, uᵢ₋₁, p, tᵢ₋₁)
423424 @. . u += Gₛ * W. dW
424425 integrator. f. g (Gₛ, uᵢ, p, tᵢ)
458459 WikJ2 = vec_χ[i]
459460 dwrange = 1 : length (W. dW)
460461 abs_dt = abs (dt)
461- @. . WikRange = 1 // 2 * (W. dW * WikJ - (dwrange == i) * abs_dt) # + (dwrange < i) * dt * WikJ2 - (dwrange > i) * dt * vec_χ)
462+ @. . WikRange = 1 // 2 *
463+ (
464+ W. dW * WikJ - (dwrange == i) * abs_dt -
465+ (dwrange > i) * abs_dt * vec_χ +
466+ (dwrange < i) * abs_dt * WikJ2
467+ )
462468 mul! (uₓ, Gₛ, WikRange)
463469 @. . uᵢ₋₂ = uᵢ + uₓ
464470 @. . WikRange = 1 // 2 * (dwrange == i)
@@ -542,14 +548,14 @@ end
542548 end
543549
544550 Gₛ = integrator. f. g (u, p, tᵢ)
545- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
551+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
546552 u += Gₛ .* W. dW
547553 else
548554 u += Gₛ * W. dW
549555 end
550556
551557 if integrator. alg. strong_order_1
552- if (W. dW isa Number) || ( length (W . dW) == 1 ) ||
558+ if (W. dW isa Number) ||
553559 (is_diagonal_noise (integrator. sol. prob))
554560 uᵢ₋₂ = @. 1 // 2 * Gₛ * (W. dW^ 2 - abs (dt))
555561 tmp = @. u + uᵢ₋₂
@@ -633,15 +639,15 @@ end
633639 end
634640
635641 integrator. f. g (Gₛ, u, p, tᵢ)
636- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
642+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
637643 @. . u += Gₛ * W. dW
638644 else
639645 mul! (uᵢ₋₁, Gₛ, W. dW)
640646 u += uᵢ₋₁
641647 end
642648
643649 if integrator. alg. strong_order_1
644- if (W. dW isa Number) || ( length (W . dW) == 1 ) ||
650+ if (W. dW isa Number) ||
645651 (is_diagonal_noise (integrator. sol. prob))
646652 @. . uᵢ₋₂ = 1 // 2 * Gₛ * (W. dW^ 2 - abs (dt))
647653 @. . tmp = u + uᵢ₋₂
982988 end
983989 end
984990
985- if (W. dW isa Number) || ( length (W . dW) == 1 )
991+ if (W. dW isa Number)
986992 Gₛ = integrator. f. g (Û₁, p, t̂₁)
987993 uₓ += Gₛ * W. dW
988994
@@ -1168,7 +1174,7 @@ end
11681174 end
11691175 end
11701176
1171- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
1177+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
11721178 integrator. f. g (Gₛ, Û₁, p, t̂₁)
11731179 @. . uₓ += Gₛ * W. dW
11741180
@@ -1227,8 +1233,7 @@ end
12271233 (; recf, mσ, mτ, mδ) = cache
12281234
12291235 gen_prob = ! (
1230- (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number) ||
1231- (length (W. dW) == 1 )
1236+ (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number)
12321237 )
12331238
12341239 alg = unwrap_alg (integrator, true )
@@ -1245,7 +1250,7 @@ end
12451250 τ = mτ[deg_index]
12461251
12471252 sqrt_dt = sqrt (abs (dt))
1248- (gen_prob) && ( vec_χ = 2 .* floor .( 1 // 2 .+ false .* W. dW .+ rand ( length (W . dW))) .- 1 )
1253+ vec_χ = gen_prob ? init_χ! ( similar ( W. dW), W) : nothing
12491254
12501255 tᵢ₋₂ = t
12511256 uᵢ₋₂ = uprev
@@ -1289,7 +1294,7 @@ end
12891294 tᵢ₋₁ += θₛ₋₃ * (tᵢ₋₁ - tᵢ₋₂)
12901295 tᵢ₋₂ = ttmp
12911296
1292- if W. dW isa Number || length (W . dW) == 1 || is_diagonal_noise (integrator. sol. prob)
1297+ if W. dW isa Number || is_diagonal_noise (integrator. sol. prob)
12931298 # stage s-3
12941299 yₛ₋₃ = integrator. f (uᵢ₋₁, p, tᵢ₋₁)
12951300 utmp = uᵢ₋₁ + μₛ₋₃ * yₛ₋₃
@@ -1431,8 +1436,7 @@ end
14311436
14321437 ccache = cache. constantcache
14331438 gen_prob = ! (
1434- (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number) ||
1435- (length (W. dW) == 1 )
1439+ (is_diagonal_noise (integrator. sol. prob)) || (W. dW isa Number)
14361440 )
14371441
14381442 alg = unwrap_alg (integrator, true )
@@ -1459,7 +1463,9 @@ end
14591463 τ = mτ[deg_index]
14601464
14611465 sqrt_dt = sqrt (abs (dt))
1462- (gen_prob) && (vec_χ .= 2 .* floor .(1 // 2 .+ false .* vec_χ .+ rand (length (vec_χ))) .- 1 )
1466+ if gen_prob
1467+ init_χ! (vec_χ, W)
1468+ end
14631469
14641470 tᵢ₋₂ = t
14651471 @. . uᵢ₋₂ = uprev
@@ -1502,7 +1508,7 @@ end
15021508 tᵢ₋₁ += θₛ₋₃ * (tᵢ₋₁ - tᵢ₋₂)
15031509 tᵢ₋₂ = ttmp
15041510
1505- if W. dW isa Number || length (W . dW) == 1 || is_diagonal_noise (integrator. sol. prob)
1511+ if W. dW isa Number || is_diagonal_noise (integrator. sol. prob)
15061512 # stage s-3
15071513 integrator. f (yₛ₋₃, uᵢ₋₁, p, tᵢ₋₁)
15081514 @. . utmp = uᵢ₋₁ + μₛ₋₃ * yₛ₋₃
@@ -1711,7 +1717,7 @@ end
17111717 uᵢ₋₂ = integrator. f (uᵢ₋₂, p, tᵢ₋₂)
17121718 u += dt * (σ + τ) * uᵢ₋₂
17131719
1714- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
1720+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
17151721 Gₛ = integrator. f. g (uᵢ₋₁, p, tᵢ₋₁)
17161722 u += Gₛ .* W. dW
17171723
@@ -1806,7 +1812,7 @@ end
18061812 integrator. f (k, uᵢ₋₂, p, tᵢ₋₂)
18071813 @. . u += dt * (σ + τ) * k
18081814
1809- if (W. dW isa Number) || ( length (W . dW) == 1 ) || is_diagonal_noise (integrator. sol. prob)
1815+ if (W. dW isa Number) || is_diagonal_noise (integrator. sol. prob)
18101816 integrator. f. g (Gₛ, uᵢ₋₁, p, tᵢ₋₁)
18111817 @. . u += Gₛ * W. dW
18121818
@@ -1840,3 +1846,24 @@ end
18401846
18411847 integrator. u = u
18421848end
1849+
1850+ # Fill `vec_χ` with independent Rademacher (±1) samples drawn from the RNG of the
1851+ # integrator's noise process. Drawn in bulk and mapped by broadcast rather than by a
1852+ # scalar loop, so the routine does not scalar-index `vec_χ` and stays usable for array
1853+ # types that forbid it.
1854+ function init_χ! (vec_χ, W)
1855+ Random. rand! (rng (W), vec_χ)
1856+ one_χ = one (eltype (vec_χ))
1857+ vec_χ .= ifelse .(vec_χ .< 1 // 2 , - one_χ, one_χ)
1858+ return vec_χ
1859+ end
1860+
1861+ # `NoiseWrapper` does not carry its own `rng`; the generator lives on the wrapped
1862+ # source process, which may itself be a wrapper (#3188). Processes that replay a
1863+ # recorded path (`NoiseGrid`) have no generator at all, so fall back to the global
1864+ # one rather than erroring.
1865+ function rng (W)
1866+ hasfield (typeof (W), :rng ) && return W. rng
1867+ hasfield (typeof (W), :source ) && return rng (W. source)
1868+ return Random. default_rng ()
1869+ end
0 commit comments