Типы массивов, специфичные для DiffEq

Во многих случаях стандартного массива может быть недостаточно для полного хранения данных для модели. Многие решатели в DifferentialEquations.jl (только собственные методы Julia) позволяют решать задачи для типов AbstractArray, расширяя значение массива. На этой странице описываются некоторые типы AbstractArray, которые могут быть полезны при моделировании задач дифференциальных уравнений.

Секции массивов (ArrayPartitions)

Секции массивов (ArrayPartitions) в DiffEq используются для неоднородных массивов. Например, решатели DynamicalODEProblem используют их внутренним образом для преобразования отдельных частей в единый массив. Построить ArrayPartition можно с помощью RecursiveArrayTools.jl:

using RecursiveArrayTools
A = ArrayPartition(x::AbstractArray...)

где x — это массив массивов. Тогда A будет вести себя как единый массив, а его трансляция будет стабильной по типу, что позволит эффективно использовать его в собственных решателях Julia DiffEq. Это хороший способ создания массива, имеющего разные единицы для разных частей или разную степень точности.

Использование

ArrayPartition действует как один массив. A[i] индексирует первый массив, затем второй и т. д., все линейно. Но A.x — это место хранения массивов. Таким образом, для

using RecursiveArrayTools
A = ArrayPartition(y, z)

мы имеем A.x[1]==y и A.x[2]==z. Эффективна трансляция типа f.(A).

Пример. Динамические уравнения

В этом примере мы покажем использование неоднородных единиц в уравнениях динамики. У нас будут следующие массивы:

using Unitful, RecursiveArrayTools, DifferentialEquations
using LinearAlgebra

r0 = [1131.340, -2282.343, 6672.423]u"km"
v0 = [-5.64305, 4.30333, 2.42879]u"km/s"
Δt = 86400.0 * 365u"s"
μ = 398600.4418u"km^3/s^2"
rv0 = ArrayPartition(r0, v0)
(Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[1131.34 km, -2282.343 km, 6672.423 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.64305 km s^-1, 4.30333 km s^-1, 2.42879 km s^-1])

Здесь r0 — начальные положения, а v0 — начальные скорости. rv0 является начальным условием ArrayPartition. Теперь запишем нашу функцию обновления с учетом ArrayPartition:

function f(dy, y, μ, t)
    r = norm(y.x[1])
    dy.x[1] .= y.x[2]
    dy.x[2] .= -μ .* y.x[1] / r^3
end
f (generic function with 1 method)

Обратите внимание, что y.x[1] — это часть r для y, а y.x[2] — это часть v для y. Использование подобного индексирования обеспечивает стабильность типов, даже если сам массив неоднороден. Заметим, что можно также использовать, например, 2y или y.+x, и трансляция будет эффективной.

Теперь, чтобы решить наши уравнения, мы делаем то же самое, что и всегда в DiffEq:

prob = ODEProblem(f, rv0, (0.0u"s", Δt), μ)
sol = solve(prob, Vern8())
retcode: Success
Interpolation: specialized 8th order lazy interpolation
t: 14925-element Vector{Quantity{Float64, 𝐓, Unitful.FreeUnits{(s,), 𝐓, nothing}}}:
                  0.0 s
   0.5010872865302903 s
    5.511960151833193 s
    49.65749620961972 s
   344.09099029529807 s
    919.0533764696446 s
   1620.9797864665975 s
    2411.297174606073 s
   3245.7215806731824 s
    4200.321308253043 s
                      ⋮
   3.15169528456449e7 s
 3.1519082125625703e7 s
  3.152177180598552e7 s
 3.1525492491336733e7 s
 3.1528468809713744e7 s
  3.153052301989648e7 s
 3.1532337301919535e7 s
 3.1534417755378913e7 s
             3.1536e7 s
