diff --git a/SpeedyWeatherSSM/Manifest.toml b/SpeedyWeatherSSM/Manifest.toml new file mode 100644 index 0000000..f7455a0 --- /dev/null +++ b/SpeedyWeatherSSM/Manifest.toml @@ -0,0 +1,1011 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.4" +manifest_format = "2.0" +project_hash = "4d7cc7338286b6f128a00d1e215bbc942db42e27" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + + [deps.AbstractFFTs.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "50c3c56a52972d78e8be9fd135bfb91c9574c140" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "4.1.1" +weakdeps = ["StaticArrays"] + + [deps.Adapt.extensions] + AdaptStaticArraysExt = "StaticArrays" + +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.AssociatedLegendrePolynomials]] +git-tree-sha1 = "3204d769e06c5678b23cf928d850f2f4ad5ec8a5" +uuid = "2119f1ac-fb78-50f5-8cc0-dda848ebdb19" +version = "1.0.1" + +[[deps.Atomix]] +deps = ["UnsafeAtomics"] +git-tree-sha1 = "c3b238aa28c1bebd4b5ea4988bebf27e9a01b72b" +uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458" +version = "1.0.1" + + [deps.Atomix.extensions] + AtomixCUDAExt = "CUDA" + AtomixMetalExt = "Metal" + AtomixoneAPIExt = "oneAPI" + + [deps.Atomix.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + oneAPI = "8f75cd03-7ff8-4ecb-9b8f-daf728133b1b" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.BitInformation]] +deps = ["Distributions", "Random", "StatsBase"] +git-tree-sha1 = "2cf994e66a0886a91ba108cb3cfc044363f0bb01" +uuid = "de688a37-743e-4ac2-a6f0-bd62414d1aa7" +version = "0.6.3" + +[[deps.Blosc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Lz4_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "ef12cdd1c7fb7e1dfd6fa8fd60d4db6bc61d2f23" +uuid = "0b7ba130-8d10-5ba8-a3d6-c5182647fed9" +version = "1.21.6+0" + +[[deps.Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "8873e196c2eb87962a2048b3b8e08946535864a1" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.8+2" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CFTime]] +deps = ["Dates", "Printf"] +git-tree-sha1 = "5afb5c5ba2688ca43a9ad2e5a91cbb93921ccfa1" +uuid = "179af706-886a-5703-950a-314cd64e0468" +version = "0.1.3" + +[[deps.ChunkSplitters]] +git-tree-sha1 = "397b871ff701290cc122cca06af61c5bdf9f5605" +uuid = "ae650224-84b6-46f8-82ea-d812ca08434e" +version = "3.1.0" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.6" + +[[deps.ColorSchemes]] +deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] +git-tree-sha1 = "c785dfb1b3bfddd1da557e861b919819b82bbe5b" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.27.1" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "c7acce7a7e1078a20a285211dd73cd3941a871d6" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.12.0" + + [deps.ColorTypes.extensions] + StyledStringsExt = "StyledStrings" + + [deps.ColorTypes.weakdeps] + StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "8b3b6f87ce8f65a2b4f857528fd8d70086cd72b1" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.11.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "64e15186f0aa277e174aa81798f7eb8598e0157e" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.13.0" + +[[deps.CommonDataModel]] +deps = ["CFTime", "DataStructures", "Dates", "Preferences", "Printf", "Statistics"] +git-tree-sha1 = "98d64d5b9e5263884276656a43c45424b3a645c2" +uuid = "1fbeeb36-5f17-413c-809b-666fb144f157" +version = "0.3.7" + +[[deps.Compat]] +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.16.0" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.1.1+0" + +[[deps.ConstructionBase]] +git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.8" + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseLinearAlgebraExt = "LinearAlgebra" + ConstructionBaseStaticArraysExt = "StaticArrays" + + [deps.ConstructionBase.weakdeps] + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.Contour]] +git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.6.3" + +[[deps.Crayons]] +git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.1.1" + +[[deps.DataAPI]] +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.16.0" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.20" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.DiskArrays]] +deps = ["LRUCache", "OffsetArrays"] +git-tree-sha1 = "e0e89a60637a62d13aa2107f0acd169b9b9b77e7" +uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" +version = "0.4.6" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[deps.Distributions]] +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "4b138e4643b577ccf355377c2bc70fa975af25de" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.115" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.FFTW]] +deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] +git-tree-sha1 = "4820348781ae578893311153d69049a93d05f39d" +uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" +version = "1.8.0" + +[[deps.FFTW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4d81ed14783ec49ce9f2e168208a12ce1815aa25" +uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a" +version = "3.3.10+1" + +[[deps.FastGaussQuadrature]] +deps = ["LinearAlgebra", "SpecialFunctions", "StaticArrays"] +git-tree-sha1 = "fd923962364b645f3719855c88f7074413a6ad92" +uuid = "442a2c76-b920-505d-bb47-c5924d526838" +version = "1.0.2" + +[[deps.FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "2dd20384bf8c6d411b5c7370865b1e9b26cb2ea3" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.16.6" + + [deps.FileIO.extensions] + HTTPExt = "HTTP" + + [deps.FileIO.weakdeps] + HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" + +[[deps.FillArrays]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.13.0" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.5" + +[[deps.GPUArrays]] +deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"] +git-tree-sha1 = "62ee71528cca49be797076a76bdc654a170a523e" +uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7" +version = "10.3.1" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.1.6" + +[[deps.GenericFFT]] +deps = ["AbstractFFTs", "FFTW", "LinearAlgebra", "Reexport"] +git-tree-sha1 = "1bc01f2ea9a0226a60723794ff86b8017739f5d9" +uuid = "a8297547-1b15-4a5a-a998-a2ac5f1cef28" +version = "0.1.6" + +[[deps.HDF5]] +deps = ["Compat", "HDF5_jll", "Libdl", "MPIPreferences", "Mmap", "Preferences", "Printf", "Random", "Requires", "UUIDs"] +git-tree-sha1 = "e856eef26cf5bf2b0f95f8f4fc37553c72c8641c" +uuid = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" +version = "0.17.2" +weakdeps = ["MPI"] + + [deps.HDF5.extensions] + MPIExt = "MPI" + +[[deps.HDF5_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "LazyArtifacts", "LibCURL_jll", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "OpenSSL_jll", "TOML", "Zlib_jll", "libaec_jll"] +git-tree-sha1 = "38c8874692d48d5440d5752d6c74b0c6b0b60739" +uuid = "0234f1f7-429e-5d53-9886-15a909be8d59" +version = "1.14.2+1" + +[[deps.Hwloc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "50aedf345a709ab75872f80a2779568dc0bb461b" +uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" +version = "2.11.2+1" + +[[deps.HypergeometricFunctions]] +deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "b1c2585431c382e3fe5805874bda6aea90a95de9" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.25" + +[[deps.IntegerMathUtils]] +git-tree-sha1 = "b8ffb903da9f7b8cf695a8bead8e01814aa24b30" +uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235" +version = "0.1.2" + +[[deps.IntelOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"] +git-tree-sha1 = "10bd689145d2c3b2a9844005d01087cc1194e79e" +uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" +version = "2024.2.1+0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.2" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLD2]] +deps = ["FileIO", "MacroTools", "Mmap", "OrderedCollections", "PrecompileTools", "Requires", "TranscodingStreams"] +git-tree-sha1 = "f1a1c1037af2a4541ea186b26b0c0e7eeaad232b" +uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +version = "0.5.10" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "be3dc50a92e5a386872a493a10050136d4703f9b" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.6.1" + +[[deps.KernelAbstractions]] +deps = ["Adapt", "Atomix", "InteractiveUtils", "MacroTools", "PrecompileTools", "Requires", "StaticArrays", "UUIDs"] +git-tree-sha1 = "b9a838cd3028785ac23822cded5126b3da394d1a" +uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c" +version = "0.9.31" + + [deps.KernelAbstractions.extensions] + EnzymeExt = "EnzymeCore" + LinearAlgebraExt = "LinearAlgebra" + SparseArraysExt = "SparseArrays" + + [deps.KernelAbstractions.weakdeps] + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.LLVM]] +deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Preferences", "Printf", "Unicode"] +git-tree-sha1 = "d422dfd9707bec6617335dc2ea3c5172a87d5908" +uuid = "929cbde3-209d-540e-8aea-75f648917ca0" +version = "9.1.3" + + [deps.LLVM.extensions] + BFloat16sExt = "BFloat16s" + + [deps.LLVM.weakdeps] + BFloat16s = "ab4f0b2a-ad5b-11e8-123f-65d77653426b" + +[[deps.LLVMExtra_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "05a8bd5a42309a9ec82f700876903abce1017dd3" +uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" +version = "0.0.34+0" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "78211fb6cbc872f77cad3fc0b6cf647d923f4929" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "18.1.7+0" + +[[deps.LRUCache]] +git-tree-sha1 = "b3cc6698599b10e652832c2f23db3cab99d51b59" +uuid = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" +version = "1.6.1" +weakdeps = ["Serialization"] + + [deps.LRUCache.extensions] + SerializationExt = ["Serialization"] + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.4.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "61dfdba58e585066d8bce214c5a51eaa0539f269" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.17.0+1" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.29" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.Lz4_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "abf88ff67f4fd89839efcae2f4c39cbc4ecd0846" +uuid = "5ced341a-0733-55b8-9ab6-a4889d929147" +version = "1.10.0+1" + +[[deps.MKL_jll]] +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "oneTBB_jll"] +git-tree-sha1 = "f046ccd0c6db2832a9f639e2c669c6fe867e5f4f" +uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" +version = "2024.2.0+0" + +[[deps.MPI]] +deps = ["Distributed", "DocStringExtensions", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "PkgVersion", "PrecompileTools", "Requires", "Serialization", "Sockets"] +git-tree-sha1 = "892676019c58f34e38743bc989b0eca5bce5edc5" +uuid = "da04e1cc-30fd-572f-bb4f-1f8673147195" +version = "0.20.22" + + [deps.MPI.extensions] + AMDGPUExt = "AMDGPU" + CUDAExt = "CUDA" + + [deps.MPI.weakdeps] + AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + +[[deps.MPICH_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "7715e65c47ba3941c502bffb7f266a41a7f54423" +uuid = "7cb0a576-ebde-5e09-9194-50597f1243b4" +version = "4.2.3+0" + +[[deps.MPIPreferences]] +deps = ["Libdl", "Preferences"] +git-tree-sha1 = "c105fe467859e7f6e9a852cb15cb4301126fac07" +uuid = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267" +version = "0.1.11" + +[[deps.MPItrampoline_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "70e830dab5d0775183c99fc75e4c24c614ed7142" +uuid = "f1f71cc9-e9ae-5b93-9b94-4fe0e1ad3748" +version = "5.5.1+0" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.13" + +[[deps.MarchingCubes]] +deps = ["PrecompileTools", "StaticArrays"] +git-tree-sha1 = "301345b808264ae42e60d10a519e55c5d992969b" +uuid = "299715c1-40a9-479a-aaf9-4a633d36f717" +version = "0.1.10" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+1" + +[[deps.MicrosoftMPI_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "bc95bf4149bf535c09602e3acdf950d9b4376227" +uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" +version = "10.1.4+3" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.2.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.1.10" + +[[deps.NCDatasets]] +deps = ["CFTime", "CommonDataModel", "DataStructures", "Dates", "DiskArrays", "NetCDF_jll", "NetworkOptions", "Printf"] +git-tree-sha1 = "2c9dc92001ac06d432f363f37ff5552954d9947c" +uuid = "85f8d34a-cbdd-5861-8df4-14fed0d494ab" +version = "0.14.6" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.0.2" + +[[deps.NetCDF_jll]] +deps = ["Artifacts", "Blosc_jll", "Bzip2_jll", "HDF5_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "OpenMPI_jll", "XML2_jll", "Zlib_jll", "Zstd_jll", "libzip_jll"] +git-tree-sha1 = "a8af1798e4eb9ff768ce7fdefc0e957097793f15" +uuid = "7243133f-43d8-5620-bbf4-c2c921802cf3" +version = "400.902.209+0" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.OffsetArrays]] +git-tree-sha1 = "5e1897147d1ff8d98883cda2be2187dcf57d8f0c" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.15.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.23+4" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+2" + +[[deps.OpenMPI_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML", "Zlib_jll"] +git-tree-sha1 = "2dace87e14256edb1dd0724ab7ba831c779b96bd" +uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" +version = "5.0.6+0" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "7493f61f55a6cce7325f197443aa80d32554ba10" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.15+1" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.5+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.7.0" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.31" + +[[deps.ParticleDA]] +deps = ["ChunkSplitters", "HDF5", "LinearAlgebra", "MPI", "PDMats", "Random", "Statistics", "StructArrays", "Test", "TimerOutputs", "YAML"] +git-tree-sha1 = "8799e295a625c885b8f1e7ce3711ced50c07afd1" +repo-rev = "238af83" +repo-url = "https://github.com/Team-RADDISH/ParticleDA.jl" +uuid = "61cd1fb4-f4c4-4bc8-80c6-ea5639a6ca2e" +version = "1.2.0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.10.0" + +[[deps.PkgVersion]] +deps = ["Pkg"] +git-tree-sha1 = "f9501cc0430a26bc3d156ae1b5b0c1b47af4d6da" +uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688" +version = "0.3.3" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.Primes]] +deps = ["IntegerMathUtils"] +git-tree-sha1 = "cb420f77dc474d23ee47ca8d14c90810cafe69e7" +uuid = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" +version = "0.5.6" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.ProgressMeter]] +deps = ["Distributed", "Printf"] +git-tree-sha1 = "8f6bc219586aef8baf0ff9a5fe16ee9c70cb65e4" +uuid = "92933f4c-e287-5a05-a399-4b506db050ca" +version = "1.10.2" + +[[deps.PtrArrays]] +git-tree-sha1 = "77a42d78b6a92df47ab37e177b2deac405e1c88f" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.2.1" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "cda3b045cf9ef07a08ad46731f5a3165e56cf3da" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.11.1" + + [deps.QuadGK.extensions] + QuadGKEnzymeExt = "Enzyme" + + [deps.QuadGK.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "852bd0f55565a9e973fcfee83a84413270224dc4" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.8.0" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "58cdd8fb2201a6267e1db87ff148dd6c1dbd8ad8" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.5.1+0" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.1" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "64cca0c26b4f31ba18f13f6c12af7c85f478cfde" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.5.0" + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + + [deps.SpecialFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + +[[deps.SpeedyWeather]] +deps = ["AbstractFFTs", "Adapt", "AssociatedLegendrePolynomials", "BitInformation", "CodecZlib", "Dates", "DocStringExtensions", "FFTW", "FastGaussQuadrature", "GPUArrays", "GenericFFT", "JLD2", "KernelAbstractions", "LinearAlgebra", "NCDatasets", "Primes", "Printf", "ProgressMeter", "Random", "Statistics", "TOML", "UnicodePlots"] +git-tree-sha1 = "74218651ed7254a03c5cec32df8b3acd32835780" +uuid = "9e226e20-d153-4fed-8a5b-493def4f21a9" +version = "0.12.1" + + [deps.SpeedyWeather.extensions] + SpeedyWeatherCUDAExt = "CUDA" + SpeedyWeatherGeoMakieExt = "GeoMakie" + SpeedyWeatherJLArraysExt = "JLArrays" + SpeedyWeatherMakieExt = "Makie" + + [deps.SpeedyWeather.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + GeoMakie = "db073c08-6b98-4ee5-b6a4-5efafb3259c6" + JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "777657803913ffc7e8cc20f0fd04b634f871af8f" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.9.8" + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + + [deps.StaticArrays.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "192954ef1208c7019899fbf8049e717f92959682" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.3" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.10.0" + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.7.0" + +[[deps.StatsBase]] +deps = ["AliasTables", "DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "29321314c920c26684834965ec2ce0dacc9cf8e5" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.34.4" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "b423576adc27097764a90e163157bcfc9acf0f46" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "1.3.2" + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + + [deps.StatsFuns.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.StringEncodings]] +deps = ["Libiconv_jll"] +git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb" +uuid = "69024149-9ee7-55f6-a4c4-859efe599b68" +version = "0.3.7" + +[[deps.StructArrays]] +deps = ["ConstructionBase", "DataAPI", "Tables"] +git-tree-sha1 = "f4dc295e983502292c4c3f951dbb4e985e35b3be" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.6.18" +weakdeps = ["Adapt", "GPUArraysCore", "SparseArrays", "StaticArrays"] + + [deps.StructArrays.extensions] + StructArraysAdaptExt = "Adapt" + StructArraysGPUArraysCoreExt = "GPUArraysCore" + StructArraysSparseArraysExt = "SparseArrays" + StructArraysStaticArraysExt = "StaticArrays" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.2.1+1" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.12.0" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.TimerOutputs]] +deps = ["ExprTools", "Printf"] +git-tree-sha1 = "d7298ebdfa1654583468a487e8e83fae9d72dac3" +uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" +version = "0.5.26" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.11.3" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.UnicodePlots]] +deps = ["ColorSchemes", "ColorTypes", "Contour", "Crayons", "Dates", "LinearAlgebra", "MarchingCubes", "NaNMath", "PrecompileTools", "Printf", "SparseArrays", "StaticArrays", "StatsBase"] +git-tree-sha1 = "f18128aa9e5cf059426a91bdc750b1f63a2fdcd9" +uuid = "b8865327-cd53-5732-bb35-84acbb429228" +version = "3.7.1" + + [deps.UnicodePlots.extensions] + FreeTypeExt = ["FileIO", "FreeType"] + ImageInTerminalExt = "ImageInTerminal" + IntervalSetsExt = "IntervalSets" + TermExt = "Term" + UnitfulExt = "Unitful" + + [deps.UnicodePlots.weakdeps] + FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" + FreeType = "b38be410-82b0-50bf-ab77-7b57e271db43" + ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254" + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + Term = "22787eb5-b846-44ae-b979-8e399b8463ab" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.UnsafeAtomics]] +git-tree-sha1 = "b13c4edda90890e5b04ba24e20a310fbe6f249ff" +uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f" +version = "0.3.0" +weakdeps = ["LLVM"] + + [deps.UnsafeAtomics.extensions] + UnsafeAtomicsLLVM = ["LLVM"] + +[[deps.XML2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] +git-tree-sha1 = "a2fccc6559132927d4c5dc183e3e01048c6dcbd6" +uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" +version = "2.13.5+0" + +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "15e637a697345f6743674f1322beefbc5dcd5cfc" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.6.3+0" + +[[deps.YAML]] +deps = ["Base64", "Dates", "Printf", "StringEncodings"] +git-tree-sha1 = "dea63ff72079443240fbd013ba006bcbc8a9ac00" +uuid = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" +version = "0.4.12" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "555d1076590a6cc2fdee2ef1469451f872d8b41b" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.6+1" + +[[deps.libaec_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "46bf7be2917b59b761247be3f317ddf75e50e997" +uuid = "477f73a3-ac25-53e9-8cc3-50b2fa2566f0" +version = "1.1.2+0" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.8.0+1" + +[[deps.libzip_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "OpenSSL_jll", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "e797fa066eba69f4c0585ffbd81bc780b5118ce2" +uuid = "337d8026-41b4-5cde-a456-74a10e5b31d1" +version = "1.11.2+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.52.0+1" + +[[deps.oneTBB_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "7d0ea0f4895ef2f5cb83645fa689e52cb55cf493" +uuid = "1317d2d5-d96f-522e-a858-c73665f53c3e" +version = "2021.12.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" diff --git a/SpeedyWeatherSSM/Project.toml b/SpeedyWeatherSSM/Project.toml new file mode 100644 index 0000000..670face --- /dev/null +++ b/SpeedyWeatherSSM/Project.toml @@ -0,0 +1,22 @@ +name = "SpeedyWeatherSSM" +uuid = "0d1ea686-ee24-4a74-b4ed-044400b22b75" +authors = ["Matt Graham"] +version = "0.1.0" + +[deps] +FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" +HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" +ParticleDA = "61cd1fb4-f4c4-4bc8-80c6-ea5639a6ca2e" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SpeedyWeather = "9e226e20-d153-4fed-8a5b-493def4f21a9" + +[compat] +ParticleDA = "1.2" +SpeedyWeather = "0.12" + +[extras] +ReadOnlyArrays = "988b38a3-91fc-5605-94a2-ee2116b3bd83" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test", "ReadOnlyArrays"] diff --git a/SpeedyWeatherSSM/src/SpeedyWeatherSSM.jl b/SpeedyWeatherSSM/src/SpeedyWeatherSSM.jl new file mode 100644 index 0000000..c0cc1ae --- /dev/null +++ b/SpeedyWeatherSSM/src/SpeedyWeatherSSM.jl @@ -0,0 +1,583 @@ +module SpeedyWeatherSSM + +using FillArrays +using HDF5 +using ParticleDA +using Random +using SpeedyWeather +using SpeedyWeather.RingGrids + +LAYERED_VARIABLES = (:vor, :div, :temp, :humid) +SURFACE_VARIABLES = (:pres,) + +function equispaced_lat_lon_grid(T, n_lat, n_lon) + lat_interval = 180 / n_lat + lon_interval = 360 / n_lon + lat_range = (-90 + lat_interval/2):lat_interval:90 + lon_range = (-180 + lon_interval/2):lon_interval:180 + lat_lon_pairs = [(T(lat), T(lon)) for lat in lat_range for lon in lon_range] + collect(reshape(reinterpret(T, lat_lon_pairs), (2, :))) +end + +Base.@kwdef struct GaussianRandomFieldParameters{T<:AbstractFloat} + output_scale::T = 1. + length_scale::T = 0.1 +end + +Base.@kwdef struct SpeedyParameters{T<:AbstractFloat, M<:SpeedyWeather.AbstractModel} + spectral_truncation::Int = 31 + n_layers::Int = 8 + n_days::T = 0.25 + start_date::DateTime = DateTime(2000, 1, 1) + float_type::Type{T} = Float64 + model_type::Type{M} = PrimitiveWetModel + observed_variable::Tuple{Symbol, Symbol} = (:physics, :precip_large_scale) + observed_coordinates::Matrix{T} = equispaced_lat_lon_grid(float_type, 6, 12) + observation_noise_std::T = 0.1 + initial_state_grf_parameters::Dict{Symbol, GaussianRandomFieldParameters{T}} = Dict( + :vor => GaussianRandomFieldParameters(; output_scale=5e-7), + :div => GaussianRandomFieldParameters(; output_scale=5e-7), + :temp => GaussianRandomFieldParameters(; output_scale=2e0), + :humid => GaussianRandomFieldParameters(; output_scale=1e-5), + :pres => GaussianRandomFieldParameters(; output_scale=2e-3), + ) + state_noise_grf_parameters::Dict{Symbol, GaussianRandomFieldParameters{T}} = Dict( + :vor => GaussianRandomFieldParameters(; output_scale=5e-8), + :div => GaussianRandomFieldParameters(; output_scale=5e-8), + :temp => GaussianRandomFieldParameters(; output_scale=2e-1), + :humid => GaussianRandomFieldParameters(; output_scale=1e-6), + :pres => GaussianRandomFieldParameters(; output_scale=2e-4), + ) +end + +struct SpeedyModel{ + T<:AbstractFloat, + G<:SpeedyWeather.AbstractSpectralGrid, + M<:SpeedyWeather.AbstractModel, + I<:SpeedyWeather.RingGrids.AbstractInterpolator, + P<:SpeedyWeather.AbstractPrognosticVariables, + D<:SpeedyWeather.AbstractDiagnosticVariables +} + parameters::SpeedyParameters{T, M} + spectral_grid::G + model::M + prognostic_variables::Vector{P} + diagnostic_variables::Vector{D} + variable_names::Tuple + n_layered_variables::Int + n_surface_variables::Int + n_observed_points::Int + observation_interpolator::I + initial_state_grf_scale_factors::Dict{Symbol, Vector{T}} + state_noise_grf_scale_factors::Dict{Symbol, Vector{T}} +end + +function init(parameters::SpeedyParameters{T, M}, n_tasks::Int=1) where { + T<:AbstractFloat, M<:SpeedyWeather.AbstractModel +} + spectral_grid = SpectralGrid(; + NF=T, trunc=parameters.spectral_truncation, nlayers=parameters.n_layers + ) + feedback = SpeedyWeather.Feedback(; verbose=false) + model = M(; spectral_grid, feedback) + model.output.active = false + simulation = initialize!(model; time=parameters.start_date) + (; prognostic_variables, diagnostic_variables) = simulation + SpeedyWeather.set_period!( + prognostic_variables.clock, SpeedyWeather.Day(parameters.n_days) + ) + SpeedyWeather.initialize!(prognostic_variables.clock, model.time_stepping) + # We need separate copies of prognostic and diagnostic variables for each task to + # allow independent parallel read-write access + per_task_prognostic_variables = Vector{typeof(prognostic_variables)}(undef, n_tasks) + per_task_diagnostic_variables = Vector{typeof(diagnostic_variables)}(undef, n_tasks) + per_task_prognostic_variables[1] = prognostic_variables + per_task_diagnostic_variables[1] = diagnostic_variables + for t in 2:n_tasks + per_task_prognostic_variables[t] = PrognosticVariables(spectral_grid, model) + copy!(per_task_prognostic_variables[t], prognostic_variables) + per_task_diagnostic_variables[t] = DiagnosticVariables(spectral_grid) + end + variable_names = SpeedyWeather.prognostic_variables(model) + n_layered_variables = count( + SpeedyWeather.has(model, var) for var in LAYERED_VARIABLES + ) + n_surface_variables = count( + SpeedyWeather.has(model, var) for var in SURFACE_VARIABLES + ) + n_observed_points = size(parameters.observed_coordinates, 2) + observation_interpolator = SpeedyWeather.AnvilInterpolator( + T, spectral_grid.Grid, spectral_grid.nlat_half, n_observed_points + ) + SpeedyWeather.RingGrids.update_locator!( + observation_interpolator, + parameters.observed_coordinates[1, :], + parameters.observed_coordinates[2, :] + ) + initial_state_grf_scale_factors = Dict( + name => get_grf_coefficient_scale_factors( + parameters.initial_state_grf_parameters[name], + parameters.spectral_truncation, + model.spectral_transform.norm_sphere + ) + for name in variable_names + ) + state_noise_grf_scale_factors = Dict( + name => get_grf_coefficient_scale_factors( + parameters.state_noise_grf_parameters[name], + parameters.spectral_truncation, + model.spectral_transform.norm_sphere + ) + for name in variable_names + ) + return SpeedyModel( + parameters, + spectral_grid, + model, + per_task_prognostic_variables, + per_task_diagnostic_variables, + variable_names, + n_layered_variables, + n_surface_variables, + n_observed_points, + observation_interpolator, + initial_state_grf_scale_factors, + state_noise_grf_scale_factors + ) +end + +function ParticleDA.get_state_dimension(model::SpeedyModel) + (model.parameters.spectral_truncation + 1)^2 * ( + model.parameters.n_layers * model.n_layered_variables + model.n_surface_variables + ) +end + +function ParticleDA.get_observation_dimension(model::SpeedyModel) + model.n_observed_points +end + +function update_spectral_coefficients_from_vector!( + spectral_coefficients::AbstractVector{Complex{T}}, + vector::AbstractVector{T}, + spectral_truncation::Int +) where {T <: AbstractFloat} + n_row, n_col = spectral_truncation + 2, spectral_truncation + 1 + # First column of spectral_coefficients (order = m = 0) are real-valued and we skip + # last row (degree = l = n_row - 1) as used only for computing meridional derivative + # for vector valued fields. LowerTriangularMatrix allows vector (flat) indexing + # skipping zero upper-triangular entries + spectral_coefficients[1:n_row - 1] .= vector[1:n_row - 1] + # Zero entry corresponding to last row as not used for scalar fields + spectral_coefficients[n_row] = 0 + # vector index is i, spectral coefficient (flat) index is j + i = n_row - 1 + j = n_row + for col_index in 2:n_col + # Slice corresponding to column has non-zero entries from col_index row and we + # ignore last row as used only for computing meridional derivative for vector + # valued fields + slice_size = n_row - col_index + # Reinterpret real valued state coefficients to complex spectral coefficients + spectral_coefficients[j + 1:j + slice_size] .= reinterpret( + Complex{T}, vector[i + 1:i + 2 * slice_size] + ) + # Zero entry corresponding to last row as not use for scalar fields + spectral_coefficients[j + slice_size + 1] = 0 + # Update vector and spectral coefficient indices, adding 1 offset + # to latter to skip entries corresponding to last row + i = i + 2 * slice_size + j = j + 1 + slice_size + end +end + +function map_over_state_vector_slices( + map_function::Function, + state::AbstractVector{T}, + variable_names::Tuple, + spectral_truncation::Int, + n_layers::Int, +) where {T <: AbstractFloat} + start_index = 1 + dim_spectral = (spectral_truncation + 1)^2 + for name in LAYERED_VARIABLES + if name in variable_names + for layer_index in 1:n_layers + end_index = start_index + dim_spectral - 1 + map_function( + view(state, start_index:end_index), + name, + layer_index, + ) + start_index = end_index + 1 + end + end + end + for name in SURFACE_VARIABLES + if name in variable_names + map_function( + view(state, start_index:start_index + dim_spectral - 1), + name, + nothing, + ) + end + end +end + +function map_over_spectral_coefficients_and_state_vector_slices( + map_function::Function, + prognostic_variables::SpeedyWeather.PrognosticVariables{T}, + state::AbstractVector{T}, + variable_names::Tuple, + leapfrog_step::Int +) where {T <: AbstractFloat} + function outer_map_function(state_slice, name, layer_index) + spectral_coefficients = getproperty(prognostic_variables, name)[leapfrog_step] + if !isnothing(layer_index) + spectral_coefficients = view(spectral_coefficients, :, layer_index) + end + map_function(spectral_coefficients, state_slice) + end + map_over_state_vector_slices( + outer_map_function, + state, + variable_names, + prognostic_variables.trunc, + prognostic_variables.nlayers, + ) +end + +function update_prognostic_variables_from_state_vector!( + prognostic_variables::SpeedyWeather.PrognosticVariables{T}, + state::AbstractVector{T}, + variable_names::Tuple; + leapfrog_step::Int = 1 +) where {T <: AbstractFloat} + spectral_truncation = prognostic_variables.trunc + map_over_spectral_coefficients_and_state_vector_slices( + (c, v) -> update_spectral_coefficients_from_vector!(c, v, spectral_truncation), + prognostic_variables, + state, + variable_names, + leapfrog_step + ) +end + +function update_prognostic_variables_from_state_vector!( + model::SpeedyModel{T}, state::AbstractVector{T}, task_index::Int +) where {T <: AbstractFloat} + update_prognostic_variables_from_state_vector!( + model.prognostic_variables[task_index], + state, + model.variable_names; + leapfrog_step=1 + ) + # Zero coefficients for second leapfrog step (corresponding to initial state) + update_prognostic_variables_from_state_vector!( + model.prognostic_variables[task_index], + Zeros(ParticleDA.get_state_dimension(model)), + model.variable_names; + leapfrog_step=2 + ) +end + +function update_vector_from_spectral_coefficients!( + vector::AbstractVector{T}, + spectral_coefficients::AbstractVector{Complex{T}}, + spectral_truncation::Int; + increment::Bool = false +) where {T <: AbstractFloat} + n_row, n_col = spectral_truncation + 2, spectral_truncation + 1 + update! = increment ? (lhs, rhs) -> (lhs .+= rhs) : (lhs, rhs) -> (lhs .= rhs) + # First column of spectral_coefficients (order = m = 0) are real-valued and we skip + # last row (degree = l = n_row - 1) as used only for computing meridional derivative + # for vector valued fields. LowerTriangularMatrix allows vector (flat) indexing + # skipping zero upper-triangular entries + @views update!(vector[1:n_row - 1], real(spectral_coefficients[1:n_row - 1])) + # vector index is i, spectral coefficient (flat) index is j + i = n_row - 1 + j = n_row + for col_index in 2:n_col + # Slice corresponding to column has non-zero entries from col_index row and we + # ignore last row as used only for computing meridional derivative for vector + # valued fields + slice_size = n_row - col_index + # Reinterpret complex valued spectral coefficients to extract both real and + # imaginary components + @views update!( + vector[i + 1:i + 2 * slice_size], + reinterpret(T, spectral_coefficients[j + 1:j + slice_size]) + ) + # Update vector and spectral coefficient indices, adding 1 offset + # to latter to skip entries corresponding to last row + i = i + 2 * slice_size + j = j + 1 + slice_size + end +end + +function update_state_vector_from_prognostic_variables!( + state::AbstractVector{T}, + prognostic_variables::SpeedyWeather.PrognosticVariables{T}, + variable_names::Tuple; + leapfrog_step::Int = 1 +) where {T <: AbstractFloat} + spectral_truncation = prognostic_variables.trunc + map_over_spectral_coefficients_and_state_vector_slices( + (c, v) -> update_vector_from_spectral_coefficients!(v, c, spectral_truncation), + prognostic_variables, + state, + variable_names, + leapfrog_step + ) +end + +function update_state_vector_from_prognostic_variables!( + state::AbstractVector{T}, model::SpeedyModel{T}, task_index::Int +) where {T <: AbstractFloat} + update_state_vector_from_prognostic_variables!( + state, + model.prognostic_variables[task_index], + model.variable_names + ) +end + +function update_clock_from_time_index!(clock::SpeedyWeather.Clock, time_index::Int) + clock.time = clock.start + clock.n_timesteps * clock.Δt * (time_index - 1) + clock.timestep_counter = clock.n_timesteps * (time_index - 1) +end + +function update_clock_from_time_index!( + model::SpeedyModel, time_index::Int, task_index::Int +) + update_clock_from_time_index!( + model.prognostic_variables[task_index].clock, time_index + ) +end + +function get_observed_variable_field( + diagnostic_variables::DiagnosticVariables, model::SpeedyModel +) + observed_outer, observed_inner = model.parameters.observed_variable + getfield(getfield(diagnostic_variables, observed_outer), observed_inner) +end + +function update_prognostic_and_diagnostic_variables_from_state_vector!( + model::SpeedyModel{T}, state::AbstractVector{T}, task_index::Int +) where {T <: AbstractFloat} + update_prognostic_variables_from_state_vector!(model, state, task_index) + SpeedyWeather.transform!( + model.diagnostic_variables[task_index], + model.prognostic_variables[task_index], + 1, + model.model, + initialize=true + ) +end + +function add_noise_to_state_vector!( + state::AbstractVector{T}, + spectral_truncation::Int, + n_layers::Int, + variable_names::Tuple, + grf_scale_factors::Dict{Symbol, Vector{T}}, + rng::AbstractRNG +) where {T <: AbstractFloat} + n_row, n_col = spectral_truncation + 2, spectral_truncation + 1 + spectral_coefficients = SpeedyWeather.LowerTriangularMatrix{Complex{T}}( + undef, n_row, n_col + ) + function map_function(state_slice, name, layer_index) + generate_random_spectral_coefficients!( + spectral_coefficients, + spectral_truncation, + grf_scale_factors[name], + rng + ) + update_vector_from_spectral_coefficients!( + state_slice, spectral_coefficients, spectral_truncation; increment=true + ) + end + map_over_state_vector_slices( + map_function, + state, + variable_names, + spectral_truncation, + n_layers, + ) +end + +function get_grf_coefficient_scale_factors( + parameters::GaussianRandomFieldParameters{T}, + spectral_truncation::Int, + norm_sphere::T +) where {T <: AbstractFloat} + el_max = spectral_truncation + 1 + (; output_scale, length_scale) = parameters + norm_factor = norm_sphere * output_scale / sqrt( + sum((2 * el + 1) * exp(-2 * length_scale^2 * el * (el + 1)) for el in 1:el_max) + ) + scale_factors = zeros(T, el_max) + # el = 1 case corresponds to mean - assume zero-mean + for el in 2:el_max + scale_factors[el] = norm_factor * exp(-length_scale^2 * el * (el + 1)) + end + return scale_factors +end + +function generate_random_spectral_coefficients!( + spectral_coefficients::AbstractVector{Complex{T}}, + spectral_truncation::Int, + scale_factors::AbstractVector{T}, + rng::AbstractRNG +) where {T <: AbstractFloat} + el_m = 0 + @inbounds for m in 1:spectral_truncation + 1 + for el in m:spectral_truncation + 2 + el_m += 1 + # Don't generate coefficients in last row (used only for meridional deriv.) + (el == spectral_truncation + 2) && continue + spectral_coefficients[el_m] = scale_factors[el] * randn(rng, Complex{T}) + end + end +end + +ParticleDA.get_state_eltype(model::SpeedyModel{T}) where {T<:AbstractFloat} = T + +ParticleDA.get_observation_eltype(model::SpeedyModel{T}) where {T<:AbstractFloat} = T + +function ParticleDA.sample_initial_state!( + state::AbstractVector{T}, model::SpeedyModel{T}, rng::R, task_index::Int=1 +) where {T<:AbstractFloat, R<:AbstractRNG} + SpeedyWeather.initialize!( + model.prognostic_variables[task_index], + model.model.initial_conditions, + model.model + ) + update_state_vector_from_prognostic_variables!(state, model, task_index) + add_noise_to_state_vector!( + state, + model.parameters.spectral_truncation, + model.parameters.n_layers, + model.variable_names, + model.initial_state_grf_scale_factors, + rng + ) +end + +function ParticleDA.update_state_deterministic!( + state::AbstractVector{T}, model::SpeedyModel{T}, time_index::Int, task_index::Int=1 +) where {T<:AbstractFloat} + update_prognostic_variables_from_state_vector!(model, state, task_index) + update_clock_from_time_index!(model, time_index, task_index) + SpeedyWeather.time_stepping!( + model.prognostic_variables[task_index], + model.diagnostic_variables[task_index], + model.model + ) + update_state_vector_from_prognostic_variables!(state, model, task_index) +end + +function ParticleDA.update_state_stochastic!( + state::AbstractVector{T}, model::SpeedyModel{T}, rng::G, task_index::Int=1 +) where {T<:AbstractFloat, G<:AbstractRNG} + add_noise_to_state_vector!( + state, + model.parameters.spectral_truncation, + model.parameters.n_layers, + model.variable_names, + model.state_noise_grf_scale_factors, + rng + ) +end + +function ParticleDA.get_observation_mean_given_state!( + observation_mean::AbstractVector{T}, + state::AbstractVector{T}, + model::SpeedyModel{T}, + task_index::Int=1 +) where {T<:AbstractFloat} + update_prognostic_and_diagnostic_variables_from_state_vector!( + model, state, task_index + ) + observed_field_grid = get_observed_variable_field( + model.diagnostic_variables[task_index], model + ) + SpeedyWeather.interpolate!( + observation_mean, observed_field_grid, model.observation_interpolator + ) +end + +function ParticleDA.sample_observation_given_state!( + observation::AbstractVector{T}, + state::AbstractVector{T}, + model::SpeedyModel{T}, + rng::G, + task_index::Int=1 +) where {T<:AbstractFloat, G<:AbstractRNG} + ParticleDA.get_observation_mean_given_state!(observation, state, model, task_index) + observation .+= ( + model.parameters.observation_noise_std + * randn(rng, T, ParticleDA.get_observation_dimension(model)) + ) +end + +function ParticleDA.get_log_density_observation_given_state( + observation::AbstractVector{T}, + state::AbstractVector{T}, + model::SpeedyModel{T}, + task_index::Int=1 +) where {T<:AbstractFloat} + observation_mean = Vector{T}(undef, ParticleDA.get_observation_dimension(model)) + ParticleDA.get_observation_mean_given_state!( + observation_mean, state, model, task_index + ) + return ( + -sum((observation - observation_mean).^2) + / (2 * model.parameters.observation_noise_std^2) + ) + +end + +const HDF5FileOrGroup = Union{HDF5.File, HDF5.Group} + +function write!( + group::HDF5FileOrGroup, key::String, value::Union{Number, String, Array} +) + attributes(group)[key] = value +end + +function write!(group::HDF5FileOrGroup, key::String, value::Union{Symbol, DateTime}) + attributes(group)[key] = string(value) +end + +function write!(group::HDF5FileOrGroup, key::String, value::Type) + attributes(group)[key] = string(nameof(value)) +end + +function write!( + group::HDF5FileOrGroup, key::String, value::NTuple{N, T} +) where {N, T <: Union{Number, String, Symbol, Type}} + subgroup = create_group(group, key) + for (index, val) in enumerate(value) + write!(subgroup, string(index), val) + end +end + +function write!(group::HDF5FileOrGroup, key::String, value::Dict) + subgroup = create_group(group, key) + for (k, v) in value + write!(subgroup, string(k), v) + end +end + +function write!(group::HDF5FileOrGroup, key::String, value) + subgroup = create_group(group, key) + for name in fieldnames(typeof(value)) + write!(subgroup, string(name), getfield(value, name)) + end +end + +function ParticleDA.write_model_metadata(file::HDF5.File, model::SpeedyModel) + write!(file, "parameters", model.parameters) +end + +end diff --git a/SpeedyWeatherSSM/test/runtests.jl b/SpeedyWeatherSSM/test/runtests.jl new file mode 100644 index 0000000..2becb45 --- /dev/null +++ b/SpeedyWeatherSSM/test/runtests.jl @@ -0,0 +1,144 @@ +using ParticleDA +using Random +using Test +using ReadOnlyArrays +using SpeedyWeather +using SpeedyWeatherSSM + + +@testset ( + "equispaced_lat_lon_grid with T=$T n_lat=$n_lat, n_lon=$n_lon" + ) for T in (Float32, Float64), n_lat in (1, 3), n_lon in (1, 2) + lat_lon_pairs = SpeedyWeatherSSM.equispaced_lat_lon_grid(T, n_lat, n_lon) + @test lat_lon_pairs isa Matrix{T} + @test size(lat_lon_pairs) == (2, n_lat * n_lon) + @test all(-90 .<= lat_lon_pairs[1, :] .<= 90) + @test all(-180 .<= lat_lon_pairs[2, :] .<= 180) +end + +function check_consistency_vector_and_spectral_coefficients( + vector::Vector{T}, spectral_coefficients::LowerTriangularMatrix{Complex{T}} +) where {T <: AbstractFloat} + n_row, n_col = size(spectral_coefficients, as=Matrix) + # Test first (n_row - 1) entries corresponding to real component of first column + @test all(vector[1:n_row - 1] == real(spectral_coefficients[1:n_row - 1])) + # Test remaining entries correspond to interleaved real and imaginary components + # scanning across columns + vector_index = n_row + for col_index in 2:n_col + for row_index in col_index:(n_row - 1) + @test vector[vector_index] == real( + spectral_coefficients[row_index, col_index] + ) + @test vector[vector_index + 1] == imag( + spectral_coefficients[row_index, col_index] + ) + vector_index += 2 + end + end +end + +@testset ( + "update_spectral_coefficients_from_vector with T = $T, trunc = $spectral_truncation" +) for T in (Float32, Float64), spectral_truncation in (1, 7, 15) + rng = Random.Xoshiro(1234) + vector = randn(T, (spectral_truncation + 1)^2) + n_row, n_col = spectral_truncation + 2, spectral_truncation + 1 + spectral_coefficients = SpeedyWeather.LowerTriangularMatrix{Complex{T}}( + undef, n_row, n_col + ) + # Set coefficients in last row to NaN - these should be replaced with zero + for col_index in 1:n_col + spectral_coefficients[n_row, col_index] = NaN + end + # Wrap vector as read-only to check not being mutated + SpeedyWeatherSSM.update_spectral_coefficients_from_vector!( + spectral_coefficients, ReadOnlyVector(vector), spectral_truncation + ) + # Check last row entries all zero + for col_index in 1:n_col + @test spectral_coefficients[n_row, col_index] == 0 + end + check_consistency_vector_and_spectral_coefficients(vector, spectral_coefficients) +end + +@testset ( + "update_vector_from_spectral_coefficients with T = $T, trunc = $spectral_truncation" +) for T in (Float32, Float64), spectral_truncation in (1, 7, 15) + rng = Random.Xoshiro(1234) + vector = Vector{T}(undef, (spectral_truncation + 1)^2) + n_row, n_col = spectral_truncation + 2, spectral_truncation + 1 + spectral_coefficients = SpeedyWeather.LowerTriangularMatrix{Complex{T}}( + undef, n_row, n_col + ) + # First column (order = m = 0) coefficients real-valued + spectral_coefficients[1:n_row] = randn(rng, T, n_row) + # Remainder of coefficients complex valued + spectral_coefficients[n_row + 1:end] = randn( + rng, Complex{T}, length(spectral_coefficients) - n_row + ) + # Set coefficients in last row to NaN - these should be ignored + for col_index in 1:n_col + spectral_coefficients[n_row, col_index] = NaN + end + # Wrap spectral_coefficient as read-only to check not being mutated + SpeedyWeatherSSM.update_vector_from_spectral_coefficients!( + vector, ReadOnlyVector(spectral_coefficients), spectral_truncation + ) + # Check no NaNs from last row ended up in vector + @test !any(isnan.(vector)) + check_consistency_vector_and_spectral_coefficients(vector, spectral_coefficients) +end + +@testset ( + "Updating prognostic variables to/from state vector with \ + T=$T, spectral_truncation=$spectral_truncation, n_layers=$n_layers" + ) for T in (Float32, Float64), spectral_truncation in (7, 15), n_layers in (1, 8) + rng = Random.Xoshiro(1234) + spectral_grid = SpectralGrid(; + NF=T, trunc=spectral_truncation, nlayers=n_layers + ) + layered_variables = (:vor, :div, :temp, :humid) + surface_variables = (:pres,) + all_variables = (layered_variables..., surface_variables...) + state_dimension = (spectral_truncation + 1)^2 * ( + n_layers * length(layered_variables) + length(surface_variables) + ) + state = rand(rng, T, state_dimension) + prognostic_variables_1 = SpeedyWeather.PrognosticVariables(spectral_grid) + prognostic_variables_1_init = SpeedyWeather.PrognosticVariables(spectral_grid) + SpeedyWeather.copy!(prognostic_variables_1_init, prognostic_variables_1) + prognostic_variables_2 = SpeedyWeather.PrognosticVariables(spectral_grid) + SpeedyWeatherSSM.update_prognostic_variables_from_state_vector!( + prognostic_variables_1, state, all_variables + ) + SpeedyWeatherSSM.update_prognostic_variables_from_state_vector!( + prognostic_variables_2, state, all_variables + ) + # Check all variables changed from initial values + for variable_name in all_variables + @test all( + getproperty(prognostic_variables_1, variable_name)[1] + != getproperty(prognostic_variables_1_init, variable_name)[1] + ) + end + # Check variables updates from same state vector match + for variable_name in all_variables + @test all( + getproperty(prognostic_variables_1, variable_name)[1] + == getproperty(prognostic_variables_2, variable_name)[1] + ) + end + # Check state vector reconstructed from prognostic variables matches original + state_2 = Vector{T}(undef, state_dimension) + SpeedyWeatherSSM.update_state_vector_from_prognostic_variables!( + state_2, prognostic_variables_1, all_variables + ) + @test all(state == state_2) +end + +@testset "Generic model interface unit tests" begin + seed = 1234 + model = SpeedyWeatherSSM.init(SpeedyWeatherSSM.SpeedyParameters()) + ParticleDA.run_unit_tests_for_generic_model_interface(model, seed) +end