diff --git a/.github/workflows/Benchmark.yml b/.github/workflows/Benchmark.yml new file mode 100644 index 0000000..d8fc450 --- /dev/null +++ b/.github/workflows/Benchmark.yml @@ -0,0 +1,51 @@ +name: Benchmark + +# Runs the benchmark suite (benchmark/benchmarks.jl, the global `SUITE`) on each +# relevant pull request and writes a comparison table to the job summary. +# +# How the comparison works (AirspeedVelocity.jl): +# * It benchmarks TWO git revisions — the base branch (`main`) and this PR's +# head commit — NOT a stored historical baseline. +# * Both revisions are checked out into separate temp environments and run in +# separate Julia processes, back-to-back on the SAME runner within this one +# job. The reported `ratio` is head/base (<1 faster, >1 slower). +# * Running both on the same machine cancels systematic hardware differences, +# but shared GitHub runners are still noisy (~±10–30% on microbenchmarks): +# trust this for order-of-magnitude / large regressions, not 5% wobble. +# +# Security: this uses the `pull_request` event (not `pull_request_target`), so a +# fork's PR code runs with a read-only token and no secrets. Output goes to the +# Actions job summary (`job-summary: "true"`) instead of a PR comment, so no +# write token is ever needed — nothing is posted to fork (or same-repo) PRs. +# View results under the workflow run's "Summary" tab. + +on: + pull_request: + branches: + - main + paths: + - "src/**" + - "benchmark/**" + - "Project.toml" + - ".github/workflows/Benchmark.yml" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + benchmark: + name: Benchmark PR vs main + runs-on: ubuntu-latest + steps: + - uses: MilesCranmer/AirspeedVelocity.jl@action-v1 + with: + julia-version: "1" + job-summary: "true" + # Default compares `main` against this PR's head SHA. Uncomment to + # restrict to a fast, low-noise subset of the suite in CI: + # filter: "special_functions,ebcm,linearization,postprocessing" diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 34137af..dab57f2 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -21,6 +21,20 @@ It is split into: The local `just ci` command mirrors the core local checks: package tests, doctests, and documentation build. +## Benchmarks + +`Benchmark.yml` runs the benchmark suite (`benchmark/benchmarks.jl`, the global +`SUITE`) via [AirspeedVelocity.jl](https://github.com/MilesCranmer/AirspeedVelocity.jl) +on pull requests that touch `src/`, `benchmark/`, or `Project.toml`. It +benchmarks the PR head commit against `main` — both revisions are run +back-to-back on the same runner (not against a stored baseline) — and writes a +`ratio` comparison table to the workflow run's **Summary** tab. It uses the +`pull_request` event with a read-only token and `job-summary: "true"`, so fork +PR code never runs with a write token and nothing is posted as a comment. +Shared CI runners are noisy, so treat the results as a guard for large +regressions rather than sub-10% changes. Run the same suite locally with +`just bench`. + ## Maintenance - `CompatHelper.yml` opens compatibility-bound update pull requests. diff --git a/.gitignore b/.gitignore index 1f2c900..80545b7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,19 @@ Manifest.toml .CondaPkg/ +# Benchmark result artifacts (benchmark/params.json is committed; raw run +# outputs are machine-specific and stay local) +/results*.json +/benchmark/results*.json + # Documentation artifacts /docs/build/ +# Intermediate Pluto render output (the committed copies live in +# docs/src/examples/, which is tracked). +/examples/*.md +!/examples/README.md + # Editor and OS metadata .DS_Store .idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fd4ce7c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,84 @@ +# Changelog + +All notable changes to this project are documented here. The format is based on +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project +adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +Work on top of `v0.4.0`. Includes a breaking change to solver selection, so the +next release is expected to be `v0.5.0`. + +### Added + +- **Sh-matrix moment-separation method** for fast parameter sweeps: + `prepare_sh`, `transition_matrix(prep, λ, mᵣ)`, and `transition_matrix_spectrum`. + The geometry quadrature is computed once and reused, so wavelength / + refractive-index sweeps are cheap; for spheroids it also reproduces the + high-aspect stabilization analytically. Works for any axisymmetric shape. +- **Two-layer solver API**: fixed-discretization solvers `EBCM`, `IITM`, + `ShMatrix`, and the `Iterative` convergence wrapper (with `ConvergencePolicy`), + selected via `transition_matrix(s, λ, solver)`. +- **Stabilized high-aspect-ratio spheroids** (`stable = true`): the + cancellation-free `F⁺` formulation of Somerville, Auguié & Le Ru (2013), + available as `EBCM(nₘₐₓ, Ng; stable = true)` and, auto-converged, as + `Iterative(EBCM; stable = true)`. +- **Performance benchmark suite** and a PR benchmark CI workflow + (AirspeedVelocity). +- **`examples/` folder** with five runnable Pluto notebooks — shapes gallery, + angular scattering & polarization, orientation averaging, solver landscape, and + spectral sensitivity — rendered into the documentation site. + +### Changed + +- **(Breaking)** Solver selection moves to solver objects passed to + `transition_matrix(s, λ, solver)`. The keyword-based auto-converge + `transition_matrix(s, λ; threshold, …)` is replaced by + `Iterative(EBCM; threshold, …)`. The bare `transition_matrix(s, λ)` / + `calc_T(s, λ)` is unchanged (auto-converged classic EBCM). +- Performance: factor `𝐐` once and reuse it across Jacobian slices instead of an + explicit `inv`; the IITM radial recursion solves `M \ X` instead of forming + `inv(M)`; the Sh-matrix precompute is optimized (coefficient precompute, folded + convolution, precision split, and an analytic-zeroing fast path for spheroids). +- Documentation: the API reference now filters internal (underscore-prefixed) + docstrings and uses `checkdocs = :exported`. + +### Fixed + +- `prepare_sh` requires an even `Ng` only for shapes with an equatorial symmetry + plane (non-symmetric shapes accept odd `Ng`). +- `transition_matrix_spectrum` validates that `λs` and `mᵣs` have matching lengths + instead of silently truncating to the shorter one. +- `ricattibessely` handles `nₘₐₓ = 1`. +- `cbrt` on `Double64` (DoubleFloats v1.9 returns a tuple). + +## [0.4.0] - 2026-06-04 + +- Performance optimizations and the analytical linearization framework + (`LinearizationProblem`, `linearize_transition_matrix`, with Mie / EBCM / IITM + backends). See [#7](https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/pull/7). + +## [0.3.1] - 2026-01-18 + +- Raise the `Wigxjpf` compatibility bound to v0.2; CI configuration updates. + +## [0.3.0] - 2025-04-03 + +- Compatible with Julia 1.13. +- Removed `ArbNumerics` from the dependencies; its types are no longer + re-exported (use `Arblib`'s `Arb`/`Acb`). + +## [0.2.0] - 2023-04-02 + +- Early development release. + +## [0.1.0] - 2023-03-17 + +- Initial release. + +[Unreleased]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/compare/v0.4.0...HEAD +[0.4.0]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/compare/v0.3.1...v0.4.0 +[0.3.1]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/compare/v0.3.0...v0.3.1 +[0.3.0]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/compare/v0.2.0...v0.3.0 +[0.2.0]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/compare/v0.1.0...v0.2.0 +[0.1.0]: https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/releases/tag/v0.1.0 diff --git a/benchmark/Project.toml b/benchmark/Project.toml new file mode 100644 index 0000000..69acf5c --- /dev/null +++ b/benchmark/Project.toml @@ -0,0 +1,7 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +TransitionMatrices = "057c4241-e127-4181-840e-6b4b92e6eef5" + +[compat] +BenchmarkTools = "1" +julia = "1.10" diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000..0e49fb1 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,70 @@ +# Benchmarks + +Performance benchmark suite for `TransitionMatrices.jl`, built on +[BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl). The suite +follows the standard Julia convention — `benchmark/benchmarks.jl` defines a +single global `const SUITE::BenchmarkGroup` — so it works unchanged with both +[PkgBenchmark.jl](https://github.com/JuliaCI/PkgBenchmark.jl) and +[AirspeedVelocity.jl](https://github.com/MilesCranmer/AirspeedVelocity.jl). + +## Layout + +| File | Purpose | +| --- | --- | +| `benchmarks.jl` | Defines `SUITE` (consumed by every tool below). | +| `runbenchmarks.jl` | Local runner: tune once, cache params, save results JSON. | +| `Project.toml` | Isolated environment; dev-depends on the parent package. | +| `params.json` | Cached `tune!` parameters (created on first run). | + +## Groups + +- `special_functions` — Riccati-Bessel and Wigner-d recursions (inner kernels). +- `ebcm` — EBCM blocks, fixed-order solves, and end-to-end auto-convergence. +- `iitm` — Invariant Imbedding T-Matrix (axisymmetric and N-fold). +- `postprocessing` — far-field observables from a precomputed T-matrix. +- `linearization` — analytical EBCM Jacobian (baseline for the `inv` → `lu` work). +- `precision` — Float64 vs Double64 on the same EBCM block. + +## Running + +The simplest path uses the parent `justfile`: + +```sh +just bench # instantiate the env and run the whole suite +``` + +Or directly: + +```sh +julia --project=benchmark -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate()' +julia --project=benchmark benchmark/runbenchmarks.jl results-baseline.json +``` + +Run a single group while iterating: + +```julia +julia --project=benchmark +julia> include("benchmark/benchmarks.jl"); +julia> run(SUITE["ebcm"]; verbose = true) +``` + +## Comparing two revisions + +Capture a baseline, make your change, capture again, then judge: + +```julia +using BenchmarkTools +old = BenchmarkTools.load("results-baseline.json")[1] +new = BenchmarkTools.load("results.json")[1] +judge(minimum(new), minimum(old)) # :improvement / :regression / :invariant +``` + +`minimum` is used because it is the most noise-robust statistic for these +deterministic numerical kernels. + +For automated cross-revision runs (and PR comments), AirspeedVelocity.jl reads +the same `SUITE`: + +```sh +benchpkg TransitionMatrices --rev=main,HEAD --bench-on=HEAD +``` diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 0000000..c15b428 --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,167 @@ +# Benchmark suite for TransitionMatrices.jl. +# +# This file follows the de-facto Julia convention: it defines a single global +# `const SUITE::BenchmarkGroup`. The same file is consumed by both +# PkgBenchmark.jl (`benchmarkpkg`, `judge`) and AirspeedVelocity.jl +# (`benchpkg`), so no tooling lock-in is introduced. +# +# Run locally with `just bench`, or directly: +# julia --project=benchmark -e 'include("benchmark/runbenchmarks.jl")' +# +# Groups +# special_functions – Riccati-Bessel and Wigner-d recursions (inner kernels) +# ebcm – EBCM blocks, fixed-order, and auto-converging solves +# iitm – Invariant Imbedding T-Matrix (axisymmetric + N-fold) +# postprocessing – far-field observables from a precomputed T-matrix +# linearization – analytical Jacobian (baseline for the inv→lu work) +# precision – Float64 vs Double64 on the same EBCM block + +using BenchmarkTools +using TransitionMatrices + +const SUITE = BenchmarkGroup() + +# -------------------------------------------------------------------------- +# Representative scatterers. With λ = 2π the size parameter is x = k·rmax = rmax. +# A mildly absorbing refractive index (1.5 + 0.02im) keeps the problems +# well-conditioned in Float64 while exercising the complex paths. +# -------------------------------------------------------------------------- +const λ = 2π +const SPHEROID = Spheroid(2.0, 1.0, complex(1.5, 0.02)) +const CYLINDER = Cylinder(1.0, 2.0, complex(1.5, 0.02)) +const CHEBYSHEV = Chebyshev(1.0, 0.1, 4, complex(1.5, 0.02)) +const PRISM = Prism(6, 1.0, 2.0, complex(1.5, 0.02)) + +# A reference T-matrix shared by the post-processing benchmarks. Built once at +# suite-load time so its cost stays out of the per-sample timings. +const T_REF = transition_matrix(SPHEROID, λ, 8, 32) +const θs = collect(range(0, π; length = 181)) + +# -------------------------------------------------------------------------- +# Special functions — the innermost recursions, sized by truncation order. +# -------------------------------------------------------------------------- +let g = SUITE["special_functions"] = BenchmarkGroup(["math", "recurrence"]) + for nmax in (20, 50, 100) + x = float(nmax) # argument near the order: the demanding regime + nextra = TransitionMatrices.estimate_ricattibesselj_extra_terms(nmax, x) + g["ricattibesselj_n$nmax"] = @benchmarkable TransitionMatrices.ricattibesselj( + $nmax, + $nextra, + $x) + end + for smax in (20, 50, 100) + g["wigner_d_recursion_s$smax"] = @benchmarkable TransitionMatrices.wigner_d_recursion( + 0, + 2, + $smax, + 0.7; + deriv = true) + end +end + +# -------------------------------------------------------------------------- +# EBCM — block construction, fixed-order solves, and end-to-end convergence. +# -------------------------------------------------------------------------- +let g = SUITE["ebcm"] = BenchmarkGroup(["core", "linalg"]) + # The m = 0 block is the per-iteration hot path of the convergence loop. + for nmax in (8, 12, 16) + Ng = 4nmax + g["m0_block_n$nmax"] = @benchmarkable transition_matrix_m₀($SPHEROID, $λ, $nmax, $Ng) + end + + # Full fixed-order T-matrix across the three axisymmetric shape families. + g["full_spheroid"] = @benchmarkable transition_matrix($SPHEROID, $λ, 8, 32) + g["full_cylinder"] = @benchmarkable transition_matrix($CYLINDER, $λ, 8, 32) + g["full_chebyshev"] = @benchmarkable transition_matrix($CHEBYSHEV, $λ, 8, 32) + + # Realistic user call: automatic nmax/Ng convergence from scratch. + g["auto_converge_spheroid"] = @benchmarkable calc_T($SPHEROID, $λ) seconds=30 + + # Stabilized spheroid path (Somerville F⁺) vs the standard assembly, for a + # high-aspect prolate (h=4, xmax≈10) where the standard Float64 integrands + # lose precision. Matched (nₘₐₓ, Ng) so the ratio is the stabilization cost. + let prolate = Spheroid(2.5198421, 10.079368, complex(1.55, 0.01)) + g["highaspect_std_n24"] = @benchmarkable transition_matrix($prolate, $λ, 24, 240) + g["highaspect_stable_n24"] = @benchmarkable transition_matrix($prolate, $λ, 24, + 240; stable = true) + end +end + +# -------------------------------------------------------------------------- +# Sh-matrix — moment-separation parameter sweeps. `prepare_sh` does the geometry +# quadrature once; each subsequent (λ, mᵣ) point is then a cheap coefficient× +# moment reconstruction. Contrasting the per-point cost with the from-scratch +# assembly is the whole point of the method. +# -------------------------------------------------------------------------- +let g = SUITE["sh_matrix"] = BenchmarkGroup(["sweep", "moment"]) + prep = prepare_sh(SPHEROID, 8, 32; B = 30) + g["prepare_n8"] = @benchmarkable prepare_sh($SPHEROID, 8, 32; B = 30) seconds=30 + g["sweep_point_n8"] = @benchmarkable transition_matrix($prep, $λ, $(SPHEROID.m)) + g["fresh_assembly_n8"] = @benchmarkable transition_matrix($SPHEROID, $λ, 8, 32) +end + +# -------------------------------------------------------------------------- +# IITM — the numerically stable solver; the GPU/N-fold work targets this path. +# -------------------------------------------------------------------------- +let g = SUITE["iitm"] = BenchmarkGroup(["core", "linalg"]) + g["axisym_spheroid"] = @benchmarkable calc_T_iitm($SPHEROID, $λ, 6, 20, 24) seconds=60 + g["nfold_prism6"] = @benchmarkable calc_T_iitm($PRISM, $λ, 6, 10, 24, 24) seconds=60 +end + +# -------------------------------------------------------------------------- +# Post-processing — far-field observables from a precomputed T-matrix. +# The analytic vs numerical orientation average contrast is intentional: it +# documents the (already implemented) speedup of Mishchenko's closed form. +# -------------------------------------------------------------------------- +let g = SUITE["postprocessing"] = BenchmarkGroup(["farfield"]) + g["amplitude_matrix"] = @benchmarkable amplitude_matrix($T_REF, 0.0, 0.0, π / 4, 0.0; + λ = $λ) + g["expansion_coefficients"] = @benchmarkable expansion_coefficients($T_REF, $λ) + g["scattering_matrix"] = @benchmarkable scattering_matrix($T_REF, $λ, $θs) + g["extinction_cross_section"] = @benchmarkable extinction_cross_section($T_REF, $λ) + g["scattering_cross_section"] = @benchmarkable scattering_cross_section($T_REF, $λ) + g["orientation_average_analytic"] = @benchmarkable RandomOrientationTransitionMatrix($T_REF) + g["orientation_average_numerical"] = @benchmarkable orientation_average($T_REF, + (α, β, γ) -> 1 / (8π^2); + Nα = 20, Nβ = 20, + Nγ = 1) seconds=30 +end + +# -------------------------------------------------------------------------- +# Linearization — analytical EBCM Jacobian. This is the direct baseline for +# the planned `inv(𝐐)` → `lu`/factorization-reuse optimization. +# -------------------------------------------------------------------------- +let g = SUITE["linearization"] = BenchmarkGroup(["jacobian"]) + x₀ = [2.0, 1.0, 1.5, 0.02, 2π] + vars = (:a, :c, :mᵣ, :mᵢ, :λ) + config = (; nₘₐₓ = 6, Ng = 24) + problem = LinearizationProblem(x₀; variables = vars) do x + (; shape = Spheroid(x[1], x[2], complex(x[3], x[4])), λ = x[5]) + end + g["ebcm_analytic_jacobian"] = @benchmarkable linearize_transition_matrix($problem, + EBCMLinearization(); + config = $config) seconds=30 +end + +# -------------------------------------------------------------------------- +# Precision — same EBCM block in Float64 vs Double64, to quantify the cost of +# the precision-escalation path the roadmap proposes to automate. +# -------------------------------------------------------------------------- +let g = SUITE["precision"] = BenchmarkGroup(["multiprecision"]) + spheroid_d64 = Spheroid(Double64(2.0), Double64(1.0), + Complex{Double64}(Double64(1.5), Double64(0.02))) + g["ebcm_m0_Float64"] = @benchmarkable transition_matrix_m₀($SPHEROID, $λ, 8, 32) + g["ebcm_m0_Double64"] = @benchmarkable transition_matrix_m₀($spheroid_d64, + 2 * Double64(π), 8, 32) seconds=30 +end + +# -------------------------------------------------------------------------- +# Reuse tuned parameters when available so CI/repeat runs stay comparable. +# -------------------------------------------------------------------------- +let paramspath = joinpath(@__DIR__, "params.json") + if isfile(paramspath) + loadparams!(SUITE, BenchmarkTools.load(paramspath)[1], :evals, :samples) + end +end + +SUITE diff --git a/benchmark/params.json b/benchmark/params.json new file mode 100644 index 0000000..bae7999 --- /dev/null +++ b/benchmark/params.json @@ -0,0 +1 @@ +[{"BenchmarkTools":"1.8.0","Julia":"1.12.6"},[["BenchmarkGroup",{"data":{"ebcm":["BenchmarkGroup",{"data":{"auto_converge_spheroid":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":30.0,"time_tolerance":0.05}],"full_chebyshev":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"full_cylinder":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"full_spheroid":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"m0_block_n12":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"m0_block_n16":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"m0_block_n8":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}]},"tags":["core","linalg"]}],"iitm":["BenchmarkGroup",{"data":{"axisym_spheroid":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":60.0,"time_tolerance":0.05}],"nfold_prism6":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":60.0,"time_tolerance":0.05}]},"tags":["core","linalg"]}],"linearization":["BenchmarkGroup",{"data":{"ebcm_analytic_jacobian":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":30.0,"time_tolerance":0.05}]},"tags":["jacobian"]}],"postprocessing":["BenchmarkGroup",{"data":{"amplitude_matrix":["Parameters",{"evals":8,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"expansion_coefficients":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"extinction_cross_section":["Parameters",{"evals":991,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"orientation_average_analytic":["Parameters",{"evals":193,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"orientation_average_numerical":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":30.0,"time_tolerance":0.05}],"scattering_cross_section":["Parameters",{"evals":110,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"scattering_matrix":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}]},"tags":["farfield"]}],"precision":["BenchmarkGroup",{"data":{"ebcm_m0_Double64":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":30.0,"time_tolerance":0.05}],"ebcm_m0_Float64":["Parameters",{"evals":1,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}]},"tags":["multiprecision"]}],"special_functions":["BenchmarkGroup",{"data":{"ricattibesselj_n100":["Parameters",{"evals":136,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"ricattibesselj_n20":["Parameters",{"evals":516,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"ricattibesselj_n50":["Parameters",{"evals":199,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"wigner_d_recursion_s100":["Parameters",{"evals":40,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"wigner_d_recursion_s20":["Parameters",{"evals":767,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}],"wigner_d_recursion_s50":["Parameters",{"evals":199,"evals_set":false,"gcsample":false,"gctrial":true,"memory_tolerance":0.01,"overhead":0.0,"samples":10000,"seconds":5.0,"time_tolerance":0.05}]},"tags":["math","recurrence"]}]},"tags":[]}]]] \ No newline at end of file diff --git a/benchmark/runbenchmarks.jl b/benchmark/runbenchmarks.jl new file mode 100644 index 0000000..66517da --- /dev/null +++ b/benchmark/runbenchmarks.jl @@ -0,0 +1,32 @@ +# Local convenience runner for the benchmark suite. +# +# julia --project=benchmark benchmark/runbenchmarks.jl [output.json] +# +# On first run it tunes the suite and caches the parameters in params.json so +# subsequent runs (and CI) are reproducible. Results are saved as JSON for +# later comparison with `BenchmarkTools.judge` / `ratio`. + +using BenchmarkTools + +include(joinpath(@__DIR__, "benchmarks.jl")) + +const PARAMS_PATH = joinpath(@__DIR__, "params.json") + +if isfile(PARAMS_PATH) + @info "Loaded tuned parameters" path=PARAMS_PATH +else + @info "Tuning benchmark parameters (first run; this is slow)…" + tune!(SUITE) + BenchmarkTools.save(PARAMS_PATH, params(SUITE)) + @info "Saved tuned parameters" path=PARAMS_PATH +end + +results = run(SUITE; verbose = true) + +output = isempty(ARGS) ? joinpath(@__DIR__, "results.json") : ARGS[1] +BenchmarkTools.save(output, results) +@info "Saved benchmark results" path=output + +println("\n==== median timings ====") +display(median(results)) +println() diff --git a/docs/Project.toml b/docs/Project.toml index 036341b..02eb656 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,5 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" +PlutoStaticHTML = "359b1769-a58e-495b-9770-312e911026ad" TransitionMatrices = "057c4241-e127-4181-840e-6b4b92e6eef5" diff --git a/docs/make.jl b/docs/make.jl index 0bc73b2..7b5986b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,28 +1,64 @@ using TransitionMatrices using Documenter +# ── Example Pluto notebooks ─────────────────────────────────────────────────── +# The rendered pages (docs/src/examples/*.md, with plots embedded as base64 SVG) +# are committed and used as-is by default, so CI does not have to run the +# notebooks (which load Plots/GR and its native graphics stack — fragile on +# headless Linux runners). To refresh them, render locally with +# BUILD_EXAMPLES=true julia --project=docs docs/make.jl +# and commit the regenerated docs/src/examples/*.md. Each notebook self-activates +# the examples/ environment in its own Pluto worker. +const NB_DIR = normpath(joinpath(@__DIR__, "..", "examples")) +const NB_OUT = joinpath(@__DIR__, "src", "examples") +const NOTEBOOKS = ["shapes_gallery.jl", "angular_scattering.jl", + "orientation_averaging.jl", "solver_landscape.jl", "spectral_sensitivity.jl"] +const NB_PAGES = ["examples/" * replace(nb, ".jl" => ".md") for nb in NOTEBOOKS] + +function build_examples() + mkpath(NB_OUT) + bopts = BuildOptions(NB_DIR; output_format = documenter_output, + use_distributed = false, previous_dir = NB_DIR) + build_notebooks(bopts, NOTEBOOKS) + for nb in NOTEBOOKS + md = replace(nb, ".jl" => ".md") + cp(joinpath(NB_DIR, md), joinpath(NB_OUT, md); force = true) + end +end + +if get(ENV, "BUILD_EXAMPLES", "false") == "true" + # Only the render path needs PlutoStaticHTML/Pluto and a headless GR; the + # default docs build (CI) uses the committed pages and loads none of this. + ENV["GKSwstype"] = "100" + using PlutoStaticHTML + build_examples() +end + DocMeta.setdocmeta!(TransitionMatrices, :DocTestSetup, :(using TransitionMatrices); - recursive = true) + recursive = true) makedocs(; - modules = [TransitionMatrices], - authors = "Gabriel Wu and contributors", - repo = "https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/blob/{commit}{path}#{line}", - sitename = "TransitionMatrices.jl", - format = Documenter.HTML(; - prettyurls = get(ENV, "CI", "false") == "true", - canonical = "https://JuliaRemoteSensing.github.io/TransitionMatrices.jl", - edit_link = "main", - assets = String[]), - pages = [ - "Home" => "index.md", - "Usage" => "usage.md", - "Linearization" => "linearization.md", - "API" => "api.md", - ]) + modules = [TransitionMatrices], + checkdocs = :exported, + authors = "Gabriel Wu and contributors", + repo = "https://github.com/JuliaRemoteSensing/TransitionMatrices.jl/blob/{commit}{path}#{line}", + sitename = "TransitionMatrices.jl", + format = Documenter.HTML(; + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://JuliaRemoteSensing.github.io/TransitionMatrices.jl", + edit_link = "main", + size_threshold_ignore = NB_PAGES, # rendered notebooks embed large plots + assets = String[]), + pages = [ + "Home" => "index.md", + "Usage" => "usage.md", + "Examples" => NB_PAGES, + "Linearization" => "linearization.md", + "API" => "api.md" + ]) if get(ENV, "DOCUMENTER_SKIP_DEPLOY", "false") != "true" deploydocs(; - repo = "github.com/JuliaRemoteSensing/TransitionMatrices.jl", - devbranch = "main") + repo = "github.com/JuliaRemoteSensing/TransitionMatrices.jl", + devbranch = "main") end diff --git a/docs/src/api.md b/docs/src/api.md index 1c88578..ee80457 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -9,4 +9,5 @@ CurrentModule = TransitionMatrices ```@autodocs Modules = [TransitionMatrices] +Filter = t -> !startswith(string(Base.nameof(t)), "_") ``` diff --git a/docs/src/examples/angular_scattering.md b/docs/src/examples/angular_scattering.md new file mode 100644 index 0000000..6a27a13 --- /dev/null +++ b/docs/src/examples/angular_scattering.md @@ -0,0 +1,3621 @@ +```@raw html + + + + + +

Angular scattering & polarization

From a T-matrix you can read off the full far field: the amplitude matrix\(\mathbf{S}\) at a fixed geometry, its phase matrix\(\mathbf{Z}\), and the orientation-averaged scattering (Mueller) matrix\(\mathbf{F}(\theta)\).

This notebook plots the phase function \(F_{11}(\theta)\), the degree of linear polarization \(-F_{12}/F_{11}\) (for unpolarized incidence) and the ratios \(F_{22}/F_{11}\), \(F_{44}/F_{11}\) for a spheroid.

+ +
begin
+    import Pkg
+    Pkg.activate(@__DIR__)
+    Pkg.develop(; path = dirname(@__DIR__))
+    Pkg.instantiate()
+    using TransitionMatrices, Plots
+end
+ + + +

Build a T-matrix

+ +
begin
+    λ = 2π
+    spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im)
+    T = calc_T(spheroid, λ)
+end
+
19×9×19×9×2×2 AxisymmetricTransitionMatrix{ComplexF64, 9, Vector{Matrix{ComplexF64}}, Float64} with indices -9:9×1:9×-9:9×1:9×1:2×1:2:
+[:, :, -9, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 1, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 2, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 3, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 4, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 5, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 6, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0-0.0im  2.19496e-13-4.50037e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0-0.0im  2.19496e-13-4.50037e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+[:, :, 8, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 7, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -4.8884e-13+1.05045e-11im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+
+[:, :, -7, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.72364e-13+3.91331e-12im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.72364e-13+3.91331e-12im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -4.8884e-13+1.05045e-11im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+
+[:, :, 9, 8, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  -5.59296e-15+1.15147e-13im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+
+[:, :, -8, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -1.61514e-15+3.75017e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+[:, :, -7, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -1.92771e-15+3.97071e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -1.92771e-15+3.97071e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -1.61514e-15+3.75017e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+[:, :, 9, 9, 1, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  -5.59296e-15+1.15147e-13im
+
+[:, :, -9, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 1, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 2, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 3, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 4, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 5, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 6, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.09407e-10-3.42822e-12im  -0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     1.09407e-10+3.42822e-12im  0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+
+[:, :, 8, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 7, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  -1.29512e-12-3.92979e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+
+[:, :, -7, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  2.10617e-13+6.9152e-15im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -2.10617e-13-6.9152e-15im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  1.29512e-12+3.92979e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+
+[:, :, 9, 8, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -2.37726e-13+3.92857e-14im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+
+[:, :, -7, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     6.21318e-13+4.06401e-14im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -6.21318e-13-4.06401e-14im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     2.37726e-13-3.92857e-14im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+
+[:, :, 9, 9, 2, 1] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  -0.0-0.0im
+
+[:, :, -9, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 1, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 2, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 3, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 4, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 5, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 6, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     9.92451e-11+3.10368e-12im  -0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -9.92451e-11-3.10368e-12im  0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+
+[:, :, 8, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 7, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  1.1946e-12+3.69915e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im         0.0+0.0im
+
+[:, :, -7, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  -1.6102e-13-4.6447e-15im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  1.6102e-13+4.6447e-15im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im         0.0+0.0im
+
+[:, :, 8, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -1.1946e-12-3.69915e-14im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+
+[:, :, 9, 8, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     1.29061e-12+3.88854e-14im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im          0.0+0.0im
+
+[:, :, -7, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -2.10404e-13-6.98428e-15im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱                             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …          0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     2.10404e-13+6.98428e-15im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im             0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.29061e-12-3.88854e-14im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, 9, 9, 1, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im   0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  -0.0-0.0im
+
+[:, :, -9, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 1, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 2, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 3, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 4, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 5, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 8, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 6, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -7, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0-0.0im  4.66754e-12-1.44642e-10im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0-0.0im  4.66754e-12-1.44642e-10im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im          0.0+0.0im
+
+[:, :, 8, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, 9, 7, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -8, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.05089e-11+3.34671e-10im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, -7, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -3.25788e-12+1.10209e-10im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -3.25788e-12+1.10209e-10im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱                              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …           0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -1.05089e-11+3.34671e-10im  -0.0-0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im              0.0+0.0im           0.0+0.0im
+
+[:, :, 9, 8, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+    ⋮                                        ⋱                        
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  0.0+0.0im  0.0+0.0im
+
+[:, :, -9, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im  -1.30289e-13+4.16766e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+
+[:, :, -8, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -3.9913e-14+1.34163e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+
+[:, :, -7, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -4.52878e-14+1.48644e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+;;; … 
+
+[:, :, 7, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+    ⋮                             ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -4.52878e-14+1.48644e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im           0.0+0.0im
+
+[:, :, 8, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+    ⋮                                        ⋱              
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …   0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     -0.0-0.0im  -3.9913e-14+1.34163e-12im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im      0.0+0.0im          0.0+0.0im
+
+[:, :, 9, 9, 2, 2] =
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+    ⋮                                        ⋱             
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im  …  0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im           0.0+0.0im
+ 0.0+0.0im  0.0+0.0im  0.0+0.0im  0.0+0.0im     0.0+0.0im  -1.30289e-13+4.16766e-12im
+ + +

Orientation-averaged scattering matrix vs angle

scattering_matrix(T, λ, θs) returns an Nθ × 6 matrix whose columns are [F₁₁, F₁₂, F₂₂, F₃₃, F₃₄, F₄₄] (θs in degrees).

+ +
begin
+    θs = collect(0.0:1.0:180.0)
+    F = scattering_matrix(T, λ, θs)
+    F11 = F[:, 1]
+    pol = -F[:, 2] ./ F[:, 1]      # degree of linear polarization
+    F22_11 = F[:, 3] ./ F[:, 1]
+    F44_11 = F[:, 6] ./ F[:, 1]
+    nothing
+end
+ + + +

Plots

+ +
let
+    p1 = plot(θs, F11; yscale = :log10, lw = 2, label = "F₁₁",
+        ylabel = "phase function", legend = :topright)
+    p2 = plot(θs, pol; lw = 2, color = 2, label = "-F₁₂/F₁₁",
+        ylabel = "lin. polarization")
+    p3 = plot(θs, [F22_11 F44_11]; lw = 2, label = ["F₂₂/F₁₁" "F₄₄/F₁₁"],
+        xlabel = "scattering angle θ (deg)", ylabel = "ratio")
+    plot(p1, p2, p3; layout = (3, 1), size = (720, 660),
+        title = ["spheroid a=2, c=1, m=1.5+0.02im" "" ""])
+end
+ + + +

Amplitude and phase matrix at a fixed geometry

For a specific incidence/scattering direction, amplitude_matrix gives the 2×2 complex \(\mathbf{S}\) and phase_matrix the 4×4 Mueller \(\mathbf{Z}\).

+ +
begin
+    S = amplitude_matrix(T, 0.0, 0.0, π / 4, 0.0; λ = λ)   # ϑᵢ,φᵢ → ϑₛ,φₛ
+    Z = phase_matrix(S)
+    (; S, Z)
+end
+
(S = ComplexF64[0.7543885545787061 + 0.41284557376054576im 0.0 + 0.0im; 0.0 + 0.0im 0.9614704949782115 + 0.5540083947286321im], Z = [0.9854471865982333 -0.24590362754520956 -0.0 0.0; -0.24590362754520956 0.9854471865982333 0.0 0.0; -0.0 0.0 0.9540422505665871 -0.020998753970686346; 0.0 0.0 0.020998753970686346 0.9540422505665871])
+ + +``` + diff --git a/docs/src/examples/orientation_averaging.md b/docs/src/examples/orientation_averaging.md new file mode 100644 index 0000000..dc4781c --- /dev/null +++ b/docs/src/examples/orientation_averaging.md @@ -0,0 +1,97 @@ +```@raw html + + + + + +

Orientation averaging

For randomly oriented particles you need the orientation-averaged scattering quantities. TransitionMatrices.jl offers two routes:

  • RandomOrientationTransitionMatrix(T) — Mishchenko's analytic closed form for the orientation average (fast, exact);

  • orientation_average(T, p; Nα, Nβ, Nγ)numerical average over the Euler angles against an orientation distribution p.

This notebook checks they agree and shows the numerical average converging to the analytic value as the angular grid is refined.

+ +
begin
+    import Pkg
+    Pkg.activate(@__DIR__)
+    Pkg.develop(; path = dirname(@__DIR__))
+    Pkg.instantiate()
+    using TransitionMatrices, Plots
+end
+ + + +

A non-spherical particle

+ +
begin
+    λ = 2π
+    spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im)
+    T = calc_T(spheroid, λ)
+    uniform = (α, β, γ) -> 1 / (8π^2)   # isotropic orientation distribution
+end
+
#5 (generic function with 1 method)
+ + +

Analytic vs numerical

Both should give the same orientation-averaged efficiencies.

+ +
begin
+    Tanalytic = RandomOrientationTransitionMatrix(T)
+    Tnumeric = orientation_average(T, uniform; Nα = 20, Nβ = 20, Nγ = 20)
+
+    compare = [
+        (; method = "analytic (Mishchenko)", Qsca = calc_Csca(Tanalytic, λ),
+            Qext = calc_Cext(Tanalytic, λ), g = asymmetry_parameter(Tanalytic, λ)),
+        (; method = "numerical (20³ grid)", Qsca = calc_Csca(Tnumeric, λ),
+            Qext = calc_Cext(Tnumeric, λ), g = asymmetry_parameter(Tnumeric, λ)),
+    ]
+end
+
2-element Vector{@NamedTuple{method::String, Qsca::Float64, Qext::Float64, g::Float64}}:
+ (method = "analytic (Mishchenko)", Qsca = 6.161024698021793, Qext = 7.59930108537653, g = 0.5833300223810896)
+ (method = "numerical (20³ grid)", Qsca = 6.1610246980217225, Qext = 7.599301085376555, g = 0.5833300223810899)
+ + +

Convergence of the numerical average

The numerical average approaches the analytic value as the β-grid is refined; the analytic closed form gives it directly, at a fraction of the cost.

+ +
begin
+    Qref = calc_Csca(Tanalytic, λ)
+    Ns = 4:2:18
+    errs = [abs(calc_Csca(orientation_average(T, uniform; Nα = 2, Nβ = N, Nγ = 2), λ) - Qref) / Qref
+            for N in Ns]
+    nothing
+end
+ + +
let
+    plot(collect(Ns), errs; yscale = :log10, lw = 2, marker = :circle,
+        xlabel = "β-grid points Nβ", ylabel = "|Qsca_numeric − Qsca_analytic| / Qsca",
+        label = "numerical average", legend = :topright,
+        title = "convergence to the analytic orientation average", size = (680, 400))
+end
+ + + +

Takeaway

The analytic RandomOrientationTransitionMatrix is both exact and much cheaper than refining a 3-D Euler-angle quadrature — prefer it for random-orientation cross sections. The numerical orientation_average remains useful for non-uniform orientation distributions (just pass a different p).

+ + +``` + diff --git a/docs/src/examples/shapes_gallery.md b/docs/src/examples/shapes_gallery.md new file mode 100644 index 0000000..6f3f447 --- /dev/null +++ b/docs/src/examples/shapes_gallery.md @@ -0,0 +1,96 @@ +```@raw html + + + + + +

Shapes quick-start gallery

TransitionMatrices.jl handles several scatterer families. This gallery defines one of each, computes its T-matrix, and reports the basic far-field efficiencies \(Q_\text{sca}\), \(Q_\text{ext}\), the asymmetry parameter \(g\) and the single-scattering albedo \(\omega\).

The axisymmetric shapes (spheroid, cylinder, Chebyshev particle) use the default EBCM solver via calc_T; the N-fold prism is not axisymmetric, so it uses the IITM solver.

+ +
begin
+    import Pkg
+    Pkg.activate(@__DIR__)
+    Pkg.develop(; path = dirname(@__DIR__))
+    Pkg.instantiate()
+    using TransitionMatrices, Plots
+end
+ + + +

Define the shapes

All at wavelength λ = 2π (so the size parameter equals the radius) and the same refractive index m = 1.5 + 0.02im.

+ +
begin
+    λ = 2π
+    m = 1.5 + 0.02im
+    shapes = (
+        spheroid  = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, m),
+        cylinder  = TransitionMatrices.Cylinder{Float64, ComplexF64}(1.0, 2.0, m),
+        chebyshev = TransitionMatrices.Chebyshev{Float64, ComplexF64}(1.0, 0.1, 4, m),
+        prism6    = TransitionMatrices.Prism(6, 1.0, 2.0, m),
+    )
+end
+
(spheroid = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im), cylinder = Cylinder{Float64, ComplexF64}(1.0, 2.0, 1.5 + 0.02im), chebyshev = Chebyshev{Float64, ComplexF64}(1.0, 0.1, 4, 1.5 + 0.02im), prism6 = Prism{6, Float64, ComplexF64}(1.0, 2.0, 1.5 + 0.02im))
+ + +

Compute and tabulate

calc_T auto-converges the axisymmetric shapes; the prism uses a fixed-order IITM solve. Pluto renders the resulting vector of named tuples as a table.

+ +
begin
+    Tmatrix(s) = s isa TransitionMatrices.Prism ?
+        transition_matrix(s, λ, IITM(8, 12, 24, 24)) : calc_T(s, λ)
+
+    summary = map(collect(pairs(shapes))) do (name, s)
+        T = Tmatrix(s)
+        (; shape = name,
+            Qsca = round(calc_Csca(T, λ); digits = 4),
+            Qext = round(calc_Cext(T, λ); digits = 4),
+            g = round(asymmetry_parameter(T, λ); digits = 4),
+            ω = round(albedo(T); digits = 4))
+    end
+end
+
4-element Vector{@NamedTuple{shape::Symbol, Qsca::Float64, Qext::Float64, g::Float64, ω::Float64}}:
+ (shape = :spheroid, Qsca = 6.6711, Qext = 7.5993, g = 0.5339, ω = 0.8779)
+ (shape = :cylinder, Qsca = 1.3708, Qext = 1.6609, g = 0.2721, ω = 0.8254)
+ (shape = :chebyshev, Qsca = 0.6613, Qext = 0.8415, g = 0.2004, ω = 0.7858)
+ (shape = :prism6, Qsca = 0.9603, Qext = 1.1905, g = 0.239, ω = 0.8066)
+ + +

Compare the efficiencies

+ +
let
+    names = String.(getindex.(summary, :shape))
+    bar(names, [getindex.(summary, :Qsca) getindex.(summary, :Qext)];
+        label = ["Qsca" "Qext"], ylabel = "efficiency", legend = :topright,
+        title = "far-field efficiencies by shape", size = (680, 380))
+end
+ + + +

Which solver?

  • Spheroid / Cylinder / Chebyshev — axisymmetric: EBCM (calc_T). For high-aspect spheroids add the stabilized path, Iterative(EBCM; stable=true).

  • Prism / arbitrary 3-D — not axisymmetric: IITM (IITM(nₘₐₓ, Nr, Nϑ, Nφ)).

  • For wavelength / refractive-index sweeps of an axisymmetric shape, see the Sh-matrix examples (ShMatrix, prepare_sh).

+ + +``` + diff --git a/docs/src/examples/solver_landscape.md b/docs/src/examples/solver_landscape.md new file mode 100644 index 0000000..78d3bde --- /dev/null +++ b/docs/src/examples/solver_landscape.md @@ -0,0 +1,88 @@ +```@raw html + + + + + +

Solver landscape & convergence

The same T-matrix can be built several ways. The two-layer API selects them with a solver object passed to transition_matrix(s, λ, solver):

  • a fixed solver — EBCM(nₘₐₓ, Ng), IITM(nₘₐₓ, Nr, Nϑ) — one build;

  • an iterative solver — Iterative(EBCM; …) — sweeps to convergence;

plus the stable = true option that removes the high-aspect EBCM cancellation. This notebook shows why it matters: on a high-aspect spheroid, classic EBCM converges briefly and then diverges as nₘₐₓ grows, while the stabilized path stays converged.

+ +
begin
+    import Pkg
+    Pkg.activate(@__DIR__)
+    Pkg.develop(; path = dirname(@__DIR__))
+    Pkg.instantiate()
+    using TransitionMatrices, Plots
+end
+ + + +

A high-aspect prolate spheroid (aspect ≈ 4)

Three routes to the same cross section:

+ +
begin
+    λ = 2π
+    prolate = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im)
+
+    routes = [
+        (; route = "EBCM fixed (n=24)", Csca = calc_Csca(transition_matrix(prolate, λ, EBCM(24, 384)), λ)),
+        (; route = "Iterative(EBCM; stable)", Csca = calc_Csca(transition_matrix(prolate, λ, Iterative(EBCM; stable = true)), λ)),
+        (; route = "IITM", Csca = calc_Csca(transition_matrix(prolate, λ, IITM(24, 30, 60)), λ)),
+    ]
+end
+
3-element Vector{@NamedTuple{route::String, Csca::Float64}}:
+ (route = "EBCM fixed (n=24)", Csca = 206.5441191992453)
+ (route = "Iterative(EBCM; stable)", Csca = 206.54412963360375)
+ (route = "IITM", Csca = 208.22584428504862)
+ + +

Convergence vs truncation order

Relative error of \(Q_\text{sca}\) against a high-order stabilized reference, for classic EBCM vs the stable = true EBCM. Watch the classic curve blow up.

+ +
begin
+    ref = calc_Csca(transition_matrix(prolate, λ, EBCM(40, 600; stable = true)), λ)
+    ns = 16:2:40
+    classic_err = [abs(calc_Csca(transition_matrix(prolate, λ, EBCM(n, 16n)), λ) - ref) / ref for n in ns]
+    stable_err = [abs(calc_Csca(transition_matrix(prolate, λ, EBCM(n, 16n; stable = true)), λ) - ref) / ref for n in ns]
+    nothing
+end
+ + +
let
+    plot(collect(ns), classic_err; yscale = :log10, lw = 2, marker = :circle,
+        label = "classic EBCM", legend = :left)
+    plot!(collect(ns), stable_err; lw = 2, marker = :square, label = "stable EBCM")
+    plot!(xlabel = "truncation order nₘₐₓ", ylabel = "relative error in Qsca",
+        title = "high-aspect spheroid: classic EBCM diverges, stable holds",
+        size = (720, 420))
+end
+ + + +

Choosing a solver

situationsolver
axisymmetric, moderate aspectcalc_T(s, λ) (auto-converged classic EBCM)
high-aspect spheroidIterative(EBCM; stable = true)
cylinder / Chebyshev / 3-D, hard casesIITM(nₘₐₓ, Nr, Nϑ[, Nφ])
wavelength / index sweepShMatrix / prepare_sh
explicit discretization (benchmarking)EBCM(nₘₐₓ, Ng), IITM(…)

The iterative layer (Iterative) wraps any of these with automatic convergence.

+ + +``` + diff --git a/docs/src/examples/spectral_sensitivity.md b/docs/src/examples/spectral_sensitivity.md new file mode 100644 index 0000000..a14ffb5 --- /dev/null +++ b/docs/src/examples/spectral_sensitivity.md @@ -0,0 +1,117 @@ +```@raw html + + + + + +

Spectral sensitivity with the Sh-matrix method

Fast, exact wavelength / refractive-index sensitivities for an axisymmetric scatterer, built on the Sh-matrix moment-separation backend of TransitionMatrices.jl.

The Sh-matrix method factors every EBCM surface integral as

$$\int = \sum_{\text{terms}} \big[\,\text{coefficient}(k, m_r)\,\big] \times \big[\,\text{shape-only moment}\,\big],$$

where the shape moments depend only on the geometry — not on the wavelength \(\lambda\) or the refractive index \(m_r\). prepare_sh computes the moments once; each transition_matrix(prep, λ, mᵣ) is then a cheap coefficient×moment sum. Because that reconstruction is a plain differentiable function of \((\lambda, m_r)\) with the moments riding through as constants, ForwardDiff straight through it gives exact \(\partial T/\partial\lambda\) and \(\partial T/\partial m_r\) — at a fraction of the cost of differentiating the full from-scratch assembly.

+ +
begin
+    import Pkg
+    Pkg.activate(@__DIR__)                 # the examples/ environment
+    Pkg.develop(; path = dirname(@__DIR__)) # point TransitionMatrices at this repo
+    Pkg.instantiate()
+    using TransitionMatrices, ForwardDiff, Plots, BenchmarkTools
+end
+ + + +

1. Define the scatterer and prepare the moments

A prolate spheroid (semi-axes a = 2, c = 1) with a fixed small absorption mᵢ = 0.02. prepare_sh runs the geometry quadrature once — every spectral point below reuses it.

+ +
begin
+    nmax, Ng = 10, 200
+    mᵢ = 0.02
+    spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + mᵢ * im)
+    prep = prepare_sh(spheroid, nmax, Ng)
+end
+
ShPreparation{Spheroid{Float64, ComplexF64}, Vector{@NamedTuple{Mτd::OffsetArrays.OffsetArray{Float64, 3, Array{Float64, 3}}, Mπd::OffsetArrays.OffsetArray{Float64, 3, Array{Float64, 3}}, Mππττ::OffsetArrays.OffsetMatrix{Float64, Matrix{Float64}}, nmin::Int64, qlo::Int64, qhi::Int64, sym::Bool, ng::Int64}}, @NamedTuple{ψ::OffsetArrays.OffsetVector{Tuple{Int64, Vector{Float64}}, Vector{Tuple{Int64, Vector{Float64}}}}, ψ′::OffsetArrays.OffsetVector{Tuple{Int64, Vector{Float64}}, Vector{Tuple{Int64, Vector{Float64}}}}, χ::OffsetArrays.OffsetVector{Tuple{Int64, Vector{Float64}}, Vector{Tuple{Int64, Vector{Float64}}}}, χ′::OffsetArrays.OffsetVector{Tuple{Int64, Vector{Float64}}, Vector{Tuple{Int64, Vector{Float64}}}}}}(Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im), 10, 200, 30, @NamedTuple{Mτd::OffsetArrays.OffsetArray{Float64, 3, Array{Float64, 3}}, Mπd::OffsetArrays.OffsetArray{Float64, 3, Array{Float64, 3}}, Mππττ::OffsetArrays.OffsetMatrix{Float64, Matrix{Float64}}, nmin::Int64, qlo::Int64, qhi::Int64, sym::Bool, ng::Int64}[(Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; -6.206320203713274e20 -3.7043146918274117e21 … -1.2596302847100982e21 -1.1144755575052641e21; 1.9520286441748424e20 8.945488012541322e20 … 3.6878598840722935e20 1.874211290640545e20; … ; -7.704772103440639e20 -6.130643443016551e21 … -1.7445612997371177e21 -2.32312597077111e21; 1.2856642865459162e21 6.464779858526699e21 … 2.5441182733039016e21 1.6044501024474978e21;;; -1.2181271182545741e21 -7.319520600228689e21 … -2.4784658637735566e21 -2.217538965244375e21; 3.806735350750353e20 1.7566675284302808e21 … 7.217160307268497e20 3.7335618909736704e20; … ; -1.5284870548773863e21 -1.2178458176945998e22 … -3.4577434184250777e21 -4.617130465351015e21; 2.5178168029101257e21 1.2730623209477232e22 … 4.993524665638477e21 3.187250244124098e21;;; -2.391399890181405e21 -1.446506316192557e22 … -4.877490825802162e21 -4.4121479131833146e21; 7.426013342190431e20 3.4504075483162477e21 … 1.4127163869515028e21 7.435501557158452e20; … ; -3.0319283822292516e21 -2.4192480454655064e22 … -6.853224471595671e21 -9.177027908077613e21; 4.931841046019026e21 2.507327652536079e22 … 9.80274658874532e21 6.331078462681293e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0], Mππττ = [0.0 0.0 … 4.946575120586221e22 9.830499550826374e22; 0.0 0.0 … 1.9346945197197015e21 3.795427652666887e21; … ; 0.0 0.0 … 2.1975955092785412e23 4.3807442820825376e23; 0.0 0.0 … 1.0244374720002233e23 2.0201699288725294e23], nmin = 1, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 3.1031601018566384e20 -5.635021315901029e19 … 5.742798058145771e19 -8.667946851631587e19; 6.472411466627936e21 -9.066818776884188e20 … 1.590203654841026e21 -1.5268660668979565e21; … ; 8.392428848806124e21 -1.4210236669974025e21 … 1.728594590137881e21 -2.287075673208998e21; 8.351851411991952e21 -8.195081096626403e20 … 2.582478286096461e21 -1.6302511555095662e21;;; 6.090635591272873e20 -1.0989098397446906e20 … 1.1392669858114291e20 -1.6975117422296472e20; 1.2787672550617607e22 -1.7801752447474747e21 … 3.1589360019247627e21 -3.0063931523826167e21; … ; 1.651212775535008e22 -2.7807225458909407e21 … 3.4261463972736124e21 -4.488772033799732e21; 1.6615460293343982e22 -1.6317758288003413e21 … 5.13247076178637e21 -3.2376926409117495e21;;; 1.1956999450907026e21 -2.1437054010596996e20 … 2.2598659885251907e20 -3.3250465549166e20; 2.526859487125398e22 -3.4959716439682025e21 … 6.275233197136797e21 -5.920482241571846e21; … ; 3.2493216539523146e22 -5.442665436062522e21 … 6.79068579994223e21 -8.811415402413289e21; 3.305386933408405e22 -3.2483180124304316e21 … 1.0201088598407628e22 -6.429714285753598e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; -3.801916124036154e21 5.3748309604363095e20 … -9.265087933132635e20 9.011881276305858e20; 5.3748309604363095e20 -9.760143220874219e19 … 9.946818014316365e19 -1.50133243443326e20; … ; -9.265087933132635e20 9.946818014316365e19 … -2.7378608943944837e20 1.897774399666024e20; 9.011881276305858e20 -1.50133243443326e20 … 1.8977743996660236e20 -2.4409700977162043e20;;; -7.509857367766209e21 1.0549290294471925e21 … -1.8405229405535968e21 1.7740319206934905e21; 1.0549290294471925e21 -1.903367675375177e20 … 1.9732683028112468e20 -2.9401765839865125e20; … ; -1.8405229405535968e21 1.9732683028112468e20 … -5.440149599371842e20 3.760968700941778e20; 1.7740319206934905e21 -2.9401765839865122e20 … 3.760968700941778e20 -4.793208036111016e20;;; -1.4836363829035095e22 2.071013055504413e21 … -3.656218614657985e21 3.492816213751279e21; 2.071013055504413e21 -3.713006671095217e20 … 3.914202710422496e20 -5.7591495706474106e20; … ; -3.656218614657985e21 3.914202710422496e20 … -1.081030102388393e21 7.453433319763579e20; 3.492816213751279e21 -5.759149570647409e20 … 7.453433319763579e20 -9.41362691105749e20], Mππττ = [0.0 0.0 … 2.4950786401194828e22 4.957991077808086e22; 0.0 0.0 … 7.356256285710468e22 1.4620944723246468e23; … ; 0.0 0.0 … 8.32005783069615e22 1.6398271642636478e23; 0.0 0.0 … 2.312335884852783e23 4.610324041601935e23], nmin = 1, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 4.594074770613525e20 … 1.5070575989112147e20 8.049483736034658e19; … ; 0.0 -7.643560411443642e21 … -1.766092590312008e21 -2.36455037882737e21; 0.0 7.941766143307472e21 … 2.49734753100036e21 1.6298383473838952e21;;; 0.0 0.0 … 0.0 0.0; 0.0 9.01841480532334e20 … 2.9488333931723853e20 1.6020853774212855e20; … ; 0.0 -1.5179484470003464e22 … -3.4988977247543084e21 -4.6993256121657233e21; 0.0 1.5633773636559363e22 … 4.900620668475255e21 3.2363051950150873e21;;; 0.0 0.0 … 0.0 0.0; 0.0 1.7707678698100773e21 … 5.7712408768976224e20 3.187882296356513e20; … ; 0.0 -3.0145480650511744e22 … -6.931851125627285e21 -9.340086622481864e21; 0.0 3.078074880381268e22 … 9.618245406516903e21 6.42584694717739e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 -5.654073469949859e21 … -1.5389515262757105e21 -1.4064218134180447e21; … ; 0.0 -1.5389515262757105e21 … -4.887082634743123e20 -3.059349494850811e20; 0.0 -1.4064218134180447e21 … -3.05934949485081e20 -4.61601158297766e20;;; 0.0 0.0 … 0.0 0.0; 0.0 -1.1169617667880552e22 … -3.0277185261848373e21 -2.797535244594491e21; … ; 0.0 -3.0277185261848373e21 … -9.584062073303448e20 -6.077094199649057e20; 0.0 -2.797535244594491e21 … -6.077094199649056e20 -9.173170260217481e20;;; 0.0 0.0 … 0.0 0.0; 0.0 -2.2068895409997875e22 … -5.95773216475517e21 -5.564395664929285e21; … ; 0.0 -5.957732164755171e21 … -1.879870225250007e21 -1.2070536642084324e21; 0.0 -5.564395664929285e21 … -1.2070536642084324e21 -1.8230913012201009e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 7.4521075895413265e22 1.4809006453784008e23; … ; 0.0 0.0 … 2.209083174871646e23 4.402503881422411e23; 0.0 0.0 … 1.0693738527972723e23 2.110346914689605e23], nmin = 2, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.7661446830436393e21 -2.1785778414973548e21; 0.0 0.0 … 2.7012752168032503e21 -1.6822157755007527e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 3.497534457590643e21 -4.273881366855639e21; 0.0 0.0 … 5.368107399963211e21 -3.338036388772147e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 6.926307822637923e21 -8.385848626008758e21; 0.0 0.0 … 1.06684163590797e22 -6.6234487943447e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -8.990807001002892e20 6.114184437419883e20; 0.0 0.0 … 6.114184437419883e20 -7.346999802820343e20;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.7861739329420132e21 1.210739585245546e21; 0.0 0.0 … 1.210739585245546e21 -1.4420557654061008e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.548735816499661e21 2.397573811540613e21; 0.0 0.0 … 2.397573811540613e21 -2.8309014734889623e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 9.587410150643736e22 1.89385476987771e23; 0.0 0.0 … 2.3459449959295518e23 4.6752641143625916e23], nmin = 3, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.820597215012839e21 -2.5010750859701843e21; 0.0 0.0 … 2.339992234576375e21 1.7008434298568222e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.6021416228753695e21 -4.969684064883718e21; 0.0 0.0 … 4.5886327221722447e21 3.3729537809165074e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -7.127245535378715e21 -9.87539286161567e21; 0.0 0.0 … 8.999765599125347e21 6.688762145888105e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -9.678291466096755e20 -6.76883240223466e20; 0.0 0.0 … -6.76883240223466e20 -1.0381314665783852e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.8966123581272592e21 -1.3426268871282105e21; 0.0 0.0 … -1.3426268871282102e21 -2.062916798283439e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.717437848190654e21 -2.663036427057152e21; 0.0 0.0 … -2.663036427057152e21 -4.099592915898166e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 2.2310459620580215e23 4.4426822418245343e23; 0.0 0.0 … 1.2346969372846651e23 2.4417839522727812e23], nmin = 4, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.8139482026302004e21 -1.922955039056183e21; 0.0 0.0 … 2.989015196736736e21 -1.774912038411314e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 3.5859082878586575e21 -3.7688114093579064e21; 0.0 0.0 … 5.937561170793925e21 -3.515877597764067e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 7.089182453901672e21 -7.387946845428333e21; 0.0 0.0 … 1.1795328954619168e22 -6.96453987340816e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.8383375851469453e21 1.1795130468977919e21; 0.0 0.0 … 1.1795130468977919e21 -1.2228474661377433e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.650076415865155e21 2.331924965712985e21; 0.0 0.0 … 2.331924965712985e21 -2.3979481572951337e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -7.24772641815432e21 4.6105337141939017e21; 0.0 0.0 … 4.6105337141939017e21 -4.703123170991452e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.3185218547213114e23 2.61363015730627e23; 0.0 0.0 … 2.3961831552439297e23 4.7708569216337396e23], nmin = 5, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.8592141868353963e21 -2.7689104691959274e21; 0.0 0.0 … 2.011932628178316e21 1.7904329052604982e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.670362919421293e21 -5.497981213210878e21; 0.0 0.0 … 3.940440191761817e21 3.542910039313437e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -7.246469088746187e21 -1.0917392475289438e22; 0.0 0.0 … 7.719105727582097e21 7.010909988786317e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.389104803633932e21 -1.1946854581280852e21; 0.0 0.0 … -1.1946854581280852e21 -1.9568381843971407e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -2.7185995237011017e21 -2.364013754991083e21; 0.0 0.0 … -2.364013754991083e21 -3.8867552897878967e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -5.321741294028404e21 -4.677933404821863e21; 0.0 0.0 … -4.677933404821863e21 -7.720456354808908e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 2.2064908035337283e23 4.387419717016566e23; 0.0 0.0 … 1.653151375972636e23 3.2790163767712275e23], nmin = 6, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.7600357330844013e21 -1.4205331514013416e21; 0.0 0.0 … 3.5990542394015356e21 -1.860532435950302e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 3.4700832823472114e21 -2.7798696628635624e21; 0.0 0.0 … 7.140966681296235e21 -3.675717471820754e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 6.842421634499441e21 -5.441226314863477e21; 0.0 0.0 … 1.4169366693256154e22 -7.262345910093292e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.792819081716976e21 2.0877946582082726e21; 0.0 0.0 … 2.0877946582082726e21 -1.657441297203784e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -7.519957972850259e21 4.117306098910232e21; 0.0 0.0 … 4.117306098910232e21 -3.245227863252615e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.4910734578195936e22 8.120612543854719e21; 0.0 0.0 … 8.120612543854719e21 -6.35544577847116e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 2.337918721715197e23 4.647117256223566e23; 0.0 0.0 … 2.4007966302950592e23 4.7724918895726194e23], nmin = 7, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.6864193045714158e21 -3.1823007591192294e21; 0.0 0.0 … 1.3754032444061773e21 1.78496478673016e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.31860658418729e21 -6.307423936448634e21; 0.0 0.0 … 2.688742658147337e21 3.5211863914994593e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -6.531590465337953e21 -1.2502443940926248e22; 0.0 0.0 … 5.257493544013438e21 6.946945810338582e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.5400537634716532e21 -1.939655454700587e21; 0.0 0.0 … -1.9396554547005867e21 -3.949250449755723e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -3.0079496503120935e21 -3.825125967959605e21; 0.0 0.0 … -3.8251259679596043e21 -7.832858021380489e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -5.876585154196315e21 -7.544202262991468e21; 0.0 0.0 … -7.544202262991467e21 -1.5536519016746729e22], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.9216010188593937e23 3.8123816015643474e23; 0.0 0.0 … 2.8184567231227362e23 5.6036590453099176e23], nmin = 8, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 9.358807377040984e20 -4.1264305131729125e20; 0.0 0.0 … 5.292562778845838e21 -1.7362945430548272e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 1.8392081353806793e21 -8.061158398572306e20; 0.0 0.0 … 1.0473642648826794e22 -3.417793850683656e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 3.6151707399067177e21 -1.5752085081383916e21; 0.0 0.0 … 2.072891905392696e22 -6.728807855623876e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -1.1874442650129877e22 4.0794095588584603e21; 0.0 0.0 … 4.0794095588584603e21 -1.7986693604463409e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -2.3474722301062827e22 8.016922398262255e21; 0.0 0.0 … 8.016922398262256e21 -3.5137774827250846e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … -4.6413637752838334e22 1.575816391889855e22; 0.0 0.0 … 1.575816391889855e22 -6.866174701980715e21], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 7.243441813324107e23 1.4399794908955394e24; 0.0 0.0 … 2.1224536094039614e23 4.209066091723316e23], nmin = 9, qlo = -12, qhi = 80, sym = 1, ng = 100), (Mτd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 9.759014279716345e20;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 1.9181374211458274e21;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 3.770852595692575e21], Mπd = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0;;; … ;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 -1.2434207832890073e22;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 -2.458366367985936e22;;; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 -4.861071903344153e22], Mππττ = [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 8.460402201366554e23 1.6819930380342997e24], nmin = 10, qlo = -12, qhi = 80, sym = 1, ng = 100)], (ψ = [(2, [0.3333333333333333, -0.03333333333333333, 0.0011904761904761906, -2.2045855379188714e-5, 2.505210838544172e-7, -1.9270852604185937e-9, 1.0706029224547743e-11, -4.498331606952833e-14, 1.4797143443923793e-16, -3.9145882126782523e-19  …  6.95188564451722e-52, -3.6782463727604336e-55, 1.778649116421873e-58, -7.891078599919579e-62, 3.2234798202285863e-65, -1.216407479331542e-68, 4.253173004655741e-72, -1.381797597354042e-75, 4.182196117899643e-79, -1.182079174081301e-82]), (3, [0.06666666666666667, -0.004761904761904762, 0.00013227513227513228, -2.0041686708353374e-6, 1.9270852604185938e-8, -1.284723506945729e-10, 6.297664249733966e-13, -2.367542951027807e-15, 7.046258782820854e-18, -1.701994875077501e-20  …  1.5448634765593823e-53, -7.826056112256243e-57, 3.6298961559630063e-60, -1.5472703137097214e-63, 6.08203739665771e-67, -2.2116499624209855e-70, 7.461707025711826e-74, -2.3420298260238e-77, 6.856059209671546e-81, -1.8763161493353983e-84]), (4, [0.009523809523809525, -0.0005291005291005291, 1.2025012025012024e-5, -1.541668208334875e-7, 1.284723506945729e-9, -7.55719709968076e-12, 3.31456013143893e-14, -1.1274014052513367e-16, 3.063590775139502e-19, -6.807979500310004e-22  …  3.2869435671476214e-55, -1.5971543086237228e-58, 7.117443443064718e-62, -2.919377950395701e-65, 1.1058249812104927e-68, -3.88008765337015e-72, 1.264696106052852e-75, -3.839393157416066e-79, 1.088263366614531e-82, -2.8866402297467667e-86]), (5, [0.0010582010582010583, -4.81000481000481e-5, 9.25000925000925e-7, -1.0277788055565833e-8, 7.55719709968076e-11, -3.977472157726716e-13, 1.5783619673518714e-15, -4.901745240223203e-18, 1.2254363100558008e-20, -2.5214738890037053e-23  …  6.708048096219635e-57, -3.131675114948476e-60, 1.3429138571820223e-63, -5.307959909810365e-67, 1.940043826685075e-70, -6.5764197514748305e-74, 2.0732723050046753e-77, -6.094274853041374e-81, 1.6742513332531247e-84, -4.308418253353383e-88]), (6, [9.62000962000962e-5, -3.7000037000037e-6, 6.1666728333395e-8, -6.045757679744608e-10, 3.977472157726716e-12, -1.8940343608222456e-14, 6.862443336312483e-17, -1.9606980960892812e-19, 4.538653000206669e-22, -8.69473754828864e-25  …  1.31530354827836e-58, -5.908820971600898e-62, 2.441661558512768e-65, -9.31221036808836e-69, 3.2882098757374153e-72, -1.0781015986024312e-75, 3.290908420642342e-79, -9.375807466217499e-83, 2.4988825869449622e-86, -6.244084425149831e-90]), (7, [7.4000074000074e-6, -2.4666691333358e-7, 3.627454607846765e-9, -3.181977726181373e-11, 1.8940343608222457e-13, -8.234932003574981e-16, 2.7449773345249934e-18, -7.26184480033067e-21, 1.565052758691955e-23, -2.8047540478350445e-26  …  2.4817048080723773e-60, -1.074331085745618e-63, 4.283616769320646e-67, -1.5783407403539593e-70, 5.390507993012156e-74, -1.7112723787340177e-77, 5.062936031757449e-81, -1.399374248689179e-84, 3.621568966586902e-88, -8.794485105844832e-92]), (8, [4.9333382666716e-7, -1.450981843138706e-8, 1.9091866357088235e-10, -1.5152274886577965e-12, 8.23493200357498e-15, -3.2939728014299924e-17, 1.0166582720462939e-19, -2.504084413907128e-22, 5.04855728610308e-25, -8.499254690409227e-28  …  4.512190560131595e-62, -1.884791378501084e-65, 7.260367405628212e-69, -2.587443836645835e-72, 8.556361893670089e-76, -2.6327267365138734e-79, 7.556620942921566e-83, -2.028078621288665e-86, 5.100801361390003e-90, -1.2047239871020318e-93]), (9, [2.901963686277412e-8, -7.636746542835294e-10, 9.091364931946779e-12, -6.587945602859985e-14, 3.293972801429992e-16, -1.2199899264555528e-18, 3.505718179469979e-21, -8.077691657764928e-24, 1.5298658442736607e-26, -2.4283584829740647e-29  …  7.916123789704553e-64, -3.194561658476414e-67, 1.190224164857084e-70, -4.107053708961643e-74, 1.3163633682569368e-77, -3.929442890319214e-81, 1.095162455495879e-84, -2.8564487623784017e-88, 6.987399125191784e-92, -1.606298649469376e-95]), (10, [1.5273493085670588e-9, -3.6365459727787115e-11, 3.9527673617159907e-13, -2.6351782411439937e-15, 1.2199899264555527e-17, -4.2068618153639746e-20, 1.13087683208709e-22, -2.447785350837857e-25, 4.371045269353316e-28, -6.56313103506504e-31  …  1.3417158965600938e-65, -5.23698632537117e-69, 1.8892447061223556e-72, -6.318544167633297e-76, 1.964721445159607e-79, -5.694844768578571e-83, 1.5424823316843368e-86, -3.9129435101073994e-90, 9.31653216692238e-94, -2.0861021421680204e-97]), (11, [7.273091945557423e-11, -1.5811069446863963e-12, 1.5811069446863962e-14, -9.759919411644421e-17, 4.2068618153639746e-19, -1.357052198504508e-21, 3.426899491173e-24, -6.993672430965306e-27, 1.181363586311707e-29, -1.6828541115551385e-32  …  2.1995342566558915e-67, -8.312676706938365e-71, 2.9065303171113163e-74, -9.430662936766114e-78, 2.8474223842892857e-81, -8.020908124758551e-85, 2.1129894954579956e-88, -5.2172580134765327e-92, 1.2099392424574518e-95, -2.6406356229974942e-99])], ψ′ = [(1, [0.6666666666666666, -0.13333333333333333, 0.0071428571428571435, -0.0001763668430335097, 2.505210838544172e-6, -2.3125023125023123e-8, 1.498844091436684e-10, -7.197330571124533e-13, 2.6634858199062827e-15, -7.829176425356505e-18  …  2.9197919706972322e-50, -1.6184284040145907e-53, 8.181785935540616e-57, -3.787717727961398e-60, 1.6117399101142932e-63, -6.325318892524018e-67, 2.2967134225141003e-70, -7.738066545182636e-74, 2.425673748381793e-77, -7.092475044487806e-81]), (2, [0.2, -0.02380952380952381, 0.000925925925925926, -1.8037518037518038e-5, 2.119793786460453e-7, -1.6701405590294477e-9, 9.44649637460095e-12, -4.024823016747272e-14, 1.3387891687359624e-16, -3.574189237662752e-19  …  6.642912949205344e-52, -3.5217252505153094e-55, 1.706051193302613e-58, -7.581624537177635e-62, 3.101839072295432e-65, -1.1721744800831223e-68, 4.1039388641415046e-72, -1.334957000833566e-75, 4.045074933706212e-79, -1.1445528510945929e-82]), (3, [0.0380952380952381, -0.0031746031746031746, 9.62000962000962e-5, -1.541668208334875e-6, 1.541668208334875e-8, -1.0580075939553064e-10, 5.303296210302288e-13, -2.029322529452406e-15, 6.127181550279003e-18, -1.497755490068201e-20  …  1.4462551695449534e-53, -7.346909819669125e-57, 3.416372852671065e-60, -1.4596889751978504e-63, 5.750289902294562e-67, -2.095247332819881e-70, 7.082298193895972e-74, -2.226848031301318e-77, 6.529580199687186e-81, -1.7897169424429953e-84]), (4, [0.005291005291005292, -0.00033670033670033666, 8.325008325008325e-6, -1.1305566861122415e-7, 9.824356229584988e-10, -5.9662082365900735e-12, 2.6832153444981813e-14, -9.313315956424085e-17, 2.5734162511171816e-19, -5.799389944708522e-22  …  3.018621643298836e-55, -1.4718873040257839e-58, 6.580277900191909e-62, -2.707059554003286e-65, 1.0282232281430897e-68, -3.6170308633111566e-72, 1.181765213852665e-75, -3.5956221632944105e-79, 1.0212933132844061e-82, -2.7143034996126314e-86]), (5, [0.0005772005772005772, -2.96000296000296e-5, 6.1666728333395e-7, -7.254909215693529e-9, 5.5684610208174025e-11, -3.030454977315593e-13, 1.2352398005362471e-15, -3.921396192178562e-18, 9.985036600454672e-21, -2.0867370115892735e-23  …  6.050396322080456e-57, -2.836234066368431e-60, 1.2208307792563839e-63, -4.842349391405947e-67, 1.7756333328982043e-70, -6.037368952173615e-74, 1.908726883972558e-77, -5.625484479730499e-81, 1.5493072039058765e-84, -3.9962140320958917e-88]), (6, [5.1800051800051795e-5, -2.22000222000222e-6, 3.9902000686314417e-8, -4.1365710440357845e-10, 2.8410515412333686e-12, -1.3999384406077467e-14, 5.215456935597487e-17, -1.524987408069441e-19, 3.5996213449914964e-22, -7.011885119587611e-25  …  1.1664012597940174e-58, -5.264222320153528e-62, 2.1846445523535294e-65, -8.365205923875984e-69, 2.964779396156686e-72, -9.754252558783901e-76, 2.9871322587368946e-79, -8.536182917003992e-83, 2.2815884489497484e-86, -5.71641531879914e-90]), (7, [3.94667061333728e-6, -1.450981843138706e-7, 2.291023962850588e-9, -2.1213184841209153e-11, 1.317589120571997e-13, -5.929151042573987e-16, 2.033316544092588e-18, -5.508985710595681e-21, 1.2116537486647392e-23, -2.209806219506399e-26  …  2.1658514688631656e-60, -9.42395689250542e-64, 3.7753910509266703e-67, -1.3972196717887509e-70, 4.79156266045525e-74, -1.5269815071780465e-77, 4.53397256575294e-81, -1.2574087451989722e-84, 3.264512871289602e-88, -7.95117831487341e-92]), (8, [2.6117673176496706e-7, -8.400421197118823e-9, 1.1818774411530812e-10, -9.881918404289976e-13, 5.5997537624309865e-15, -2.3179808602655502e-17, 7.362008176886955e-20, -1.8578690812859335e-22, 3.824664610684152e-25, -6.556567904029974e-28  …  3.878900656955231e-62, -1.6292264458229712e-65, 6.308188073742545e-69, -2.2588795399289037e-72, 7.50327119906454e-76, -2.3183713052883363e-79, 6.680490978524862e-83, -1.799562720298393e-86, 4.54180943137466e-90, -1.0762200951444819e-93]), (9, [1.527349308567059e-8, -4.363855167334454e-10, 5.5338743064023874e-12, -4.21628518583039e-14, 2.1959818676199949e-16, -8.413723630727949e-19, 2.487929030591598e-21, -5.8746848420108574e-24, 1.1364717700318621e-26, -1.837676689818211e-29  …  6.708579482800469e-64, -2.7232328891930083e-67, 1.020192141306072e-70, -3.538384733874646e-74, 1.1395384381925722e-77, -3.4169068611471427e-81, 9.563390456442889e-85, -2.5042838464687356e-88, 6.148911230168771e-92, -1.4185494566742538e-95]), (10, [8.000401140113166e-10, -2.055439028092315e-11, 2.3716604170295944e-13, -1.6591862999795517e-15, 7.993037449191552e-18, -2.849809616859467e-20, 7.881868829697899e-23, -1.7484181077413264e-25, 3.189681683041609e-28, -4.880276923509902e-31  …  1.1217624708945047e-65, -4.4057186546773336e-69, 1.5985916744112238e-72, -5.3754778739566846e-76, 1.6799792067306786e-79, -4.892753956102716e-83, 1.3311833821385373e-86, -3.391217708759746e-90, 8.106592924464927e-94, -1.822038579868271e-97])], χ = [(-1, [-1.0, -0.5, 0.125, -0.006944444444444444, 0.00017361111111111112, -2.48015873015873e-6, 2.296443268665491e-8, -1.4911969277048643e-10, 7.169215998581078e-13, -2.6552651846596585e-15  …  4.7799080126007045e-47, -2.9181367598294903e-50, 1.6175924389298726e-53, -8.177919307026656e-57, 3.786073753253082e-60, -1.6110952141502475e-63, 6.322979647371458e-67, -2.2959257978836086e-70, 7.735599049473075e-74, -2.4249526800856032e-77]), (-2, [-3.0, -0.5, -0.125, 0.020833333333333332, -0.0008680555555555555, 1.736111111111111e-5, -2.066798941798942e-7, 1.6403166204753507e-9, -9.319980798155402e-12, 3.982897776989488e-14  …  -1.768565964662261e-45, 1.1380733363335011e-48, -6.6321289996124775e-52, 3.516505302021462e-55, -1.7037331889638866e-58, 7.572147506506163e-62, -3.0982600272120143e-65, 1.1709221569206403e-68, -4.0998674962207297e-72, 1.3337239740470818e-75]), (-3, [-15.0, -1.5, -0.125, -0.020833333333333332, 0.0026041666666666665, -8.680555555555556e-5, 1.4467592592592592e-6, -1.4762849584278155e-8, 1.0251978877970942e-10, -5.177767110086334e-13  …  6.189980876317913e-44, -4.210871344433954e-47, 2.5865303098488663e-50, -1.4417671738287994e-53, 7.326052712544713e-57, -3.407466377927773e-60, 1.4561822127896468e-63, -5.7375185689111376e-67, 2.090932423072572e-70, -7.0687370624495336e-74]), (-4, [-105.0, -7.5, -0.375, -0.020833333333333332, -0.0026041666666666665, 0.00026041666666666666, -7.2337962962962966e-6, 1.033399470899471e-7, -9.226780990173847e-10, 5.6955438210949675e-12  …  -2.0426936891849113e-42, 1.473804970551884e-45, -9.570162146440805e-49, 5.622891977932318e-52, -3.0036816121433323e-55, 1.4652105425089426e-58, -6.55281995755341e-62, 2.6966337273882347e-65, -1.0245568873055603e-68, 3.6050559018492623e-72]), (-5, [-945.0, -52.5, -1.875, -0.0625, -0.0026041666666666665, -0.00026041666666666666, 2.170138888888889e-5, -5.166997354497355e-7, 6.458746693121693e-9, -5.125989438985471e-11  …  6.332350436473224e-41, -4.863556402821217e-44, 3.349556751254282e-47, -2.0804700318349577e-50, 1.1714358287358995e-53, -6.007363224286664e-57, 2.8177125817479663e-60, -1.2134851773247056e-63, 4.815417370336133e-67, -1.7664773919061385e-70]), (-6, [-10395.0, -472.5, -13.125, -0.3125, -0.0078125, -0.00026041666666666666, -2.170138888888889e-5, 1.5500992063492063e-6, -3.229373346560847e-8, 3.5881926072898297e-10  …  -1.8363816265772353e-39, 1.5077024848745773e-42, -1.105353727913913e-45, 7.281645111422351e-49, -4.3343125663228286e-52, 2.342871657471799e-55, -1.1552621585166662e-58, 5.2179862624962345e-62, -2.16693781665126e-65, 8.302443741958851e-69]), (-7, [-135135.0, -5197.5, -118.125, -2.1875, -0.0390625, -0.00078125, -2.170138888888889e-5, -1.5500992063492063e-6, 9.68812003968254e-8, -1.7940963036449148e-9  …  4.958230391758535e-38, -4.372337206136274e-41, 3.4265965565331304e-44, -2.402942886769376e-47, 1.5170093982129898e-50, -8.668625132645657e-54, 4.5055224182149983e-57, -2.139374367623456e-60, 9.317832611600418e-64, -3.7360996838814826e-67]), (-8, [-2.027025e6, -67567.5, -1299.375, -19.6875, -0.2734375, -0.00390625, -6.510416666666667e-5, -1.5500992063492063e-6, -9.68812003968254e-8, 5.382288910934745e-9  …  -1.2395575979396338e-36, 1.1805310456567941e-39, -9.937130013946078e-43, 7.449122948985067e-46, -5.0061310141028664e-49, 3.03401879642598e-52, -1.6670432947395494e-55, 8.343560033731478e-59, -3.8203113707561713e-62, 1.6065228640690376e-65]), (-9, [-3.4459425e7, -1.0135125e6, -16891.875, -216.5625, -2.4609375, -0.02734375, -0.0003255208333333333, -4.6502976190476195e-6, -9.68812003968254e-8, -5.382288910934745e-9  …  2.8509824752611576e-35, -2.951327614141985e-38, 2.683025103765441e-41, -2.160245655205669e-44, 1.5519006143718887e-47, -1.0012262028205733e-50, 5.834651531588423e-54, -3.087117212480647e-57, 1.4899214345949068e-60, -6.586743742683055e-64]), (-10, [-6.54729075e8, -1.72297125e7, -253378.125, -2815.3125, -27.0703125, -0.24609375, -0.0022786458333333335, -2.3251488095238094e-5, -2.906436011904762e-7, -5.382288910934745e-9  …  -5.987063198048431e-34, 6.788053512526565e-37, -6.707562759413602e-40, 5.8326632690553065e-43, -4.500511781678477e-46, 3.1038012287437775e-49, -1.9254350054241794e-52, 1.0804910243682265e-55, -5.512709308001156e-59, 2.568830059646391e-62])], χ′ = [(-2, [1.0, -0.5, 0.375, -0.034722222222222224, 0.0012152777777777778, -2.232142857142857e-5, 2.5260875955320403e-7, -1.9385560060163236e-9, 1.0753823997871616e-11, -4.5139508139214194e-14  …  1.8641641249142746e-45, -1.196436071530091e-48, 6.955647487398453e-52, -3.680063688161995e-55, 1.7794546640289485e-58, -7.894366549336212e-62, 3.2247196201594434e-65, -1.2168406728783126e-68, 4.254579477210191e-72, -1.3822230276487938e-75]), (-3, [6.0, -0.0, -0.25, 0.08333333333333333, -0.005208333333333333, 0.0001388888888888889, -2.066798941798942e-6, 1.968379944570421e-8, -1.3047973117417563e-10, 6.372636443183181e-13  …  -6.720550665716591e-44, 4.552293345334004e-47, -2.7854941798372404e-50, 1.5472623328894435e-53, -7.837172669233879e-57, 3.634630803122958e-60, -1.549130013606007e-63, 6.08879521598733e-67, -2.213928447959194e-70, 7.468854254663658e-74]), (-4, [45.0, 1.5, -0.125, -0.0625, 0.013020833333333332, -0.0006076388888888889, 1.3020833333333332e-5, -1.6239134542705971e-7, 1.3327572541362226e-9, -7.766650665129502e-12  …  2.2902929242376276e-42, -1.642239824329242e-45, 1.0604774270380352e-48, -6.199598847463838e-52, 3.2967237206451204e-55, -1.6015091976260532e-58, 7.1352928426692695e-62, -2.92613447014468e-65, 1.1081941842284631e-68, -3.8878053843472433e-72]), (-5, [420.0, 15.0, -0.0, -0.041666666666666664, -0.010416666666666666, 0.0015625, -5.787037037037037e-5, 1.033399470899471e-6, -1.1072137188208615e-8, 7.973761349532954e-11  …  -7.353697281065681e-41, 5.600458888097159e-44, -3.828064858576322e-47, 2.3616146307315735e-50, -1.3216199093430663e-53, 6.739968495541137e-57, -3.1453535796256366e-60, 1.3483168636941173e-63, -5.3276958139889134e-67, 1.9467301869986017e-70]), (-6, [4725.0, 157.5, 1.875, -0.0625, -0.0078125, -0.0013020833333333333, 0.00015190972222222222, -4.6502976190476195e-6, 7.104621362433863e-8, -6.663786270681113e-10  …  2.2163226527656285e-39, -1.7995158690438504e-42, 1.30632713298917e-45, -8.529927130523327e-49, 5.037174063564368e-52, -2.703313450928999e-55, 1.324324913421544e-58, -5.946077368891057e-62, 2.4558628588714277e-65, -9.362330177102533e-69]), (-7, [62370.0, 1890.0, 26.25, -0.0, -0.015625, -0.0010416666666666667, -0.00013020833333333333, 1.240079365079365e-5, -3.229373346560847e-7, 4.305831128747796e-9  …  -6.2436975303626e-38, 5.427728945548479e-41, -4.20034416607287e-44, 2.9126580445689405e-47, -1.820411277855588e-50, 1.0308635292875916e-53, -5.314205929176664e-57, 2.5046334059981926e-60, -1.08346890832563e-63, 4.317270745818602e-67]), (-8, [945945.0, 25987.5, 354.375, 2.1875, -0.0390625, -0.0023437500000000003, -0.00010850694444444445, -1.0850694444444445e-5, 8.719308035714285e-7, -1.973505934009406e-8  …  1.6362160292803167e-36, -1.530318022147696e-39, 1.2678407259172583e-42, -9.371477258400566e-46, 6.219738532673258e-49, -3.7275088070376326e-52, 2.027485088196749e-55, -1.0055059527830242e-58, 4.565737979684205e-62, -1.905410838779556e-65]), (-9, [1.62162e7, 405405.0, 5197.5, 39.375, -0.0, -0.0078125, -0.00026041666666666666, -9.300595238095239e-6, -7.750496031746032e-7, 5.3822889109347446e-8  …  -3.966584313406828e-35, 4.0138055552331e-38, -3.577366805020588e-41, 2.8306667206143253e-44, -2.0024524056411467e-47, 1.2742878944989115e-50, -7.334990496854017e-54, 3.83803761551648e-57, -1.8337494579629622e-60, 8.032614320345189e-64]), (-10, [3.10134825e8, 7.0945875e6, 84459.375, 649.6875, 2.4609375, -0.02734375, -0.0009765625, -2.3251488095238097e-5, -6.781684027777778e-7, -4.84406001984127e-8  …  8.838045673309588e-34, -9.73938112666855e-37, 9.390587863179044e-40, -7.992908924260976e-43, 6.0524123960503656e-46, -4.10502743156435e-49, 2.508900158583022e-52, -1.3892027456162912e-55, 7.002630742596062e-59, -3.2275044339146967e-62]), (-11, [6.54729075e9, 1.378377e8, 1.52026875e6, 11261.25, 54.140625, -0.0, -0.004557291666666667, -9.300595238095238e-5, -1.7438616071428573e-6, -4.305831128747796e-8  …  -1.7961189594145292e-32, 2.172177124008501e-35, -2.2805713382006248e-38, 2.0997587768599102e-41, -1.7101944770378213e-44, 1.241520491497511e-47, -8.086827022781553e-51, 4.7541605072201964e-54, -2.5358462816805317e-57, 1.2330384286302677e-60])]), true)
+ + +

2. Spectrum and sensitivities

Sweep the wavelength across a band; at each point reconstruct the T-matrix and read off the scattering / extinction cross sections. The sensitivities \(\partial C_\text{sca}/\partial\lambda\) and \(\partial C_\text{sca}/\partial m_r\) come from ForwardDiff applied to the reconstruction only — the moments in prep are constants.

+ +
begin
+    mᵣ = 1.5
+    λs = collect(range(2π / 1.6, 2π / 0.6; length = 60))
+
+    Csca(λ, m) = calc_Csca(transition_matrix(prep, λ, complex(m, mᵢ)), λ)
+    Cext(λ, m) = calc_Cext(transition_matrix(prep, λ, complex(m, mᵢ)), λ)
+
+    csca = [Csca(λ, mᵣ) for λ in λs]
+    cext = [Cext(λ, mᵣ) for λ in λs]
+
+    ∂Csca_∂λ = [ForwardDiff.derivative(l -> Csca(l, mᵣ), λ) for λ in λs]
+    ∂Csca_∂mᵣ = [ForwardDiff.derivative(m -> Csca(λ, m), mᵣ) for λ in λs]
+    nothing
+end
+ + + +

3. The spectra and their sensitivities

+ +
let
+    p1 = plot(λs, [csca cext]; label = ["Csca" "Cext"], lw = 2,
+        ylabel = "cross section", legend = :topright)
+    p2 = plot(λs, ∂Csca_∂λ; label = "∂Csca/∂λ", lw = 2, color = 3, ylabel = "∂/∂λ")
+    p3 = plot(λs, ∂Csca_∂mᵣ; label = "∂Csca/∂mᵣ", lw = 2, color = 4,
+        xlabel = "wavelength λ", ylabel = "∂/∂mᵣ")
+    plot(p1, p2, p3; layout = (3, 1), size = (720, 660),
+        title = ["spheroid a=2, c=1, m=1.5+0.02im" "" ""])
+end
+ + + +

4. Why it is cheap — and how much

Differentiating the reconstruction reuses the single prepare_sh for the whole spectrum; differentiating the classic from-scratch assembly re-runs the full quadrature and Bessel recursions (in dual numbers) at every wavelength.

+ +
begin
+    function Csca_classic(λ, m)
+        T = promote_type(typeof(λ), typeof(m))
+        s = TransitionMatrices.Spheroid{T, Complex{T}}(T(2.0), T(1.0), Complex{T}(m, mᵢ))
+        calc_Csca(transition_matrix(s, λ, EBCM(nmax, Ng)), λ)
+    end
+
+    f_sh(λ) = ForwardDiff.derivative(l -> Csca(l, mᵣ), λ)
+    f_classic(λ) = ForwardDiff.derivative(l -> Csca_classic(l, mᵣ), λ)
+    f_sh(λs[1]); f_classic(λs[1])   # warm up
+
+    t_prepare = @belapsed prepare_sh($spheroid, $nmax, $Ng) samples=1 evals=1
+    t_sh = @belapsed [f_sh(λ) for λ in $λs] samples=1 evals=1
+    t_classic = @belapsed [f_classic(λ) for λ in $λs] samples=1 evals=1
+
+    (; n_points = length(λs),
+        sh_ms = round((t_prepare + t_sh) * 1e3; digits = 1),
+        classic_ms = round(t_classic * 1e3; digits = 1),
+        speedup = round(t_classic / (t_prepare + t_sh); digits = 1))
+end
+
(n_points = 60, sh_ms = 224.5, classic_ms = 5927.6, speedup = 26.4)
+ + +

Takeaway

prepare_sh once, then ForwardDiff the reconstruction, gives exact \(\partial C/\partial\lambda\) and \(\partial C/\partial m_r\) (matching the classic result to machine precision) at a large speedup for spectra — the win grows with the number of wavelengths because the geometry quadrature is amortized.

Ideal for material/wavelength sensitivity (retrievals, dispersion fitting). Shape-parameter derivatives act on the moments themselves and are better served by the dedicated analytical EBCM linearization backend.

+ + +``` + diff --git a/docs/src/usage.md b/docs/src/usage.md index 0b1bacc..f065ffd 100644 --- a/docs/src/usage.md +++ b/docs/src/usage.md @@ -38,24 +38,122 @@ chebyshev = Chebyshev{Arb, Acb}(1.0, 0.1, 4, 1.5+0.01im); ## Calculate the T-Matrix -After defining a shape, the T-Matrix can be calculated using the `transition_matrix` function. It has an alias `calc_T` for convenience. +After defining a shape, the T-Matrix is computed with `transition_matrix` (alias +`calc_T`). The solvers are organized into **two layers**, selected by the kind of +*solver object* you pass as the third argument: -Take the spheroid defined above as an example, and suppose the wavelength is `λ=2π`. The T-Matrix can be calculated iteratively as follows: +- an **iterative solver** ([`Iterative`](@ref)) sweeps the discretization until + the scattering/extinction efficiencies converge; +- a **fixed solution** ([`EBCM`](@ref), [`IITM`](@ref), [`ShMatrix`](@ref)) + builds the T-matrix once at an explicit discretization. + +The bare call uses an automatically-converged classic EBCM — the common default: ```julia -𝐓 = calc_T(spheroid, 2π) +𝐓 = calc_T(spheroid, 2π) # ≡ transition_matrix(spheroid, 2π, Iterative(EBCM)) ``` -To see the process, you can turn on debugging by setting `ENV["JULIA_DEBUG"] = "TransitionMatrices"`, and then run the above code. +To see the convergence process, set `ENV["JULIA_DEBUG"] = "TransitionMatrices"` +before running. Tune the convergence (or switch on stabilization) by passing an +explicit `Iterative`: -There are many optional keyword arguments, and you can refer to the detailed documentation of the [`transition_matrix`](@ref). +```julia +𝐓 = transition_matrix(spheroid, 2π, Iterative(EBCM; threshold = 1e-7)) +``` -You can also calculate the T-Matrix directly by specifying the truncation order and number of Gauss-Legendre quadrature points: +For a fixed build, pass a fixed solver with its discretization: ```julia -𝐓 = transition_matrix(spheroid, 2π, 10, 100) +𝐓 = transition_matrix(spheroid, 2π, EBCM(10, 100)) # order 10, 100 quadrature points +𝐓 = transition_matrix(cylinder, 2π, IITM(10, 20, 24)) # IITM: order, Nr, Nϑ +𝐓 = transition_matrix(spheroid, 2π, ShMatrix(10, 200)) # Sh-matrix moment separation ``` +### High-aspect-ratio spheroids (`stable`) + +For spheroids of high aspect ratio the standard EBCM surface integrals lose all +precision in `Float64`: the irregular Riccati–Bessel products develop large +Laurent terms that cancel analytically on integration but not numerically. The +`stable` option assembles the `𝐔`-matrix with the cancellation-free `F⁺` +formulation of [Somerville, Auguié & Le Ru (2013)](https://doi.org/10.1016/j.jqsrt.2012.07.017), +which removes the cancellation and restores a relative accuracy of about `1e-9` +in `Float64`, independent of aspect ratio. It is available on **both layers** — +auto-converged or fixed: + +```julia +prolate = Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im) # aspect 4 +𝐓 = transition_matrix(prolate, 2π, Iterative(EBCM; stable = true)) # converged + stabilized +𝐓 = transition_matrix(prolate, 2π, EBCM(32, 400; stable = true)) # fixed + stabilized +``` + +`stable` is **only valid for `Spheroid`** (the cancellation relies on the spheroid +surface) and costs roughly 2–3× the default assembly, so it is opt-in. For a fixed +build to help, choose `nₘₐₓ` large enough that `nₘₐₓ + 1 ≳ k·c + 15`, where `c` is +the largest semi-axis — comparable to the order needed for convergence at that +size anyway (the iterative form finds it for you). + +`stable` and extended precision are **orthogonal** and stack. Just raising +precision without `stable` (e.g. `Spheroid{Double64}`) only buys ~15 extra digits +of headroom against the cancellation — enough for moderate aspect ratios but not +high ones — and is several times slower; for a high-aspect spheroid `stable` in +`Float64` is both more accurate and faster. When you need more than `~1e-9`, +combine the two: `stable` with a `Double64` element type reaches `~1e-25` at high +aspect ratio, and also lowers the residual `Float64` round-off floor that appears +as the refractive index approaches `s → 1`. + +### Parameter sweeps with the Sh-matrix method (`prepare_sh`) + +When you need the T-matrix of one fixed shape at *many* wavelengths or +refractive indices — a spectrum, a dispersion curve, a refractive-index scan — +the bulk of the work (the Gauss–Legendre surface quadrature and the Wigner +functions) does not change between points. The Sh-matrix moment-separation +method (Farafonov family) exploits this: every EBCM surface integral factors as + +```math +\int = \sum_{\text{terms}} \big[\text{coefficient in } (k, m_r)\big]\times\big[\text{shape-only moment } M(q)\big], +``` + +where the *shape moments* depend only on the particle geometry and the azimuthal +index — not on the wavelength or the refractive index. `prepare_sh` computes the +moments once; each `transition_matrix(prep, λ, mᵣ)` is then a cheap +coefficient×moment reconstruction: + +```julia +spheroid = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) +prep = prepare_sh(spheroid, 10, 200) + +# one wavelength / refractive index +𝐓 = transition_matrix(prep, 2π, 1.5 + 0.02im) + +# a full sweep, reusing the single preparation +λs = range(2π, 3π; length = 50) +𝐓s = transition_matrix_spectrum(prep, λs, 1.5 + 0.02im) # fixed index +𝐓s = transition_matrix_spectrum(prep, λs, my_dispersion.(λs)) # λ-dependent index +``` + +The same sweep is available through the [`ShMatrix`](@ref) fixed-solver façade, +which prepares once internally and reconstructs at each point: + +```julia +𝐓s = transition_matrix(spheroid, λs, my_dispersion.(λs), ShMatrix(10, 200)) +``` + +For a spheroid the reconstruction also inherits the high-aspect-ratio +stabilization for free: the negative-`r`-power moments vanish analytically, so — +accumulated at high precision inside `prepare_sh` — they contribute ≈0 and the +irregular-product cancellation that defeats the standard `Float64` assembly +never forms (`prep.stable` reports this). The cross sections of the +reconstructed T-matrix match the standard assembly to roughly `1e-9`–`1e-15` for +moderate sizes, and the high-aspect path tracks the `stable=true` result. + +`prepare_sh` accepts a keyword `B` (the number of radial power-series terms, +default `max(30, nₘₐₓ+15)`). Like the `F⁺` evaluation, the series needs more +terms as the size parameter `k·rₘₐₓ·|mᵣ|` grows, so the method is best suited to +small-to-moderate size parameters; very large particles still want the recursion +path. The analytic `𝐔` stabilization is enabled only for `Spheroid` — for other +axisymmetric shapes the moment machinery and `𝐏` are correct and the sweep reuse +still applies, but the `𝐔` reconstruction is not stabilized. + ## Post-processing After getting the T-Matrix, you can calculate the far-field scattering properties using the following functions: @@ -112,14 +210,14 @@ function f(x) Csca = calc_Csca(T₀) end -gradient = ForwardDiff.gradient(f, [2.0, 3.0, 1.311, 0.02, 2π]) +gradient = round.(ForwardDiff.gradient(f, [2.0, 3.0, 1.311, 0.02, 2π]); digits = 12) # output 5-element Vector{Float64}: - 19.872009666582716 - 5.740718904091895 - 89.1305069099317 - -45.84568759716397 - -9.066448506675068 + 19.872009666583 + 5.740718904092 + 89.130506909932 + -45.845687597164 + -9.066448506675 ``` diff --git a/examples/Project.toml b/examples/Project.toml new file mode 100644 index 0000000..d7d3994 --- /dev/null +++ b/examples/Project.toml @@ -0,0 +1,6 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781" +TransitionMatrices = "057c4241-e127-4181-840e-6b4b92e6eef5" diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..27bebf8 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,40 @@ +# Examples + +Runnable examples for `TransitionMatrices.jl`, as [Pluto.jl](https://plutojl.org) +notebooks. They use this `examples/` environment ([`Project.toml`](Project.toml)), +which includes `Pluto`, `Plots`, `ForwardDiff`, and develops the parent package. + +## Running a notebook + +```julia +julia> import Pkg; Pkg.activate("examples"); Pkg.instantiate() # first time only +julia> using Pluto; Pluto.run() +``` + +Then open the notebook from the Pluto start page. Each notebook's first cell +activates this environment and develops `TransitionMatrices` from the repo root, +so it works from a fresh checkout (the first run installs dependencies). + +## Notebooks + +- [`shapes_gallery.jl`](shapes_gallery.jl) — **quick-start gallery**: define a + spheroid, cylinder, Chebyshev particle, and N-fold prism; compute each + T-matrix and its `Qsca`/`Qext`/`g`/`ω`; notes on which solver to use. +- [`angular_scattering.jl`](angular_scattering.jl) — **angular scattering & + polarization**: the orientation-averaged scattering (Mueller) matrix vs angle + (phase function `F₁₁`, linear polarization `-F₁₂/F₁₁`, `F₂₂/F₁₁`, `F₄₄/F₁₁`), + plus the fixed-geometry amplitude/phase matrices. +- [`orientation_averaging.jl`](orientation_averaging.jl) — **orientation + averaging**: Mishchenko's analytic `RandomOrientationTransitionMatrix` vs the + numerical `orientation_average`, and the numerical average converging to it. +- [`solver_landscape.jl`](solver_landscape.jl) — **solver landscape & + convergence**: the two-layer API (`EBCM`, `IITM`, `Iterative`, `stable`) on a + high-aspect spheroid, showing classic EBCM diverging with `nₘₐₓ` while the + stabilized path holds. +- [`spectral_sensitivity.jl`](spectral_sensitivity.jl) — **fast wavelength / + refractive-index sensitivities** via the Sh-matrix moment-separation backend. + `prepare_sh` runs the geometry quadrature once; differentiating the cheap + reconstruction with `ForwardDiff` then gives exact `∂Cₛ𝚌ₐ/∂λ` and `∂Cₛ𝚌ₐ/∂mᵣ` + across a whole spectrum at a large speedup over differentiating the + from-scratch assembly. Includes plots of the spectra and their sensitivities, + and a timing comparison. diff --git a/examples/angular_scattering.jl b/examples/angular_scattering.jl new file mode 100644 index 0000000..08dcf89 --- /dev/null +++ b/examples/angular_scattering.jl @@ -0,0 +1,102 @@ +### A Pluto.jl notebook ### +# v1.0.1 + +using Markdown +using InteractiveUtils + +# ╔═╡ 226c9e5c-6082-11f1-9059-f9e778e9b2f8 +begin + import Pkg + Pkg.activate(@__DIR__) + Pkg.develop(; path = dirname(@__DIR__)) + Pkg.instantiate() + using TransitionMatrices, Plots +end + +# ╔═╡ 226c9e04-6082-11f1-9773-191ee2516176 +md""" +# Angular scattering & polarization + +From a T-matrix you can read off the full far field: the **amplitude matrix** +``\mathbf{S}`` at a fixed geometry, its **phase matrix** ``\mathbf{Z}``, and the +orientation-averaged **scattering (Mueller) matrix** ``\mathbf{F}(\theta)``. + +This notebook plots the phase function ``F_{11}(\theta)``, the degree of linear +polarization ``-F_{12}/F_{11}`` (for unpolarized incidence) and the ratios +``F_{22}/F_{11}``, ``F_{44}/F_{11}`` for a spheroid. +""" + +# ╔═╡ 226c9e70-6082-11f1-a65b-3b159155fbf8 +md""" +## Build a T-matrix +""" + +# ╔═╡ 226c9e7a-6082-11f1-9dc0-75a4e1f6bbbb +begin + λ = 2π + spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + T = calc_T(spheroid, λ) +end + +# ╔═╡ 226c9e84-6082-11f1-bc9f-71d54665c33b +md""" +## Orientation-averaged scattering matrix vs angle + +`scattering_matrix(T, λ, θs)` returns an `Nθ × 6` matrix whose columns are +`[F₁₁, F₁₂, F₂₂, F₃₃, F₃₄, F₄₄]` (`θs` in degrees). +""" + +# ╔═╡ 226c9e8e-6082-11f1-bdcf-7b0495b58d1e +begin + θs = collect(0.0:1.0:180.0) + F = scattering_matrix(T, λ, θs) + F11 = F[:, 1] + pol = -F[:, 2] ./ F[:, 1] # degree of linear polarization + F22_11 = F[:, 3] ./ F[:, 1] + F44_11 = F[:, 6] ./ F[:, 1] + nothing +end + +# ╔═╡ 226c9eac-6082-11f1-8892-375f3d9f7416 +md""" +## Plots +""" + +# ╔═╡ 226c9eb6-6082-11f1-9cb8-e38b0c25c94a +let + p1 = plot(θs, F11; yscale = :log10, lw = 2, label = "F₁₁", + ylabel = "phase function", legend = :topright) + p2 = plot(θs, pol; lw = 2, color = 2, label = "-F₁₂/F₁₁", + ylabel = "lin. polarization") + p3 = plot(θs, [F22_11 F44_11]; lw = 2, label = ["F₂₂/F₁₁" "F₄₄/F₁₁"], + xlabel = "scattering angle θ (deg)", ylabel = "ratio") + plot(p1, p2, p3; layout = (3, 1), size = (720, 660), + title = ["spheroid a=2, c=1, m=1.5+0.02im" "" ""]) +end + +# ╔═╡ 226c9eca-6082-11f1-a933-f9b57543d7a2 +md""" +## Amplitude and phase matrix at a fixed geometry + +For a specific incidence/scattering direction, `amplitude_matrix` gives the 2×2 +complex ``\mathbf{S}`` and `phase_matrix` the 4×4 Mueller ``\mathbf{Z}``. +""" + +# ╔═╡ 226c9ede-6082-11f1-82d2-43db7f93d579 +begin + S = amplitude_matrix(T, 0.0, 0.0, π / 4, 0.0; λ = λ) # ϑᵢ,φᵢ → ϑₛ,φₛ + Z = phase_matrix(S) + (; S, Z) +end + +# ╔═╡ Cell order: +# ╟─226c9e04-6082-11f1-9773-191ee2516176 +# ╠═226c9e5c-6082-11f1-9059-f9e778e9b2f8 +# ╟─226c9e70-6082-11f1-a65b-3b159155fbf8 +# ╠═226c9e7a-6082-11f1-9dc0-75a4e1f6bbbb +# ╟─226c9e84-6082-11f1-bc9f-71d54665c33b +# ╠═226c9e8e-6082-11f1-bdcf-7b0495b58d1e +# ╟─226c9eac-6082-11f1-8892-375f3d9f7416 +# ╠═226c9eb6-6082-11f1-9cb8-e38b0c25c94a +# ╟─226c9eca-6082-11f1-a933-f9b57543d7a2 +# ╠═226c9ede-6082-11f1-82d2-43db7f93d579 diff --git a/examples/orientation_averaging.jl b/examples/orientation_averaging.jl new file mode 100644 index 0000000..2261ae2 --- /dev/null +++ b/examples/orientation_averaging.jl @@ -0,0 +1,110 @@ +### A Pluto.jl notebook ### +# v1.0.1 + +using Markdown +using InteractiveUtils + +# ╔═╡ 2366dfd4-6082-11f1-bc99-e3b4423633f0 +begin + import Pkg + Pkg.activate(@__DIR__) + Pkg.develop(; path = dirname(@__DIR__)) + Pkg.instantiate() + using TransitionMatrices, Plots +end + +# ╔═╡ 2366df48-6082-11f1-880f-99c1a49d5d94 +md""" +# Orientation averaging + +For randomly oriented particles you need the orientation-averaged scattering +quantities. `TransitionMatrices.jl` offers two routes: + +- **`RandomOrientationTransitionMatrix(T)`** — Mishchenko's *analytic* closed + form for the orientation average (fast, exact); +- **`orientation_average(T, p; Nα, Nβ, Nγ)`** — *numerical* average over the + Euler angles against an orientation distribution `p`. + +This notebook checks they agree and shows the numerical average converging to the +analytic value as the angular grid is refined. +""" + +# ╔═╡ 2366dfe8-6082-11f1-b905-b7bae29b9c75 +md""" +## A non-spherical particle +""" + +# ╔═╡ 2366dff2-6082-11f1-bcad-09c1d7464bc5 +begin + λ = 2π + spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + T = calc_T(spheroid, λ) + uniform = (α, β, γ) -> 1 / (8π^2) # isotropic orientation distribution +end + +# ╔═╡ 2366dff2-6082-11f1-b19f-9f43b5fe61a4 +md""" +## Analytic vs numerical + +Both should give the same orientation-averaged efficiencies. +""" + +# ╔═╡ 2366dffc-6082-11f1-8c98-1fba91e58dc3 +begin + Tanalytic = RandomOrientationTransitionMatrix(T) + Tnumeric = orientation_average(T, uniform; Nα = 20, Nβ = 20, Nγ = 20) + + compare = [ + (; method = "analytic (Mishchenko)", Qsca = calc_Csca(Tanalytic, λ), + Qext = calc_Cext(Tanalytic, λ), g = asymmetry_parameter(Tanalytic, λ)), + (; method = "numerical (20³ grid)", Qsca = calc_Csca(Tnumeric, λ), + Qext = calc_Cext(Tnumeric, λ), g = asymmetry_parameter(Tnumeric, λ)), + ] +end + +# ╔═╡ 2366e008-6082-11f1-b755-1527ca352dc3 +md""" +## Convergence of the numerical average + +The numerical average approaches the analytic value as the `β`-grid is refined; +the analytic closed form gives it directly, at a fraction of the cost. +""" + +# ╔═╡ 2366e024-6082-11f1-bc7a-5d2a795a9fec +begin + Qref = calc_Csca(Tanalytic, λ) + Ns = 4:2:18 + errs = [abs(calc_Csca(orientation_average(T, uniform; Nα = 2, Nβ = N, Nγ = 2), λ) - Qref) / Qref + for N in Ns] + nothing +end + +# ╔═╡ 2366e02e-6082-11f1-9678-c1ad121a4222 +let + plot(collect(Ns), errs; yscale = :log10, lw = 2, marker = :circle, + xlabel = "β-grid points Nβ", ylabel = "|Qsca_numeric − Qsca_analytic| / Qsca", + label = "numerical average", legend = :topright, + title = "convergence to the analytic orientation average", size = (680, 400)) +end + +# ╔═╡ 2366e03a-6082-11f1-958b-71200c5d7a31 +md""" +## Takeaway + +The analytic `RandomOrientationTransitionMatrix` is both exact and much cheaper +than refining a 3-D Euler-angle quadrature — prefer it for random-orientation +cross sections. The numerical `orientation_average` remains useful for +*non-uniform* orientation distributions (just pass a different `p`). +""" + +# ╔═╡ Cell order: +# ╟─2366df48-6082-11f1-880f-99c1a49d5d94 +# ╠═2366dfd4-6082-11f1-bc99-e3b4423633f0 +# ╟─2366dfe8-6082-11f1-b905-b7bae29b9c75 +# ╠═2366dff2-6082-11f1-bcad-09c1d7464bc5 +# ╟─2366dff2-6082-11f1-b19f-9f43b5fe61a4 +# ╠═2366dffc-6082-11f1-8c98-1fba91e58dc3 +# ╟─2366e008-6082-11f1-b755-1527ca352dc3 +# ╠═2366e024-6082-11f1-bc7a-5d2a795a9fec +# ╠═2366e02e-6082-11f1-9678-c1ad121a4222 +# ╟─2366e03a-6082-11f1-958b-71200c5d7a31 diff --git a/examples/shapes_gallery.jl b/examples/shapes_gallery.jl new file mode 100644 index 0000000..f0924ce --- /dev/null +++ b/examples/shapes_gallery.jl @@ -0,0 +1,106 @@ +### A Pluto.jl notebook ### +# v1.0.1 + +using Markdown +using InteractiveUtils + +# ╔═╡ 2173870e-6082-11f1-89cd-4976913f2274 +begin + import Pkg + Pkg.activate(@__DIR__) + Pkg.develop(; path = dirname(@__DIR__)) + Pkg.instantiate() + using TransitionMatrices, Plots +end + +# ╔═╡ 21738632-6082-11f1-8c1a-07c117ac9474 +md""" +# Shapes quick-start gallery + +`TransitionMatrices.jl` handles several scatterer families. This gallery defines +one of each, computes its T-matrix, and reports the basic far-field efficiencies +``Q_\text{sca}``, ``Q_\text{ext}``, the asymmetry parameter ``g`` and the +single-scattering albedo ``\omega``. + +The axisymmetric shapes (spheroid, cylinder, Chebyshev particle) use the default +EBCM solver via `calc_T`; the N-fold **prism** is not axisymmetric, so it uses +the IITM solver. +""" + +# ╔═╡ 21738718-6082-11f1-b6a5-5d3fd6d47663 +md""" +## Define the shapes + +All at wavelength `λ = 2π` (so the size parameter equals the radius) and the same +refractive index `m = 1.5 + 0.02im`. +""" + +# ╔═╡ 2173872c-6082-11f1-808e-0fe676b65624 +begin + λ = 2π + m = 1.5 + 0.02im + shapes = ( + spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, m), + cylinder = TransitionMatrices.Cylinder{Float64, ComplexF64}(1.0, 2.0, m), + chebyshev = TransitionMatrices.Chebyshev{Float64, ComplexF64}(1.0, 0.1, 4, m), + prism6 = TransitionMatrices.Prism(6, 1.0, 2.0, m), + ) +end + +# ╔═╡ 21738736-6082-11f1-a54e-010814dd76d9 +md""" +## Compute and tabulate + +`calc_T` auto-converges the axisymmetric shapes; the prism uses a fixed-order +IITM solve. Pluto renders the resulting vector of named tuples as a table. +""" + +# ╔═╡ 2173874a-6082-11f1-8f4b-f3cee77b5fae +begin + Tmatrix(s) = s isa TransitionMatrices.Prism ? + transition_matrix(s, λ, IITM(8, 12, 24, 24)) : calc_T(s, λ) + + summary = map(collect(pairs(shapes))) do (name, s) + T = Tmatrix(s) + (; shape = name, + Qsca = round(calc_Csca(T, λ); digits = 4), + Qext = round(calc_Cext(T, λ); digits = 4), + g = round(asymmetry_parameter(T, λ); digits = 4), + ω = round(albedo(T); digits = 4)) + end +end + +# ╔═╡ 21738752-6082-11f1-8f31-fb7e99c75cc0 +md""" +## Compare the efficiencies +""" + +# ╔═╡ 2173875e-6082-11f1-8933-7da031c63642 +let + names = String.(getindex.(summary, :shape)) + bar(names, [getindex.(summary, :Qsca) getindex.(summary, :Qext)]; + label = ["Qsca" "Qext"], ylabel = "efficiency", legend = :topright, + title = "far-field efficiencies by shape", size = (680, 380)) +end + +# ╔═╡ 21738768-6082-11f1-8536-4125de072774 +md""" +## Which solver? + +- **Spheroid / Cylinder / Chebyshev** — axisymmetric: EBCM (`calc_T`). For + high-aspect spheroids add the stabilized path, `Iterative(EBCM; stable=true)`. +- **Prism / arbitrary 3-D** — not axisymmetric: IITM (`IITM(nₘₐₓ, Nr, Nϑ, Nφ)`). +- For wavelength / refractive-index **sweeps** of an axisymmetric shape, see the + Sh-matrix examples (`ShMatrix`, `prepare_sh`). +""" + +# ╔═╡ Cell order: +# ╟─21738632-6082-11f1-8c1a-07c117ac9474 +# ╠═2173870e-6082-11f1-89cd-4976913f2274 +# ╟─21738718-6082-11f1-b6a5-5d3fd6d47663 +# ╠═2173872c-6082-11f1-808e-0fe676b65624 +# ╟─21738736-6082-11f1-a54e-010814dd76d9 +# ╠═2173874a-6082-11f1-8f4b-f3cee77b5fae +# ╟─21738752-6082-11f1-8f31-fb7e99c75cc0 +# ╠═2173875e-6082-11f1-8933-7da031c63642 +# ╟─21738768-6082-11f1-8536-4125de072774 diff --git a/examples/solver_landscape.jl b/examples/solver_landscape.jl new file mode 100644 index 0000000..cfc8266 --- /dev/null +++ b/examples/solver_landscape.jl @@ -0,0 +1,101 @@ +### A Pluto.jl notebook ### +# v1.0.1 + +using Markdown +using InteractiveUtils + +# ╔═╡ 246053ac-6082-11f1-bed7-11580218e966 +begin + import Pkg + Pkg.activate(@__DIR__) + Pkg.develop(; path = dirname(@__DIR__)) + Pkg.instantiate() + using TransitionMatrices, Plots +end + +# ╔═╡ 2460532a-6082-11f1-83c5-3796c2e835e2 +md""" +# Solver landscape & convergence + +The same T-matrix can be built several ways. The two-layer API selects them with +a solver object passed to `transition_matrix(s, λ, solver)`: + +- a **fixed** solver — `EBCM(nₘₐₓ, Ng)`, `IITM(nₘₐₓ, Nr, Nϑ)` — one build; +- an **iterative** solver — `Iterative(EBCM; …)` — sweeps to convergence; + +plus the `stable = true` option that removes the high-aspect EBCM cancellation. +This notebook shows *why* it matters: on a high-aspect spheroid, classic EBCM +converges briefly and then **diverges** as `nₘₐₓ` grows, while the stabilized +path stays converged. +""" + +# ╔═╡ 246053b6-6082-11f1-a95d-e7ab43aaff16 +md""" +## A high-aspect prolate spheroid (aspect ≈ 4) + +Three routes to the same cross section: +""" + +# ╔═╡ 246053c2-6082-11f1-9425-cd50e8e63bdd +begin + λ = 2π + prolate = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im) + + routes = [ + (; route = "EBCM fixed (n=24)", Csca = calc_Csca(transition_matrix(prolate, λ, EBCM(24, 384)), λ)), + (; route = "Iterative(EBCM; stable)", Csca = calc_Csca(transition_matrix(prolate, λ, Iterative(EBCM; stable = true)), λ)), + (; route = "IITM", Csca = calc_Csca(transition_matrix(prolate, λ, IITM(24, 30, 60)), λ)), + ] +end + +# ╔═╡ 246053ca-6082-11f1-ba56-6f4f921058ef +md""" +## Convergence vs truncation order + +Relative error of ``Q_\text{sca}`` against a high-order stabilized reference, for +classic EBCM vs the `stable = true` EBCM. Watch the classic curve blow up. +""" + +# ╔═╡ 246053d4-6082-11f1-b47b-0143b9abc039 +begin + ref = calc_Csca(transition_matrix(prolate, λ, EBCM(40, 600; stable = true)), λ) + ns = 16:2:40 + classic_err = [abs(calc_Csca(transition_matrix(prolate, λ, EBCM(n, 16n)), λ) - ref) / ref for n in ns] + stable_err = [abs(calc_Csca(transition_matrix(prolate, λ, EBCM(n, 16n; stable = true)), λ) - ref) / ref for n in ns] + nothing +end + +# ╔═╡ 246053de-6082-11f1-a6ce-e998a04e4ad7 +let + plot(collect(ns), classic_err; yscale = :log10, lw = 2, marker = :circle, + label = "classic EBCM", legend = :left) + plot!(collect(ns), stable_err; lw = 2, marker = :square, label = "stable EBCM") + plot!(xlabel = "truncation order nₘₐₓ", ylabel = "relative error in Qsca", + title = "high-aspect spheroid: classic EBCM diverges, stable holds", + size = (720, 420)) +end + +# ╔═╡ 246053fc-6082-11f1-9730-eb288864dde4 +md""" +## Choosing a solver + +| situation | solver | +|---|---| +| axisymmetric, moderate aspect | `calc_T(s, λ)` (auto-converged classic EBCM) | +| high-aspect **spheroid** | `Iterative(EBCM; stable = true)` | +| cylinder / Chebyshev / 3-D, hard cases | `IITM(nₘₐₓ, Nr, Nϑ[, Nφ])` | +| wavelength / index **sweep** | `ShMatrix` / `prepare_sh` | +| explicit discretization (benchmarking) | `EBCM(nₘₐₓ, Ng)`, `IITM(…)` | + +The iterative layer (`Iterative`) wraps any of these with automatic convergence. +""" + +# ╔═╡ Cell order: +# ╟─2460532a-6082-11f1-83c5-3796c2e835e2 +# ╠═246053ac-6082-11f1-bed7-11580218e966 +# ╟─246053b6-6082-11f1-a95d-e7ab43aaff16 +# ╠═246053c2-6082-11f1-9425-cd50e8e63bdd +# ╟─246053ca-6082-11f1-ba56-6f4f921058ef +# ╠═246053d4-6082-11f1-b47b-0143b9abc039 +# ╠═246053de-6082-11f1-a6ce-e998a04e4ad7 +# ╟─246053fc-6082-11f1-9730-eb288864dde4 diff --git a/examples/spectral_sensitivity.jl b/examples/spectral_sensitivity.jl new file mode 100644 index 0000000..2bd8d28 --- /dev/null +++ b/examples/spectral_sensitivity.jl @@ -0,0 +1,157 @@ +### A Pluto.jl notebook ### +# v1.0.1 + +using Markdown +using InteractiveUtils + +# ╔═╡ 162c8ff8-6080-11f1-af6b-f5508490c007 +begin + import Pkg + Pkg.activate(@__DIR__) # the examples/ environment + Pkg.develop(; path = dirname(@__DIR__)) # point TransitionMatrices at this repo + Pkg.instantiate() + using TransitionMatrices, ForwardDiff, Plots, BenchmarkTools +end + +# ╔═╡ 162c8f8c-6080-11f1-ba76-6fd14a8cf585 +md""" +# Spectral sensitivity with the Sh-matrix method + +Fast, **exact** wavelength / refractive-index sensitivities for an axisymmetric +scatterer, built on the Sh-matrix moment-separation backend of +`TransitionMatrices.jl`. + +The Sh-matrix method factors every EBCM surface integral as + +```math +\int = \sum_{\text{terms}} \big[\,\text{coefficient}(k, m_r)\,\big] \times \big[\,\text{shape-only moment}\,\big], +``` + +where the **shape moments depend only on the geometry** — not on the wavelength +``\lambda`` or the refractive index ``m_r``. `prepare_sh` computes the moments +*once*; each `transition_matrix(prep, λ, mᵣ)` is then a cheap coefficient×moment +sum. Because that reconstruction is a plain differentiable function of +``(\lambda, m_r)`` with the moments riding through as constants, `ForwardDiff` +straight through it gives exact ``\partial T/\partial\lambda`` and +``\partial T/\partial m_r`` — at a fraction of the cost of differentiating the +full from-scratch assembly. +""" + +# ╔═╡ 162c900e-6080-11f1-8b5d-bfd5a06ead20 +md""" +## 1. Define the scatterer and prepare the moments + +A prolate spheroid (semi-axes `a = 2`, `c = 1`) with a fixed small absorption +`mᵢ = 0.02`. `prepare_sh` runs the geometry quadrature **once** — every spectral +point below reuses it. +""" + +# ╔═╡ 162c9018-6080-11f1-b436-23097d1541c2 +begin + nmax, Ng = 10, 200 + mᵢ = 0.02 + spheroid = TransitionMatrices.Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + mᵢ * im) + prep = prepare_sh(spheroid, nmax, Ng) +end + +# ╔═╡ 162c9022-6080-11f1-bb17-05963c0ec94f +md""" +## 2. Spectrum and sensitivities + +Sweep the wavelength across a band; at each point reconstruct the T-matrix and +read off the scattering / extinction cross sections. The sensitivities +``\partial C_\text{sca}/\partial\lambda`` and ``\partial C_\text{sca}/\partial m_r`` +come from `ForwardDiff` applied to the **reconstruction only** — the moments in +`prep` are constants. +""" + +# ╔═╡ 162c9040-6080-11f1-b8d1-031603b7cffa +begin + mᵣ = 1.5 + λs = collect(range(2π / 1.6, 2π / 0.6; length = 60)) + + Csca(λ, m) = calc_Csca(transition_matrix(prep, λ, complex(m, mᵢ)), λ) + Cext(λ, m) = calc_Cext(transition_matrix(prep, λ, complex(m, mᵢ)), λ) + + csca = [Csca(λ, mᵣ) for λ in λs] + cext = [Cext(λ, mᵣ) for λ in λs] + + ∂Csca_∂λ = [ForwardDiff.derivative(l -> Csca(l, mᵣ), λ) for λ in λs] + ∂Csca_∂mᵣ = [ForwardDiff.derivative(m -> Csca(λ, m), mᵣ) for λ in λs] + nothing +end + +# ╔═╡ 162c904a-6080-11f1-8f00-37f3c3cde468 +md""" +## 3. The spectra and their sensitivities +""" + +# ╔═╡ 162c9054-6080-11f1-99a7-5b1abfb33ebb +let + p1 = plot(λs, [csca cext]; label = ["Csca" "Cext"], lw = 2, + ylabel = "cross section", legend = :topright) + p2 = plot(λs, ∂Csca_∂λ; label = "∂Csca/∂λ", lw = 2, color = 3, ylabel = "∂/∂λ") + p3 = plot(λs, ∂Csca_∂mᵣ; label = "∂Csca/∂mᵣ", lw = 2, color = 4, + xlabel = "wavelength λ", ylabel = "∂/∂mᵣ") + plot(p1, p2, p3; layout = (3, 1), size = (720, 660), + title = ["spheroid a=2, c=1, m=1.5+0.02im" "" ""]) +end + +# ╔═╡ 162c905e-6080-11f1-92ea-571ed46028d5 +md""" +## 4. Why it is cheap — and how much + +Differentiating the **reconstruction** reuses the single `prepare_sh` for the +whole spectrum; differentiating the **classic from-scratch assembly** re-runs the +full quadrature and Bessel recursions (in dual numbers) at every wavelength. +""" + +# ╔═╡ 162c906a-6080-11f1-a118-e37de9a387e2 +begin + function Csca_classic(λ, m) + T = promote_type(typeof(λ), typeof(m)) + s = TransitionMatrices.Spheroid{T, Complex{T}}(T(2.0), T(1.0), Complex{T}(m, mᵢ)) + calc_Csca(transition_matrix(s, λ, EBCM(nmax, Ng)), λ) + end + + f_sh(λ) = ForwardDiff.derivative(l -> Csca(l, mᵣ), λ) + f_classic(λ) = ForwardDiff.derivative(l -> Csca_classic(l, mᵣ), λ) + f_sh(λs[1]); f_classic(λs[1]) # warm up + + t_prepare = @belapsed prepare_sh($spheroid, $nmax, $Ng) samples=1 evals=1 + t_sh = @belapsed [f_sh(λ) for λ in $λs] samples=1 evals=1 + t_classic = @belapsed [f_classic(λ) for λ in $λs] samples=1 evals=1 + + (; n_points = length(λs), + sh_ms = round((t_prepare + t_sh) * 1e3; digits = 1), + classic_ms = round(t_classic * 1e3; digits = 1), + speedup = round(t_classic / (t_prepare + t_sh); digits = 1)) +end + +# ╔═╡ 162c9072-6080-11f1-983e-97897cdba9f0 +md""" +## Takeaway + +`prepare_sh` once, then `ForwardDiff` the reconstruction, gives exact +``\partial C/\partial\lambda`` and ``\partial C/\partial m_r`` (matching the +classic result to machine precision) at a large speedup for spectra — the win +grows with the number of wavelengths because the geometry quadrature is +amortized. + +Ideal for **material/wavelength sensitivity** (retrievals, dispersion fitting). +Shape-parameter derivatives act on the moments themselves and are better served +by the dedicated analytical EBCM linearization backend. +""" + +# ╔═╡ Cell order: +# ╟─162c8f8c-6080-11f1-ba76-6fd14a8cf585 +# ╠═162c8ff8-6080-11f1-af6b-f5508490c007 +# ╟─162c900e-6080-11f1-8b5d-bfd5a06ead20 +# ╠═162c9018-6080-11f1-b436-23097d1541c2 +# ╟─162c9022-6080-11f1-bb17-05963c0ec94f +# ╠═162c9040-6080-11f1-b8d1-031603b7cffa +# ╟─162c904a-6080-11f1-8f00-37f3c3cde468 +# ╠═162c9054-6080-11f1-99a7-5b1abfb33ebb +# ╟─162c905e-6080-11f1-92ea-571ed46028d5 +# ╠═162c906a-6080-11f1-a118-e37de9a387e2 +# ╟─162c9072-6080-11f1-983e-97897cdba9f0 diff --git a/justfile b/justfile index bfe51e4..078a4a0 100644 --- a/justfile +++ b/justfile @@ -17,11 +17,22 @@ alias t := test test-coverage: julia --project=. -e 'using Pkg; Pkg.test(; coverage=true)' +[group("benchmark")] +bench *args: + julia --project=benchmark -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + julia --project=benchmark benchmark/runbenchmarks.jl {{args}} +alias b := bench + [group("docs")] docs: julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate(); ENV["DOCUMENTER_SKIP_DEPLOY"]="true"; include("docs/make.jl")' alias d := docs +# Re-render example notebooks + rebuild docs (commit docs/src/examples/*.md after) +[group("docs")] +docs-examples: + julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate(); ENV["BUILD_EXAMPLES"]="true"; ENV["DOCUMENTER_SKIP_DEPLOY"]="true"; include("docs/make.jl")' + [group("docs")] doctest: julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate(); using Documenter: DocMeta, doctest; using TransitionMatrices; DocMeta.setdocmeta!(TransitionMatrices, :DocTestSetup, :(using TransitionMatrices); recursive=true); doctest(TransitionMatrices)' diff --git a/packages/EBCMPrecisionLossEstimators/src/EBCMPrecisionLossEstimators.jl b/packages/EBCMPrecisionLossEstimators/src/EBCMPrecisionLossEstimators.jl index 77ea2c5..724f35d 100644 --- a/packages/EBCMPrecisionLossEstimators/src/EBCMPrecisionLossEstimators.jl +++ b/packages/EBCMPrecisionLossEstimators/src/EBCMPrecisionLossEstimators.jl @@ -10,22 +10,22 @@ for shape in [Spheroid, Cylinder] @eval function estimate_integral_loss(s::$shape, nₘₐₓ) mach = machine(joinpath(@__DIR__, "..", "fixtures", "$(string($shape)).Q.model")) predict(mach, - [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), - mi = imag(s.m))])[1] + [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), + mi = imag(s.m))])[1] end @eval function estimate_inverse_loss(s::$shape, nₘₐₓ) mach = machine(joinpath(@__DIR__, "..", "fixtures", "$(string($shape)).T.model")) predict(mach, - [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), - mi = imag(s.m))])[1] + [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), + mi = imag(s.m))])[1] end @eval function estimate_total_loss(s::$shape, nₘₐₓ) mach = machine(joinpath(@__DIR__, "..", "fixtures", "$(string($shape)).AT.model")) predict(mach, - [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), - mi = imag(s.m))])[1] + [(rmax = rmax(s), rmin = rmin(s), nmax = nₘₐₓ, mr = real(s.m), + mi = imag(s.m))])[1] end end diff --git a/src/EBCM/axisymmetric.jl b/src/EBCM/axisymmetric.jl index 8d7d514..103ff42 100644 --- a/src/EBCM/axisymmetric.jl +++ b/src/EBCM/axisymmetric.jl @@ -19,8 +19,8 @@ Parameters: """ function amplitude_matrix(axi::AxisymmetricTransitionMatrix{CT, N, V, T}, ϑᵢ, φᵢ, ϑₛ, φₛ; - λ = 2π, - rot::Union{Nothing, Rotation{3}} = nothing) where {CT, N, V, T} + λ = 2π, + rot::Union{Nothing, Rotation{3}} = nothing) where {CT, N, V, T} k₁ = 2π / λ if isnothing(rot) α, β = zero(T), zero(T) @@ -113,6 +113,7 @@ function amplitude_matrix(axi::AxisymmetricTransitionMatrix{CT, N, V, T}, ϑᵢ, sinmφ = sin(m * φ) for n′ in 1:nₘ, n in 1:nₘ + T₁₁ = axi.𝐓[m + 1][n, n′] T₂₂ = axi.𝐓[m + 1][n + nₘ, n′ + nₘ] if m == 0 @@ -150,7 +151,7 @@ end @testset "Spheroid" begin params = Iterators.product((0.5, 1.0, 5.0), (1.0,), (1.311, 1.5 + 0.01im), - (0.0, 0.5), (0.0, 0.5)) + (0.0, 0.5), (0.0, 0.5)) @testset "a = $a, c = $c, m = $m, α = $α, β = $β" for (a, c, m, α, β) in params s = Spheroid{Float64, ComplexF64}(a, c, m) @@ -167,10 +168,10 @@ end @doc raw""" ``` -transition_matrix(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng) where {T, CT} +transition_matrix(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng; stable = false) where {T, CT} ``` -Calculate the T-Matrix for a given scatterer and wavelengthg`. +Calculate the T-Matrix for a given scatterer and wavelength. Parameters: @@ -178,32 +179,70 @@ Parameters: - `λ`: the wavelength. - `nₘₐₓ`: the maximum order of the T-Matrix. - `Ng`: the number of Gauss-Legendre quadrature points to be used. +- `stable`: when `true`, assemble the `𝐔`-matrix integrals with the + cancellation-free `F⁺` formulation of Somerville, Auguié & Le Ru, JQSRT 123 + (2013). The standard integrands lose all precision for spheroids of high aspect + ratio (the irregular `χ_n·ψ_k` products develop huge Laurent terms that should + cancel on integration but do not numerically); `stable=true` removes that + cancellation, recovering a relative accuracy of about `1e-9` in `Float64` + regardless of aspect ratio. It is **only valid for `Spheroid`** (the + cancellation relies on the spheroid surface) and costs roughly 2–3× the default + assembly, so it is opt-in. For it to help, `nₘₐₓ` must be large enough that + `nₘₐₓ+1 ≳ k·c + 15`, where `c` is the largest semi-axis — comparable to the + order needed for convergence at that size anyway. The remaining `Float64` + round-off (in particular a `~1e-9` floor as the refractive index `s → 1`) is + orthogonal to the cancellation and is lowered by using an extended-precision + element type: `stable=true` with `Double64` reaches `~1e-25` at high aspect + ratio. Returns: - `𝐓`: an `AxisymmetricTransitionMatrix` struct representing the T-Matrix. """ function transition_matrix(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng; - zerofn = () -> zero(CT)) where {T, CT} + zerofn = () -> zero(CT), stable = false) where {T, CT} + stable && !(s isa Spheroid) && + throw(ArgumentError("stable=true is only valid for spheroids: the \ + cancellation-free F⁺ integrands rely on the spheroid surface making \ + the divergent Laurent terms integrate to zero (Somerville et al. 2013).")) 𝐓 = Vector{Matrix{CT}}(undef, nₘₐₓ + 1) - 𝐓[1], cache = transition_matrix_m₀(s, λ, nₘₐₓ, Ng; zerofn = zerofn, reuse = true) + 𝐓[1], + cache = transition_matrix_m₀(s, λ, nₘₐₓ, Ng; zerofn = zerofn, reuse = true, + stable = stable) for m in 1:nₘₐₓ - 𝐓[m + 1] = transition_matrix_m(m, s, λ, nₘₐₓ, Ng; zerofn = zerofn, cache = cache) + 𝐓[m + 1] = transition_matrix_m(m, s, λ, nₘₐₓ, Ng; zerofn = zerofn, cache = cache, + stable = stable) end AxisymmetricTransitionMatrix{CT, nₘₐₓ, typeof(𝐓), T}(𝐓) end +# Factor 𝐐 once so the factorization can be reused for the value block and +# every Jacobian slice (𝐐 depends only on 𝐏 and 𝐔, not on the differentiated +# parameter). Arblib matrices have no generic `lu`/`\`, so fall back to their +# dedicated `inv` and right-multiply. The `_ebcm_rdiv` methods dispatch on +# whether the second argument is an explicit inverse (a `Matrix`) or an `lu` +# factorization (which is not an `AbstractMatrix`). +_ebcm_factor(𝐐::AbstractMatrix{<:Union{Arb, Acb}}) = inv(𝐐) +_ebcm_factor(𝐐::AbstractMatrix) = lu(𝐐) + +_ebcm_rdiv(𝐀, 𝐐⁻¹::AbstractMatrix) = 𝐀 * 𝐐⁻¹ +_ebcm_rdiv(𝐀, F) = 𝐀 / F + function 𝐓_from_𝐏_and_𝐔(𝐏, 𝐔) 𝐐 = @. 𝐏 + 1im * 𝐔 - 𝐓 = -𝐏 * inv(𝐐) + # 𝐓 = -𝐏 𝐐⁻¹, via a factorization instead of an explicit inverse. + return -_ebcm_rdiv(𝐏, _ebcm_factor(𝐐)) end function ∂𝐓_from_𝐏_and_𝐔(𝐏, 𝐔, ∂𝐏, ∂𝐔) 𝐐 = @. 𝐏 + 1im * 𝐔 ∂𝐐 = @. ∂𝐏 + 1im * ∂𝐔 - 𝐐⁻¹ = inv(𝐐) - -∂𝐏 * 𝐐⁻¹ + 𝐏 * 𝐐⁻¹ * ∂𝐐 * 𝐐⁻¹ + F = _ebcm_factor(𝐐) + 𝐓 = -_ebcm_rdiv(𝐏, F) + # ∂𝐓 = -∂𝐏 𝐐⁻¹ + 𝐏 𝐐⁻¹ ∂𝐐 𝐐⁻¹ = -(∂𝐏 + 𝐓 ∂𝐐) 𝐐⁻¹ (since 𝐏 𝐐⁻¹ = -𝐓), + # reusing the single factorization `F` and the already-computed `𝐓`. + return -_ebcm_rdiv(∂𝐏 + 𝐓 * ∂𝐐, F) end function _axisymmetric_transition_matrix_from_blocks(𝐓s::AbstractVector) @@ -221,9 +260,9 @@ function ebcm_transition_matrix_from_matrices(𝐏s::AbstractVector, 𝐔s::Abst end function ∂ebcm_transition_matrix_from_matrices(𝐏s::AbstractVector, - 𝐔s::AbstractVector, - ∂𝐏s::AbstractVector, - ∂𝐔s::AbstractVector) + 𝐔s::AbstractVector, + ∂𝐏s::AbstractVector, + ∂𝐔s::AbstractVector) length(𝐏s) == length(𝐔s) == length(∂𝐏s) == length(∂𝐔s) || throw(ArgumentError("EBCM P, U, ∂P, and ∂U block counts must match")) ∂𝐓s = [∂𝐓_from_𝐏_and_𝐔(𝐏, 𝐔, ∂𝐏, ∂𝐔) @@ -239,7 +278,8 @@ ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng) wher Calculate the `P` and `U` matrices for the `m=0` EBCM block. """ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, - Ng; zerofn = () -> zero(CT), reuse = false) where {T, CT} + Ng; zerofn = () -> zero(CT), reuse = false, + stable = false) where {T, CT} @assert iseven(Ng) "Ng must be even!" k = 2 * T(π) / λ @@ -275,7 +315,7 @@ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Threads.@threads for i in 1:ng kₛr = k * s.m * r[i] ricattibesselj!(view(ψₛ, i, :), view(ψₛ′, i, :), view(zₛ, :, i), nₘₐₓ, nₑₓₜᵣₐ, - kₛr) + kₛr) ricattibessely!(view(χₛ, i, :), view(χₛ′, i, :), nₘₐₓ, kₛr) end @@ -285,7 +325,7 @@ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Threads.@threads for i in eachindex(ϑ) wigner_d_recursion!(view(d, i, :), 0, 0, nₘₐₓ, ϑ[i]; - deriv = view(τ, i, :)) + deriv = view(τ, i, :)) for n in 0:nₘₐₓ 𝜋[i, n] = pi_func(T, 0, n, ϑ[i]; d = d[i, n]) @@ -299,6 +339,19 @@ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, 𝐔₁₁ = view(𝐔, 1:nₘₐₓ, 1:nₘₐₓ) 𝐔₂₂ = view(𝐔, (nₘₐₓ + 1):(2nₘₐₓ), (nₘₐₓ + 1):(2nₘₐₓ)) + # For spheroids the off-diagonal `𝐔` integrands lose all precision at high + # aspect ratio (the χ_n·ψ_k products have huge cancelling negative powers). + # When `stable`, replace those products by the cancellation-free `F⁺` matrix + # (Somerville et al. 2013); the diagonal (n=n′) has no cancellation and `𝐏` + # is regular, so both keep the standard direct products. The x-independent + # last-row series coefficients are computed once and shared across all points. + Fmats = if stable + lastrow = _F⁺_lastrow(s.m, nₘₐₓ, k * rₘₐₓ) + [_F⁺_matrix(s.m, k * r[i], nₘₐₓ; lastrow) for i in 1:ng] + else + nothing + end + Threads.@threads for (n, n′) in collect(Iterators.product(1:nₘₐₓ, 1:nₘₐₓ)) if sym && isodd(n + n′) continue @@ -325,14 +378,24 @@ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, (ψ′[i, n] * ψₛ′[i, n′] + a[n′] * ψ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) - UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χ[i, n] * ψₛ[i, n′] - UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χ[i, n] * ψₛ[i, n′] - UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * - (χ′[i, n] * ψₛ′[i, n′] + - a[n] * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) - UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * - (χ′[i, n] * ψₛ′[i, n′] + - a[n′] * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + if stable + F = Fmats[i] + xi = k * r[i] + χψ = _Fp(F, n, n′) / xi + UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χψ + UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χψ + UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * (_L⁷⁺_mat(F, n, n′) / xi) + UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * (_L⁸⁺_mat(F, n, n′) / xi) + else + UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χ[i, n] * ψₛ[i, n′] + UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χ[i, n] * ψₛ[i, n′] + UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * + (χ′[i, n] * ψₛ′[i, n′] + + a[n] * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * + (χ′[i, n] * ψₛ′[i, n′] + + a[n′] * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + end end 𝐏₁₁[n, n′] = 1im * A[n] * A[n′] * (s.m^2 - 1) / (s.m * (a[n] - a[n′])) * @@ -377,7 +440,9 @@ function ebcm_matrices_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, end if reuse - cache = x, w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, χₛ, χₛ′ + # `Fmats` (the per-quadrature-point F⁺ matrices) depend only on s.m, k and + # r[i] — not on m — so they are computed once here and reused for all m>0. + cache = x, w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, χₛ, χₛ′, Fmats return 𝐏, 𝐔, cache end @@ -392,13 +457,14 @@ transition_matrix_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng) Calculate the `m=0` block of the T-Matrix for a given axisymmetric scatterer. """ function transition_matrix_m₀(s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, - Ng; zerofn = () -> zero(CT), reuse = false) where {T, CT} + Ng; zerofn = () -> zero(CT), reuse = false, + stable = false) where {T, CT} if reuse - 𝐏, 𝐔, cache = ebcm_matrices_m₀(s, λ, nₘₐₓ, Ng; zerofn, reuse) + 𝐏, 𝐔, cache = ebcm_matrices_m₀(s, λ, nₘₐₓ, Ng; zerofn, reuse, stable) return 𝐓_from_𝐏_and_𝐔(𝐏, 𝐔), cache end - 𝐏, 𝐔 = ebcm_matrices_m₀(s, λ, nₘₐₓ, Ng; zerofn, reuse) + 𝐏, 𝐔 = ebcm_matrices_m₀(s, λ, nₘₐₓ, Ng; zerofn, reuse, stable) return 𝐓_from_𝐏_and_𝐔(𝐏, 𝐔) end @@ -410,7 +476,8 @@ ebcm_matrices_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng) wher Calculate the `P` and `U` matrices for the `m`-th EBCM block. """ function ebcm_matrices_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, - Ng; zerofn = () -> zero(CT), cache = nothing) where {T, CT} + Ng; zerofn = () -> zero(CT), cache = nothing, + stable = false) where {T, CT} @assert iseven(Ng) "Ng must be even!" k = 2 * T(π) / λ @@ -420,9 +487,9 @@ function ebcm_matrices_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, ng = sym ? Ng ÷ 2 : Ng if !isnothing(cache) - _, w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, _, _ = cache + _, w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, _, _, Fmats = cache return _transition_matrix_m_core(m, s, k, nₘₐₓ, Ng, nₘᵢₙ, nn, ng, sym, zerofn, - w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′) + w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, Fmats) else x, w, r, r′ = gaussquad(s, Ng) ϑ = acos.(x) @@ -451,24 +518,32 @@ function ebcm_matrices_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Threads.@threads for i in 1:ng kₛr = k * s.m * r[i] ricattibesselj!(view(ψₛ, i, :), view(ψₛ′, i, :), view(zₛ, :, i), nₘₐₓ, nₑₓₜᵣₐ, - kₛr) + kₛr) + end + + Fmats = if stable + lastrow = _F⁺_lastrow(s.m, nₘₐₓ, k * rₘₐₓ) + [_F⁺_matrix(s.m, k * r[i], nₘₐₓ; lastrow) for i in 1:ng] + else + nothing end return _transition_matrix_m_core(m, s, k, nₘₐₓ, Ng, nₘᵢₙ, nn, ng, sym, zerofn, - w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′) + w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, Fmats) end end function _transition_matrix_m_core(m, s::AbstractAxisymmetricShape{T, CT}, k, nₘₐₓ, Ng, - nₘᵢₙ, nn, ng, sym, zerofn, w, r, r′, ϑ, a, A, ψ, - ψ′, χ, χ′, ψₛ, ψₛ′) where {T, CT} + nₘᵢₙ, nn, ng, sym, zerofn, w, r, r′, ϑ, a, A, ψ, + ψ′, χ, χ′, ψₛ, ψₛ′, Fmats = nothing) where {T, CT} + stable = Fmats !== nothing d = OffsetArray(zeros(T, Ng, nₘₐₓ - m + 1), 1:Ng, m:nₘₐₓ) 𝜋 = similar(d) τ = similar(d) Threads.@threads for i in eachindex(ϑ) wigner_d_recursion!(view(d, i, :), 0, m, nₘₐₓ, ϑ[i]; - deriv = view(τ, i, :)) + deriv = view(τ, i, :)) for n in nₘᵢₙ:nₘₐₓ 𝜋[i, n] = pi_func(T, m, n, ϑ[i]; d = d[i, n]) @@ -499,8 +574,20 @@ function _transition_matrix_m_core(m, s::AbstractAxisymmetricShape{T, CT}, k, n PK₁ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * ψ[i, n] * ψₛ′[i, n′] PK₂ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * ψ′[i, n] * ψₛ[i, n′] - UK₁ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * χ[i, n] * ψₛ′[i, n′] - UK₂ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * χ′[i, n] * ψₛ[i, n′] + if stable + F = Fmats[i] + xi = k * r[i] + # Cancellation-free K¹/K² integrands (Somerville, Auguié & Le Ru, + # JQSRT 123 (2013), Eqs. 53–54): K¹ ← [x·χ_n·ψ′_{n′}]⁺/x (their + # Eq. 59), K² ← [x·χ′_n·ψ_{n′}]⁺/x (their Eq. 60). + UK₁ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * + (_xχψ′⁺_mat(F, n, n′) / xi) + UK₂ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * + (_xχ′ψ⁺_mat(F, n, n′) / xi) + else + UK₁ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * χ[i, n] * ψₛ′[i, n′] + UK₂ += w[i] * k * r′[i] * 𝜋[i, n] * d[i, n′] * χ′[i, n] * ψₛ[i, n′] + end end 𝐏₁₂[n, n′] = A[n] * A[n′] * (s.m^2 - 1) / s.m * PK₁ @@ -532,14 +619,26 @@ function _transition_matrix_m_core(m, s::AbstractAxisymmetricShape{T, CT}, k, n (ψ′[i, n] * ψₛ′[i, n′] + n′ * (n′ + 1) * ψ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) - UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χ[i, n] * ψₛ[i, n′] - UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χ[i, n] * ψₛ[i, n′] - UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * - (χ′[i, n] * ψₛ′[i, n′] + - n * (n + 1) * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) - UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * - (χ′[i, n] * ψₛ′[i, n′] + - n′ * (n′ + 1) * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + if stable + F = Fmats[i] + xi = k * r[i] + χψ = _Fp(F, n, n′) / xi + UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χψ + UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χψ + UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * + (_L⁷⁺_mat(F, n, n′) / xi) + UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * + (_L⁸⁺_mat(F, n, n′) / xi) + else + UL₁ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * χ[i, n] * ψₛ[i, n′] + UL₂ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * χ[i, n] * ψₛ[i, n′] + UL₇ += w[i] * k * r′[i] * τ[i, n] * d[i, n′] * + (χ′[i, n] * ψₛ′[i, n′] + + n * (n + 1) * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + UL₈ += w[i] * k * r′[i] * d[i, n] * τ[i, n′] * + (χ′[i, n] * ψₛ′[i, n′] + + n′ * (n′ + 1) * χ[i, n] * ψₛ[i, n′] / (s.m * (k * r[i])^2)) + end end 𝐏₁₁[n, n′] = 1im * A[n] * A[n′] * (s.m^2 - 1) / (s.m * (a[n] - a[n′])) * @@ -596,8 +695,9 @@ transition_matrix_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, Ng) Calculate the `m`-th block of the T-Matrix for a given axisymmetric scatterer. """ function transition_matrix_m(m, s::AbstractAxisymmetricShape{T, CT}, λ, nₘₐₓ, - Ng; zerofn = () -> zero(CT), cache = nothing) where {T, CT} - 𝐏, 𝐔 = ebcm_matrices_m(m, s, λ, nₘₐₓ, Ng; zerofn, cache) + Ng; zerofn = () -> zero(CT), cache = nothing, + stable = false) where {T, CT} + 𝐏, 𝐔 = ebcm_matrices_m(m, s, λ, nₘₐₓ, Ng; zerofn, cache, stable) return 𝐓_from_𝐏_and_𝐔(𝐏, 𝐔) end @@ -632,7 +732,7 @@ end @testset "Chebyshev" begin params = Iterators.product((0.5, 1.0, 5.0), (-0.5, 0.1, 0.9), (2, 3, 8), - (1.311, 1.5 + 0.01im)) + (1.311, 1.5 + 0.01im)) nₘₐₓ = 10 Ng = 200 λ = 2π diff --git a/src/EBCM/index.jl b/src/EBCM/index.jl index d7bbb78..2fc6449 100644 --- a/src/EBCM/index.jl +++ b/src/EBCM/index.jl @@ -1,3 +1,5 @@ include("axisymmetric.jl") +include("stabilization.jl") +include("shmatrix.jl") include("routines.jl") include("linearization.jl") diff --git a/src/EBCM/linearization.jl b/src/EBCM/linearization.jl index 86d6a9b..4a22d03 100644 --- a/src/EBCM/linearization.jl +++ b/src/EBCM/linearization.jl @@ -34,16 +34,16 @@ function _ebcm_linearization_shape(shape::Cylinder, λ) end function _ebcm_linearization_input(problem::LinearizationProblem, config, - x = problem.x) + x = problem.x) rebuilt = rebuild(problem, x) shape = _linearization_property(config, :shape; - default = _linearization_property(rebuilt, :shape)) + default = _linearization_property(rebuilt, :shape)) λ = _linearization_property(config, :λ; - default = _linearization_property(rebuilt, :λ)) + default = _linearization_property(rebuilt, :λ)) nₘₐₓ = _linearization_property(config, :nₘₐₓ; - default = _linearization_property(rebuilt, :nₘₐₓ)) + default = _linearization_property(rebuilt, :nₘₐₓ)) Ng = _linearization_property(config, :Ng; - default = _linearization_property(rebuilt, :Ng)) + default = _linearization_property(rebuilt, :Ng)) if isnothing(shape) || isnothing(λ) || isnothing(nₘₐₓ) || isnothing(Ng) return nothing @@ -54,8 +54,9 @@ function _ebcm_linearization_input(problem::LinearizationProblem, config, end function _ebcm_matrices(input) - 𝐏₀, 𝐔₀, cache = ebcm_matrices_m₀(input.shape, input.λ, input.nₘₐₓ, input.Ng; - reuse = true) + 𝐏₀, 𝐔₀, + cache = ebcm_matrices_m₀(input.shape, input.λ, input.nₘₐₓ, input.Ng; + reuse = true) CT = eltype(𝐏₀) 𝐏s = Vector{Matrix{CT}}(undef, input.nₘₐₓ + 1) 𝐔s = Vector{Matrix{CT}}(undef, input.nₘₐₓ + 1) @@ -63,9 +64,10 @@ function _ebcm_matrices(input) 𝐔s[1] = 𝐔₀ for m in 1:input.nₘₐₓ - 𝐏s[m + 1], 𝐔s[m + 1] = ebcm_matrices_m(m, input.shape, input.λ, - input.nₘₐₓ, input.Ng; - cache) + 𝐏s[m + 1], + 𝐔s[m + 1] = ebcm_matrices_m(m, input.shape, input.λ, + input.nₘₐₓ, input.Ng; + cache) end return 𝐏s, 𝐔s @@ -78,40 +80,38 @@ end _ebcm_linearized(value, derivative) = _EBCMLinearizedScalar(value, derivative) _ebcm_linearized_zero(::Type{T}) where {T} = _ebcm_linearized(zero(T), zero(T)) -_ebcm_linearized_entry(value, derivative, i, n) = +function _ebcm_linearized_entry(value, derivative, i, n) _ebcm_linearized(value[i, n], derivative[i, n]) +end -Base.:+(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) = +function Base.:+(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) _ebcm_linearized(x.value + y.value, x.derivative + y.derivative) -Base.:+(x::_EBCMLinearizedScalar, y) = - _ebcm_linearized(x.value + y, x.derivative) -Base.:+(x, y::_EBCMLinearizedScalar) = - _ebcm_linearized(x + y.value, y.derivative) - -Base.:-(x::_EBCMLinearizedScalar) = - _ebcm_linearized(-x.value, -x.derivative) -Base.:-(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) = +end +Base.:+(x::_EBCMLinearizedScalar, y) = _ebcm_linearized(x.value + y, x.derivative) +Base.:+(x, y::_EBCMLinearizedScalar) = _ebcm_linearized(x + y.value, y.derivative) + +Base.:-(x::_EBCMLinearizedScalar) = _ebcm_linearized(-x.value, -x.derivative) +function Base.:-(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) _ebcm_linearized(x.value - y.value, x.derivative - y.derivative) -Base.:-(x::_EBCMLinearizedScalar, y) = - _ebcm_linearized(x.value - y, x.derivative) -Base.:-(x, y::_EBCMLinearizedScalar) = - _ebcm_linearized(x - y.value, -y.derivative) +end +Base.:-(x::_EBCMLinearizedScalar, y) = _ebcm_linearized(x.value - y, x.derivative) +Base.:-(x, y::_EBCMLinearizedScalar) = _ebcm_linearized(x - y.value, -y.derivative) -Base.:*(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) = +function Base.:*(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) _ebcm_linearized(x.value * y.value, - x.derivative * y.value + x.value * y.derivative) -Base.:*(x::_EBCMLinearizedScalar, y) = - _ebcm_linearized(x.value * y, x.derivative * y) -Base.:*(x, y::_EBCMLinearizedScalar) = - _ebcm_linearized(x * y.value, x * y.derivative) + x.derivative * y.value + x.value * y.derivative) +end +Base.:*(x::_EBCMLinearizedScalar, y) = _ebcm_linearized(x.value * y, x.derivative * y) +Base.:*(x, y::_EBCMLinearizedScalar) = _ebcm_linearized(x * y.value, x * y.derivative) -Base.:/(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) = +function Base.:/(x::_EBCMLinearizedScalar, y::_EBCMLinearizedScalar) _ebcm_linearized(x.value / y.value, - (x.derivative * y.value - x.value * y.derivative) / y.value^2) -Base.:/(x::_EBCMLinearizedScalar, y) = - _ebcm_linearized(x.value / y, x.derivative / y) -Base.:/(x, y::_EBCMLinearizedScalar) = + (x.derivative * y.value - x.value * y.derivative) / y.value^2) +end +Base.:/(x::_EBCMLinearizedScalar, y) = _ebcm_linearized(x.value / y, x.derivative / y) +function Base.:/(x, y::_EBCMLinearizedScalar) _ebcm_linearized(x / y.value, -x * y.derivative / y.value^2) +end function Base.:^(x::_EBCMLinearizedScalar, n::Integer) n == 0 && return _ebcm_linearized(one(x.value), zero(x.derivative)) @@ -233,11 +233,11 @@ function _ebcm_geometric_derivatives(c::Cylinder, x, w, r, r′, variable::Symbo if H / cosϑ < R / sinϑ ∂rᵢ = ∂H / cosϑ - H * ∂cosϑ / cosϑ^2 ∂r′ᵣₐw = ∂H * sinϑ / cosϑ^2 + - H * (∂sinϑ / cosϑ^2 - 2sinϑ * ∂cosϑ / cosϑ^3) + H * (∂sinϑ / cosϑ^2 - 2sinϑ * ∂cosϑ / cosϑ^3) else ∂rᵢ = ∂R / sinϑ - R * ∂sinϑ / sinϑ^2 ∂r′ᵣₐw = -∂R * cosϑ / sinϑ^2 - R * ∂cosϑ / sinϑ^2 + - 2R * cosϑ * ∂sinϑ / sinϑ^3 + 2R * cosϑ * ∂sinϑ / sinϑ^3 end ∂r[i] = ∂rᵢ @@ -290,7 +290,7 @@ function _ebcm_ricatti_argument_derivatives!(∂f, ∂f′, f, f′, z, ∂z) end function _ebcm_wigner_tables(::Type{T}, m::Integer, nₘₐₓ::Integer, Ng::Integer, - ϑ, nₘᵢₙ::Integer, ∂ϑ = nothing) where {T} + ϑ, nₘᵢₙ::Integer, ∂ϑ = nothing) where {T} d = OffsetArray(zeros(T, Ng, nₘₐₓ - m + 1), 1:Ng, m:nₘₐₓ) 𝜋 = similar(d) τ = similar(d) @@ -303,7 +303,7 @@ function _ebcm_wigner_tables(::Type{T}, m::Integer, nₘₐₓ::Integer, Ng::Int for i in eachindex(ϑ) wigner_d_recursion!(view(d, i, :), 0, m, nₘₐₓ, ϑ[i]; - deriv = view(τ, i, :)) + deriv = view(τ, i, :)) sinϑ = sin(ϑ[i]) cosϑ = cos(ϑ[i]) @@ -315,7 +315,7 @@ function _ebcm_wigner_tables(::Type{T}, m::Integer, nₘₐₓ::Integer, Ng::Int (n * (n + 1) - m^2 / sinϑ^2) * d[i, n] ∂τ[i, n] = d² * ∂ϑᵢ ∂𝜋[i, n] = m * (∂d[i, n] / sinϑ - - d[i, n] * cosϑ * ∂ϑᵢ / sinϑ^2) + d[i, n] * cosϑ * ∂ϑᵢ / sinϑ^2) end end @@ -345,22 +345,22 @@ function _ebcm_directional_data(input, cache, variable::Symbol) ∂ksr = ∂m * k * r[i] + s.m * ∂k * r[i] + s.m * k * ∂r[i] _ebcm_ricatti_argument_derivatives!(view(∂ψ, i, :), - view(∂ψ′, i, :), - view(ψ, i, :), - view(ψ′, i, :), kr, ∂kr) + view(∂ψ′, i, :), + view(ψ, i, :), + view(ψ′, i, :), kr, ∂kr) _ebcm_ricatti_argument_derivatives!(view(∂χ, i, :), - view(∂χ′, i, :), - view(χ, i, :), - view(χ′, i, :), kr, ∂kr) + view(∂χ′, i, :), + view(χ, i, :), + view(χ′, i, :), kr, ∂kr) _ebcm_ricatti_argument_derivatives!(view(∂ψₛ, i, :), - view(∂ψₛ′, i, :), - view(ψₛ, i, :), - view(ψₛ′, i, :), ksr, ∂ksr) + view(∂ψₛ′, i, :), + view(ψₛ, i, :), + view(ψₛ′, i, :), ksr, ∂ksr) end return (; x, w, r, r′, ϑ, a, A, ψ, ψ′, χ, χ′, ψₛ, ψₛ′, - k, ∂k, ∂m, ∂r, ∂r′, ∂ψ, ∂ψ′, - ∂χ, ∂χ′, ∂ψₛ, ∂ψₛ′, ∂x, ∂w, ∂ϑ) + k, ∂k, ∂m, ∂r, ∂r′, ∂ψ, ∂ψ′, + ∂χ, ∂χ′, ∂ψₛ, ∂ψₛ′, ∂x, ∂w, ∂ϑ) end function _ebcm_matrices_m₀_derivative(input, data) @@ -371,7 +371,7 @@ function _ebcm_matrices_m₀_derivative(input, data) T = eltype(data.r) CT = eltype(data.ψₛ) d, 𝜋, τ, ∂d, ∂𝜋, ∂τ = _ebcm_wigner_tables(T, 0, nₘₐₓ, Ng, data.ϑ, 0, - data.∂ϑ) + data.∂ϑ) ∂𝐏 = zeros(CT, 2nₘₐₓ, 2nₘₐₓ) ∂𝐏₁₁ = view(∂𝐏, 1:nₘₐₓ, 1:nₘₐₓ) @@ -384,6 +384,7 @@ function _ebcm_matrices_m₀_derivative(input, data) k = _ebcm_linearized(data.k, data.∂k) for n in 1:nₘₐₓ, n′ in 1:nₘₐₓ + if isodd(n + n′) continue end @@ -484,10 +485,10 @@ function _ebcm_matrices_m₀_derivative(input, data) ∂𝐏₁₁[n, n] = (-1im / m * data.A[n]^2 * PL̃₁).derivative ∂𝐏₂₂[n, n] = (-1im / m * data.A[n]^2 * - (PL̃₂ + (m^2 - 1) * data.a[n] * PL̃₃)).derivative + (PL̃₂ + (m^2 - 1) * data.a[n] * PL̃₃)).derivative ∂𝐔₁₁[n, n] = (-1im / m * data.A[n]^2 * UL̃₁).derivative ∂𝐔₂₂[n, n] = (-1im / m * data.A[n]^2 * - (UL̃₂ + (m^2 - 1) * data.a[n] * UL̃₃)).derivative + (UL̃₂ + (m^2 - 1) * data.a[n] * UL̃₃)).derivative end end @@ -504,29 +505,30 @@ function _ebcm_matrices_m_derivative(input, data, m_order::Integer) T = eltype(data.r) CT = eltype(data.ψₛ) d, 𝜋, τ, ∂d, ∂𝜋, ∂τ = _ebcm_wigner_tables(T, m_order, nₘₐₓ, Ng, - data.ϑ, nₘᵢₙ, data.∂ϑ) + data.ϑ, nₘᵢₙ, data.∂ϑ) ∂𝐏 = zeros(CT, 2nn, 2nn) ∂𝐏₁₁ = OffsetArray(view(∂𝐏, 1:nn, 1:nn), nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) ∂𝐏₁₂ = OffsetArray(view(∂𝐏, 1:nn, (nn + 1):(2nn)), nₘᵢₙ:nₘₐₓ, - nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ) ∂𝐏₂₁ = OffsetArray(view(∂𝐏, (nn + 1):(2nn), 1:nn), nₘᵢₙ:nₘₐₓ, - nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ) ∂𝐏₂₂ = OffsetArray(view(∂𝐏, (nn + 1):(2nn), (nn + 1):(2nn)), - nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) ∂𝐔 = zeros(CT, 2nn, 2nn) ∂𝐔₁₁ = OffsetArray(view(∂𝐔, 1:nn, 1:nn), nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) ∂𝐔₁₂ = OffsetArray(view(∂𝐔, 1:nn, (nn + 1):(2nn)), nₘᵢₙ:nₘₐₓ, - nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ) ∂𝐔₂₁ = OffsetArray(view(∂𝐔, (nn + 1):(2nn), 1:nn), nₘᵢₙ:nₘₐₓ, - nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ) ∂𝐔₂₂ = OffsetArray(view(∂𝐔, (nn + 1):(2nn), (nn + 1):(2nn)), - nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) + nₘᵢₙ:nₘₐₓ, nₘᵢₙ:nₘₐₓ) m = _ebcm_linearized(s.m, data.∂m) k = _ebcm_linearized(data.k, data.∂k) for n in nₘᵢₙ:nₘₐₓ, n′ in nₘᵢₙ:nₘₐₓ + if !iseven(n + n′) PK₁ = _ebcm_linearized_zero(CT) PK₂ = _ebcm_linearized_zero(CT) @@ -655,10 +657,10 @@ function _ebcm_matrices_m_derivative(input, data, m_order::Integer) ∂𝐏₁₁[n, n] = (-1im / m * data.A[n]^2 * PL̃₁).derivative ∂𝐏₂₂[n, n] = (-1im / m * data.A[n]^2 * - (PL̃₂ + (m^2 - 1) * data.a[n] * PL̃₃)).derivative + (PL̃₂ + (m^2 - 1) * data.a[n] * PL̃₃)).derivative ∂𝐔₁₁[n, n] = (-1im / m * data.A[n]^2 * UL̃₁).derivative ∂𝐔₂₂[n, n] = (-1im / m * data.A[n]^2 * - (UL̃₂ + (m^2 - 1) * data.a[n] * UL̃₃)).derivative + (UL̃₂ + (m^2 - 1) * data.a[n] * UL̃₃)).derivative end end end @@ -668,7 +670,7 @@ end function _ebcm_matrix_derivatives(input, variables) _, _, cache = ebcm_matrices_m₀(input.shape, input.λ, input.nₘₐₓ, input.Ng; - reuse = true) + reuse = true) map(variables) do variable data = _ebcm_directional_data(input, cache, variable) ∂𝐏s = Vector{Matrix{eltype(data.ψₛ)}}(undef, input.nₘₐₓ + 1) @@ -702,11 +704,11 @@ function _ebcm_variable_list_message(canonical) end function supports_linearization(problem::LinearizationProblem, ::EBCMLinearization; - output::Symbol = :transition_matrix, - config = nothing) + output::Symbol = :transition_matrix, + config = nothing) output == :transition_matrix || return LinearizationSupport(false, - "EBCM analytical linearization only supports transition matrices") + "EBCM analytical linearization only supports transition matrices") input = try _ebcm_linearization_input(problem, config) @@ -715,21 +717,21 @@ function supports_linearization(problem::LinearizationProblem, ::EBCMLinearizati end isnothing(input) && return LinearizationSupport(false, - "EBCM analytical linearization requires shape, λ, nₘₐₓ, and Ng") + "EBCM analytical linearization requires shape, λ, nₘₐₓ, and Ng") canonical_variables = _ebcm_linearization_variables(input.shape) isnothing(canonical_variables) && return LinearizationSupport(false, - "EBCM analytical linearization currently supports Spheroid, Chebyshev, and Cylinder slices only") + "EBCM analytical linearization currently supports Spheroid, Chebyshev, and Cylinder slices only") _linearization_variables_supported(variables(problem), canonical_variables) || return LinearizationSupport(false, - "EBCM analytical linearization supports unique canonical variables drawn from $(_ebcm_variable_list_message(canonical_variables))") + "EBCM analytical linearization supports unique canonical variables drawn from $(_ebcm_variable_list_message(canonical_variables))") return LinearizationSupport(true, "") end function _checked_ebcm_linearization_input(problem::LinearizationProblem, - backend::EBCMLinearization, - config) + backend::EBCMLinearization, + config) support = supports_linearization(problem, backend; output = :transition_matrix, config) Bool(support) || throw(UnsupportedLinearization(backend, :transition_matrix, support.reason)) @@ -737,18 +739,30 @@ function _checked_ebcm_linearization_input(problem::LinearizationProblem, end function linearize_transition_matrix(problem::LinearizationProblem, - backend::EBCMLinearization; config = nothing) + backend::EBCMLinearization; config = nothing) input = _checked_ebcm_linearization_input(problem, backend, config) 𝐏s, 𝐔s = _ebcm_matrices(input) - value = ebcm_transition_matrix_from_matrices(𝐏s, 𝐔s) + + # 𝐐 = 𝐏 + i𝐔 per m-block depends only on 𝐏 and 𝐔, not on the differentiated + # parameter. Factor each block once here and reuse it for the value block and + # every Jacobian slice, instead of recomputing inv(𝐐) per parameter per block. + factors = [_ebcm_factor(@. 𝐏 + 1im * 𝐔) for (𝐏, 𝐔) in zip(𝐏s, 𝐔s)] + 𝐓blocks = [-_ebcm_rdiv(𝐏, F) for (𝐏, F) in zip(𝐏s, factors)] + value = _axisymmetric_transition_matrix_from_blocks(𝐓blocks) + matrix_derivatives = _ebcm_matrix_derivatives(input, variables(problem)) jacobian = map(matrix_derivatives) do (∂𝐏s, ∂𝐔s) - ∂ebcm_transition_matrix_from_matrices(𝐏s, 𝐔s, ∂𝐏s, ∂𝐔s) + ∂blocks = map(∂𝐏s, ∂𝐔s, 𝐓blocks, factors) do ∂𝐏, ∂𝐔, 𝐓, F + ∂𝐐 = @. ∂𝐏 + 1im * ∂𝐔 + # ∂𝐓 = -(∂𝐏 + 𝐓 ∂𝐐) 𝐐⁻¹, reusing the block factor and value block. + -_ebcm_rdiv(∂𝐏 + 𝐓 * ∂𝐐, F) + end + _axisymmetric_transition_matrix_from_blocks(∂blocks) end return LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :ebcm_analytic, - λ = input.λ, - nₘₐₓ = input.nₘₐₓ, - Ng = input.Ng)) + metadata = (; backend = :ebcm_analytic, + λ = input.λ, + nₘₐₓ = input.nₘₐₓ, + Ng = input.Ng)) end diff --git a/src/EBCM/routines.jl b/src/EBCM/routines.jl index e3f3485..e41691e 100644 --- a/src/EBCM/routines.jl +++ b/src/EBCM/routines.jl @@ -41,86 +41,3 @@ function routine_mishchenko(threshold, ndgs, nₘₐₓ_only) return routine end - -@doc raw""" -``` -transition_matrix(s::AbstractAxisymmetricShape{T, CT}, λ; ...) where {T, CT} -``` - -Main function for calculating the transition matrix of an axisymmetric shape. - -Parameters: - -- `s`: Axisymmetric shape -- `λ`: Wavelength - -Keyword arguments: - -- `threshold`: Convergence threshold, defaults to `0.0001` -- `ndgs`: Number of discrete Gauss quadrature points per degree, defaults to `4` -- `routine_generator`: Function that generates the convergence routine, defaults to `routine_mishchenko` -- `nₛₜₐᵣₜ`: The initial number of the truncation order, defaults to `0`, and the actual value will be calculated automatically using the following formula: - -```math -n_{\text{start}} = \max(4, \lceil kr_{\max} + 4.05 \sqrt[3]{kr_{\max}} \rceil) -``` - -- `Ngₛₜₐᵣₜ`: The initial number of discrete Gauss quadrature points, defaults to `nₛₜₐᵣₜ * ndgs` -- `nₘₐₓ_only`: Only check convergence of `nₘₐₓ`, defaults to `false`, meaning that convergence of both `nₘₐₓ` and `Ng` will be checked -- `full`: Whether to calculate the whole transition matrix in each iteration, defaults to `false`, and only the `m=m′=0` block will be calculated -- `reuse`: Whether to reuse the cache of the previous iteration, defaults to `true` -- `maxiter`: Maximum number of iterations, defaults to `20` -- `zerofn`: Function that defines the type used for numerical integration, defaults to `() -> zero(CT)` where `CT` is defined by the shape -""" -function transition_matrix(s::AbstractAxisymmetricShape{T, CT}, λ; threshold = 0.0001, - ndgs = 4, routine_generator = routine_mishchenko, - nₛₜₐᵣₜ = 0, Ngₛₜₐᵣₜ = nₛₜₐᵣₜ * ndgs, nₘₐₓ_only = false, - full = false, reuse = true, maxiter = 20, - zerofn = () -> zero(CT)) where {T, CT} - if nₛₜₐᵣₜ == 0 - kr = 2π * rmax(s) / λ - if nₛₜₐᵣₜ == 0 - nₛₜₐᵣₜ = max(4, ceil(Int, kr + 4.05 * ∛kr)) - Ngₛₜₐᵣₜ = nₛₜₐᵣₜ * ndgs - end - end - - routine = routine_generator(threshold, ndgs, nₘₐₓ_only) - nₘₐₓ, Ng = nₛₜₐᵣₜ, Ngₛₜₐᵣₜ - counter = 0 - while true - cache = nothing - counter += 1 - - if !full - T₀, cache = transition_matrix_m₀(s, λ, nₘₐₓ, Ng; reuse = true) - Qext, Qsca = extinction_efficiency_m₀(T₀), scattering_efficiency_m₀(T₀) - else - 𝐓 = transition_matrix(s, λ, nₘₐₓ, Ng) - Qext, Qsca = extinction_cross_section(𝐓, λ), scattering_cross_section(𝐓, λ) - end - - @debug "Qsca = $Qsca, Qext = $Qext" - nₘₐₓ′, Ng′ = routine(nₘₐₓ, Ng, Qsca, Qext) - if nₘₐₓ′ == -1 - if full - return 𝐓 - else - Ts = [T₀] - for m in 1:nₘₐₓ - @debug "Calculating for m = $m" - Tₘ = transition_matrix_m(m, s, λ, nₘₐₓ, Ng; - cache = reuse ? cache : nothing) - push!(Ts, Tₘ) - end - return AxisymmetricTransitionMatrix{CT, nₘₐₓ, typeof(Ts), T}(Ts) - end - else - nₘₐₓ, Ng = nₘₐₓ′, Ng′ - end - - if counter > maxiter - error("Maximum number of iterations reached, failed to converge.") - end - end -end diff --git a/src/EBCM/shmatrix.jl b/src/EBCM/shmatrix.jl new file mode 100644 index 0000000..146e692 --- /dev/null +++ b/src/EBCM/shmatrix.jl @@ -0,0 +1,814 @@ +# ── Sh-matrix moment-separation feature ────────────────────────────────────── +# +# The EBCM surface integrals that build `𝐏` and `𝐔` all have the form +# +# ∫ (angular×geometry) · f_n(kr) · g_{n′}(s·kr) dϑ , +# +# where `f,g` are Riccati–Bessel functions `ψ,ψ′,χ,χ′`, `k = 2π/λ` is the size +# parameter and `s` the relative refractive index. Expanding the radial +# functions in their power series (DLMF 10.53, coefficients `_β`,`_γ` — the same +# tables used by the `F⁺` stabilization) factors every integral as +# +# ∫ = Σ_{terms} [size/material coefficient in (k,s)] × [shape-only moment M(q)] , +# +# where the *shape moment* `M(q) = ∫ (angular×geometry) · r^q dϑ` depends only on +# the particle geometry and the azimuthal index `m`, **not** on `k` or `s`. The +# moments are therefore computed once (`prepare_sh`); each `(λ, s)` evaluation is +# a cheap coefficient×moment sum, which is what makes parameter sweeps fast. +# +# This is the same idea as the `F⁺` construction (expand and integrate term by +# term), generalized to every EBCM integral. It also recovers the spheroid `𝐔` +# stabilization for free: for a spheroid the negative-`r`-power moments vanish +# analytically, so — computed at high precision — they contribute ≈0 and the +# catastrophic cancellation in the irregular `χ_n·ψ_{n′}` products never forms. +# +# References: +# - V. G. Farafonov, Sh-matrix family (parameter separation). +# - Somerville, Auguié & Le Ru, JQSRT 123 (2013) 153 (the `F⁺` projection). + +# ── Radial power-series term tables (reuse `_β`, `_γ`) ──────────────────────── +# +# For order `n`, each Riccati–Bessel function is `Σ_{b≥0} c_b · z^{base+2b}`: +# ψ_n(z) : base = n+1, c_b = β_{n,b} +# ψ′_n(z) : base = n, c_b = β_{n,b}·(n+1+2b) +# χ_n(z) : base = -n, c_b = γ_{n,b} +# χ′_n(z) : base = -n-1, c_b = γ_{n,b}·(2b-n) +""" + _sh_series(kind, n, B, R) -> (base, coeffs::Vector{R}) + +Coefficients `c_b` (`b = 0:B-1`) and the lowest exponent `base` of the power +series of a Riccati–Bessel function `kind ∈ (:ψ, :ψ′, :χ, :χ′)` of order `n`, +i.e. `f_n(z) = Σ_b coeffs[b+1] · z^{base + 2b}`. +""" +function _sh_series(kind::Symbol, n::Integer, B::Integer, ::Type{R}) where {R} + coeffs = Vector{R}(undef, B) + if kind === :ψ + base = n + 1 + for b in 0:(B - 1) + coeffs[b + 1] = R(_β(n, b)) + end + elseif kind === :ψ′ + base = n + for b in 0:(B - 1) + coeffs[b + 1] = R(_β(n, b)) * (n + 1 + 2b) + end + elseif kind === :χ + base = -n + for b in 0:(B - 1) + coeffs[b + 1] = R(_γ(n, b)) + end + elseif kind === :χ′ + base = -n - 1 + for b in 0:(B - 1) + coeffs[b + 1] = R(_γ(n, b)) * (2b - n) + end + else + throw(ArgumentError("unknown Riccati–Bessel kind $kind")) + end + return base, coeffs +end + +# ── Precomputed coefficient tables (size/material-independent) ──────────────── +""" + _sh_coeff_tables(nmax, B, R) -> NamedTuple(ψ, ψ′, χ, χ′) + +Build the radial power-series coefficient tables once (they depend only on the +order and `B`, not on `k`/`mᵣ`), so a parameter sweep never re-runs the BigInt +`_β`/`_γ` arithmetic. Each entry is an `OffsetVector` over `n = 1:nmax` of +`(base, coeffs)` from `_sh_series`. +""" +function _sh_coeff_tables(nmax::Integer, B::Integer, ::Type{R}) where {R} + mk(kind) = OffsetArray([_sh_series(kind, n, B, R) for n in 1:nmax], 1:nmax) + return (ψ = mk(:ψ), ψ′ = mk(:ψ′), χ = mk(:χ), χ′ = mk(:χ′)) +end + +# ── Per-evaluation power weighting ──────────────────────────────────────────── +""" + _sh_weighted(tbl, nmin, nmax, z) -> OffsetVector of (base, w) + +Fold the argument power `z^{base+2b}` into the series coefficients, giving +`w[b+1] = coeffs[b+1]·z^{base+2b}`, with `z = k` for the regular factor `f(kr)` +or `z = s·k` for the internal factor `g(s·kr)`. Built once per `(k, mᵣ)` point +per order and reused across all integrands. Powers advance incrementally — no +`^` in the hot loop. The `base` is kept so `_sh_conv` can index the +shape moment by the correct `r`-power. +""" +function _sh_weighted(tbl, nmin::Integer, nmax::Integer, z::Number) + z2 = z * z + Tz = typeof(z * one(eltype(tbl[nmin][2]))) + out = OffsetArray(Vector{Tuple{Int, Vector{Tz}}}(undef, nmax - nmin + 1), nmin:nmax) + for n in nmin:nmax + base, cf = tbl[n] + B = length(cf) + w = Vector{Tz}(undef, B) + zb = z^base + @inbounds for b in 1:B + w[b] = cf[b] * zb + zb *= z2 + end + out[n] = (base, w) + end + return out +end + +# ── Folded coefficient×moment reconstruction ────────────────────────────────── +""" + _sh_conv(f, g, M, shift) -> Complex + +Reconstruct `∫ (geometry) · f_n(kr) · g_{n′}(s·kr) · r^{shift} dϑ` from the +weighted radial terms `f = (basef, u)`, `g = (baseg, v)` (see `_sh_weighted`) +and the shape-moment lookup `M(q)`. The double sum is folded along the +anti-diagonals `j = b+c`: the `r`-power is `q₀ + 2j` (`q₀ = basef+baseg+shift`) +and depends only on `j`, so the moment `M` is fetched `O(B)` times instead of +`O(B²)`, and the inner convolution `Σ_{b+c=j} u[b]·v[c]` reuses the precomputed +weighted terms with no `^` and no per-term coefficient work. +""" +@inline function _sh_conv(f, g, M, shift::Integer) + basef, u = f + baseg, v = g + Bf = length(u) + Bg = length(v) + q0 = basef + baseg + shift + acc = zero(eltype(v)) + @inbounds for j in 0:(Bf + Bg - 2) + si = zero(eltype(v)) + for b in max(0, j - (Bg - 1)):min(j, Bf - 1) + si += u[b + 1] * v[j - b + 1] + end + acc += si * M(q0 + 2j) + end + return acc +end + +# ── High-precision shape widening (for the vanishing negative-power moments) ── +function _sh_widen(s::Spheroid, ::Type{R}) where {R} + Spheroid{R, Complex{R}}(R(s.a), R(s.c), Complex{R}(s.m)) +end +# Fallback: a general shape is used at its native precision. The negative-power +# moments then carry only native round-off, so the analytic `𝐔` stabilization is +# *not* available for non-spheroid shapes (gated in `prepare_sh`); `𝐏` and the +# parameter-sweep reuse work for any axisymmetric shape. +_sh_widen(s, ::Type{R}) where {R} = s + +# ── Shape moments for one azimuthal index `m` ──────────────────────────────── +""" + _sh_geometry(shape, Ng, qlo, qhi; momtype, store) -> NamedTuple + +Compute the `m`-independent geometry once: the (high-precision) Gauss–Legendre +nodes/weights, the polar angles `ϑ`, and the two `r`-power weight tables shared +by every azimuthal block, + + WR[i,q] = wᵢ r′ᵢ rᵢ^q (for the `τd`/`πd` families) + Wq[i,q] = wᵢ rᵢ^q (for the `ππττ` family, which carries no `r′`) + +`gaussquad` and the `rᵢ^q` table do not depend on `m`, so hoisting them out of +the per-`m` loop avoids recomputing them `nmax+1` times. + +The weights are also returned cast to the fast accumulation type +`Tf = store<:IEEEFloat ? store : momtype` as `WRf`/`Wqf`: the catastrophic +cancellation lives entirely in the negative-`r`-power (`q<0`) moments, so the +well-conditioned `q≥0` bulk can be contracted in hardware precision while only +the `q<0` part keeps the slow `momtype` accumulation (see `_sh_moments_m`). +""" +function _sh_geometry(shape, Ng::Integer, qlo::Integer, qhi::Integer; + momtype::Type{R} = BigFloat, store::Type = Float64) where {R} + sym = has_symmetric_plane(shape) + ng = sym ? Ng ÷ 2 : Ng + + sh = _sh_widen(shape, R) + x, w, r, r′ = gaussquad(sh, Ng) + ϑ = acos.(x) + + nq = qhi - qlo + 1 + WR = OffsetArray(zeros(R, ng, nq), 1:ng, qlo:qhi) + Wq = OffsetArray(zeros(R, ng, nq), 1:ng, qlo:qhi) + for i in 1:ng + ri = r[i] + wi = w[i] + wri = wi * r′[i] + rqᵢ = one(R) + Wq[i, 0] = wi + WR[i, 0] = wri + for q in 1:qhi + rqᵢ *= ri + Wq[i, q] = wi * rqᵢ + WR[i, q] = wri * rqᵢ + end + rqᵢ = one(R) + for q in -1:-1:qlo + rqᵢ /= ri + Wq[i, q] = wi * rqᵢ + WR[i, q] = wri * rqᵢ + end + end + + Tf = store <: Base.IEEEFloat ? store : R + WRf = Tf === R ? WR : Tf.(WR) + Wqf = Tf === R ? Wq : Tf.(Wq) + + return (; sym, ng, ϑ, WR, Wq, WRf, Wqf, qlo, qhi) +end + +""" + _sh_moments_m(geom, m, nmax; store) -> NamedTuple + +Compute the shape-only moment tables for azimuthal index `m` from the shared +`_sh_geometry` `geom`, stored as `store` (default `Float64`). Families +(sum over `i in 1:ng`, mirroring `ebcm_matrices_m₀`): + + Mτd[n,n′,q] = Σ WR[i,q] τ[i,n] d[i,n′] + Mπd[n,n′,q] = Σ WR[i,q] π[i,n] d[i,n′] (only `m>0`) + Mππττ[n,q] = Σ Wq[i,q] (π[i,n]²+τ[i,n]²) + +`Mdτ[n,n′,q] = Mτd[n′,n,q]` exactly (swap the two orders), so it is not stored — +the assembly reads `Mτd` with the indices transposed. The angular products are +formed once per `(n,n′)` instead of once per `q`. + +**Precision split.** The catastrophic cancellation that motivates the +high-precision accumulation lives entirely in the negative-`r`-power (`q<0`) +moments — for a spheroid those vanish analytically and must reach ≈0 rather than +round-off. The `q≥0` bulk is well conditioned, so it is contracted in the fast +type `Tf` (hardware float when `store` is one), while only the `q<0` slice keeps +the slow `momtype` accumulation. This is where most of the precompute time goes, +so the split is the dominant speedup; it leaves results unchanged because the +`q≥0` moments never needed the extra precision. +""" +function _sh_moments_m(geom, m::Integer, nmax::Integer; + store::Type{Ts} = Float64, vanish_negative::Bool = false) where {Ts} + WR, Wq, WRf, Wqf = geom.WR, geom.Wq, geom.WRf, geom.Wqf + R = eltype(WR) + Tf = eltype(WRf) + ϑ = geom.ϑ + ng = geom.ng + qlo, qhi = geom.qlo, geom.qhi + Ng = length(ϑ) + mm = Int(m) + nmin = max(1, mm) + nq = qhi - qlo + 1 + + # When the negative-power moments vanish analytically (spheroid), skip them + # entirely (they stay 0) and integrate the well-conditioned q ≥ -1 moments in + # the fast type; otherwise integrate q < 0 in the high-precision type and the + # q ≥ 0 bulk fast. + qbulk_lo = vanish_negative ? -1 : 0 + qneg = vanish_negative ? (1:0) : (qlo:-1) + + d = OffsetArray(zeros(R, Ng, nmax - mm + 1), 1:Ng, mm:nmax) + τ = similar(d) + 𝜋 = similar(d) + for i in 1:Ng + wigner_d_recursion!(view(d, i, :), 0, mm, nmax, ϑ[i]; deriv = view(τ, i, :)) + for n in mm:nmax + 𝜋[i, n] = pi_func(R, mm, n, ϑ[i]; d = d[i, n]) + end + end + # Fast-type copies of the angular functions for the well-conditioned q≥0 bulk. + df = Tf === R ? d : Tf.(d) + τf = Tf === R ? τ : Tf.(τ) + 𝜋f = Tf === R ? 𝜋 : Tf.(𝜋) + + Mτd = OffsetArray(zeros(Ts, nmax, nmax, nq), 1:nmax, 1:nmax, qlo:qhi) + Mπd = OffsetArray(zeros(Ts, nmax, nmax, nq), 1:nmax, 1:nmax, qlo:qhi) + Mππττ = OffsetArray(zeros(Ts, nmax, nq), 1:nmax, qlo:qhi) + + gτd = Vector{R}(undef, ng) + gπd = Vector{R}(undef, ng) + gτdf = Vector{Tf}(undef, ng) + gπdf = Vector{Tf}(undef, ng) + for n in nmin:nmax, n′ in nmin:nmax + # q < 0: ill-conditioned, accumulate in momtype precision. + @inbounds for i in 1:ng + dᵢ = d[i, n′] + gτd[i] = τ[i, n] * dᵢ + gπd[i] = 𝜋[i, n] * dᵢ + end + @inbounds for q in qneg + sτd = zero(R) + sπd = zero(R) + for i in 1:ng + wr = WR[i, q] + sτd += wr * gτd[i] + sπd += wr * gπd[i] + end + Mτd[n, n′, q] = Ts(sτd) + Mπd[n, n′, q] = Ts(sπd) + end + # q ≥ qbulk_lo: well conditioned, fast accumulation. + @inbounds for i in 1:ng + dᵢ = df[i, n′] + gτdf[i] = τf[i, n] * dᵢ + gπdf[i] = 𝜋f[i, n] * dᵢ + end + @inbounds for q in qbulk_lo:qhi + sτd = zero(Tf) + sπd = zero(Tf) + @simd for i in 1:ng + wr = WRf[i, q] + sτd += wr * gτdf[i] + sπd += wr * gπdf[i] + end + Mτd[n, n′, q] = Ts(sτd) + Mπd[n, n′, q] = Ts(sπd) + end + end + + gππττ = Vector{R}(undef, ng) + gππττf = Vector{Tf}(undef, ng) + for n in nmin:nmax + @inbounds for i in 1:ng + gππττ[i] = 𝜋[i, n]^2 + τ[i, n]^2 + end + @inbounds for q in qneg + sm = zero(R) + for i in 1:ng + sm += Wq[i, q] * gππττ[i] + end + Mππττ[n, q] = Ts(sm) + end + @inbounds for i in 1:ng + gππττf[i] = 𝜋f[i, n]^2 + τf[i, n]^2 + end + @inbounds for q in qbulk_lo:qhi + sm = zero(Tf) + @simd for i in 1:ng + sm += Wqf[i, q] * gππττf[i] + end + Mππττ[n, q] = Ts(sm) + end + end + + return (; Mτd, Mπd, Mππττ, nmin, qlo, qhi, sym = geom.sym, ng) +end + +# Default `q` band wide enough for every `m=0..nmax` integrand: +# lowest : χ′_n·ψ_{n′}/(kr)² → (-n-1)+(n′)-2 ≥ -(nmax+2) +# highest : ψ_n·ψ_{n′} → (n+1)+(n′+1)+2(B-1) ≤ 2nmax+2B +_sh_qband(nmax::Integer, B::Integer) = (-(nmax + 2), 2nmax + 2B) + +# Bounds-safe moment lookup (terms outside the stored band are negligibly small +# high-order tails / analytically absent low orders). +@inline function _sh_lookup(M3, n::Integer, n′::Integer, q::Integer, qlo::Integer, + qhi::Integer) + (qlo ≤ q ≤ qhi) ? (@inbounds M3[n, n′, q]) : zero(eltype(M3)) +end +@inline function _sh_lookup(M2, n::Integer, q::Integer, qlo::Integer, qhi::Integer) + (qlo ≤ q ≤ qhi) ? (@inbounds M2[n, q]) : zero(eltype(M2)) +end + +# ── m=0 assembly from moments (mirrors `ebcm_matrices_m₀`) ──────────────────── +""" + _sh_matrices_m₀(mom, coeffs, k, s, nmax, CT) -> (𝐏, 𝐔) + +Reconstruct the `m=0` `𝐏` and `𝐔` blocks from the precomputed `m=0` moment +tables `mom` and the size/material-independent coefficient tables `coeffs` at +size parameter `k` and refractive index `s`. The algebra reproduces +`ebcm_matrices_m₀` term by term. +""" +function _sh_matrices_m₀(mom, coeffs, k::Real, s::Number, nmax::Integer, + ::Type{CT}) where {CT} + R = real(CT) + sym = mom.sym + qlo, qhi = mom.qlo, mom.qhi + Mτd, Mππττ = mom.Mτd, mom.Mππττ + + a = [n * (n + 1) for n in 1:nmax] + A = [√(R(2n + 1) / (2n * (n + 1))) for n in 1:nmax] + + sc = Complex{R}(s) + kk = R(k) + sk = sc * kk + Uψ = _sh_weighted(coeffs.ψ, 1, nmax, kk) + Uψ′ = _sh_weighted(coeffs.ψ′, 1, nmax, kk) + Uχ = _sh_weighted(coeffs.χ, 1, nmax, kk) + Uχ′ = _sh_weighted(coeffs.χ′, 1, nmax, kk) + Vψ = _sh_weighted(coeffs.ψ, 1, nmax, sk) + Vψ′ = _sh_weighted(coeffs.ψ′, 1, nmax, sk) + + 𝐏 = zeros(CT, 2nmax, 2nmax) + 𝐏₁₁ = view(𝐏, 1:nmax, 1:nmax) + 𝐏₂₂ = view(𝐏, (nmax + 1):(2nmax), (nmax + 1):(2nmax)) + 𝐔 = zeros(CT, 2nmax, 2nmax) + 𝐔₁₁ = view(𝐔, 1:nmax, 1:nmax) + 𝐔₂₂ = view(𝐔, (nmax + 1):(2nmax), (nmax + 1):(2nmax)) + + # Mdτ[n,n′,q] = Mτd[n′,n,q] exactly, so read Mτd with the orders swapped. + Mτd_q(n, n′) = q -> _sh_lookup(Mτd, n, n′, q, qlo, qhi) + Mdτ_q(n, n′) = q -> _sh_lookup(Mτd, n′, n, q, qlo, qhi) + Mππττ_q(n) = q -> _sh_lookup(Mππττ, n, q, qlo, qhi) + + for n in 1:nmax, n′ in 1:nmax + + sym && isodd(n + n′) && continue + if n != n′ + fτd = Mτd_q(n, n′) + fdτ = Mdτ_q(n, n′) + PL₁ = kk * _sh_conv(Uψ[n], Vψ[n′], fτd, 0) + PL₂ = kk * _sh_conv(Uψ[n], Vψ[n′], fdτ, 0) + PL₇ = kk * _sh_conv(Uψ′[n], Vψ′[n′], fτd, 0) + + (a[n] / sc / kk) * _sh_conv(Uψ[n], Vψ[n′], fτd, -2) + PL₈ = kk * _sh_conv(Uψ′[n], Vψ′[n′], fdτ, 0) + + (a[n′] / sc / kk) * _sh_conv(Uψ[n], Vψ[n′], fdτ, -2) + + UL₁ = kk * _sh_conv(Uχ[n], Vψ[n′], fτd, 0) + UL₂ = kk * _sh_conv(Uχ[n], Vψ[n′], fdτ, 0) + UL₇ = kk * _sh_conv(Uχ′[n], Vψ′[n′], fτd, 0) + + (a[n] / sc / kk) * _sh_conv(Uχ[n], Vψ[n′], fτd, -2) + UL₈ = kk * _sh_conv(Uχ′[n], Vψ′[n′], fdτ, 0) + + (a[n′] / sc / kk) * _sh_conv(Uχ[n], Vψ[n′], fdτ, -2) + + pref = 1im * A[n] * A[n′] * (sc^2 - 1) / (sc * (a[n] - a[n′])) + 𝐏₁₁[n, n′] = pref * (a[n] * PL₂ - a[n′] * PL₁) + 𝐏₂₂[n, n′] = pref * (a[n] * PL₈ - a[n′] * PL₇) + 𝐔₁₁[n, n′] = pref * (a[n] * UL₂ - a[n′] * UL₁) + 𝐔₂₂[n, n′] = pref * (a[n] * UL₈ - a[n′] * UL₇) + else + fππττ = Mππττ_q(n) + fτd = Mτd_q(n, n) + PL̃₁ = _sh_conv(Uψ′[n], Vψ[n], fππττ, 0) - + sc * _sh_conv(Uψ[n], Vψ′[n], fππττ, 0) + PL̃₂ = sc * _sh_conv(Uψ′[n], Vψ[n], fππττ, 0) - + _sh_conv(Uψ[n], Vψ′[n], fππττ, 0) + PL̃₃ = (1 / sc / kk) * _sh_conv(Uψ[n], Vψ[n], fτd, -2) + + UL̃₁ = _sh_conv(Uχ′[n], Vψ[n], fππττ, 0) - + sc * _sh_conv(Uχ[n], Vψ′[n], fππττ, 0) + UL̃₂ = sc * _sh_conv(Uχ′[n], Vψ[n], fππττ, 0) - + _sh_conv(Uχ[n], Vψ′[n], fππττ, 0) + UL̃₃ = (1 / sc / kk) * _sh_conv(Uχ[n], Vψ[n], fτd, -2) + + 𝐏₁₁[n, n] = -1im / sc * A[n]^2 * PL̃₁ + 𝐏₂₂[n, n] = -1im / sc * A[n]^2 * (PL̃₂ + (sc^2 - 1) * a[n] * PL̃₃) + 𝐔₁₁[n, n] = -1im / sc * A[n]^2 * UL̃₁ + 𝐔₂₂[n, n] = -1im / sc * A[n]^2 * (UL̃₂ + (sc^2 - 1) * a[n] * UL̃₃) + end + end + + return 𝐏, 𝐔 +end + +# ── m>0 assembly from moments (mirrors `_transition_matrix_m_core`) ─────────── +""" + _sh_matrices_m(mom, coeffs, m, k, s, nmax, CT) -> (𝐏, 𝐔) + +Reconstruct the `m`-th `𝐏` and `𝐔` blocks (`2nn × 2nn`, `nn = nmax-m+1` for +`m≥1`) from the precomputed moment tables `mom` for that `m` and the +size/material-independent coefficient tables `coeffs`. The `K`-blocks use the +`M^{πd}` family; the `L`-blocks reuse the same reconstruction as the `m=0` case +(with the `m`-dependent Wigner functions baked into `mom`). The algebra +reproduces `_transition_matrix_m_core` term by term. +""" +function _sh_matrices_m(mom, coeffs, m::Integer, k::Real, s::Number, nmax::Integer, + ::Type{CT}) where {CT} + R = real(CT) + sym = mom.sym + qlo, qhi = mom.qlo, mom.qhi + Mτd, Mπd, Mππττ = mom.Mτd, mom.Mπd, mom.Mππττ + nₘᵢₙ = max(1, Int(m)) + nn = nmax - nₘᵢₙ + 1 + + a = OffsetArray([n * (n + 1) for n in nₘᵢₙ:nmax], nₘᵢₙ:nmax) + A = OffsetArray([√(R(2n + 1) / (2n * (n + 1))) for n in nₘᵢₙ:nmax], nₘᵢₙ:nmax) + + sc = Complex{R}(s) + kk = R(k) + sk = sc * kk + Uψ = _sh_weighted(coeffs.ψ, nₘᵢₙ, nmax, kk) + Uψ′ = _sh_weighted(coeffs.ψ′, nₘᵢₙ, nmax, kk) + Uχ = _sh_weighted(coeffs.χ, nₘᵢₙ, nmax, kk) + Uχ′ = _sh_weighted(coeffs.χ′, nₘᵢₙ, nmax, kk) + Vψ = _sh_weighted(coeffs.ψ, nₘᵢₙ, nmax, sk) + Vψ′ = _sh_weighted(coeffs.ψ′, nₘᵢₙ, nmax, sk) + + 𝐏 = zeros(CT, 2nn, 2nn) + 𝐏₁₁ = OffsetArray(view(𝐏, 1:nn, 1:nn), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐏₁₂ = OffsetArray(view(𝐏, 1:nn, (nn + 1):(2nn)), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐏₂₁ = OffsetArray(view(𝐏, (nn + 1):(2nn), 1:nn), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐏₂₂ = OffsetArray(view(𝐏, (nn + 1):(2nn), (nn + 1):(2nn)), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + + 𝐔 = zeros(CT, 2nn, 2nn) + 𝐔₁₁ = OffsetArray(view(𝐔, 1:nn, 1:nn), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐔₁₂ = OffsetArray(view(𝐔, 1:nn, (nn + 1):(2nn)), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐔₂₁ = OffsetArray(view(𝐔, (nn + 1):(2nn), 1:nn), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + 𝐔₂₂ = OffsetArray(view(𝐔, (nn + 1):(2nn), (nn + 1):(2nn)), nₘᵢₙ:nmax, nₘᵢₙ:nmax) + + # Mdτ[n,n′,q] = Mτd[n′,n,q] exactly, so read Mτd with the orders swapped. + Mτd_q(n, n′) = q -> _sh_lookup(Mτd, n, n′, q, qlo, qhi) + Mdτ_q(n, n′) = q -> _sh_lookup(Mτd, n′, n, q, qlo, qhi) + Mπd_q(n, n′) = q -> _sh_lookup(Mπd, n, n′, q, qlo, qhi) + Mππττ_q(n) = q -> _sh_lookup(Mππττ, n, q, qlo, qhi) + + for n in nₘᵢₙ:nmax, n′ in nₘᵢₙ:nmax + + if !(sym && iseven(n + n′)) + fπd = Mπd_q(n, n′) + PK₁ = kk * _sh_conv(Uψ[n], Vψ′[n′], fπd, 0) + PK₂ = kk * _sh_conv(Uψ′[n], Vψ[n′], fπd, 0) + UK₁ = kk * _sh_conv(Uχ[n], Vψ′[n′], fπd, 0) + UK₂ = kk * _sh_conv(Uχ′[n], Vψ[n′], fπd, 0) + + 𝐏₁₂[n, n′] = A[n] * A[n′] * (sc^2 - 1) / sc * PK₁ + 𝐏₂₁[n, n′] = A[n] * A[n′] * (1 - sc^2) / sc * PK₂ + 𝐔₁₂[n, n′] = A[n] * A[n′] * (sc^2 - 1) / sc * UK₁ + 𝐔₂₁[n, n′] = A[n] * A[n′] * (1 - sc^2) / sc * UK₂ + end + + if !(sym && isodd(n + n′)) + if n != n′ + fτd = Mτd_q(n, n′) + fdτ = Mdτ_q(n, n′) + PL₁ = kk * _sh_conv(Uψ[n], Vψ[n′], fτd, 0) + PL₂ = kk * _sh_conv(Uψ[n], Vψ[n′], fdτ, 0) + PL₇ = kk * _sh_conv(Uψ′[n], Vψ′[n′], fτd, 0) + + (a[n] / sc / kk) * _sh_conv(Uψ[n], Vψ[n′], fτd, -2) + PL₈ = kk * _sh_conv(Uψ′[n], Vψ′[n′], fdτ, 0) + + (a[n′] / sc / kk) * _sh_conv(Uψ[n], Vψ[n′], fdτ, -2) + + UL₁ = kk * _sh_conv(Uχ[n], Vψ[n′], fτd, 0) + UL₂ = kk * _sh_conv(Uχ[n], Vψ[n′], fdτ, 0) + UL₇ = kk * _sh_conv(Uχ′[n], Vψ′[n′], fτd, 0) + + (a[n] / sc / kk) * _sh_conv(Uχ[n], Vψ[n′], fτd, -2) + UL₈ = kk * _sh_conv(Uχ′[n], Vψ′[n′], fdτ, 0) + + (a[n′] / sc / kk) * _sh_conv(Uχ[n], Vψ[n′], fdτ, -2) + + pref = 1im * A[n] * A[n′] * (sc^2 - 1) / (sc * (a[n] - a[n′])) + 𝐏₁₁[n, n′] = pref * (a[n] * PL₂ - a[n′] * PL₁) + 𝐏₂₂[n, n′] = pref * (a[n] * PL₈ - a[n′] * PL₇) + 𝐔₁₁[n, n′] = pref * (a[n] * UL₂ - a[n′] * UL₁) + 𝐔₂₂[n, n′] = pref * (a[n] * UL₈ - a[n′] * UL₇) + else + fππττ = Mππττ_q(n) + fτd = Mτd_q(n, n) + PL̃₁ = _sh_conv(Uψ′[n], Vψ[n], fππττ, 0) - + sc * _sh_conv(Uψ[n], Vψ′[n], fππττ, 0) + PL̃₂ = sc * _sh_conv(Uψ′[n], Vψ[n], fππττ, 0) - + _sh_conv(Uψ[n], Vψ′[n], fππττ, 0) + PL̃₃ = (1 / sc / kk) * _sh_conv(Uψ[n], Vψ[n], fτd, -2) + + UL̃₁ = _sh_conv(Uχ′[n], Vψ[n], fππττ, 0) - + sc * _sh_conv(Uχ[n], Vψ′[n], fππττ, 0) + UL̃₂ = sc * _sh_conv(Uχ′[n], Vψ[n], fππττ, 0) - + _sh_conv(Uχ[n], Vψ′[n], fππττ, 0) + UL̃₃ = (1 / sc / kk) * _sh_conv(Uχ[n], Vψ[n], fτd, -2) + + 𝐏₁₁[n, n] = -1im / sc * A[n]^2 * PL̃₁ + 𝐏₂₂[n, n] = -1im / sc * A[n]^2 * (PL̃₂ + (sc^2 - 1) * a[n] * PL̃₃) + 𝐔₁₁[n, n] = -1im / sc * A[n]^2 * UL̃₁ + 𝐔₂₂[n, n] = -1im / sc * A[n]^2 * (UL̃₂ + (sc^2 - 1) * a[n] * UL̃₃) + end + end + end + + return 𝐏, 𝐔 +end + +# ── Two-step public API: `prepare_sh` then `transition_matrix(prep, λ, mᵣ)` ─── +""" + ShPreparation + +Precomputed shape-only moment tables for the Sh-matrix moment-separation method, +returned by [`prepare_sh`](@ref). Holds the moments for every azimuthal index +`m = 0:nmax`, which depend only on the particle geometry — not on the wavelength +or refractive index — so a single preparation feeds an arbitrarily long sweep of +`transition_matrix(prep, λ, mᵣ)` evaluations cheaply. + +The `stable` field records whether the analytic `𝐔` stabilization is valid: it +is `true` only for spheroids, whose negative-`r`-power moments vanish (computed +at high precision they contribute ≈0, removing the irregular-product +cancellation). For other axisymmetric shapes the moment machinery and `𝐏` are +still correct, but the `𝐔` reconstruction is not stabilized. +""" +struct ShPreparation{ST, MT, CF} + shape::ST + nmax::Int + Ng::Int + B::Int + moments::MT + coeffs::CF + stable::Bool +end + +""" + prepare_sh(shape, nmax, Ng; B, momtype, store) -> ShPreparation + +Precompute the Sh-matrix shape-only moment tables for `shape` up to order `nmax` +with `Ng` Gauss–Legendre points. The result is reused across many +`transition_matrix(prep, λ, mᵣ)` calls (a wavelength / refractive-index sweep) +at the cost of only a cheap coefficient×moment sum each. + +Keyword arguments: + +- `B`: number of radial power-series terms per Riccati–Bessel function. It sets + the largest size parameter the reconstruction resolves (the series, like the + `F⁺` evaluation, needs more terms as `k·rₘₐₓ·|mᵣ|` grows); it is fixed at + preparation time because it determines the moment band. Default `max(30, + nmax+15)`. +- `momtype`: precision used to accumulate the moments. The default (`nothing`) + selects automatically: for a `Spheroid` the negative-power moments vanish + analytically (the `F⁺` result), so they are set to zero and the whole + precompute runs in the shape's hardware precision — orders of magnitude faster + and with no `BigFloat` dependency, at the same accuracy as `stable=true`. For + other shapes (whose negative-power moments do not vanish) it falls back to + `BigFloat` so the cancellation is resolved numerically. Pass `momtype=BigFloat` + explicitly to force the high-precision path for a spheroid too (slower, and + bit-for-bit closer to the full-precision moments in the highest-order, smallest + `𝐓` entries). +- `store`: element type the moments are stored as (default the shape's real + type); reconstruction runs in this precision. + +The analytic `𝐔` stabilization is enabled only for `Spheroid` (see +[`ShPreparation`](@ref)). +""" +function prepare_sh(shape::AbstractAxisymmetricShape{T}, nmax::Integer, Ng::Integer; + B::Integer = max(30, nmax + 15), momtype::Union{Nothing, Type} = nothing, + store::Type = T) where {T} + # Only the symmetry shortcut (folding the quadrature to Ng ÷ 2 for shapes with + # an equatorial symmetry plane) requires an even Ng; see `_sh_geometry`. + if has_symmetric_plane(shape) + @assert iseven(Ng) "Ng must be even!" + end + qlo, qhi = _sh_qband(nmax, B) + + # For a spheroid the negative-r-power moments vanish analytically (the F⁺ + # result), so they can be set to zero and the whole precompute run in fast + # hardware precision; only the well-conditioned q ≥ -1 moments are integrated. + # Other shapes (and an explicit high-precision `momtype`) keep the robust + # high-precision path that resolves the cancellation numerically. + vanish = shape isa Spheroid + mt = momtype === nothing ? (vanish ? T : BigFloat) : momtype + vanish_negative = vanish && (mt <: Base.IEEEFloat) + + geom = _sh_geometry(shape, Ng, qlo, qhi; momtype = mt, store) + moments = [_sh_moments_m(geom, m, nmax; store, vanish_negative) for m in 0:nmax] + coeffs = _sh_coeff_tables(nmax, B, store) + return ShPreparation(shape, Int(nmax), Int(Ng), Int(B), moments, coeffs, vanish) +end + +""" + transition_matrix(prep::ShPreparation, λ, mᵣ) -> AxisymmetricTransitionMatrix + transition_matrix(prep::ShPreparation, λ) # uses the prepared shape's mᵣ + +Assemble the full T-matrix at wavelength `λ` and relative refractive index `mᵣ` +from a [`prepare_sh`](@ref) preparation, reconstructing every `m`-block from the +precomputed moments. This is the cheap inner call of a parameter sweep; the +expensive geometry quadrature was done once in `prepare_sh`. +""" +function transition_matrix(prep::ShPreparation, λ::Real, mᵣ::Number) + nmax = prep.nmax + R = promote_type(eltype(prep.moments[1].Mτd), typeof(float(λ)), + typeof(float(real(mᵣ)))) + CT = Complex{R} + k = 2R(π) / R(λ) + s = CT(mᵣ) + coeffs = prep.coeffs + + 𝐓 = Vector{Matrix{CT}}(undef, nmax + 1) + 𝐏, 𝐔 = _sh_matrices_m₀(prep.moments[1], coeffs, k, s, nmax, CT) + 𝐓[1] = 𝐓_from_𝐏_and_𝐔(𝐏, 𝐔) + for m in 1:nmax + 𝐏ₘ, 𝐔ₘ = _sh_matrices_m(prep.moments[m + 1], coeffs, m, k, s, nmax, CT) + 𝐓[m + 1] = 𝐓_from_𝐏_and_𝐔(𝐏ₘ, 𝐔ₘ) + end + + return AxisymmetricTransitionMatrix{CT, nmax, typeof(𝐓), R}(𝐓) +end + +transition_matrix(prep::ShPreparation, λ::Real) = transition_matrix(prep, λ, prep.shape.m) + +""" + transition_matrix_spectrum(prep::ShPreparation, λs, mᵣs) -> Vector + +Reconstruct a T-matrix at each `(λ, mᵣ)` pair, reusing the prepared moments. If +`mᵣs` is a single number it is held fixed across all `λs`; otherwise `λs` and +`mᵣs` are iterated together (and must have equal length). Pass a dispersion +table as `mᵣs` to sweep a material with wavelength-dependent index. +""" +function transition_matrix_spectrum(prep::ShPreparation, λs, mᵣs) + if mᵣs isa Number + ms = Iterators.repeated(mᵣs, length(λs)) + else + length(mᵣs) == length(λs) || throw(ArgumentError( + "transition_matrix_spectrum: length(mᵣs) = $(length(mᵣs)) does not match \ + length(λs) = $(length(λs))")) + ms = mᵣs + end + return [transition_matrix(prep, λ, m) for (λ, m) in zip(λs, ms)] +end + +@testitem "Sh-matrix reproduces the ebcm P and U blocks (m=0 and m>0)" begin + using TransitionMatrices: Spheroid, ebcm_matrices_m₀, ebcm_matrices_m, + _sh_geometry, _sh_moments_m, _sh_matrices_m₀, + _sh_matrices_m, _sh_qband, _sh_coeff_tables + + relmax(A, + B; + tol = 1e-10) = maximum( + (abs(B[i, j]) < tol ? 0.0 : abs(A[i, j] - B[i, j]) / abs(B[i, j]) + for i in axes(A, 1), j in axes(A, 2)); init = 0.0) + + a, c, λ, sm = 2.0, 1.0, 2π, 1.5 + 0.02im + nmax, Ng, B = 6, 120, 26 + shape = Spheroid{Float64, ComplexF64}(a, c, sm) + k = 2π / λ + qlo, qhi = _sh_qband(nmax, B) + coeffs = _sh_coeff_tables(nmax, B, Float64) + geom = _sh_geometry(shape, Ng, qlo, qhi) + + mom0 = _sh_moments_m(geom, 0, nmax) + Psh, Ush = _sh_matrices_m₀(mom0, coeffs, k, sm, nmax, ComplexF64) + Pref, Uref = ebcm_matrices_m₀(shape, λ, nmax, Ng) + @test relmax(Psh, Pref) < 1e-9 + @test relmax(Ush, Uref) < 1e-7 + + for m in 1:4 + mom = _sh_moments_m(geom, m, nmax) + Pm, Um = _sh_matrices_m(mom, coeffs, m, k, sm, nmax, ComplexF64) + Pr, Ur = ebcm_matrices_m(m, shape, λ, nmax, Ng) + @test relmax(Pm, Pr) < 1e-9 + @test relmax(Um, Ur) < 1e-7 + end +end + +@testitem "Sh-matrix transition_matrix reproduces the package T and cross sections" begin + using TransitionMatrices: Spheroid, prepare_sh, transition_matrix, calc_Csca, calc_Cext + + # Moderate aspect-2 spheroid: full T must match the standard assembly. + sh = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + nmax, Ng, λ = 8, 160, 2π + Tpkg = transition_matrix(sh, λ, nmax, Ng) + prep = prepare_sh(sh, nmax, Ng; B = 28) + Tsh = transition_matrix(prep, λ) + @test prep.stable + @test calc_Csca(Tsh) ≈ calc_Csca(Tpkg) rtol = 1e-9 + @test calc_Cext(Tsh) ≈ calc_Cext(Tpkg) rtol = 1e-9 + + # High-aspect prolate: matches the stabilized (F⁺) path where the standard + # Float64 assembly loses precision. + shp = Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im) + nmax2, Ng2 = 22, 360 + Tstab = transition_matrix(shp, λ, nmax2, Ng2; stable = true) + prep2 = prepare_sh(shp, nmax2, Ng2; B = 42) + Tsh2 = transition_matrix(prep2, λ) + @test calc_Csca(Tsh2) ≈ calc_Csca(Tstab) rtol = 1e-6 +end + +@testitem "Sh-matrix spectrum sweep matches per-point assembly" begin + using TransitionMatrices: Spheroid, prepare_sh, transition_matrix, + transition_matrix_spectrum, calc_Csca + + sh = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + nmax, Ng = 8, 160 + prep = prepare_sh(sh, nmax, Ng; B = 28) + + λs = [2π, 2.3π, 2.6π] + ms = [1.5 + 0.02im, 1.52 + 0.02im, 1.55 + 0.03im] + Ts = transition_matrix_spectrum(prep, λs, ms) + @test length(Ts) == length(λs) + for (Ti, λi, mi) in zip(Ts, λs, ms) + Tp = transition_matrix(Spheroid{Float64, ComplexF64}(2.0, 1.0, mi), λi, nmax, Ng) + @test calc_Csca(Ti) ≈ calc_Csca(Tp) rtol = 1e-9 + end + + # A scalar refractive index is held fixed across the whole sweep. + Tsf = transition_matrix_spectrum(prep, λs, sh.m) + @test length(Tsf) == length(λs) + @test calc_Csca(Tsf[1]) ≈ calc_Csca(transition_matrix(prep, λs[1], sh.m)) rtol = 1e-12 +end + +@testitem "Sh-matrix reconstructs non-spheroid shapes (cylinder, Chebyshev)" begin + using TransitionMatrices: Cylinder, Chebyshev, ebcm_matrices_m₀, _sh_geometry, + _sh_moments_m, _sh_matrices_m₀, _sh_qband, _sh_coeff_tables, + prepare_sh, transition_matrix, calc_Csca, calc_Cext + + relmax(A, + B; + tol = 1e-10) = maximum( + (abs(B[i, j]) < tol ? 0.0 : abs(A[i, j] - B[i, j]) / abs(B[i, j]) + for i in axes(A, 1), j in axes(A, 2)); init = 0.0) + + λ, nmax, Ng, B = 2π, 8, 160, 26 + k = 2π / λ + qlo, qhi = _sh_qband(nmax, B) + coeffs = _sh_coeff_tables(nmax, B, Float64) + + @testset "$name" for (name, s) in ( + ("cylinder", Cylinder{Float64, ComplexF64}(1.0, 2.0, 1.5 + 0.02im)), + ("chebyshev", Chebyshev{Float64, ComplexF64}(1.0, 0.1, 4, 1.5 + 0.02im))) + # The analytic-zeroing fast path is spheroid-only; non-spheroids use the + # high-precision moment path. Both P and U still reconstruct correctly at + # moderate size (the χ negative-power moments are physical, not vanishing). + prep = prepare_sh(s, nmax, Ng; B) + @test prep.stable == false + + geom = _sh_geometry(s, Ng, qlo, qhi; momtype = BigFloat, store = Float64) + mom = _sh_moments_m(geom, 0, nmax) + Psh, Ush = _sh_matrices_m₀(mom, coeffs, k, s.m, nmax, ComplexF64) + Pref, Uref = ebcm_matrices_m₀(s, λ, nmax, Ng) + @test relmax(Psh, Pref) < 1e-10 + @test relmax(Ush, Uref) < 1e-10 + + Tsh = transition_matrix(prep, λ) + Tcl = transition_matrix(s, λ, nmax, Ng) + @test calc_Csca(Tsh) ≈ calc_Csca(Tcl) rtol = 1e-9 + @test calc_Cext(Tsh) ≈ calc_Cext(Tcl) rtol = 1e-9 + end +end diff --git a/src/EBCM/stabilization.jl b/src/EBCM/stabilization.jl new file mode 100644 index 0000000..bdd5308 --- /dev/null +++ b/src/EBCM/stabilization.jl @@ -0,0 +1,531 @@ +# ── Numerically stable EBCM integrands for spheroids (Somerville/Le Ru) ────── +# +# The EBCM `U`-matrix integrands contain products χ_n(x)·ψ_k(sx) of an +# irregular Riccati–Bessel function χ_n (which behaves like x^{-n} for small x) +# and a regular one ψ_k. For a spheroid, the negative-power part of their +# Laurent expansion integrates *exactly* to zero, but evaluated directly it +# dominates the integrand by many orders of magnitude and destroys precision in +# `Float64` (Somerville, Auguié & Le Ru, JQSRT 113:524 (2012)). +# +# The fix (Somerville et al., JQSRT 123:153 (2013)) replaces χ_n(x)·ψ_k(sx) by +# F⁺_{nk}(s,x)/x, where (their Eq. 45) +# +# F_{nk}(s,x) = x · χ_n(x) · ψ_k(sx), +# F⁺_{nk}(s,x) = P⁺[F_{nk}] (the part with non-negative powers of x), +# +# computed directly from the power series so the cancelling negative powers are +# never formed (their Eq. 46 and §4.1). +# +# Power series (DLMF 10.53.1/10.53.2). This package uses ψ_k = z·j_k and the +# convention χ_n = z·y_n (NO minus sign; see `ricattibessely`): +# +# ψ_k(z) = Σ_{b≥0} β_{k,b} z^{k+1+2b}, β_{k,b} = (-1)^b / (2^b b! (2k+2b+1)!!) +# χ_n(z) = Σ_{a≥0} γ_{n,a} z^{2a-n}, +# γ_{n,a} = -(2n-2a-1)!! / (2^a a!) (a ≤ n) +# γ_{n,a} = (-1)^{n+a+1} / (2^a a! (2a-2n-1)!!) (a ≥ n+1) +# +# Hence F_{nk}(s,x) = Σ_{q≥0} c_{nk,q}(s) x^{2q+k-n+2}, with +# +# c_{nk,q}(s) = Σ_{a=0}^{q} γ_{n,a} β_{k,q-a} s^{k+1+2(q-a)}, +# +# and F⁺ keeps q ≥ qmin = max(0, (n-k-2)÷2) (the blocks needed have n+k even, so +# n-k-2 is even). The leading coefficients c_{nk,q} themselves suffer +# catastrophic cancellation (γ_{n,0} = (2n-1)!! is enormous and the β alternate +# in sign), so they are accumulated in high-precision `BigFloat` once; the +# resulting F⁺ is a well-behaved series that is cheap and safe to evaluate in +# the requested floating-point type. +# +# `_F⁺_matrix` assembles the whole F⁺ matrix stably for all x (series-seeded +# recursion, §4.2); `transition_matrix(…; stable=true)` uses it to rebuild the +# spheroid `𝐔`-matrix integrands for both m=0 and m>0. + +""" + _odd_dfact(m) -> BigInt + +Odd double factorial `m!!` for odd `m ≥ -1`, with the convention `(-1)!! = 1`. +""" +function _odd_dfact(m::Integer) + isodd(m) || throw(ArgumentError("_odd_dfact expects an odd integer, got $m")) + m ≥ -1 || throw(ArgumentError("_odd_dfact expects m ≥ -1, got $m")) + r = BigInt(1) + j = BigInt(m) + while j > 1 + r *= j + j -= 2 + end + return r +end + +""" + _γ(n, a) -> Rational{BigInt} + +`γ_{n,a}`: coefficient of `z^{2a-n}` in the series of `χ_n(z) = -z y_n(z)` +(DLMF 10.53.2). +""" +function _γ(n::Integer, a::Integer) + # This package uses χ_n(z) = z·y_n(z) (NO minus sign; see `ricattibessely`), + # which is the negative of the DLMF/Mishchenko χ = -z·y_n. Hence + # χ_n(z) = (-1)^{n+1} Σ_a (-1)^a z^{2a-n} / (2^a a! (2a-2n-1)!!), + # with the negative odd double-factorial convention folded into the two + # branches below (a ≤ n: singular/principal part, a ≥ n+1: regular tail). + den = (BigInt(2)^a) * Base.factorial(big(a)) # Base: the package overrides `factorial` + if a ≤ n + return -_odd_dfact(2n - 2a - 1) // den + else + sgn = iseven(n + a) ? big(-1) : big(1) + return sgn // (den * _odd_dfact(2a - 2n - 1)) + end +end + +""" + _β(k, b) -> Rational{BigInt} + +`β_{k,b}`: coefficient of `z^{k+1+2b}` in the series of `ψ_k(z) = z j_k(z)` +(DLMF 10.53.1). +""" +function _β(k::Integer, b::Integer) + sgn = iseven(b) ? big(1) : big(-1) + den = (BigInt(2)^b) * Base.factorial(big(b)) * _odd_dfact(2k + 2b + 1) + return sgn // den +end + +""" + _F⁺_coeffs(n, k, s; nterms, prec) -> (qmin, coeffs) + +High-precision coefficients of `F⁺_{nk}(s,x) = Σ c_q x^{2q+k-n+2}` for +`q = qmin, …, qmin+nterms-1`, returned as a `Vector{Complex{BigFloat}}`. +`s` is the (generally complex) relative refractive index. The sum defining each +`c_q` is accumulated in `BigFloat` at precision `prec` bits to defeat the +`(2n-1)!!`-scale cancellation. This `BigFloat` accumulation also subsumes the +additional `s≈1` cancellation that Somerville et al. 2013 handle analytically in +their Appendix B (the leading coefficients vanish at `s=1`): the base precision +has many digits of margin for it, so no special treatment is needed — the s≈1 +accuracy floor of the stabilized assembly is instead the `Float64` round-off in +`_eval_F⁺`, which extra coefficient precision cannot remove. +""" +function _F⁺_coeffs(n::Integer, k::Integer, s::Number; nterms::Integer = 48, + prec::Integer = max(256, 12n + 128)) + qmin = max(0, (n - k - 2) ÷ 2) + qmax = qmin + nterms - 1 + coeffs = Vector{Complex{BigFloat}}(undef, nterms) + setprecision(BigFloat, prec) do + sb = Complex{BigFloat}(s) + γ = [BigFloat(_γ(n, a)) for a in 0:qmax] + β = [BigFloat(_β(k, b)) for b in 0:qmax] + spow = [sb^(k + 1 + 2j) for j in 0:qmax] # s^{k+1+2(q-a)}, indexed by (q-a) + for (idx, q) in enumerate(qmin:qmax) + acc = zero(Complex{BigFloat}) + for a in 0:q + acc += γ[a + 1] * β[q - a + 1] * spow[q - a + 1] + end + coeffs[idx] = acc + end + end + return qmin, coeffs +end + +""" + _eval_F⁺(qmin, coeffs, n, k, x::T) -> Complex{T} + +Evaluate `F⁺_{nk}(s,x) = Σ_q c_q x^{2q+k-n+2}` at `x` in floating type `T`, +converting the high-precision `coeffs` to `Complex{T}` first. + +The terms `c_q x^{2q+…}` first grow then decay; the sum is truncated once it has +started to decay and a term is negligible relative to the running total +(Somerville et al. 2013, §4.1). This both avoids summing past convergence and, +crucially, prevents the monomial `xp = x^{2q+…}` from overflowing to `Inf`/`NaN` +for large `x` (it would reach `x^{2·length(coeffs)}`). The series is only well +conditioned in `Float64` when the order `n` exceeds the argument `x`; in that +regime convergence is reached long before `xp` overflows. +""" +function _eval_F⁺(qmin::Integer, coeffs::AbstractVector{<:Complex}, n::Integer, + k::Integer, x::T) where {T <: Real} + p0 = 2qmin + k - n + 2 + x2 = x * x + xp = x^p0 + val = zero(Complex{T}) + tol = eps(T) + prevmag = T(Inf) + decaying = false + @inbounds for idx in eachindex(coeffs) + isfinite(xp) || break + term = Complex{T}(coeffs[idx]) * xp + val += term + tmag = abs(term) + decaying |= tmag < prevmag + if decaying && tmag ≤ tol * abs(val) + break + end + prevmag = tmag + xp *= x2 + end + return val +end + +""" + F⁺(n, k, s, x; nterms, prec) -> Complex + +Numerically stable `F⁺_{nk}(s,x)` (Somerville et al. 2013, Eq. 45–46), +evaluated in the precision of `x`. `F⁺/x` is the cancellation-free replacement +for `χ_n(x)·ψ_k(sx)` in the spheroid EBCM `U`-matrix integrand. +""" +function F⁺(n::Integer, k::Integer, s::Number, x::T; + nterms::Integer = max(24, ceil(Int, 2 * abs(s) * x + 16)), + prec::Integer = max(256, 12n + 128)) where {T <: Real} + qmin, coeffs = _F⁺_coeffs(n, k, s; nterms, prec) + return _eval_F⁺(qmin, coeffs, n, k, x) +end + +# ── Cancellation-free "modified" Bessel products via F⁺ (Somerville 2013) ───── +# Each returns the P⁺ (non-negative-power) part of a product appearing in the +# spheroid EBCM U-matrix integrand, assembled from F⁺ at shifted indices through +# the Riccati–Bessel recurrences (their Eqs. 57–62). All carry the leading `x` +# factor, like `F⁺` itself. For small enough n−k these equal the full products +# (no negative powers), which the tests exploit for validation. + +""" + _xχψ′⁺(n, k, s, x) -> Complex + +`[x·χ_n(x)·ψ′_k(sx)]⁺` (Somerville 2013, Eq. 59), from +`(2k+1)ψ′_k(sx) = (k+1)ψ_{k-1}(sx) − k ψ_{k+1}(sx)`. +""" +function _xχψ′⁺(n, k, s, x; kw...) + ((k + 1) * F⁺(n, k - 1, s, x; kw...) - k * F⁺(n, k + 1, s, x; kw...)) / (2k + 1) +end + +""" + _xχ′ψ⁺(n, k, s, x) -> Complex + +`[x·χ′_n(x)·ψ_k(sx)]⁺` (Somerville 2013, Eq. 60), from +`(2n+1)χ′_n(x) = (n+1)χ_{n-1}(x) − n χ_{n+1}(x)`. +""" +function _xχ′ψ⁺(n, k, s, x; kw...) + ((n + 1) * F⁺(n - 1, k, s, x; kw...) - n * F⁺(n + 1, k, s, x; kw...)) / (2n + 1) +end + +""" + _L⁷⁺(n, k, s, x) -> Complex + +`[x·(χ′_n ψ′_k + n(n+1) χ_n ψ_k /(s x²))]⁺` (Somerville 2013, Eq. 62) — the +cancellation-free radial factor of the `L⁷` integrand. +""" +function _L⁷⁺(n, k, s, x; kw...) + Fmm = F⁺(n - 1, k - 1, s, x; kw...) + Fpp = F⁺(n + 1, k + 1, s, x; kw...) + Fmp = F⁺(n - 1, k + 1, s, x; kw...) + Fpm = F⁺(n + 1, k - 1, s, x; kw...) + return ((n + k + 1) * ((n + 1) * Fmm + n * Fpp) + + (n - k) * ((n + 1) * Fmp + n * Fpm)) / ((2n + 1) * (2k + 1)) +end + +""" + _L⁸⁺(n, k, s, x) -> Complex + +`[x·(χ′_n ψ′_k + k(k+1) χ_n ψ_k /(s x²))]⁺` (Somerville 2013, Eq. 61) — the +cancellation-free radial factor of the `L⁸` integrand. +""" +function _L⁸⁺(n, k, s, x; kw...) + Fmm = F⁺(n - 1, k - 1, s, x; kw...) + Fpp = F⁺(n + 1, k + 1, s, x; kw...) + Fmp = F⁺(n - 1, k + 1, s, x; kw...) + Fpm = F⁺(n + 1, k - 1, s, x; kw...) + return ((n + k + 1) * ((k + 1) * Fmm + k * Fpp) + + (k - n) * ((k + 1) * Fpm + k * Fmp)) / ((2n + 1) * (2k + 1)) +end + +""" + _F⁺_lastrow(s, N, xmax; prec, nterms) -> Vector + +Precompute the *x-independent* power-series coefficients of the F⁺-matrix last row +`n = N+1` (the entries with `n-k ≥ 4`, `n+k` even, that seed the recursion). These +are the only expensive (`BigFloat`) part of `_F⁺_matrix`, so computing them once +and passing them to every per-quadrature-point `_F⁺_matrix` call removes the +dominant cost of the stabilized assembly. `nterms` is sized for the *largest* +argument `xmax = k·rₘₐₓ` that will be evaluated (`_eval_F⁺` truncates adaptively +for smaller `x`). Element `k+1` holds `(qmin, coeffs)`, or `nothing` where unused. +""" +function _F⁺_lastrow(s::Number, N::Integer, xmax::Real; + prec::Integer = max(256, 12 * (N + 1) + 128), + nterms::Integer = max(48, ceil(Int, 2 * abs(s) * xmax + 40))) + M = N + 1 + lastrow = Vector{Union{Nothing, Tuple{Int, Vector{Complex{BigFloat}}}}}(nothing, + M + 1) + for k in 0:(M - 4) + iseven(M + k) || continue + lastrow[k + 1] = _F⁺_coeffs(M, k, s; nterms, prec) + end + return lastrow +end + +@doc raw""" + _F⁺_matrix(s, x, N; prec, nterms, lastrow) -> Matrix{Complex{T}} + +Stably evaluate the whole matrix of `F⁺_{nk}(s,x)` for `0 ≤ n,k ≤ N+1`, returned +with a 1-based offset (`F[n+1, k+1]` holds `F⁺_{nk}`). Only `n+k`-even entries are +filled; the rest stay zero (they are only needed for `m>0`). + +The bare power series is well conditioned in `Float64` *only* where the order +exceeds the argument, so it cannot be used alone for the small-`n`/large-`x` +corner. This routine combines the three regimes of Somerville, Auguié & Le Ru, +JQSRT 123 (2013) §4.2, so the result is accurate for all `x`: + + * `n ≤ k+2` — `F⁺ = F = x·χ_n(x)·ψ_k(sx)`, the direct Riccati–Bessel product + (no negative powers ⇒ no cancellation, stable for all `x`); + * last row `n = N+1`, deep entries `n-k ≥ 4` — the power series (Eq. 46), which + is accurate because `N` is taken large enough that `N+1 ≫ x`; + * `n ≥ k+4` — the stable recursion (Eq. 51, scheme (c) of their Fig. 3), filled + along diagonals `j = n-k = 4, 6, …` from high `n` down, seeded by the last row + and the `n = k+2` sub-diagonal: + + ```math + F^+_{n,k} = \frac{2k+3}{s(2n+1)}\,(F^+_{n+1,k+1} + F^+_{n-1,k+1}) - F^+_{n,k+2}. + ``` + +`N` must satisfy roughly `N+1 ≳ x + 15` for the last-row seed (and hence the whole +bottom-left block) to be accurate; this is comparable to the multipole order +needed for convergence anyway. +""" +function _F⁺_matrix(s::Number, x::T, N::Integer; + prec::Integer = max(256, 12 * (N + 1) + 128), + nterms::Integer = max(48, ceil(Int, 2 * abs(s) * x + 40)), + lastrow = nothing) where {T <: Real} + CT = Complex{T} + M = N + 1 + # x-independent last-row series coefficients (precompute once across points). + lastrow === nothing && (lastrow = _F⁺_lastrow(s, N, x; prec, nterms)) + F = zeros(CT, M + 1, M + 1) # F[n+1, k+1] = F⁺_{nk}, n,k ∈ 0:M + at(n, k) = @inbounds F[n + 1, k + 1] + + # Riccati–Bessel functions at this point, indexed 0:M. + sx = s * x + χ1, _ = ricattibessely(M, x) + nex = estimate_ricattibesselj_extra_terms(M, abs(s) * x) + ψ1, _ = ricattibesselj(M, nex, sx) + χv = Vector{T}(undef, M + 1) + ψv = Vector{CT}(undef, M + 1) + χv[1] = -cos(x) # χ_0(x) = x·y_0(x) = -cos x + ψv[1] = sin(sx) # ψ_0(z) = z·j_0(z) = sin z + @inbounds for n in 1:M + χv[n + 1] = χ1[n] + ψv[n + 1] = ψ1[n] + end + + # (1) direct products for n ≤ k+2 (covers all entries with no cancellation). + @inbounds for k in 0:M, n in 0:min(k + 2, M) + + iseven(n + k) || continue + F[n + 1, k + 1] = x * χv[n + 1] * ψv[k + 1] + end + + # (2) last row n = M (= N+1), only the deep entries n-k ≥ 4 (the shallow part + # of the last row is already filled by the direct products above). + @inbounds for k in 0:(M - 4) + iseven(M + k) || continue + qmin, coeffs = lastrow[k + 1] + F[M + 1, k + 1] = _eval_F⁺(qmin, coeffs, M, k, x) + end + + # (3) stable recursion (Eq. 51, scheme c): diagonals j = 4, 6, … filled from + # high n down; each entry uses the same-diagonal entry at n+1 and the j-2 + # diagonal at (n-1,k+1) and (n,k+2), all already known. + @inbounds for j in 4:2:M + for n in (M - 1):-1:j + k = n - j + F[n + 1, k + 1] = (2k + 3) / (s * (2n + 1)) * + (at(n + 1, k + 1) + at(n - 1, k + 1)) - at(n, k + 2) + end + end + + return F +end + +# ── Modified products read from a precomputed `_F⁺_matrix` ──────────────────── +# The bare `_xχψ′⁺`/`_L⁷⁺`/… above call `F⁺` (the small-x-only series) directly +# and are kept for testing. Production assembly uses these matrix-backed variants +# instead, fed by `_F⁺_matrix`, which is stable for all x. `F` is the offset +# matrix returned by `_F⁺_matrix` (`F[n+1,k+1] = F⁺_{nk}`). +@inline _Fp(F, n, k) = @inbounds F[n + 1, k + 1] + +"`[x·χ_n·ψ′_k]⁺` (Somerville et al., JQSRT 123 (2013), Eq. 59) from a precomputed F⁺ matrix." +_xχψ′⁺_mat(F, n, k) = ((k + 1) * _Fp(F, n, k - 1) - k * _Fp(F, n, k + 1)) / (2k + 1) + +"`[x·χ′_n·ψ_k]⁺` (Somerville et al., JQSRT 123 (2013), Eq. 60) from a precomputed F⁺ matrix." +_xχ′ψ⁺_mat(F, n, k) = ((n + 1) * _Fp(F, n - 1, k) - n * _Fp(F, n + 1, k)) / (2n + 1) + +"L⁷ radial factor (Somerville et al., JQSRT 123 (2013), Eq. 62) from a precomputed F⁺ matrix." +function _L⁷⁺_mat(F, n, k) + Fmm = _Fp(F, n - 1, k - 1); + Fpp = _Fp(F, n + 1, k + 1) + Fmp = _Fp(F, n - 1, k + 1); + Fpm = _Fp(F, n + 1, k - 1) + return ((n + k + 1) * ((n + 1) * Fmm + n * Fpp) + + (n - k) * ((n + 1) * Fmp + n * Fpm)) / ((2n + 1) * (2k + 1)) +end + +"L⁸ radial factor (Somerville et al., JQSRT 123 (2013), Eq. 61) from a precomputed F⁺ matrix." +function _L⁸⁺_mat(F, n, k) + Fmm = _Fp(F, n - 1, k - 1); + Fpp = _Fp(F, n + 1, k + 1) + Fmp = _Fp(F, n - 1, k + 1); + Fpm = _Fp(F, n + 1, k - 1) + return ((n + k + 1) * ((k + 1) * Fmm + k * Fpp) + + (k - n) * ((k + 1) * Fpm + k * Fmp)) / ((2n + 1) * (2k + 1)) +end + +@testitem "_F⁺_matrix is stable across x (series-seeded Eq.51 recursion)" begin + using TransitionMatrices: _F⁺_matrix, _F⁺_coeffs, _eval_F⁺ + s = 1.5 + 0.02im + # The bare series fails for small n / large x; the matrix builder must stay + # accurate over the whole bottom-left (cancellation) block n ≥ k+4 for every x. + for x in (0.5, 8.0, 16.0, 35.0) + N = max(20, ceil(Int, x) + 18) # N+1 ≳ x+15 for the last-row seed + F = _F⁺_matrix(s, x, N) + nt = max(60, ceil(Int, 2 * abs(s) * x + 50)) + maxrel = 0.0 + for n in 4:N, k in 0:(n - 4) + + iseven(n + k) || continue + vbig = setprecision(BigFloat, 600) do + qmin, co = _F⁺_coeffs(n, k, s; nterms = nt, prec = 600) + _eval_F⁺(qmin, co, n, k, BigFloat(x)) + end + ab = abs(ComplexF64(vbig)) + ab < 1e-285 && continue + maxrel = max(maxrel, + abs(ComplexF64(F[n + 1, k + 1]) - ComplexF64(vbig)) / ab) + end + @test maxrel < 1e-9 + end +end + +@testitem "F⁺ matches the Bessel product where no negative powers exist (n ≤ k+2)" begin + using TransitionMatrices: F⁺, ricattibesselj, ricattibessely, + estimate_ricattibesselj_extra_terms + setprecision(BigFloat, 320) do + s = Complex{BigFloat}(1.5, 0.02) + for x in BigFloat.((0.3, 1.0, 2.5)), + (n, k) in ((1, 1), (2, 2), (1, 3), (3, 5), + (4, 4), (2, 4)) + # n ≤ k+2 ⇒ F⁺ = F = x·χ_n(x)·ψ_k(s·x) (the full product, no truncation) + @assert n ≤ k + 2 + # request ≥ 2 orders: ricattibessely! unconditionally writes χ[2]. + χ, _ = ricattibessely(max(n, 2), x) + nextra = estimate_ricattibesselj_extra_terms(max(k, 2), abs(s) * x) + ψ, _ = ricattibesselj(max(k, 2), nextra, s * x) + ref = x * χ[n] * ψ[k] + got = F⁺(n, k, s, x; nterms = 80) + @test isapprox(got, ref; rtol = 1e-25, atol = 1e-25) + end + end +end + +@testitem "F⁺ satisfies the Somerville recurrence Eq. 51" begin + using TransitionMatrices: F⁺ + # F⁺_{n+1,k} + F⁺_{n-1,k} = s (2n+1)/(2k+1) (F⁺_{n,k+1} + F⁺_{n,k-1}) + setprecision(BigFloat, 512) do + s = Complex{BigFloat}(1.5, 0.02) + for x in BigFloat.((0.1, 0.5, 2.0)), (n, k) in ((8, 3), (10, 2), (12, 6), (15, 4)) + + nt = 80 + lhs = F⁺(n + 1, k, s, x; nterms = nt) + F⁺(n - 1, k, s, x; nterms = nt) + rhs = s * (2n + 1) / (2k + 1) * + (F⁺(n, k + 1, s, x; nterms = nt) + F⁺(n, k - 1, s, x; nterms = nt)) + @test isapprox(lhs, rhs; rtol = 1e-30, atol = 1e-30) + end + end +end + +@testitem "F⁺ Float64 evaluation matches BigFloat (no precision loss in the kept series)" begin + using TransitionMatrices: _F⁺_coeffs, _eval_F⁺ + s = ComplexF64(1.5, 0.02) + for (n, k) in ((10, 2), (16, 4), (20, 6)), x64 in (0.1, 0.5, 1.0, 2.0) + + qmin, coeffs = _F⁺_coeffs(n, k, s; nterms = 60, prec = 600) + v64 = _eval_F⁺(qmin, coeffs, n, k, x64) + vbig = _eval_F⁺(qmin, coeffs, n, k, BigFloat(x64)) + @test isapprox(ComplexF64(vbig), v64; rtol = 1e-12, atol = 1e-300) + end +end + +@testitem "Modified Bessel products (Eq. 59-62) match direct products for n ≤ k" begin + using TransitionMatrices: _xχψ′⁺, _xχ′ψ⁺, _L⁷⁺, _L⁸⁺, ricattibesselj, + ricattibessely, estimate_ricattibesselj_extra_terms + setprecision(BigFloat, 320) do + s = Complex{BigFloat}(1.5, 0.02) + for x in BigFloat.((0.5, 1.5)), + (n, k) in ((1, 1), (2, 2), (3, 3), (1, 3), + (2, 4), (3, 5), (2, 5), (4, 6)) + # n ≤ k ⇒ all four products have only non-negative powers ⇒ ⁺ = full. + @assert n ≤ k + χ, χ′ = ricattibessely(max(n, 2), x) + nextra = estimate_ricattibesselj_extra_terms(max(k, 2), abs(s) * x) + ψ, ψ′ = ricattibesselj(max(k, 2), nextra, s * x) + nt = 80 + @test isapprox(_xχψ′⁺(n, k, s, x; nterms = nt), x * χ[n] * ψ′[k]; + rtol = 1e-22, atol = 1e-22) + @test isapprox(_xχ′ψ⁺(n, k, s, x; nterms = nt), x * χ′[n] * ψ[k]; + rtol = 1e-22, atol = 1e-22) + l7 = x * (χ′[n] * ψ′[k] + n * (n + 1) * χ[n] * ψ[k] / (s * x^2)) + l8 = x * (χ′[n] * ψ′[k] + k * (k + 1) * χ[n] * ψ[k] / (s * x^2)) + @test isapprox(_L⁷⁺(n, k, s, x; nterms = nt), l7; rtol = 1e-22, atol = 1e-22) + @test isapprox(_L⁸⁺(n, k, s, x; nterms = nt), l8; rtol = 1e-22, atol = 1e-22) + end + end +end + +@testitem "ebcm_matrices_m₀(; stable=true) fixes high-aspect spheroid 𝐔 vs BigFloat" begin + using TransitionMatrices: Spheroid, ebcm_matrices_m₀, 𝐓_from_𝐏_and_𝐔 + + relmax(A, B) = begin + m = 0.0 + for I in eachindex(B) + b = ComplexF64(B[I]) + abs(b) < 1e-12 && continue + m = max(m, abs(ComplexF64(A[I]) - b) / abs(b)) + end + m + end + + λ = 2π + a, c, N, Ng = 0.3, 5.0, 16, 300 # prolate, aspect ≈ 17: std Float64 𝐔 is hopeless + mr = 1.5 + 0.01im + sb = Spheroid{BigFloat, Complex{BigFloat}}(big(a), big(c), Complex{BigFloat}(mr)) + s64 = Spheroid{Float64, ComplexF64}(a, c, ComplexF64(mr)) + + Pb, Ub = setprecision(BigFloat, 320) do + ebcm_matrices_m₀(sb, big(λ), N, Ng) + end + Ps, Us = ebcm_matrices_m₀(s64, λ, N, Ng) + Pst, Ust = ebcm_matrices_m₀(s64, λ, N, Ng; stable = true) + + @test relmax(Us, Ub) > 1e1 # standard products are catastrophically wrong + @test relmax(Ust, Ub) < 1e-6 # the F⁺ matrix recovers full precision + @test Pst == Ps # `stable` must leave 𝐏 untouched + + Tb = 𝐓_from_𝐏_and_𝐔(ComplexF64.(Pb), ComplexF64.(Ub)) + @test relmax(𝐓_from_𝐏_and_𝐔(Pst, Ust), Tb) < 1e-5 +end + +@testitem "stable=true reproduces Somerville 2013 Table 2 (prolate Qsca/Qext)" begin + using TransitionMatrices: Spheroid, transition_matrix, scattering_cross_section, + extinction_cross_section + + # Somerville, Auguié & Le Ru, JQSRT 123 (2013), Table 2 (Model 1 of their + # Ref. [35]): prolate, s = 1.55+0.01i, aspect h = 4, xmax = k·c = 10.079368. + # Reference (their New DP / AP): Qsca = 3.21290554203156, Qext = 3.36721292620922. + c = 10.079368 + a = c / 4 + s = Spheroid{Float64, ComplexF64}(a, c, 1.55 + 0.01im) + + # efficiencies are normalised by the equal-surface-area radius (prolate, a n zero(CT) else @@ -72,7 +72,7 @@ The T-Matrix of a Mie scatterer is invariant under rotation. Therefore, the orig orientation_average(mie::MieTransitionMatrix, _pₒ; _kwargs...) = mie function scattering_cross_section(mie::MieTransitionMatrix{CT, N, V}, - λ = 2π) where {CT, N, V} + λ = 2π) where {CT, N, V} Cˢᶜᵃ = zero(real(CT)) @inbounds for n in 1:N @@ -83,7 +83,7 @@ function scattering_cross_section(mie::MieTransitionMatrix{CT, N, V}, end function extinction_cross_section(mie::MieTransitionMatrix{CT, N, V}, - λ = 2π) where {CT, N, V} + λ = 2π) where {CT, N, V} Cᵉˣᵗ = zero(real(CT)) @inbounds for n in 1:N @@ -94,7 +94,7 @@ function extinction_cross_section(mie::MieTransitionMatrix{CT, N, V}, end function amplitude_matrix(mie::MieTransitionMatrix{CT, N, V}, ϑᵢ, φᵢ, ϑₛ, φₛ; - λ = 2π) where {CT, N, V} + λ = 2π) where {CT, N, V} T = real(CT) k₁ = 2π / λ 𝐒₁₁, 𝐒₁₂, 𝐒₂₁, 𝐒₂₂ = zero(CT), zero(CT), zero(CT), zero(CT) @@ -112,9 +112,9 @@ function amplitude_matrix(mie::MieTransitionMatrix{CT, N, V}, ϑᵢ, φᵢ, ϑ for m in 0:N wigner_d_recursion!(view(πᵢ, m, m:N), 0, m, N, ϑᵢ; - deriv = view(τᵢ, m, m:N)) + deriv = view(τᵢ, m, m:N)) wigner_d_recursion!(view(πₛ, m, m:N), 0, m, N, ϑₛ; - deriv = view(τₛ, m, m:N)) + deriv = view(τₛ, m, m:N)) end for n in 1:N @@ -160,21 +160,21 @@ end @testset "of a homogeneous sphere remains the same under rotations" begin 𝐓 = MieTransitionMatrix{ComplexF64, 5}(1.0, 1.311) @test all(isapprox.(𝐓, - rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), - RotZYZ(0.2, 0.3, 0.4)); atol = eps(Float64))) + rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), + RotZYZ(0.2, 0.3, 0.4)); atol = eps(Float64))) @test all(isapprox.(𝐓, - rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), - RotZYZ(0.8, 0.0, -1.0)); atol = eps(Float64))) + rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), + RotZYZ(0.8, 0.0, -1.0)); atol = eps(Float64))) end @testset "of a coated sphere remains the same under rotations" begin 𝐓 = MieTransitionMatrix{ComplexF64, 5}(0.4, 0.8, 1.0, 1.311) @test all(isapprox.(𝐓, - rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), - RotZYZ(0.2, 0.3, 0.4)); atol = eps(Float64))) + rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), + RotZYZ(0.2, 0.3, 0.4)); atol = eps(Float64))) @test all(isapprox.(𝐓, - rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), - RotZYZ(0.8, 0.0, -1.0)); atol = eps(Float64))) + rotate(TransitionMatrix{ComplexF64, 5, typeof(𝐓)}(𝐓), + RotZYZ(0.8, 0.0, -1.0)); atol = eps(Float64))) end end @@ -190,5 +190,5 @@ end @test scattering_cross_section(𝐓, λ) ≈ scattering_cross_section(𝐓_fallback, λ) @test extinction_cross_section(𝐓, λ) ≈ extinction_cross_section(𝐓_fallback, λ) @test all(isapprox.(amplitude_matrix(𝐓, angles...; λ = λ), - amplitude_matrix(𝐓_fallback, angles...; λ = λ))) + amplitude_matrix(𝐓_fallback, angles...; λ = λ))) end diff --git a/src/Mie/bhcoat.jl b/src/Mie/bhcoat.jl index c94c884..dc2f50c 100644 --- a/src/Mie/bhcoat.jl +++ b/src/Mie/bhcoat.jl @@ -25,11 +25,11 @@ References: - Bohren, C.F., Huffman, D.R., 1983. Absorption and scattering of light by small particles. John Wiley & Sons. """ function bhcoat(T, xᵢₙ, - xₒᵤₜ, mᵢₙ, mₒᵤₜ; - nₘₐₓ = ceil(Int, - max(xₒᵤₜ + 4 * ∛xₒᵤₜ + 2, - xₒᵤₜ * max(abs(mᵢₙ), abs(mₒᵤₜ)))), - tolerance = 1e-8) + xₒᵤₜ, mᵢₙ, mₒᵤₜ; + nₘₐₓ = ceil(Int, + max(xₒᵤₜ + 4 * ∛xₒᵤₜ + 2, + xₒᵤₜ * max(abs(mᵢₙ), abs(mₒᵤₜ)))), + tolerance = 1e-8) @assert xₒᵤₜ>=xᵢₙ "xₒᵤₜ must be greater than or equal to xᵢₙ" C = complex(T) @@ -127,10 +127,10 @@ function bhcoat(T, xᵢₙ, end function bhcoat(xᵢₙ, xₒᵤₜ, mᵢₙ, mₒᵤₜ; - nₘₐₓ = ceil(Int, - max(xₒᵤₜ + 4 * ∛xₒᵤₜ + 2, - xₒᵤₜ * max(abs(mᵢₙ), abs(mₒᵤₜ)))), - tolerance = 1e-8) + nₘₐₓ = ceil(Int, + max(xₒᵤₜ + 4 * ∛xₒᵤₜ + 2, + xₒᵤₜ * max(abs(mᵢₙ), abs(mₒᵤₜ)))), + tolerance = 1e-8) bhcoat(Float64, xᵢₙ, xₒᵤₜ, mᵢₙ, mₒᵤₜ; nₘₐₓ = nₘₐₓ, tolerance = tolerance) end @@ -139,7 +139,7 @@ end @testset "converges to bhmie when x = $x, m = $m" for (x, m) in [ (1.0, 1.311), - (2.0, 1.5 + 0.01im), + (2.0, 1.5 + 0.01im) ] am, bm = bhmie(x, m) ac, bc = bhcoat(x, x, m, m) diff --git a/src/Mie/linearization.jl b/src/Mie/linearization.jl index 722d474..aa1a754 100644 --- a/src/Mie/linearization.jl +++ b/src/Mie/linearization.jl @@ -4,21 +4,21 @@ const _MIE_LINEARIZATION_SUPPORTED_OUTPUTS = ( :extinction_cross_section, :absorption_cross_section, :albedo, - :amplitude_matrix, + :amplitude_matrix ) const _MIE_LINEARIZATION_VARIABLES = (:x, :mᵣ, :mᵢ, :λ) function _mie_linearization_input(problem::LinearizationProblem, config) rebuilt = rebuild(problem) x = _linearization_property(config, :x; - default = _linearization_property(rebuilt, :x)) + default = _linearization_property(rebuilt, :x)) m = _linearization_property(config, :m; - default = _linearization_property(rebuilt, :m)) + default = _linearization_property(rebuilt, :m)) nₘₐₓ = _linearization_property(config, :nₘₐₓ; - default = _linearization_property(rebuilt, :nₘₐₓ)) + default = _linearization_property(rebuilt, :nₘₐₓ)) λ = _linearization_property(config, :λ; - default = _linearization_property(rebuilt, :λ; - default = 2π)) + default = _linearization_property(rebuilt, :λ; + default = 2π)) if isnothing(x) || isnothing(m) || isnothing(nₘₐₓ) return nothing @@ -64,8 +64,8 @@ function _mie_amplitude_angles(config) end function supports_linearization(problem::LinearizationProblem, ::MieLinearization; - output::Symbol = :transition_matrix, - config = nothing) + output::Symbol = :transition_matrix, + config = nothing) input = try _mie_linearization_input(problem, config) catch err @@ -73,15 +73,15 @@ function supports_linearization(problem::LinearizationProblem, ::MieLinearizatio end isnothing(input) && return LinearizationSupport(false, - "Mie linearization requires x, m, and nₘₐₓ") + "Mie linearization requires x, m, and nₘₐₓ") isnothing(_mie_linearization_variable_derivatives(problem)) && return LinearizationSupport(false, - "Mie linearization supports unique canonical variables drawn from :x, :mᵣ, :mᵢ, and :λ") + "Mie linearization supports unique canonical variables drawn from :x, :mᵣ, :mᵢ, and :λ") output in _MIE_LINEARIZATION_SUPPORTED_OUTPUTS || return LinearizationSupport(false, "Mie linearization does not support output :$output") output == :amplitude_matrix && isnothing(_mie_amplitude_angles(config)) && return LinearizationSupport(false, - "Mie amplitude matrix linearization requires angle config") + "Mie amplitude matrix linearization requires angle config") return LinearizationSupport(true, "") end @@ -154,13 +154,13 @@ function _bhmie_linearized(::Type{T}, x, m, nₘₐₓ::Integer, ẋ, ṁ) where numerator_dot = Ȧ * ψ + A * ψ̇ - ψ̇₁[j] denominator_dot = Ȧ * ξ + A * ξ̇ - ξ̇₁[j] ȧ[n, j] = (numerator_dot * denominator_a - - numerator_a * denominator_dot) / denominator_a^2 + numerator_a * denominator_dot) / denominator_a^2 Ḃ = ḋ[n, j] * m + d[n] * ṁ[j] - n * ẋ[j] / x^2 numerator_dot = Ḃ * ψ + B * ψ̇ - ψ̇₁[j] denominator_dot = Ḃ * ξ + B * ξ̇ - ξ̇₁[j] ḃ[n, j] = (numerator_dot * denominator_b - - numerator_b * denominator_dot) / denominator_b^2 + numerator_b * denominator_dot) / denominator_b^2 end a[n] = numerator_a / denominator_a @@ -180,38 +180,38 @@ function _bhmie_linearized(::Type{T}, x, m, nₘₐₓ::Integer, ẋ, ṁ) where end function _checked_mie_linearization_input(problem::LinearizationProblem, - backend::MieLinearization, - output::Symbol, - config) + backend::MieLinearization, + output::Symbol, + config) output in _MIE_LINEARIZATION_SUPPORTED_OUTPUTS || throw(UnsupportedLinearization(backend, output, - "Mie linearization does not support output :$output")) + "Mie linearization does not support output :$output")) input = try _mie_linearization_input(problem, config) catch err throw(UnsupportedLinearization(backend, output, - "failed to rebuild Mie input: $err")) + "failed to rebuild Mie input: $err")) end isnothing(input) && throw(UnsupportedLinearization(backend, output, - "Mie linearization requires x, m, and nₘₐₓ")) + "Mie linearization requires x, m, and nₘₐₓ")) variable_derivatives = _mie_linearization_variable_derivatives(problem) isnothing(variable_derivatives) && throw(UnsupportedLinearization(backend, output, - "Mie linearization supports unique canonical variables drawn from :x, :mᵣ, :mᵢ, and :λ")) + "Mie linearization supports unique canonical variables drawn from :x, :mᵣ, :mᵢ, and :λ")) output == :amplitude_matrix && isnothing(_mie_amplitude_angles(config)) && throw(UnsupportedLinearization(backend, output, - "Mie amplitude matrix linearization requires angle config")) + "Mie amplitude matrix linearization requires angle config")) return input, variable_derivatives end function _mie_transition_linearization_data(problem::LinearizationProblem, - backend::MieLinearization, - config; - output::Symbol = :transition_matrix) + backend::MieLinearization, + config; + output::Symbol = :transition_matrix) input, (ẋ, ṁ, λ̇) = _checked_mie_linearization_input(problem, backend, output, config) T = typeof(float(real(input.x))) CT = complex(T) @@ -223,18 +223,18 @@ function _mie_transition_linearization_data(problem::LinearizationProblem, for j in 1:length(variables(problem))] result = LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :mie, λ = input.λ)) + metadata = (; backend = :mie, λ = input.λ)) return result, input, λ̇ end function _mie_transition_linearization(problem::LinearizationProblem, - backend::MieLinearization, config) + backend::MieLinearization, config) result, _, _ = _mie_transition_linearization_data(problem, backend, config) return result end function linearize_transition_matrix(problem::LinearizationProblem, - backend::MieLinearization; config = nothing) + backend::MieLinearization; config = nothing) return _mie_transition_linearization(problem, backend, config) end @@ -261,7 +261,7 @@ function _mie_cross_section_linearization(result::LinearizationResult, λ, λ̇, ∂T = result.jacobian[j] if kind == :scattering basė[j] += weight * 2real(conj(mie.a[n]) * ∂T.a[n] + - conj(mie.b[n]) * ∂T.b[n]) + conj(mie.b[n]) * ∂T.b[n]) else basė[j] += weight * real(∂T.a[n] + ∂T.b[n]) end @@ -293,7 +293,7 @@ function _mie_cross_section_pair_linearization(result::LinearizationResult, λ, for j in 1:p ∂T = result.jacobian[j] scattering_basė[j] += weight * 2real(conj(mie.a[n]) * ∂T.a[n] + - conj(mie.b[n]) * ∂T.b[n]) + conj(mie.b[n]) * ∂T.b[n]) extinction_basė[j] += weight * real(∂T.a[n] + ∂T.b[n]) end end @@ -301,58 +301,62 @@ function _mie_cross_section_pair_linearization(result::LinearizationResult, λ, scattering_jacobian = @. scattering_basė * scale + scattering_base * scalė extinction_jacobian = @. extinction_basė * scale + extinction_base * scalė return (; scattering = scattering_base * scale, - scattering_jacobian, - extinction = extinction_base * scale, - extinction_jacobian) + scattering_jacobian, + extinction = extinction_base * scale, + extinction_jacobian) end function linearize_observable(::typeof(scattering_cross_section), - problem::LinearizationProblem, - backend::MieLinearization; config = nothing) - result, input, λ̇ = _mie_transition_linearization_data(problem, backend, config; - output = :scattering_cross_section) + problem::LinearizationProblem, + backend::MieLinearization; config = nothing) + result, input, + λ̇ = _mie_transition_linearization_data(problem, backend, config; + output = :scattering_cross_section) value, jacobian = _mie_cross_section_linearization(result, input.λ, λ̇, :scattering) return LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :mie, - observable = :scattering_cross_section)) + metadata = (; backend = :mie, + observable = :scattering_cross_section)) end function linearize_observable(::typeof(extinction_cross_section), - problem::LinearizationProblem, - backend::MieLinearization; config = nothing) - result, input, λ̇ = _mie_transition_linearization_data(problem, backend, config; - output = :extinction_cross_section) + problem::LinearizationProblem, + backend::MieLinearization; config = nothing) + result, input, + λ̇ = _mie_transition_linearization_data(problem, backend, config; + output = :extinction_cross_section) value, jacobian = _mie_cross_section_linearization(result, input.λ, λ̇, :extinction) return LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :mie, - observable = :extinction_cross_section)) + metadata = (; backend = :mie, + observable = :extinction_cross_section)) end function linearize_observable(::typeof(absorption_cross_section), - problem::LinearizationProblem, - backend::MieLinearization; config = nothing) - result, input, λ̇ = _mie_transition_linearization_data(problem, backend, config; - output = :absorption_cross_section) + problem::LinearizationProblem, + backend::MieLinearization; config = nothing) + result, input, + λ̇ = _mie_transition_linearization_data(problem, backend, config; + output = :absorption_cross_section) cross_sections = _mie_cross_section_pair_linearization(result, input.λ, λ̇) return LinearizationResult(cross_sections.extinction - cross_sections.scattering, - cross_sections.extinction_jacobian - - cross_sections.scattering_jacobian, - variables(problem); - metadata = (; backend = :mie, - observable = :absorption_cross_section)) + cross_sections.extinction_jacobian - + cross_sections.scattering_jacobian, + variables(problem); + metadata = (; backend = :mie, + observable = :absorption_cross_section)) end function linearize_observable(::typeof(albedo), problem::LinearizationProblem, - backend::MieLinearization; config = nothing) - result, input, λ̇ = _mie_transition_linearization_data(problem, backend, config; - output = :albedo) + backend::MieLinearization; config = nothing) + result, input, + λ̇ = _mie_transition_linearization_data(problem, backend, config; + output = :albedo) cross_sections = _mie_cross_section_pair_linearization(result, input.λ, λ̇) value = cross_sections.scattering / cross_sections.extinction jacobian = @. (cross_sections.scattering_jacobian * cross_sections.extinction - - cross_sections.scattering * cross_sections.extinction_jacobian) / - cross_sections.extinction^2 + cross_sections.scattering * cross_sections.extinction_jacobian) / + cross_sections.extinction^2 return LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :mie, observable = :albedo)) + metadata = (; backend = :mie, observable = :albedo)) end function _mie_amplitude_matrix_linearization(result::LinearizationResult, λ, λ̇, angles) @@ -375,9 +379,9 @@ function _mie_amplitude_matrix_linearization(result::LinearizationResult, λ, λ for m in 0:N wigner_d_recursion!(view(πᵢ, m, m:N), 0, m, N, ϑᵢ; - deriv = view(τᵢ, m, m:N)) + deriv = view(τᵢ, m, m:N)) wigner_d_recursion!(view(πₛ, m, m:N), 0, m, N, ϑₛ; - deriv = view(τₛ, m, m:N)) + deriv = view(τₛ, m, m:N)) end for m in 0:N @@ -447,14 +451,15 @@ function _mie_amplitude_matrix_linearization(result::LinearizationResult, λ, λ end function linearize_observable(::typeof(amplitude_matrix), - problem::LinearizationProblem, - backend::MieLinearization; config = nothing) - result, input, λ̇ = _mie_transition_linearization_data(problem, backend, config; - output = :amplitude_matrix) + problem::LinearizationProblem, + backend::MieLinearization; config = nothing) + result, input, + λ̇ = _mie_transition_linearization_data(problem, backend, config; + output = :amplitude_matrix) angles = _mie_amplitude_angles(config) value, jacobian = _mie_amplitude_matrix_linearization(result, input.λ, λ̇, angles) return LinearizationResult(value, jacobian, variables(problem); - metadata = (; backend = :mie, - observable = :amplitude_matrix)) + metadata = (; backend = :mie, + observable = :amplitude_matrix)) end diff --git a/src/TransitionMatrices.jl b/src/TransitionMatrices.jl index 057f03a..6af0e58 100644 --- a/src/TransitionMatrices.jl +++ b/src/TransitionMatrices.jl @@ -28,6 +28,7 @@ include("linearization.jl") include("Mie/index.jl") include("EBCM/index.jl") include("IITM/index.jl") +include("solvers.jl") # Various types of transition matrices export AbstractTransitionMatrix, TransitionMatrix, RandomOrientationTransitionMatrix, @@ -46,7 +47,10 @@ export OrderDegreeIterator, rotate, amplitude_matrix, phase_matrix, scattering_m absorption_cross_section, albedo, asymmetry_parameter, transition_matrix, transition_matrix_m, transition_matrix_m₀, - transition_matrix_iitm + transition_matrix_iitm, prepare_sh, transition_matrix_spectrum, + ShPreparation, + AbstractSolver, AbstractFixedSolver, EBCM, IITM, ShMatrix, + Iterative, ConvergencePolicy # Utility functions (short names) const calc_T = transition_matrix diff --git a/src/common/AbstractTransitionMatrix.jl b/src/common/AbstractTransitionMatrix.jl index 930ce85..d2d735e 100644 --- a/src/common/AbstractTransitionMatrix.jl +++ b/src/common/AbstractTransitionMatrix.jl @@ -54,7 +54,7 @@ function rotate(𝐓::AbstractTransitionMatrix{CT, N}, rot::Rotation{3}) where { # Calculate the coefficients used for wigner-D functions coeff = OffsetArray([cis(-(m * α + m′ * γ)) for m in (-N):N, m′ in (-N):N], (-N):N, - (-N):N) + (-N):N) # Calculate the rotated T-Matrix 𝐓′ = similar(𝐓) @@ -63,8 +63,10 @@ function rotate(𝐓::AbstractTransitionMatrix{CT, N}, rot::Rotation{3}) where { # Enable multi-threading Threads.@threads for (n′, m′) in OrderDegreeIterator(N) for p in 1:2, p′ in 1:2 + for (n, m) in OrderDegreeIterator(N) for m₂ in (-n′):n′, m₁ in (-n):n + sig = iseven(m′ + m₂) ? 1 : -1 𝐓′[m, n, m′, n′, p, p′] += coeff[m, m₁] * d[m, m₁, n] * conj(coeff[m′, m₂]) * d[m₂, m′, n′] * sig * @@ -123,7 +125,7 @@ Where ``` """ function amplitude_matrix(𝐓::AbstractTransitionMatrix{CT, N}, ϑᵢ, φᵢ, ϑₛ, φₛ; - λ = 2π) where {CT, N} + λ = 2π) where {CT, N} T = real(CT) k₁ = 2π / λ 𝐒₁₁, 𝐒₁₂, 𝐒₂₁, 𝐒₂₂ = zero(CT), zero(CT), zero(CT), zero(CT) @@ -134,12 +136,12 @@ function amplitude_matrix(𝐓::AbstractTransitionMatrix{CT, N}, ϑᵢ, φᵢ, τₛ = OffsetArray(zeros(T, 2N + 1, N + 1), (-N):N, 0:N) for m in 0:N wigner_d_recursion!(view(πᵢ, m, m:N), - 0, m, N, ϑᵢ; - deriv = view(τᵢ, m, m:N)) + 0, m, N, ϑᵢ; + deriv = view(τᵢ, m, m:N)) wigner_d_recursion!(view(πₛ, m, m:N), - 0, m, N, ϑₛ; - deriv = view(τₛ, m, m:N)) + 0, m, N, ϑₛ; + deriv = view(τₛ, m, m:N)) end for n in 1:N @@ -156,6 +158,7 @@ function amplitude_matrix(𝐓::AbstractTransitionMatrix{CT, N}, ϑᵢ, φᵢ, end for n′ in 1:N, n in 1:N + αₙ = 1.0im^((n′ - n - 1) & 3) * √(T(2n + 1) * (2n′ + 1) / (n * (n + 1) * n′ * (n′ + 1))) for m′ in (-n′):n′ @@ -218,7 +221,7 @@ Parameters: You may also need to test the convergence of `Nα`, `Nβ` and `Nγ` manually. If any one is too small, there will be large errors in the results. """ function orientation_average(𝐓::AbstractTransitionMatrix{CT, N}, pₒ; Nα = 10, Nβ = 10, - Nγ = 10) where {CT, N} + Nγ = 10) where {CT, N} T̄ = similar(𝐓) fill!(T̄, zero(CT)) @@ -266,7 +269,7 @@ Parameters: - `λ`: the wavelength of the incident wave in the host medium. Default to 2π. """ function scattering_cross_section(𝐓::AbstractTransitionMatrix{CT, N}, - λ = 2π) where {CT, N} + λ = 2π) where {CT, N} return sum(abs2, 𝐓) * λ^2 / 2π end @@ -287,7 +290,7 @@ Parameters: - `λ`: the wavelength of the incident wave in the host medium. Default to 2π. """ function extinction_cross_section(𝐓::AbstractTransitionMatrix{CT, N}, - λ = 2π) where {CT, N} + λ = 2π) where {CT, N} Cᵉˣᵗ = zero(CT) for n in 1:N @@ -415,7 +418,7 @@ Keyword arguments: - `full`: Whether to return the full expansion coefficients (`β₃` to `β₆`). Default to `false`. """ function expansion_coefficients(𝐓::AbstractTransitionMatrix{CT, N}, λ; - full = false) where {CT, N} + full = false) where {CT, N} Cˢᶜᵃ = Float64(scattering_cross_section(𝐓, λ)) λ = Float64(λ) ci = OffsetArray([(1im)^(i & 3) for i in (-N):N], (-N):N) @@ -457,18 +460,19 @@ function expansion_coefficients(𝐓::AbstractTransitionMatrix{CT, N}, λ; A₄ = OffsetArray(zeros(ComplexF64, N, 2N + 1), 1:N, 0:(2N)) B₁ = OffsetArray(zeros(ComplexF64, 2N + 1, 2N + 1, N, 2N + 1), (-N):N, (-N):N, 1:N, - 0:(2N)) + 0:(2N)) B₂ = OffsetArray(zeros(ComplexF64, 2N + 1, 2N + 1, N, 2N + 1), (-N):N, (-N):N, 1:N, - 0:(2N)) + 0:(2N)) B₃ = OffsetArray(zeros(ComplexF64, 2N + 1, 2N + 1, N, 2N + 1), (-N):N, (-N):N, 1:N, - 0:(2N)) + 0:(2N)) B₄ = OffsetArray(zeros(ComplexF64, 2N + 1, 2N + 1, N, 2N + 1), (-N):N, (-N):N, 1:N, - 0:(2N)) + 0:(2N)) Threads.@threads for n₁ in 0:(2N) @debug "n₁ = $n₁..." for n in 1:N, k in (-N):N + for n′ in max(1, abs(n - n₁)):min(n + n₁, N) a₁ = 0.0 a₂ = 0.0 @@ -529,11 +533,11 @@ function expansion_coefficients(𝐓::AbstractTransitionMatrix{CT, N}, λ; d₋₀₋₀ = 0.0 for n₁ in abs(m - 1):(min(n, n′) + N) d₀₀ += (2n₁ + 1) * sum(B₃[k, m, n, n₁] * B₃[k, m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₀₋₀ += (2n₁ + 1) * sum(B₂[k, m, n, n₁] * B₂[k, m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₋₀₋₀ += (2n₁ + 1) * sum(B₁[k, m, n, n₁] * B₁[k, m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) end D₀₀[m, n, n′] = d₀₀ D₀₋₀[m, n, n′] = d₀₋₀ @@ -549,15 +553,15 @@ function expansion_coefficients(𝐓::AbstractTransitionMatrix{CT, N}, λ; for n₁ in abs(m - 1):(min(n, n′) + N) d₂₂ += (2n₁ + 1) * sum(B₁[k, m, n, n₁] * B₃[-k, 2 - m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₂₋₂ += (2n₁ + 1) * sum(B₄[k, m, n, n₁] * B₂[-k, 2 - m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₋₂₋₂ += (2n₁ + 1) * sum(B₃[k, m, n, n₁] * B₁[-k, 2 - m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₀₂ += (2n₁ + 1) * sum(B₂[k, m, n, n₁] * B₃[-k, 2 - m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) d₋₀₂ += (2n₁ + 1) * sum(B₁[k, m, n, n₁] * B₄[-k, 2 - m, n′, n₁]' - for k in max(-N, -n₁):min(N, n₁)) + for k in max(-N, -n₁):min(N, n₁)) end D₂₂[m, n, n′] = d₂₂ @@ -572,9 +576,9 @@ function expansion_coefficients(𝐓::AbstractTransitionMatrix{CT, N}, λ; h_const = λ^2 / (Cˢᶜᵃ * 4 * π) h = OffsetArray([s[l] * h_const * ss[n] / ss[n′] for l in 0:(2N), n in 1:N, n′ in 1:N], - 0:(2N), - 1:N, - 1:N) + 0:(2N), + 1:N, + 1:N) @debug "Calculating g..." g₀₀ = OffsetArray(zeros(ComplexF64, 2N + 1), 0:(2N)) diff --git a/src/common/AxisymmetricTransitionMatrix.jl b/src/common/AxisymmetricTransitionMatrix.jl index d4bd0c7..4256ee0 100644 --- a/src/common/AxisymmetricTransitionMatrix.jl +++ b/src/common/AxisymmetricTransitionMatrix.jl @@ -3,10 +3,11 @@ struct AxisymmetricTransitionMatrix{CT, N, V <: AbstractVector{<:AbstractMatrix{ 𝐓::V end -Base.@propagate_inbounds function Base.getindex(axi::AxisymmetricTransitionMatrix{CT, N, V}, - m::Integer, n::Integer, m′::Integer, - n′::Integer, p::Integer, - p′::Integer) where {CT, N, V} +Base.@propagate_inbounds function Base.getindex( + axi::AxisymmetricTransitionMatrix{CT, N, V}, + m::Integer, n::Integer, m′::Integer, + n′::Integer, p::Integer, + p′::Integer) where {CT, N, V} if m != m′ || abs(m) > min(n, n′) zero(CT) else @@ -36,11 +37,13 @@ Parameters: - `λ`: the wavelength of the incident wave in the host medium. Default to 2π. """ function scattering_cross_section(𝐓::AxisymmetricTransitionMatrix{CT, N, V, T}, - λ = 2π) where {CT, N, V, T} + λ = 2π) where {CT, N, V, T} Cˢᶜᵃ = zero(T) for m in 0:N for p′ in 1:2, p in 1:2 + for n′ in max(m, 1):N, n in max(m, 1):N + if m == 0 Cˢᶜᵃ += abs2(𝐓[m, n, m, n′, p, p′]) else @@ -81,7 +84,7 @@ Parameters: - `λ`: the wavelength of the incident wave in the host medium. Default to 2π. """ function extinction_cross_section(𝐓::AxisymmetricTransitionMatrix{CT, N, V, T}, - λ = 2π) where {CT, N, V, T} + λ = 2π) where {CT, N, V, T} Cᵉˣᵗ = zero(CT) for m in 0:N coeff = m == 0 ? 1 : 2 @@ -113,8 +116,9 @@ end function scattering_efficiency_m₀(T₀) nₘₐₓ = size(T₀, 1) ÷ 2 Qˢᶜᵃ = sum((2n + 1) * - real(T₀[n, n] * T₀[n, n]' + T₀[n + nₘₐₓ, n + nₘₐₓ] * T₀[n + nₘₐₓ, n + nₘₐₓ]') - for n in 1:nₘₐₓ) + real(T₀[n, n] * T₀[n, n]' + + T₀[n + nₘₐₓ, n + nₘₐₓ] * T₀[n + nₘₐₓ, n + nₘₐₓ]') + for n in 1:nₘₐₓ) return Qˢᶜᵃ end @@ -131,7 +135,7 @@ Parameters: - `λ`: The wavelength. """ function expansion_coefficients(𝐓::AxisymmetricTransitionMatrix{CT, N, V, T}, - λ) where {CT, N, V, T} + λ) where {CT, N, V, T} Cˢᶜᵃ = Float64(scattering_cross_section(𝐓, λ)) λ = Float64(λ) @@ -234,9 +238,9 @@ function expansion_coefficients(𝐓::AxisymmetricTransitionMatrix{CT, N, V, T}, h_const = λ^2 / (Cˢᶜᵃ * 4 * π) h = OffsetArray([s[l] * h_const * ss[n] / ss[n′] for l in 0:(2N), n in 1:N, n′ in 1:N], - 0:(2N), - 1:N, - 1:N) + 0:(2N), + 1:N, + 1:N) @debug "Calculating g..." g₀₀ = OffsetArray(zeros(2N + 1), 0:(2N)) diff --git a/src/common/RandomOrientationTransitionMatrix.jl b/src/common/RandomOrientationTransitionMatrix.jl index 8cb2cf4..459fa64 100644 --- a/src/common/RandomOrientationTransitionMatrix.jl +++ b/src/common/RandomOrientationTransitionMatrix.jl @@ -22,12 +22,13 @@ function RandomOrientationTransitionMatrix(𝐓::AbstractTransitionMatrix{CT, N} return RandomOrientationTransitionMatrix{CT, N, typeof(T̄)}(T̄) end -Base.@propagate_inbounds function Base.getindex(oa::RandomOrientationTransitionMatrix{CT, - N, V - }, - m::Integer, n::Integer, m′::Integer, - n′::Integer, p::Integer, - p′::Integer) where {CT, N, V} +Base.@propagate_inbounds function Base.getindex( + oa::RandomOrientationTransitionMatrix{CT, + N, V + }, + m::Integer, n::Integer, m′::Integer, + n′::Integer, p::Integer, + p′::Integer) where {CT, N, V} if m != m′ || n != n′ || abs(m) > n zero(CT) else diff --git a/src/compat/index.jl b/src/compat/index.jl index 8aa5a49..2ea7c36 100644 --- a/src/compat/index.jl +++ b/src/compat/index.jl @@ -4,6 +4,32 @@ Base.round(x::Arb, ::RoundingMode{:Up}) = ceil(BigFloat(x)) Base.abs2(x::AcbLike) = abs2(real(x)) + abs2(imag(x)) Base.complex(::Type{Arb}) = Acb +# Workaround for DoubleFloats v1.9.x: `cbrt` (and thus its alias `∛`) on a +# `Double64` returns the raw `(hi, lo)` component tuple instead of a `Double64` +# (the upstream `cbrt_db_db` forgets to wrap its result; `sqrt` is unaffected). +# This breaks every `∛` call reached with a `Double64` argument, e.g. +# `volume_equivalent_radius` and the Riccati-Bessel term estimators. +# +# The fix is behavior-gated: the guard below calls the upstream `cbrt` before +# our method exists, so it installs the workaround only while upstream is still +# broken. Once a fixed DoubleFloats returns a `Double64` here, this block is +# skipped at load time and the upstream method is used unchanged — no sticky +# shadowing, no dead code. (A package upgrade recompiles this module, so the +# guard is re-evaluated against the new DoubleFloats version.) +if !(cbrt(Double64(8.0)) isa Double64) + # Specialized to `Double64` (more specific than upstream's parametric + # method); recovers full precision with two Newton steps from a Float64 + # seed. `cbrt(Float64(a))` dispatches to Base, so there is no recursion. + function Base.cbrt(x::Double64) + iszero(x) && return x + a = abs(x) + y = Double64(cbrt(Float64(a))) + y = (2y + a / (y * y)) / 3 + y = (2y + a / (y * y)) / 3 + return x < 0 ? -y : y + end +end + function Base.inv(x::Matrix{Arb}) a = ArbMatrix(x) Arblib.inv!(a, a) @@ -23,8 +49,8 @@ Base.precision(::Type{ComplexF128}) = 113 Base.precision(::Type{Complex{Arb}}) = precision(Arb) function Base.precision(::Type{ - Complex{ForwardDiff.Dual{ForwardDiff.Tag{F, T}, - T, N}}}) where {F, T, N} + Complex{ForwardDiff.Dual{ForwardDiff.Tag{F, T}, + T, N}}}) where {F, T, N} precision(T) end @@ -55,7 +81,7 @@ function Base.BigFloat(x::T) where {T <: ForwardDiff.Dual} end function Base.convert(::Type{Complex{ForwardDiff.Dual{ForwardDiff.Tag{F, T}, T, N}}}, - x::AcbLike) where {F, T, N} + x::AcbLike) where {F, T, N} re = ForwardDiff.Dual{ForwardDiff.Tag{F, T}, T, N}(real(x)) im = ForwardDiff.Dual{ForwardDiff.Tag{F, T}, T, N}(imag(x)) return Complex{ForwardDiff.Dual{ForwardDiff.Tag{F, T}, T, N}}(re, im) diff --git a/src/linearization.jl b/src/linearization.jl index d912048..75407c3 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -98,7 +98,7 @@ end function LinearizationResult(value, jacobian, variables; metadata = (;)) vars = Tuple(variables) return LinearizationResult{typeof(value), typeof(jacobian), typeof(vars), - typeof(metadata)}(value, jacobian, vars, metadata) + typeof(metadata)}(value, jacobian, vars, metadata) end variables(result::LinearizationResult) = result.variables @@ -159,7 +159,7 @@ end function Base.showerror(io::IO, err::UnsupportedLinearization) print(io, "Unsupported linearization for output :", err.output, - " with backend ", typeof(err.backend), ": ", err.reason) + " with backend ", typeof(err.backend), ": ", err.reason) end """ @@ -169,11 +169,11 @@ Return a [`LinearizationSupport`](@ref) record describing whether an analytical linearization implementation is available for the requested output. """ function supports_linearization(::LinearizationProblem, - backend::AbstractLinearizationBackend; - output::Symbol = :transition_matrix, - config = nothing) + backend::AbstractLinearizationBackend; + output::Symbol = :transition_matrix, + config = nothing) return LinearizationSupport(false, - "no analytical linearization implementation is registered") + "no analytical linearization implementation is registered") end """ @@ -184,8 +184,8 @@ Backends that do not implement analytical derivatives throw [`UnsupportedLinearization`](@ref). """ function linearize_transition_matrix(problem::LinearizationProblem, - backend::AbstractLinearizationBackend; - config = nothing) + backend::AbstractLinearizationBackend; + config = nothing) support = supports_linearization(problem, backend; output = :transition_matrix, config) throw(UnsupportedLinearization(backend, :transition_matrix, support.reason)) end @@ -198,7 +198,7 @@ The default method only defines the unsupported boundary; analytical backends should add methods that reuse `linearize_transition_matrix`. """ function linearize_observable(observable, problem::LinearizationProblem, - backend::AbstractLinearizationBackend; config = nothing) + backend::AbstractLinearizationBackend; config = nothing) output = observable isa Symbol ? observable : :observable support = supports_linearization(problem, backend; output, config) throw(UnsupportedLinearization(backend, output, support.reason)) diff --git a/src/shapes/chebyshev.jl b/src/shapes/chebyshev.jl index dc8dca2..db36570 100644 --- a/src/shapes/chebyshev.jl +++ b/src/shapes/chebyshev.jl @@ -41,7 +41,7 @@ has_symmetric_plane(c::Chebyshev) = iseven(c.n) @testset "r₀ = $r₀, ε = $ε, n = $n" for (r₀, ε, n, V, rᵥ) in [ (1.0, 0.5, 2, 3.4258319889145845, 0.9351741286290055), (3.0, -1.0, 3, 277.8963101575429, 4.048225756255873), - (5.0, 1.0, 8, 1274.5227007709325, 6.725939997427172), + (5.0, 1.0, 8, 1274.5227007709325, 6.725939997427172) ] c = Chebyshev(r₀, ε, n, 1.5 + 0.01im) @test volume(c) ≈ V diff --git a/src/shapes/cylinder.jl b/src/shapes/cylinder.jl index 115aea8..dfa0c35 100644 --- a/src/shapes/cylinder.jl +++ b/src/shapes/cylinder.jl @@ -24,7 +24,7 @@ has_symmetric_plane(::Cylinder) = true @testset "r = $r, h = $h" for (r, h, V, rᵥ) in [ (2.0, 0.5, 6.283185307179586, 1.1447142425533319), (1.0, 1.0, 3.141592653589793, 0.9085602964160698), - (0.5, 2.0, 1.5707963267948966, 0.7211247851537042), + (0.5, 2.0, 1.5707963267948966, 0.7211247851537042) ] c = Cylinder(r, h, 1.311) @test volume(c) ≈ V diff --git a/src/shapes/prism.jl b/src/shapes/prism.jl index f7035b7..99e9517 100644 --- a/src/shapes/prism.jl +++ b/src/shapes/prism.jl @@ -31,7 +31,7 @@ has_symmetric_plane(::Prism) = true @testset "N = $N, a = $a, h = $h" for (N, a, h, V, rᵥ) in [ (5, 2.0, 3.0, 20.645728807067606, 1.701820965727639), (3, 0.5, 5.0, 0.5412658773652743, 0.5055615227215154), - (20, 2.0, 0.1, 12.627503029350088, 1.4445845221839735), + (20, 2.0, 0.1, 12.627503029350088, 1.4445845221839735) ] p = Prism(N, a, h, 1.311) @test volume(p) ≈ V diff --git a/src/shapes/spheroid.jl b/src/shapes/spheroid.jl index 24559bd..f51df87 100644 --- a/src/shapes/spheroid.jl +++ b/src/shapes/spheroid.jl @@ -24,7 +24,7 @@ has_symmetric_plane(::Spheroid) = true @testset "a = $a, c = $c" for (a, c, V, rᵥ) in [ (1.0, 0.5, 2.0943951023931953, 0.7937005259840998), (1.0, 1.0, 4.1887902047863905, 1.0), - (0.5, 1.0, 1.0471975511965976, 0.6299605249474366), + (0.5, 1.0, 1.0471975511965976, 0.6299605249474366) ] s = Spheroid(a, c, 1.311) @test volume(s) ≈ V diff --git a/src/solvers.jl b/src/solvers.jl new file mode 100644 index 0000000..388fed6 --- /dev/null +++ b/src/solvers.jl @@ -0,0 +1,306 @@ +# ── Two-layer solver API ────────────────────────────────────────────────────── +# +# The T-matrix of an axisymmetric scatterer can be obtained by several methods +# (classic EBCM, the cancellation-free `stable` EBCM, the Sh-matrix moment +# separation, IITM), each with its own discretization knobs. This file unifies +# them behind one verb, `transition_matrix(s, λ, solver)`, organized into two +# clearly separated layers: +# +# • Fixed solution — a solver carrying an explicit discretization; one build. +# transition_matrix(s, λ, EBCM(nₘₐₓ, Ng; stable)) +# transition_matrix(s, λ, IITM(nₘₐₓ, Nr, Nϑ)) +# transition_matrix(s, λ, ShMatrix(nₘₐₓ, Ng)) +# +# • Iterative solver — wraps a method + convergence policy and sweeps the +# discretization until the scattering/extinction efficiencies stabilize. +# transition_matrix(s, λ, Iterative(EBCM; stable, threshold, …)) +# +# Each fixed solver dispatches to the underlying implementation unchanged; the +# iterative driver reuses `routine_mishchenko` and the `m=0` efficiency probes. + +""" + AbstractSolver + +Supertype of every T-matrix solver. A solver is either a fixed-discretization +solver ([`EBCM`](@ref), [`IITM`](@ref), [`ShMatrix`](@ref) — subtypes of +`AbstractFixedSolver`) or an [`Iterative`](@ref) wrapper that converges one. +""" +abstract type AbstractSolver end + +"Supertype of fixed-discretization solvers (one build, no iteration)." +abstract type AbstractFixedSolver <: AbstractSolver end + +# ── Fixed solvers ───────────────────────────────────────────────────────────── +""" + EBCM(nₘₐₓ, Ng; stable = false) + +Fixed-discretization Extended Boundary Condition Method solver: truncation order +`nₘₐₓ` and `Ng` Gauss–Legendre quadrature points. `stable = true` assembles the +`𝐔` matrix with the cancellation-free `F⁺` formulation (spheroids only). Used as +`transition_matrix(s, λ, EBCM(nₘₐₓ, Ng))`. +""" +struct EBCM <: AbstractFixedSolver + nₘₐₓ::Int + Ng::Int + stable::Bool +end +EBCM(nₘₐₓ::Integer, Ng::Integer; stable::Bool = false) = EBCM(Int(nₘₐₓ), Int(Ng), stable) + +""" + IITM(nₘₐₓ, Nr, Nϑ; rₘᵢₙ = nothing) + IITM(nₘₐₓ, Nr, Nϑ, Nφ; rₘᵢₙ = nothing) + +Fixed-discretization invariant-imbedding (IITM) solver: order `nₘₐₓ`, `Nr` radial +and `Nϑ` zenithal quadrature points (plus `Nφ` azimuthal points for arbitrary / +N-fold shapes). `rₘᵢₙ` defaults to `rmin(s)` when left `nothing`. +""" +struct IITM{F} <: AbstractFixedSolver + nₘₐₓ::Int + Nr::Int + Nϑ::Int + Nφ::Union{Nothing, Int} + rₘᵢₙ::F +end +function IITM(nₘₐₓ::Integer, Nr::Integer, Nϑ::Integer; rₘᵢₙ = nothing) + IITM(Int(nₘₐₓ), Int(Nr), Int(Nϑ), nothing, rₘᵢₙ) +end +function IITM(nₘₐₓ::Integer, Nr::Integer, Nϑ::Integer, Nφ::Integer; rₘᵢₙ = nothing) + IITM(Int(nₘₐₓ), Int(Nr), Int(Nϑ), Int(Nφ), rₘᵢₙ) +end + +""" + ShMatrix(nₘₐₓ, Ng; B = nothing, momtype = nothing, store = nothing) + +Fixed-discretization Sh-matrix (moment-separation) solver. `B` is the number of +radial power-series terms; `momtype`/`store` control the moment precision (see +[`prepare_sh`](@ref); `nothing` selects the defaults). As a single build, +`transition_matrix(s, λ, ShMatrix(nₘₐₓ, Ng))`; for a parameter sweep, +`transition_matrix(s, λs, mᵣs, ShMatrix(nₘₐₓ, Ng))` prepares once and reuses. +""" +struct ShMatrix <: AbstractFixedSolver + nₘₐₓ::Int + Ng::Int + B::Union{Nothing, Int} + momtype::Union{Nothing, Type} + store::Union{Nothing, Type} +end +function ShMatrix(nₘₐₓ::Integer, Ng::Integer; B = nothing, momtype = nothing, + store = nothing) + ShMatrix(Int(nₘₐₓ), Int(Ng), B, momtype, store) +end + +# ── Fixed dispatch (thin shims over the existing implementations) ───────────── +function transition_matrix(s::AbstractAxisymmetricShape, λ, slv::EBCM) + return transition_matrix(s, λ, slv.nₘₐₓ, slv.Ng; stable = slv.stable) +end + +function transition_matrix(s::AbstractShape, λ, slv::IITM) + rₘᵢₙ = slv.rₘᵢₙ === nothing ? rmin(s) : slv.rₘᵢₙ + if slv.Nφ === nothing + return transition_matrix_iitm(s, λ, slv.nₘₐₓ, slv.Nr, slv.Nϑ; rₘᵢₙ) + else + return transition_matrix_iitm(s, λ, slv.nₘₐₓ, slv.Nr, slv.Nϑ, slv.Nφ; rₘᵢₙ) + end +end + +function transition_matrix(s::AbstractAxisymmetricShape{T}, λ, slv::ShMatrix) where {T} + B = slv.B === nothing ? max(30, slv.nₘₐₓ + 15) : slv.B + store = slv.store === nothing ? T : slv.store + prep = prepare_sh(s, slv.nₘₐₓ, slv.Ng; B, momtype = slv.momtype, store) + return transition_matrix(prep, λ) +end + +# Sh-matrix parameter sweep: prepare once, reconstruct at each (λ, mᵣ). +function transition_matrix(s::AbstractAxisymmetricShape{T}, λs::AbstractVector, mᵣs, + slv::ShMatrix) where {T} + B = slv.B === nothing ? max(30, slv.nₘₐₓ + 15) : slv.B + store = slv.store === nothing ? T : slv.store + prep = prepare_sh(s, slv.nₘₐₓ, slv.Ng; B, momtype = slv.momtype, store) + return transition_matrix_spectrum(prep, λs, mᵣs) +end + +# ── Iterative solver ────────────────────────────────────────────────────────── +""" + ConvergencePolicy(; threshold, ndgs, maxiter, nₘₐₓ_only, nₛₜₐᵣₜ, Ngₛₜₐᵣₜ, routine_generator) + +Convergence settings for an [`Iterative`](@ref) solver. `threshold` is the +relative `Qsca`/`Qext` tolerance, `ndgs` the quadrature points added per order, +`nₛₜₐᵣₜ`/`Ngₛₜₐᵣₜ` the starting resolution (`0` ⇒ auto from `k·rₘₐₓ`), +`nₘₐₓ_only` stops once `nₘₐₓ` converges, and `routine_generator` builds the +stepping routine (default `routine_mishchenko`). +""" +struct ConvergencePolicy{G} + threshold::Float64 + ndgs::Int + maxiter::Int + nₘₐₓ_only::Bool + nₛₜₐᵣₜ::Int + Ngₛₜₐᵣₜ::Int + routine_generator::G +end +function ConvergencePolicy(; threshold = 1.0e-4, ndgs = 4, maxiter = 20, + nₘₐₓ_only = false, nₛₜₐᵣₜ = 0, Ngₛₜₐᵣₜ = 0, + routine_generator = routine_mishchenko) + ConvergencePolicy(Float64(threshold), Int(ndgs), Int(maxiter), nₘₐₓ_only, + Int(nₛₜₐᵣₜ), Int(Ngₛₜₐᵣₜ), routine_generator) +end + +""" + Iterative(EBCM; stable = false, threshold = 1e-4, ndgs = 4, maxiter = 20, …) + +Iterative solver that sweeps the discretization of a fixed-solver method until +convergence. Currently the EBCM method is supported, including `stable = true`: + +```julia +transition_matrix(s, λ, Iterative(EBCM)) # classic, auto-converged +transition_matrix(s, λ, Iterative(EBCM; stable = true)) # stabilized + auto-converged +``` + +The non-resolution method options (e.g. `stable`) and the [`ConvergencePolicy`](@ref) +keywords are passed together; the method is named by its fixed-solver type. +""" +struct Iterative{F <: AbstractFixedSolver, O <: NamedTuple, P <: ConvergencePolicy} <: + AbstractSolver + opts::O + policy::P +end + +function Iterative(::Type{EBCM}; stable::Bool = false, kwargs...) + opts = (; stable) + policy = ConvergencePolicy(; kwargs...) + return Iterative{EBCM, typeof(opts), typeof(policy)}(opts, policy) +end + +# Generic driver: resolution-agnostic. Each method provides the four hooks below. +function transition_matrix(s::AbstractAxisymmetricShape, λ, it::Iterative) + pol = it.policy + routine = pol.routine_generator(pol.threshold, pol.ndgs, pol.nₘₐₓ_only) + fixed = _solver_initial(it, s, λ) + for _ in 1:(pol.maxiter) + pr = _solver_probe(it, s, λ, fixed) + nxt = _solver_step(it, fixed, pr.Qsca, pr.Qext, routine) + nxt === nothing && return _solver_assemble(it, s, λ, fixed, pr.state) + fixed = nxt + end + error("transition_matrix: failed to converge in $(pol.maxiter) iterations") +end + +# ── Iterative interface — EBCM specialization (cheap m=0 probe) ─────────────── +function _solver_initial(it::Iterative{EBCM}, s, λ) + it.opts.stable && !(s isa Spheroid) && + throw(ArgumentError("Iterative(EBCM; stable=true) is only valid for spheroids: the \ + cancellation-free F⁺ integrands rely on the spheroid surface making \ + the divergent Laurent terms integrate to zero (Somerville et al. 2013).")) + pol = it.policy + nₛₜₐᵣₜ = pol.nₛₜₐᵣₜ + if nₛₜₐᵣₜ == 0 + kr = 2π * rmax(s) / λ + nₛₜₐᵣₜ = max(4, ceil(Int, kr + 4.05 * ∛kr)) + end + Ng = pol.Ngₛₜₐᵣₜ == 0 ? nₛₜₐᵣₜ * pol.ndgs : pol.Ngₛₜₐᵣₜ + return EBCM(nₛₜₐᵣₜ, Ng; stable = it.opts.stable) +end + +function _solver_probe(it::Iterative{EBCM}, s, λ, f::EBCM) + T₀, + cache = transition_matrix_m₀(s, λ, f.nₘₐₓ, f.Ng; reuse = true, + stable = it.opts.stable) + return (; Qsca = scattering_efficiency_m₀(T₀), Qext = extinction_efficiency_m₀(T₀), + state = (; T₀, cache)) +end + +function _solver_step(it::Iterative{EBCM}, f::EBCM, Qsca, Qext, routine) + nₘₐₓ′, Ng′ = routine(f.nₘₐₓ, f.Ng, Qsca, Qext) + return nₘₐₓ′ == -1 ? nothing : EBCM(nₘₐₓ′, Ng′; stable = f.stable) +end + +function _solver_assemble(it::Iterative{EBCM}, s::AbstractAxisymmetricShape{T, CT}, λ, + f::EBCM, state) where {T, CT} + 𝐓 = Vector{Matrix{CT}}(undef, f.nₘₐₓ + 1) + 𝐓[1] = state.T₀ + for m in 1:(f.nₘₐₓ) + 𝐓[m + 1] = transition_matrix_m(m, s, λ, f.nₘₐₓ, f.Ng; cache = state.cache, + stable = it.opts.stable) + end + return AxisymmetricTransitionMatrix{CT, f.nₘₐₓ, typeof(𝐓), T}(𝐓) +end + +# ── Iterative interface — generic fallback (extensibility seam) ─────────────── +# Any iterable method without a cheap probe can converge via a full-T build and +# the decoupled cross-section probes. Not exercised in v1 (only EBCM is iterable); +# this is where `Iterative(IITM)` for axisymmetric shapes will plug in. +function _solver_probe(it::Iterative, s, λ, fixed::AbstractFixedSolver) + 𝐓 = transition_matrix(s, λ, fixed) + return (; Qsca = scattering_cross_section(𝐓, λ), Qext = extinction_cross_section(𝐓, λ), + state = (; 𝐓)) +end +_solver_assemble(::Iterative, s, λ, ::AbstractFixedSolver, state) = state.𝐓 + +# ── Bare entry: no solver ⇒ auto-converged classic EBCM ─────────────────────── +""" + transition_matrix(s::AbstractAxisymmetricShape, λ) + +Compute the T-matrix of an axisymmetric scatterer at wavelength `λ`, automatically +converging the truncation order and quadrature with classic EBCM. Equivalent to +`transition_matrix(s, λ, Iterative(EBCM))`. For a stabilized or fixed build, or +another method, pass an explicit solver (see [`AbstractSolver`](@ref)). +""" +function transition_matrix(s::AbstractAxisymmetricShape, λ) + transition_matrix(s, λ, Iterative(EBCM)) +end + +@testitem "Fixed solver dispatch matches the underlying implementations" begin + using TransitionMatrices: Spheroid, Cylinder, transition_matrix_iitm, prepare_sh, + calc_Csca + λ = 2π + s = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + + # EBCM fixed solver === the 4-arg call (same computation) + @test transition_matrix(s, λ, EBCM(8, 64)).𝐓 == transition_matrix(s, λ, 8, 64).𝐓 + + # EBCM stable fixed solver === the 4-arg stable call + sp = Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im) + @test transition_matrix(sp, λ, EBCM(20, 240; stable = true)).𝐓 == + transition_matrix(sp, λ, 20, 240; stable = true).𝐓 + + # ShMatrix fixed solver === prepare_sh + assemble + prep = prepare_sh(s, 8, 64) + @test calc_Csca(transition_matrix(s, λ, ShMatrix(8, 64))) ≈ + calc_Csca(transition_matrix(prep, λ)) + + # IITM fixed solver === transition_matrix_iitm + c = Cylinder{Float64, ComplexF64}(1.0, 2.0, 1.5 + 0.02im) + @test transition_matrix(c, λ, IITM(6, 16, 20)).𝐓 == + transition_matrix_iitm(c, λ, 6, 16, 20).𝐓 +end + +@testitem "Iterative(EBCM) auto-converges and equals the bare call" begin + using TransitionMatrices: Spheroid, calc_Csca, calc_Cext + λ = 2π + s = Spheroid{Float64, ComplexF64}(2.0, 1.0, 1.5 + 0.02im) + + Ti = transition_matrix(s, λ, Iterative(EBCM)) + Tb = transition_matrix(s, λ) # bare === Iterative(EBCM) + @test calc_Csca(Ti) == calc_Csca(Tb) + + Tf = transition_matrix(s, λ, EBCM(16, 200)) # high-resolution reference + @test calc_Csca(Ti)≈calc_Csca(Tf) rtol=1e-3 + @test calc_Cext(Ti)≈calc_Cext(Tf) rtol=1e-3 + + Tt = transition_matrix(s, λ, Iterative(EBCM; threshold = 1e-7)) + @test calc_Csca(Tt)≈calc_Csca(Tf) rtol=1e-5 +end + +@testitem "Iterative(EBCM; stable=true) converges a high-aspect spheroid" begin + using TransitionMatrices: Spheroid, Cylinder, calc_Csca + λ = 2π + sp = Spheroid{Float64, ComplexF64}(2.5198421, 10.079368, 1.55 + 0.01im) + + Tst = transition_matrix(sp, λ, Iterative(EBCM; stable = true, threshold = 1e-6)) + Tref = transition_matrix(sp, λ, EBCM(28, 400; stable = true)) + @test calc_Csca(Tst)≈calc_Csca(Tref) rtol=1e-3 + + # stable iterative is gated to spheroids + c = Cylinder{Float64, ComplexF64}(1.0, 2.0, 1.5 + 0.02im) + @test_throws ArgumentError transition_matrix(c, λ, Iterative(EBCM; stable = true)) +end diff --git a/src/special_functions/bessel.jl b/src/special_functions/bessel.jl index bdc2335..593e412 100644 --- a/src/special_functions/bessel.jl +++ b/src/special_functions/bessel.jl @@ -86,7 +86,7 @@ end using GSL: sf_bessel_jl_array @testset "x = $x, n ∈ [1, $n]" for x in (0.01, 0.1, 1.0, 10.0, 100.0, 1000.0), - n in (40,) + n in (40,) ψ, ψ′ = ricattibesselj(n, estimate_ricattibesselj_extra_terms(n, x), x) @@ -117,7 +117,9 @@ In-place version of [`ricattibessely`](@ref). function ricattibessely!(χ, χ′, nₘₐₓ, x) x⁻¹ = one(x) / x χ[1] = -cos(x) * x⁻¹ - sin(x) - χ[2] = (-3x⁻¹^2 + 1) * cos(x) - 3x⁻¹ * sin(x) + if nₘₐₓ ≥ 2 + χ[2] = (-3x⁻¹^2 + 1) * cos(x) - 3x⁻¹ * sin(x) + end for n in 2:(nₘₐₓ - 1) χ[n + 1] = (2n + 1) * x⁻¹ * χ[n] - χ[n - 1] end @@ -167,6 +169,7 @@ end using GSL: sf_bessel_yl_array @testset "x = $x, n ∈ [1, $n]" for x in (0.1, 1.0, 10.0, 100.0), n in (40,) + χ, χ′ = ricattibessely(n, x) y = sf_bessel_yl_array(n, x) @@ -178,3 +181,15 @@ end @test all(χ′ .≈ χ₁′) end end + +@testitem "Ricatti-Bessel χ handles nₘₐₓ = 1 without out-of-bounds write" begin + using TransitionMatrices: ricattibessely + + for x in (0.1, 1.0, 10.0) + χ₁, χ₁′ = ricattibessely(1, x) # used to throw BoundsError (wrote χ[2]) + χ₂, χ₂′ = ricattibessely(2, x) + @test length(χ₁) == 1 && length(χ₁′) == 1 + @test χ₁[1] ≈ χ₂[1] + @test χ₁′[1] ≈ χ₂′[1] + end +end diff --git a/src/special_functions/quadrature.jl b/src/special_functions/quadrature.jl index e1bd751..6af924d 100644 --- a/src/special_functions/quadrature.jl +++ b/src/special_functions/quadrature.jl @@ -26,14 +26,14 @@ end function gausslegendre!(x, w, n::Integer) for i in 1:(n ÷ 2) Arblib.hypgeom_legendre_p_ui_root!(x[n + 1 - i], w[n + 1 - i], UInt64(n), - UInt64(i - 1)) + UInt64(i - 1)) x[i] = -x[n + 1 - i] w[i] = w[n + 1 - i] end if n % 2 == 1 Arblib.hypgeom_legendre_p_ui_root!(x[n ÷ 2 + 1], w[n ÷ 2 + 1], UInt64(n), - UInt64(n ÷ 2)) + UInt64(n ÷ 2)) end end diff --git a/src/special_functions/wignerd.jl b/src/special_functions/wignerd.jl index 5fa1fb8..68b150b 100644 --- a/src/special_functions/wignerd.jl +++ b/src/special_functions/wignerd.jl @@ -1,8 +1,9 @@ const WIGNER_D_EPS = 1e-12 _wigner_sqrt_constant(::Type{T}, x) where {T} = √T(x) -_wigner_sqrt_constant(::Type{T}, x) where {T <: ForwardDiff.Dual} = +function _wigner_sqrt_constant(::Type{T}, x) where {T <: ForwardDiff.Dual} T(sqrt(ForwardDiff.value(x))) +end @doc raw""" ``` @@ -88,7 +89,7 @@ where ``` """ function wigner_d_recursion(::Type{T}, m::Integer, n::Integer, sₘₐₓ::Integer, ϑ::Number; - deriv::Bool = false) where {T} + deriv::Bool = false) where {T} sₘₐₓ >= max(abs(m), abs(n)) || error("Error: sₘₐₓ < max(|m|, |n|)") sₘᵢₙ = max(abs(m), abs(n)) @@ -99,7 +100,7 @@ function wigner_d_recursion(::Type{T}, m::Integer, n::Integer, sₘₐₓ::Integ end @inline function wigner_d_recursion(m::Integer, n::Integer, sₘₐₓ::Integer, ϑ::Number; - deriv::Bool = false) + deriv::Bool = false) return wigner_d_recursion(Float64, m, n, sₘₐₓ, ϑ; deriv) end @@ -111,7 +112,7 @@ wigner_d_recursion!(d::AbstractVector{T}, m::Integer, n::Integer, sₘₐₓ::In Calculate the Wigner d-function recursively, in place. """ function wigner_d_recursion!(d::AbstractVector{T}, m::Integer, n::Integer, sₘₐₓ::Integer, - ϑ::Number; deriv = nothing) where {T} + ϑ::Number; deriv = nothing) where {T} sₘₐₓ >= max(abs(m), abs(n)) || error("Error: sₘₐₓ < max(|m|, |n|)") sₘᵢₙ = max(abs(m), abs(n)) @@ -124,8 +125,8 @@ function wigner_d_recursion!(d::AbstractVector{T}, m::Integer, n::Integer, sₘ end function _wigner_d_recursion_core!(d::AbstractVector{T}, m::Integer, n::Integer, - sₘₐₓ::Integer, ϑ::Number; - deriv = nothing) where {T} + sₘₐₓ::Integer, ϑ::Number; + deriv = nothing) where {T} sₘₐₓ >= max(abs(m), abs(n)) || error("Error: sₘₐₓ < max(|m|, |n|)") ϑ = T(ϑ) cosϑ = cos(ϑ) @@ -158,9 +159,9 @@ function _wigner_d_recursion_core!(d::AbstractVector{T}, m::Integer, n::Integer, else normalization = abs(m) == sₘᵢₙ && abs(n) == sₘᵢₙ ? one(T) : _wigner_sqrt_constant(T, - factorial(T, 2sₘᵢₙ) / - factorial(T, abs(m - n)) / - factorial(T, abs(m + n))) + factorial(T, 2sₘᵢₙ) / + factorial(T, abs(m - n)) / + factorial(T, abs(m + n))) d₁ = sig * T(2)^(-sₘᵢₙ) * normalization * (1 - cosϑ)^(abs(m - n) / 2) * (1 + cosϑ)^(abs(m + n) / 2) d[d_offset + sₘᵢₙ] = d₁ @@ -213,7 +214,7 @@ end # Workaround to avoid NaNs in ForwardDiff function wigner_d_recursion!(d::AbstractVector{T}, m::Integer, n::Integer, sₘₐₓ::Integer, - ϑ::Number; deriv = nothing) where {T <: ForwardDiff.Dual} + ϑ::Number; deriv = nothing) where {T <: ForwardDiff.Dual} if !(ϑ isa ForwardDiff.Dual) || iszero(ForwardDiff.partials(ϑ)) dv = map(ForwardDiff.value, d) wigner_d_recursion!(dv, m, n, sₘₐₓ, ForwardDiff.value(ϑ); deriv = deriv) @@ -236,8 +237,7 @@ end using TransitionMatrices: wigner_d, wigner_d_recursion, wigner_d_recursion! @testset "d($m, $m′, $n, $ϑ) is correct" for m in -2:2, m′ in -2:2, n in (5,), - ϑ in (-2e-4, 2e-4, 0.5, π - 2e-4, π + 2e-4) - + ϑ in (-2e-4, 2e-4, 0.5, π - 2e-4, π + 2e-4) d₁ = [wigner_d(m, m′, n, ϑ) for n in max(abs(m′), abs(m)):n] d₂ = wigner_d_recursion(m, m′, n, ϑ) @test all(d₁ .≈ collect(d₂)) @@ -319,12 +319,12 @@ where This function easily overflows for large values of `s`, and it is no faster than the recursive method. It is provided here only for checking the correctness of the recursive method. Users are recommended to use `wigner_D_recursion` instead. """ @inline function wigner_D(::Type{T}, m::Integer, m′::Integer, n::Integer, α::Number, - β::Number, γ::Number) where {T} + β::Number, γ::Number) where {T} return cis(-(m * T(α) + m′ * T(γ))) * wigner_d(T, m, m′, n, β) end @inline function wigner_D(m::Integer, m′::Integer, n::Integer, α::Number, β::Number, - γ::Number) + γ::Number) return wigner_D(Float64, m, m′, n, α, β, γ) end @@ -336,14 +336,14 @@ wigner_D_recursion([T=Float64,], m::Integer, m′::Integer, nmax::Integer, α::N Calculate the Wigner D-function recursively (use `wigner_d_recursion`). """ function wigner_D_recursion(::Type{T}, m::Integer, m′::Integer, nmax::Integer, α::Number, - β::Number, - γ::Number) where {T} + β::Number, + γ::Number) where {T} d = wigner_d_recursion(T, m, m′, nmax, β) return cis(-(m * T(α) + m′ * T(γ))) * d end @inline function wigner_D_recursion(m::Integer, m′::Integer, nmax::Integer, α::Number, - β::Number, γ::Number) + β::Number, γ::Number) return wigner_D_recursion(Float64, m, m′, nmax, α, β, γ) end @@ -355,8 +355,8 @@ wigner_D_recursion!(d::AbstractVector{CT}, m::Integer, m′::Integer, nmax::Inte Calculate the Wigner D-function recursively, in place. """ function wigner_D_recursion!(d::AbstractVector{CT}, m::Integer, m′::Integer, nmax::Integer, - α::Number, β::Number, - γ::Number) where {CT} + α::Number, β::Number, + γ::Number) where {CT} T = real(CT) α = T(α) β = T(β) @@ -395,7 +395,7 @@ Calculate - If `d` is given, it is used as the value of ``d_{0 m}^n(\vartheta)``. """ function pi_func(::Type{T}, m::Integer, n::Integer, ϑ::Number; - d = nothing) where {T} + d = nothing) where {T} ϑ = T(ϑ) cosϑ = cos(ϑ) @@ -412,7 +412,7 @@ function pi_func(::Type{T}, m::Integer, n::Integer, ϑ::Number; end @inline function pi_func(m::Integer, n::Integer, ϑ::Number; - d = nothing) + d = nothing) return pi_func(Float64, m, n, ϑ; d = d) end diff --git a/test/compat.jl b/test/compat.jl index 41ecc62..58f5d04 100644 --- a/test/compat.jl +++ b/test/compat.jl @@ -60,3 +60,28 @@ @test Float64(abs(real(AcbI[2, 1]))) < 1e-30 @test Float64(abs(real(AcbI[2, 2] - 1))) < 1e-30 end + +@testitem "cbrt on Double64 returns a Double64 (DoubleFloats v1.9 workaround)" begin + using TransitionMatrices + + # Upstream DoubleFloats returns a (hi, lo) tuple here; ensure our shim wraps it. + @test cbrt(Double64(8.0)) isa Double64 + @test ∛(Double64(8.0)) isa Double64 + + @test cbrt(Double64(8.0)) ≈ Double64(2.0) + @test cbrt(Double64(27.0)) ≈ Double64(3.0) + @test cbrt(Double64(-8.0)) ≈ Double64(-2.0) + @test iszero(cbrt(zero(Double64))) + + # Full-precision check: the Newton refinement must beat Float64 accuracy. + x = Double64(2.0) + y = cbrt(x) + @test abs(y * y * y - x) < Double64(1e-30) + + # The bug surfaced through shape utilities; verify the realistic call path. + s = Spheroid(Double64(2.0), Double64(1.0), Complex{Double64}(Double64(1.5), + Double64(0.02))) + @test volume_equivalent_radius(s) isa Double64 + @test TransitionMatrices.transition_matrix_m₀(s, 2 * Double64(π), 6, 24) isa + Matrix{Complex{Double64}} +end diff --git a/test/linearization.jl b/test/linearization.jl index 25bfba3..2f656fc 100644 --- a/test/linearization.jl +++ b/test/linearization.jl @@ -1,6 +1,6 @@ @testitem "Linearization framework" begin problem = LinearizationProblem([2.0, 3.0, 1.311, 0.02, 2π]; - variables = (:a, :c, :mᵣ, :mᵢ, :λ)) do x + variables = (:a, :c, :mᵣ, :mᵢ, :λ)) do x (; shape = Spheroid(x[1], x[2], complex(x[3], x[4])), λ = x[5]) end @@ -20,7 +20,7 @@ value = [1.0 2.0; 3.0 4.0] jacobian = reshape(collect(1.0:12.0), 2, 2, 3) matrix_result = LinearizationResult(value, jacobian, (:a, :c, :λ)) - @test derivative(matrix_result, :c) == view(jacobian, :, :, 2) + @test derivative(matrix_result, :c) == view(jacobian,:,:,2) @test_throws BoundsError derivative(matrix_result, 0) @test_throws BoundsError derivative(matrix_result, 4) @test_throws ArgumentError derivative(matrix_result, :unknown) @@ -36,11 +36,11 @@ @test err isa UnsupportedLinearization @test occursin("Unsupported linearization", sprint(showerror, err)) @test_throws UnsupportedLinearization linearize_observable(scattering_cross_section, - problem, - IITMLinearization()) + problem, + IITMLinearization()) @test_throws UnsupportedLinearization linearize_observable(:scattering_cross_section, - problem, - EBCMLinearization()) + problem, + EBCMLinearization()) @test_throws ArgumentError LinearizationProblem([1.0]; variables = ("x",)) do x x end @@ -59,11 +59,11 @@ end @test Bool(supports_linearization(base_problem, IITMLinearization(); config)) @test Bool(supports_linearization(base_problem, IITMLinearization(:auto); config)) @test Bool(supports_linearization(base_problem, IITMLinearization(:axisymmetric); - config)) + config)) unsupported_output = supports_linearization(base_problem, - IITMLinearization(:axisymmetric); - output = :observable, config) + IITMLinearization(:axisymmetric); + output = :observable, config) @test !Bool(unsupported_output) @test occursin("only supports transition matrices", unsupported_output.reason) @@ -75,18 +75,18 @@ end (; shape = Spheroid(x[1], 1.2, 1.311 + 0.02im), λ = 2π) end geometry_support = supports_linearization(geometry_problem, - IITMLinearization(:axisymmetric); - config) + IITMLinearization(:axisymmetric); + config) @test !Bool(geometry_support) @test occursin("fixed-geometry", geometry_support.reason) duplicate_problem = LinearizationProblem([1.311, 1.4]; - variables = (:mᵣ, :mᵣ)) do x + variables = (:mᵣ, :mᵣ)) do x (; shape = Spheroid(0.9, 1.2, complex(x[1], 0.02)), λ = 2π) end duplicate_support = supports_linearization(duplicate_problem, - IITMLinearization(:axisymmetric); - config) + IITMLinearization(:axisymmetric); + config) @test !Bool(duplicate_support) @test occursin("unique canonical variables", duplicate_support.reason) @@ -94,19 +94,19 @@ end (; shape = Prism(5, 0.8, 1.1, complex(x[1], 0.02)), λ = 2π) end axisymmetric_support = supports_linearization(prism_problem, - IITMLinearization(:axisymmetric); - config) + IITMLinearization(:axisymmetric); + config) @test !Bool(axisymmetric_support) @test occursin("requires an axisymmetric shape", axisymmetric_support.reason) nfold_missing_phi = supports_linearization(prism_problem, - IITMLinearization(:nfold); config) + IITMLinearization(:nfold); config) @test !Bool(nfold_missing_phi) @test occursin("requires Nφ", nfold_missing_phi.reason) arbitrary_missing_phi = supports_linearization(prism_problem, - IITMLinearization(:arbitrary); - config) + IITMLinearization(:arbitrary); + config) @test !Bool(arbitrary_missing_phi) @test occursin("requires Nφ", arbitrary_missing_phi.reason) end @@ -143,8 +143,8 @@ end ∂b = coefficient_jacobian[(2N + 1):(3N), j] .+ coefficient_jacobian[(3N + 1):(4N), j] .* im - @test ∂T.a ≈ ∂a atol=1e-9 rtol=1e-9 - @test ∂T.b ≈ ∂b atol=1e-9 rtol=1e-9 + @test ∂T.a≈∂a atol=1e-9 rtol=1e-9 + @test ∂T.b≈∂b atol=1e-9 rtol=1e-9 end subset_x₀ = [x₀[2], x₀[1]] @@ -170,8 +170,8 @@ end ∂b = subset_coefficient_jacobian[(2N + 1):(3N), j] .+ subset_coefficient_jacobian[(3N + 1):(4N), j] .* im - @test ∂T.a ≈ ∂a atol=1e-9 rtol=1e-9 - @test ∂T.b ≈ ∂b atol=1e-9 rtol=1e-9 + @test ∂T.a≈∂a atol=1e-9 rtol=1e-9 + @test ∂T.b≈∂b atol=1e-9 rtol=1e-9 end function mie_scattering(x) @@ -211,24 +211,25 @@ end Cabs = linearize_observable(absorption_cross_section, problem, MieLinearization()) ω = linearize_observable(albedo, problem, MieLinearization()) S = linearize_observable(amplitude_matrix, problem, MieLinearization(); - config = (; angles)) + config = (; angles)) @test Csca.value ≈ mie_scattering(x₀) @test Cext.value ≈ mie_extinction(x₀) @test Cabs.value ≈ mie_absorption(x₀) @test ω.value ≈ mie_albedo(x₀) @test S.value ≈ amplitude_matrix(reference, angles...; λ = x₀[4]) - @test Csca.jacobian ≈ ForwardDiff.gradient(mie_scattering, x₀) atol=1e-8 rtol=1e-8 - @test Cext.jacobian ≈ ForwardDiff.gradient(mie_extinction, x₀) atol=1e-8 rtol=1e-8 - @test Cabs.jacobian ≈ ForwardDiff.gradient(mie_absorption, x₀) atol=1e-8 rtol=1e-8 - @test ω.jacobian ≈ ForwardDiff.gradient(mie_albedo, x₀) atol=1e-8 rtol=1e-8 + @test Csca.jacobian≈ForwardDiff.gradient(mie_scattering, x₀) atol=1e-8 rtol=1e-8 + @test Cext.jacobian≈ForwardDiff.gradient(mie_extinction, x₀) atol=1e-8 rtol=1e-8 + @test Cabs.jacobian≈ForwardDiff.gradient(mie_absorption, x₀) atol=1e-8 rtol=1e-8 + @test ω.jacobian≈ForwardDiff.gradient(mie_albedo, x₀) atol=1e-8 rtol=1e-8 amplitude_jacobian = ForwardDiff.jacobian(mie_amplitude_vector, x₀) for (j, var) in enumerate(vars) ∂S = derivative(S, var) - ∂S_ref = reshape(amplitude_jacobian[1:4, j] .+ - amplitude_jacobian[5:8, j] .* im, 2, 2) - @test ∂S ≈ ∂S_ref atol=1e-8 rtol=1e-8 + ∂S_ref = reshape( + amplitude_jacobian[1:4, j] .+ + amplitude_jacobian[5:8, j] .* im, 2, 2) + @test ∂S≈∂S_ref atol=1e-8 rtol=1e-8 end end @@ -249,7 +250,7 @@ end ∂𝐓_fd = (𝐓_from_𝐏_and_𝐔(𝐏 .+ ϵ .* ∂𝐏, 𝐔 .+ ϵ .* ∂𝐔) - 𝐓_from_𝐏_and_𝐔(𝐏 .- ϵ .* ∂𝐏, 𝐔 .- ϵ .* ∂𝐔)) ./ (2ϵ) - @test ∂𝐓 ≈ ∂𝐓_fd atol=1e-9 rtol=1e-8 + @test ∂𝐓≈∂𝐓_fd atol=1e-9 rtol=1e-8 end @testitem "EBCM block assembly exposes P-U matrices" begin @@ -277,19 +278,19 @@ end function test_matrix(n, offset; scale = 1.0) [scale * ((i == j ? 1.5 + offset : 0.03 * (i + j + offset)) + - 0.02im * (i - j + offset)) for i in 1:n, j in 1:n] + 0.02im * (i - j + offset)) for i in 1:n, j in 1:n] end 𝐏s = [test_matrix(4, 1), test_matrix(4, 2), test_matrix(2, 3)] 𝐔s = [test_matrix(4, 4; scale = 0.2), - test_matrix(4, 5; scale = 0.2), - test_matrix(2, 6; scale = 0.2)] + test_matrix(4, 5; scale = 0.2), + test_matrix(2, 6; scale = 0.2)] ∂𝐏s = [test_matrix(4, 7; scale = 0.1), - test_matrix(4, 8; scale = 0.1), - test_matrix(2, 9; scale = 0.1)] + test_matrix(4, 8; scale = 0.1), + test_matrix(2, 9; scale = 0.1)] ∂𝐔s = [test_matrix(4, 10; scale = 0.1), - test_matrix(4, 11; scale = 0.1), - test_matrix(2, 12; scale = 0.1)] + test_matrix(4, 11; scale = 0.1), + test_matrix(2, 12; scale = 0.1)] 𝐓 = ebcm_transition_matrix_from_matrices(𝐏s, 𝐔s) ∂𝐓 = ∂ebcm_transition_matrix_from_matrices(𝐏s, 𝐔s, ∂𝐏s, ∂𝐔s) @@ -297,7 +298,7 @@ end for m in 0:2 @test 𝐓.𝐓[m + 1] ≈ 𝐓_from_𝐏_and_𝐔(𝐏s[m + 1], 𝐔s[m + 1]) @test ∂𝐓.𝐓[m + 1] ≈ ∂𝐓_from_𝐏_and_𝐔(𝐏s[m + 1], 𝐔s[m + 1], - ∂𝐏s[m + 1], ∂𝐔s[m + 1]) + ∂𝐏s[m + 1], ∂𝐔s[m + 1]) end end @@ -306,7 +307,7 @@ end function test_matrix(n, offset; scale = 1.0) [scale * ((i == j ? 1.3 + offset : 0.02 * (i + j + offset)) + - 0.03im * (i - j + offset)) for i in 1:n, j in 1:n] + 0.03im * (i - j + offset)) for i in 1:n, j in 1:n] end 𝐓 = test_matrix(4, 1; scale = 0.1) @@ -320,24 +321,24 @@ end ∂𝐐ₕⱼ = test_matrix(4, 9; scale = 0.01) ∂𝐐ₕₕ = test_matrix(4, 10; scale = 0.01) - 𝐓next, ∂𝐓next = _iitm_update_transition_solve_block(𝐓, ∂𝐓, 𝐐ⱼⱼ, - 𝐐ⱼₕ, 𝐐ₕⱼ, 𝐐ₕₕ, - ∂𝐐ⱼⱼ, ∂𝐐ⱼₕ, - ∂𝐐ₕⱼ, ∂𝐐ₕₕ) + 𝐓next, + ∂𝐓next = _iitm_update_transition_solve_block(𝐓, ∂𝐓, 𝐐ⱼⱼ, + 𝐐ⱼₕ, 𝐐ₕⱼ, 𝐐ₕₕ, + ∂𝐐ⱼⱼ, ∂𝐐ⱼₕ, + ∂𝐐ₕⱼ, ∂𝐐ₕₕ) - update_value(ϵ) = - _iitm_update_transition_solve_block(𝐓 .+ ϵ .* ∂𝐓, zero(∂𝐓), - 𝐐ⱼⱼ .+ ϵ .* ∂𝐐ⱼⱼ, - 𝐐ⱼₕ .+ ϵ .* ∂𝐐ⱼₕ, - 𝐐ₕⱼ .+ ϵ .* ∂𝐐ₕⱼ, - 𝐐ₕₕ .+ ϵ .* ∂𝐐ₕₕ, - zero(∂𝐐ⱼⱼ), zero(∂𝐐ⱼₕ), - zero(∂𝐐ₕⱼ), zero(∂𝐐ₕₕ))[1] + update_value(ϵ) = _iitm_update_transition_solve_block(𝐓 .+ ϵ .* ∂𝐓, zero(∂𝐓), + 𝐐ⱼⱼ .+ ϵ .* ∂𝐐ⱼⱼ, + 𝐐ⱼₕ .+ ϵ .* ∂𝐐ⱼₕ, + 𝐐ₕⱼ .+ ϵ .* ∂𝐐ₕⱼ, + 𝐐ₕₕ .+ ϵ .* ∂𝐐ₕₕ, + zero(∂𝐐ⱼⱼ), zero(∂𝐐ⱼₕ), + zero(∂𝐐ₕⱼ), zero(∂𝐐ₕₕ))[1] ϵ = 1e-6 ∂𝐓_fd = (update_value(ϵ) - update_value(-ϵ)) ./ (2ϵ) @test 𝐓next ≈ update_value(0) - @test ∂𝐓next ≈ ∂𝐓_fd atol=1e-8 rtol=1e-7 + @test ∂𝐓next≈∂𝐓_fd atol=1e-8 rtol=1e-7 end @testitem "EBCM fixed spheroid linearization matches ForwardDiff references" begin @@ -371,15 +372,17 @@ end result = linearize_transition_matrix(problem, EBCMLinearization(); config) @test result.metadata.backend == :ebcm_analytic @test !hasproperty(result.metadata, :reference) - reference = TransitionMatrices.transition_matrix(Spheroid(x₀[1], x₀[2], - complex(x₀[3], x₀[4])), - x₀[5], nₘₐₓ, Ng) + reference = TransitionMatrices.transition_matrix( + Spheroid(x₀[1], x₀[2], + complex(x₀[3], x₀[4])), + x₀[5], nₘₐₓ, Ng) reference_jacobian = ForwardDiff.jacobian(transition_vector_from_parameters, x₀) - @test transition_vector_from_matrix(result.value) ≈ transition_vector_from_matrix(reference) + @test transition_vector_from_matrix(result.value) ≈ + transition_vector_from_matrix(reference) for (j, var) in enumerate(vars) - @test transition_vector_from_matrix(derivative(result, var)) ≈ reference_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(result, var))≈reference_jacobian[:, j] atol=1e-7 rtol=1e-7 end subset_x₀ = [x₀[5], x₀[1]] @@ -387,13 +390,13 @@ end subset_problem = LinearizationProblem(subset_x₀; variables = subset_vars) do x c = zero(x[1]) + zero(x[2]) + x₀[2] (; shape = Spheroid(x[2], c, complex(x₀[3], x₀[4])), - λ = x[1]) + λ = x[1]) end function transition_vector_from_subset(x) base = zero(x[1]) + zero(x[2]) s = Spheroid(base + x[2], base + x₀[2], - complex(base + x₀[3], base + x₀[4])) + complex(base + x₀[3], base + x₀[4])) 𝐓 = TransitionMatrices.transition_matrix(s, x[1], nₘₐₓ, Ng) return transition_vector_from_matrix(𝐓) end @@ -403,7 +406,7 @@ end subset_jacobian = ForwardDiff.jacobian(transition_vector_from_subset, subset_x₀) for (j, var) in enumerate(subset_vars) - @test transition_vector_from_matrix(derivative(subset_result, var)) ≈ subset_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(subset_result, var))≈subset_jacobian[:, j] atol=1e-7 rtol=1e-7 end real_m_problem = LinearizationProblem([x₀[5]]; variables = (:λ,)) do x @@ -449,7 +452,7 @@ end reference_jacobian = ForwardDiff.jacobian(transition_vector_from_parameters, x₀) for (j, var) in enumerate(vars) - @test transition_vector_from_matrix(derivative(result, var)) ≈ reference_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(result, var))≈reference_jacobian[:, j] atol=1e-7 rtol=1e-7 end end @@ -487,7 +490,7 @@ end reference_jacobian = ForwardDiff.jacobian(transition_vector_from_parameters, x₀) for (j, var) in enumerate(vars) - @test transition_vector_from_matrix(derivative(result, var)) ≈ reference_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(result, var))≈reference_jacobian[:, j] atol=1e-7 rtol=1e-7 end end @@ -506,7 +509,7 @@ end problem = LinearizationProblem(x₀; variables = vars) do x base = zero(x[1]) + zero(x[2]) + zero(x[3]) (; shape = Spheroid(base + a, base + c, complex(x[3], x[2])), - λ = x[1]) + λ = x[1]) end function transition_vector_from_matrix(𝐓) @@ -525,27 +528,29 @@ end @test Bool(support) result = linearize_transition_matrix(problem, IITMLinearization(:axisymmetric); - config) + config) @test result.metadata.backend == :iitm_axisymmetric_analytic @test !hasproperty(result.metadata, :reference) - reference = TransitionMatrices.transition_matrix_iitm(Spheroid(a, c, - complex(x₀[3], - x₀[2])), - x₀[1], nₘₐₓ, Nr, Nϑ) + reference = TransitionMatrices.transition_matrix_iitm( + Spheroid(a, c, + complex(x₀[3], + x₀[2])), + x₀[1], nₘₐₓ, Nr, Nϑ) reference_jacobian = ForwardDiff.jacobian(transition_vector_from_parameters, x₀) - @test transition_vector_from_matrix(result.value) ≈ transition_vector_from_matrix(reference) + @test transition_vector_from_matrix(result.value) ≈ + transition_vector_from_matrix(reference) for (j, var) in enumerate(vars) - @test transition_vector_from_matrix(derivative(result, var)) ≈ reference_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(result, var))≈reference_jacobian[:, j] atol=1e-7 rtol=1e-7 end geometry_problem = LinearizationProblem([a]; variables = (:a,)) do x (; shape = Spheroid(x[1], c, complex(x₀[3], x₀[2])), λ = x₀[1]) end geometry_support = supports_linearization(geometry_problem, - IITMLinearization(:axisymmetric); - config) + IITMLinearization(:axisymmetric); + config) @test !Bool(geometry_support) @test occursin("fixed-geometry", geometry_support.reason) end @@ -560,8 +565,7 @@ end TransitionMatrices.rmin(s::LinearizationArbitraryPrism) = rmin(s.s) TransitionMatrices.rmax(s::LinearizationArbitraryPrism) = rmax(s.s) - TransitionMatrices.refractive_index(s::LinearizationArbitraryPrism, x) = - refractive_index(s.s, x) + TransitionMatrices.refractive_index(s::LinearizationArbitraryPrism, x) = refractive_index(s.s, x) nₘₐₓ = 2 Nr = 3 @@ -581,12 +585,11 @@ end (; shape = shape_from_parameters(x), λ = x[1]) end - transition_vector_from_matrix(𝐓) = - vcat(real.(vec(𝐓.container)), imag.(vec(𝐓.container))) + transition_vector_from_matrix(𝐓) = vcat(real.(vec(𝐓.container)), imag.(vec(𝐓.container))) function transition_vector_from_parameters(x) 𝐓 = TransitionMatrices.transition_matrix_iitm(shape_from_parameters(x), x[1], - nₘₐₓ, Nr, Nϑ, Nφ) + nₘₐₓ, Nr, Nϑ, Nφ) return transition_vector_from_matrix(𝐓) end @@ -594,18 +597,19 @@ end @test Bool(support) result = linearize_transition_matrix(problem, IITMLinearization(:arbitrary); - config) + config) @test result.metadata.backend == :iitm_arbitrary_analytic @test !hasproperty(result.metadata, :reference) reference = TransitionMatrices.transition_matrix_iitm(shape_from_parameters(x₀), - x₀[1], nₘₐₓ, Nr, Nϑ, - Nφ) + x₀[1], nₘₐₓ, Nr, Nϑ, + Nφ) reference_jacobian = ForwardDiff.jacobian(transition_vector_from_parameters, x₀) - @test transition_vector_from_matrix(result.value) ≈ transition_vector_from_matrix(reference) + @test transition_vector_from_matrix(result.value) ≈ + transition_vector_from_matrix(reference) for (j, var) in enumerate(vars) - @test transition_vector_from_matrix(derivative(result, var)) ≈ reference_jacobian[:, j] atol=1e-7 rtol=1e-7 + @test transition_vector_from_matrix(derivative(result, var))≈reference_jacobian[:, j] atol=1e-7 rtol=1e-7 end end @@ -627,12 +631,11 @@ end (; shape = shape_from_parameters(x), λ = x[1]) end - transition_vector_from_matrix(𝐓) = - vcat(real.(vec(𝐓.container)), imag.(vec(𝐓.container))) + transition_vector_from_matrix(𝐓) = vcat(real.(vec(𝐓.container)), imag.(vec(𝐓.container))) function transition_vector_from_parameters(x) 𝐓 = TransitionMatrices.transition_matrix_iitm(shape_from_parameters(x), x[1], - nₘₐₓ, Nr, Nϑ, Nφ) + nₘₐₓ, Nr, Nϑ, Nφ) return transition_vector_from_matrix(𝐓) end @@ -640,14 +643,15 @@ end @test Bool(support) result = linearize_transition_matrix(problem, IITMLinearization(:nfold); - config) + config) @test result.metadata.backend == :iitm_nfold_analytic @test !hasproperty(result.metadata, :reference) reference = TransitionMatrices.transition_matrix_iitm(shape_from_parameters(x₀), - x₀[1], nₘₐₓ, Nr, Nϑ, - Nφ) - @test transition_vector_from_matrix(result.value) ≈ transition_vector_from_matrix(reference) + x₀[1], nₘₐₓ, Nr, Nϑ, + Nφ) + @test transition_vector_from_matrix(result.value) ≈ + transition_vector_from_matrix(reference) δ = 1e-6 for (j, var) in enumerate(vars) @@ -657,6 +661,6 @@ end x⁻[j] -= δ ∂ref = (transition_vector_from_parameters(x⁺) .- transition_vector_from_parameters(x⁻)) ./ (2δ) - @test transition_vector_from_matrix(derivative(result, var)) ≈ ∂ref atol=2e-5 rtol=2e-5 + @test transition_vector_from_matrix(derivative(result, var))≈∂ref atol=2e-5 rtol=2e-5 end end diff --git a/test/runtests.jl b/test/runtests.jl index 7b59fa4..1a0ce30 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,4 +2,6 @@ using TransitionMatrices using Test using TestItemRunner -@testset "TransitionMatrices.jl" begin @run_package_tests() end +@testset "TransitionMatrices.jl" begin + @run_package_tests() +end