u: 14925-element Vector{ArrayPartition{Quantity{Float64}, Tuple{Vector{Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}}, Vector{Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}}}}}:
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[1131.34 km, -2282.343 km, 6672.423 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.64305 km s^-1, 4.30333 km s^-1, 2.42879 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[1128.5121841206073 km, -2280.186342651942 km, 6673.639119236024 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.6436694625389 km s^-1, 4.304580664105494 km s^-1, 2.4251316255351654 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[1100.217102647565 km, -2258.5854152557135 km, 6685.699423475585 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.649778787886409 km s^-1, 4.317022208036712 km s^-1, 2.3885114106020557 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[849.7204937464173 km, -2065.668453772683 km, 6783.977810416442 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.696876656609012 km s^-1, 4.421468139572094 km s^-1, 2.0631714481847045 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-841.2213025895506 km, -687.1542939115907 km, 7062.8169801172 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-5.698325368328203 km s^-1, 4.868180996349745 km s^-1, -0.18351261265070093 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-3777.542619913166 km, 2067.134112110032 km, 5728.944948604166 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-4.209837923943154 km s^-1, 4.424343430911492 km s^-1, -4.3103879373428 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-5519.835765354315 km, 4381.22474932109 km, 1509.0443248053725 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-0.5438725039197423 km s^-1, 1.8829679700495678 km s^-1, -7.170480733822731 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-4177.78719105982 km, 4341.084576300797 km, -4027.5530248936416 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[3.739544894847063 km s^-1, -1.9682271895725276 km s^-1, -6.065265528516156 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[7.35981319465464 km, 1405.5691509791045 km, -7120.092589718263 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[5.675094956563403 km s^-1, -4.634379554130762 km s^-1, -0.8962629329643912 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[4599.099903766753 km, -2965.1588129394418 km, -4713.237400575327 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[3.15981000502549 km s^-1, -3.779041198598221 km s^-1, 5.5462342618575216 km s^-1])
 ⋮
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[2528.887705991007 km, 224.8647124452155 km, -11948.388051998214 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[4.565660151224991 km s^-1, -3.6151467050732093 km s^-1, -1.2921946144027088 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[10384.533896362598 km, -6767.8485899879415 km, -10275.75516681439 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[2.678418597403076 km s^-1, -2.7248288063545396 km s^-1, 2.288175710976672 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[14080.937816554622 km, -11580.7537979118 km, -1810.1478676632807 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[0.10840454520311822 km s^-1, -0.8113345142380913 km s^-1, 3.6281800929569052 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[8381.542244077935 km, -9165.23132596768 km, 10380.256545910703 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-3.105339044707374 km s^-1, 2.182439338506913 km s^-1, 2.2728733445532305 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-3267.518318071178 km, 791.6638201660726 km, 9980.416213912104 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[-3.8971982694778275 km s^-1, 4.0563437739246835 km s^-1, -3.791426397696102 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[-5641.111005389567 km, 5507.423526867451 km, -3652.031907848906 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[2.6378241293739917 km s^-1, -0.7725964758708339 km s^-1, -7.383801340663307 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[2043.766577548585 km, 607.1767706461003 km, -11801.94386418947 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[4.6183267730878175 km s^-1, -3.603740687636387 km s^-1, -1.5749373843593577 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[9957.692625433827 km, -6336.485222314852 km, -10625.911924688176 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[2.831943936623866 km s^-1, -2.8233353973874222 km s^-1, 2.12844387805993 km s^-1])
 (Quantity{Float64, 𝐋, Unitful.FreeUnits{(km,), 𝐋, nothing}}[13207.331596820251 km, -9964.830981267367 km, -6223.808334445178 km], Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(km, s^-1), 𝐋 𝐓^-1, nothing}}[1.28639473314743 km s^-1, -1.740551531917572 km s^-1, 3.2769755293028027 km s^-1])

MultiScaleArrays

Функциональность многомасштабного моделирования обеспечивается пакетом MultiScaleArrays.jl. Вы можете сконструировать многомасштабную модель как расширение массива, которое, в свою очередь, может напрямую использоваться в собственных решателях Julia из пакета DifferentialEquations.jl.

Дополнительные сведения см. в файле сведений о MultiScaleArrays.jl.