From 4bf4690279f6f385b5f78b3c558c30bcffc1b4d2 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 00:11:38 +0100 Subject: [PATCH 01/10] Ignore .mem files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0eb37c2..3f34835 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ node_modules **.old play/Project.toml docs/.CondaPkg/meta +*.mem From 84d24f9a163d37aad4c77fbfe0a9a8ff16876a90 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 00:15:42 +0100 Subject: [PATCH 02/10] Add AbstractObserver struct --- docs/src/reference.md | 1 + src/Positioning/Positioning.jl | 52 ++++++++++++++++++++++------------ src/Positioning/utils.jl | 2 +- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/docs/src/reference.md b/docs/src/reference.md index 2b11ad4..4ef556a 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -24,6 +24,7 @@ SolarPosition.Positioning.solar_position! ## Observer and Position Types ```@docs +SolarPosition.Positioning.AbstractObserver SolarPosition.Positioning.Observer SolarPosition.Positioning.SolPos SolarPosition.Positioning.ApparentSolPos diff --git a/src/Positioning/Positioning.jl b/src/Positioning/Positioning.jl index e622005..778f16a 100644 --- a/src/Positioning/Positioning.jl +++ b/src/Positioning/Positioning.jl @@ -32,6 +32,22 @@ struct MyAlgorithm <: SolarAlgorithm end """ abstract type SolarAlgorithm end +""" + $(TYPEDEF) + +Abstract base type for Observers. + +All concrete observer types must inherit from this type. Most algorithms will use the +default `Observer` struct defined in this module. More specialized observer types can be +defined by inheriting from this abstract type, see for example [`SPAObserver`](@ref). + +# Examples +```julia +struct MyObserver <: AbstractObserver{Float64} end +``` +""" +abstract type AbstractObserver{T<:AbstractFloat} end + """ $(TYPEDEF) @@ -59,7 +75,7 @@ The `horizon` parameter can be specified as: - A number in degrees (e.g., `0.5667`) - A `degrees=>arcminutes` pair (e.g., `0=>34` for 34 arcminutes = 0.5667°) """ -struct Observer{T<:AbstractFloat} +struct Observer{T<:AbstractFloat} <: AbstractObserver{T} "Geodetic latitude (+N)" latitude::T "Longitude (+E)" @@ -172,7 +188,7 @@ an observer's geographic location and timestamp(s). It supports multiple input f automatically handles time zone conversions. # Arguments -- `obs::Observer`: Observer location with latitude, longitude, and altitude +- `obs::AbstractObserver`: Observer location with latitude, longitude, and altitude - `dt::DateTime` or `dt::ZonedDateTime`: Single timestamp - `dts::AbstractVector`: Vector of timestamps (DateTime or ZonedDateTime) - `alg::SolarAlgorithm`: Solar positioning algorithm (default: `PSA()`) @@ -270,26 +286,26 @@ function _solar_position(obs, dt, alg::SolarAlgorithm, refraction::RefractionAlg end function solar_position( - obs::Observer{T}, + obs::AbstractObserver{T}, dt::DateTime, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), ) where {T<:AbstractFloat} - _solar_position(obs, dt, alg, refraction) + return _solar_position(obs, dt, alg, refraction) end function solar_position( - obs::Observer{T}, + obs::AbstractObserver{T}, dt::ZonedDateTime, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), ) where {T<:AbstractFloat} - solar_position(obs, DateTime(dt, UTC), alg, refraction) + return solar_position(obs, DateTime(dt, UTC), alg, refraction) end function solar_position!( pos::StructArrays.StructVector{T}, - obs::Observer, + obs::AbstractObserver, dts::AbstractVector{Union{DateTime,ZonedDateTime}}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -302,7 +318,7 @@ end function solar_position!( pos::StructArrays.StructVector{T}, - obs::Observer, + obs::AbstractObserver, dts::AbstractVector{DateTime}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -315,7 +331,7 @@ end function solar_position!( pos::StructArrays.StructVector{T}, - obs::Observer, + obs::AbstractObserver, dts::AbstractVector{ZonedDateTime}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -327,7 +343,7 @@ function solar_position!( end function solar_position( - obs::Observer{T}, + obs::AbstractObserver{T}, dts::AbstractVector{Union{DateTime,ZonedDateTime}}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -335,11 +351,11 @@ function solar_position( RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) - pos + return pos end function solar_position( - obs::Observer{T}, + obs::AbstractObserver{T}, dts::AbstractVector{DateTime}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -347,11 +363,11 @@ function solar_position( RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) - pos + return pos end function solar_position( - obs::Observer{T}, + obs::AbstractObserver{T}, dts::AbstractVector{ZonedDateTime}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(), @@ -359,7 +375,7 @@ function solar_position( RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) - pos + return pos end @@ -370,7 +386,7 @@ Compute solar positions for all times in a table and add the results as new colu # Arguments - `table` : Table-like object with datetime column (must support Tables.jl interface). -- `obs::Observer` : Observer location (latitude, longitude, altitude). +- `obs::AbstractObserver` : Observer location (latitude, longitude, altitude). - `latitude, longitude, altitude` : Specify observer location directly. - `dt_col::Symbol` : Name of the datetime column (default: `:datetime`). - `alg::SolarAlgorithm` : Algorithm to use (default: `PSA()`). @@ -386,7 +402,7 @@ The input table is modified **in-place** by adding new columns. """ function solar_position!( table, - obs::Observer{T}, + obs::AbstractObserver{T}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(); dt_col::Symbol = :datetime, @@ -414,7 +430,7 @@ See [`solar_position!`](@ref) for detailed documentation of arguments, examples, """ function solar_position( table, - obs::Observer{T}, + obs::AbstractObserver{T}, alg::SolarAlgorithm = PSA(), refraction::RefractionAlgorithm = DefaultRefraction(); kwargs..., diff --git a/src/Positioning/utils.jl b/src/Positioning/utils.jl index 3d5333d..b7094f0 100644 --- a/src/Positioning/utils.jl +++ b/src/Positioning/utils.jl @@ -1,7 +1,7 @@ """Utility functions to be used across solar positioning algorithms.""" # dt.instant.value = milliseconds since epoch -@inline fractional_hour(dt::DateTime) = (Dates.value(dt) % 86_400_000) / 3_600_000 +@inline fractional_hour(dt::DateTime) = (dt.instant.value % 86_400_000) / 3_600_000 # constants const EMR = 6371.01 # Earth Mean Radius in km From d731df8c9483203ce51952e13d067f91480489d6 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 00:18:22 +0100 Subject: [PATCH 03/10] Update SPA algorithm --- src/Positioning/spa.jl | 73 +++++++++--------------------------------- 1 file changed, 16 insertions(+), 57 deletions(-) diff --git a/src/Positioning/spa.jl b/src/Positioning/spa.jl index 8d99d75..e887a2f 100644 --- a/src/Positioning/spa.jl +++ b/src/Positioning/spa.jl @@ -65,7 +65,7 @@ multiple times at the same location. # Internal Fields $(TYPEDFIELDS) """ -struct SPAObserver{T<:AbstractFloat} +struct SPAObserver{T<:AbstractFloat} <: AbstractObserver{T} "Geodetic latitude (+N)" latitude::T "Longitude (+E)" @@ -448,71 +448,30 @@ function _solar_position( return SolPos{T}(az, e0, θz0) end -# SPA with DefaultRefraction applies SPA's built-in atmospheric refraction model -function _solar_position( - obs::Observer{T}, - dt::DateTime, - alg::SPA, - ::Refraction.DefaultRefraction, -) where {T<:AbstractFloat} +function _solar_position(obs::Observer{T}, dt::DateTime, alg::SPA) where {T<:AbstractFloat} spa_obs = SPAObserver{T}(obs.latitude, obs.longitude, obs.altitude) - - # Get base position without refraction - base_pos = _solar_position(spa_obs, dt, alg) - - # Apply SPA's atmospheric refraction correction - Δe = atmospheric_refraction_correction( - alg.pressure, - alg.temperature, - base_pos.elevation, - alg.atmos_refract, - ) - - # Calculate apparent positions - e = base_pos.elevation + Δe # apparent elevation - θz = 90.0 - e # apparent zenith - - return ApparentSolPos{T}(base_pos.azimuth, base_pos.elevation, base_pos.zenith, e, θz) + return _solar_position(spa_obs, dt, alg) end -# SPA with NoRefraction returns SolPos (no refraction applied) -function _solar_position( - obs::Observer{T}, - dt::DateTime, - alg::SPA, - ::Refraction.NoRefraction, -) where {T<:AbstractFloat} - spa_obs = SPAObserver{T}(obs.latitude, obs.longitude, obs.altitude) - return _solar_position(spa_obs, dt, alg) +function _solar_position(obs, dt, alg::SPA, ::DefaultRefraction) + return _solar_position(obs, dt, alg, SPARefraction()) end -# SPA with external refraction algorithm: apply the external refraction to base position -function _solar_position( - obs::Observer{T}, - dt::DateTime, +function solar_position!( + pos::StructArrays.StructVector{S}, + obs::AbstractObserver{T}, + dts::AbstractVector{DateTime}, alg::SPA, - refraction::Refraction.RefractionAlgorithm, -) where {T<:AbstractFloat} + refraction::RefractionAlgorithm = DefaultRefraction(), +) where {S<:AbstractSolPos,T<:AbstractFloat} spa_obs = SPAObserver{T}(obs.latitude, obs.longitude, obs.altitude) - - # Get base position without refraction - base_pos = _solar_position(spa_obs, dt, alg) - - # Apply external refraction correction - refraction_correction_deg = Refraction.refraction(refraction, base_pos.elevation) - apparent_elevation_deg = base_pos.elevation + refraction_correction_deg - apparent_zenith_deg = 90.0 - apparent_elevation_deg - - return ApparentSolPos{T}( - base_pos.azimuth, - base_pos.elevation, - base_pos.zenith, - apparent_elevation_deg, - apparent_zenith_deg, - ) + @inbounds for i in eachindex(dts, pos) + pos[i] = solar_position(spa_obs, dts[i], alg, refraction) + end + return pos end # SPA returns SolPos with NoRefraction, ApparentSolPos with any refraction result_type(::Type{SPA}, ::Type{NoRefraction}, ::Type{T}) where {T} = SolPos{T} -result_type(::Type{SPA}, ::Type{<:Refraction.RefractionAlgorithm}, ::Type{T}) where {T} = +result_type(::Type{SPA}, ::Type{<:RefractionAlgorithm}, ::Type{T}) where {T} = ApparentSolPos{T} From f4c290ba0d32574a702166f164f93db2f6d7f9ae Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 01:29:59 +0100 Subject: [PATCH 04/10] Remove unnecessary reexport macro --- src/Positioning/Positioning.jl | 3 +-- src/Refraction/Refraction.jl | 1 - src/Utilities/Utilities.jl | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Positioning/Positioning.jl b/src/Positioning/Positioning.jl index 778f16a..7bfa106 100644 --- a/src/Positioning/Positioning.jl +++ b/src/Positioning/Positioning.jl @@ -14,9 +14,8 @@ using TimeZones: ZonedDateTime, UTC using StructArrays: StructArrays using Tables: Tables using DocStringExtensions: TYPEDFIELDS, TYPEDEF, TYPEDSIGNATURES -using Reexport: @reexport import ..Refraction -using ..Refraction: RefractionAlgorithm, NoRefraction, DefaultRefraction +using ..Refraction: RefractionAlgorithm, NoRefraction, DefaultRefraction, SPARefraction """ $(TYPEDEF) diff --git a/src/Refraction/Refraction.jl b/src/Refraction/Refraction.jl index 98637ef..f627719 100644 --- a/src/Refraction/Refraction.jl +++ b/src/Refraction/Refraction.jl @@ -9,7 +9,6 @@ for atmospheric refraction effects. module Refraction using DocStringExtensions: TYPEDFIELDS, TYPEDEF -using Reexport: @reexport """ diff --git a/src/Utilities/Utilities.jl b/src/Utilities/Utilities.jl index 9d98a48..66b2faa 100644 --- a/src/Utilities/Utilities.jl +++ b/src/Utilities/Utilities.jl @@ -1,6 +1,5 @@ module Utilities -using Reexport: @reexport using DocStringExtensions: TYPEDEF, TYPEDFIELDS, TYPEDSIGNATURES using ..Positioning: Observer, SPA, SolarAlgorithm, calculate_deltat import Dates: DateTime, Date, Day From 13adf610f62bf227ab683a21bf13dc6acc97cf5a Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 01:30:18 +0100 Subject: [PATCH 05/10] Update fractional_hour function to use periods value --- src/Positioning/utils.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Positioning/utils.jl b/src/Positioning/utils.jl index b7094f0..6db759a 100644 --- a/src/Positioning/utils.jl +++ b/src/Positioning/utils.jl @@ -1,7 +1,7 @@ """Utility functions to be used across solar positioning algorithms.""" -# dt.instant.value = milliseconds since epoch -@inline fractional_hour(dt::DateTime) = (dt.instant.value % 86_400_000) / 3_600_000 +# dt.instant.periods.value = milliseconds since epoch +@inline fractional_hour(dt::DateTime) = (dt.instant.periods.value % 86_400_000) / 3_600_000 # constants const EMR = 6371.01 # Earth Mean Radius in km From c06bec15f5c534f6b4d32690add4eaca7550ab6a Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 01:35:12 +0100 Subject: [PATCH 06/10] Remove unused @tz_str import from Utilities module --- src/Utilities/Utilities.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Utilities/Utilities.jl b/src/Utilities/Utilities.jl index 66b2faa..0eff072 100644 --- a/src/Utilities/Utilities.jl +++ b/src/Utilities/Utilities.jl @@ -4,7 +4,6 @@ using DocStringExtensions: TYPEDEF, TYPEDFIELDS, TYPEDSIGNATURES using ..Positioning: Observer, SPA, SolarAlgorithm, calculate_deltat import Dates: DateTime, Date, Day import TimeZones: ZonedDateTime, timezone, UTC -using TimeZones: @tz_str include("spa.jl") include("srt.jl") From 35ae2dd8ae3ca012939e24162ec2f61a626bcf66 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 02:13:56 +0100 Subject: [PATCH 07/10] Fix interfacing issues to SPA --- src/Positioning/Positioning.jl | 2 +- src/Positioning/spa.jl | 14 ++++++++++++-- test/positioning/test-interface.jl | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Positioning/Positioning.jl b/src/Positioning/Positioning.jl index 7bfa106..eaae4bf 100644 --- a/src/Positioning/Positioning.jl +++ b/src/Positioning/Positioning.jl @@ -273,7 +273,7 @@ function _solar_position(obs, dt, alg::SolarAlgorithm, refraction::RefractionAlg # apply refraction correction refraction_correction_deg = Refraction.refraction(refraction, pos.elevation) apparent_elevation_deg = pos.elevation + refraction_correction_deg - apparent_zenith_deg = 90.0 - apparent_elevation_deg + apparent_zenith_deg = 90 - apparent_elevation_deg return ApparentSolPos( pos.azimuth, diff --git a/src/Positioning/spa.jl b/src/Positioning/spa.jl index e887a2f..e5846c9 100644 --- a/src/Positioning/spa.jl +++ b/src/Positioning/spa.jl @@ -453,8 +453,18 @@ function _solar_position(obs::Observer{T}, dt::DateTime, alg::SPA) where {T<:Abs return _solar_position(spa_obs, dt, alg) end -function _solar_position(obs, dt, alg::SPA, ::DefaultRefraction) - return _solar_position(obs, dt, alg, SPARefraction()) +function _solar_position( + obs::AbstractObserver{T}, + dt, + alg::SPA, + ::DefaultRefraction, +) where {T<:AbstractFloat} + return _solar_position( + obs, + dt, + alg, + SPARefraction{T}(T(alg.pressure), T(alg.temperature), T(alg.atmos_refract)), + ) end function solar_position!( diff --git a/test/positioning/test-interface.jl b/test/positioning/test-interface.jl index 5b70b69..2491eb2 100644 --- a/test/positioning/test-interface.jl +++ b/test/positioning/test-interface.jl @@ -88,7 +88,8 @@ using Dates: Hour, @dateformat_str # test a second time to ensure there are minimal allocations alloc_limit = alg isa SPA ? 300 : 48 - @test @allocated(solar_position!(pos, obs, dts, alg)) ≤ alloc_limit + @test @allocated(solar_position!(pos, obs, dts, alg)) ≤ alloc_limit broken = + (VERSION == v"1.12.4") @test all(pos.azimuth .!= 0.0) @test pos[1] == single_result @test pos isa StructVector{PosType} From a6cdda403828eeac83a7dd47c4f5797f433f053b Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 11:59:06 +0100 Subject: [PATCH 08/10] Remove alloc limit check --- test/positioning/test-interface.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/positioning/test-interface.jl b/test/positioning/test-interface.jl index 2491eb2..5b70b69 100644 --- a/test/positioning/test-interface.jl +++ b/test/positioning/test-interface.jl @@ -88,8 +88,7 @@ using Dates: Hour, @dateformat_str # test a second time to ensure there are minimal allocations alloc_limit = alg isa SPA ? 300 : 48 - @test @allocated(solar_position!(pos, obs, dts, alg)) ≤ alloc_limit broken = - (VERSION == v"1.12.4") + @test @allocated(solar_position!(pos, obs, dts, alg)) ≤ alloc_limit @test all(pos.azimuth .!= 0.0) @test pos[1] == single_result @test pos isa StructVector{PosType} From c996ea2b8ed024ed7d1d74246a8627e6968a59d0 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 12:16:11 +0100 Subject: [PATCH 09/10] JET compatibility --- test/linting.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/linting.jl b/test/linting.jl index d664ece..42f69e2 100644 --- a/test/linting.jl +++ b/test/linting.jl @@ -2,14 +2,14 @@ using SolarPosition using Test using Aqua: Aqua -using JET: JET @testset "Aqua tests" begin @info "...with Aqua.jl" Aqua.test_all(SolarPosition) end -if VERSION > v"1.11" # JET v0.10 requires Julia v1.12 +if VERSION == v"1.12" # JET compatibility + using JET: JET @testset "JET tests" begin @info "...with JET.jl" JET.test_package(SolarPosition; target_modules = (SolarPosition,)) From 156d13dd7175859075821f026de6ba6344252842 Mon Sep 17 00:00:00 2001 From: Stefan de Lange Date: Fri, 16 Jan 2026 18:01:13 +0100 Subject: [PATCH 10/10] Harmonize refraction models for SPA --- src/Positioning/spa.jl | 6 +++++- src/Refraction/spa.jl | 23 ++++++++++------------- test/positioning/test-interface.jl | 3 ++- test/refraction/test-refraction.jl | 4 ++-- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Positioning/spa.jl b/src/Positioning/spa.jl index e5846c9..5ac5987 100644 --- a/src/Positioning/spa.jl +++ b/src/Positioning/spa.jl @@ -463,7 +463,11 @@ function _solar_position( obs, dt, alg, - SPARefraction{T}(T(alg.pressure), T(alg.temperature), T(alg.atmos_refract)), + SPARefraction{T}( + pressure = T(alg.pressure), + temperature = T(alg.temperature), + atmos_refract = T(alg.atmos_refract), + ), ) end diff --git a/src/Refraction/spa.jl b/src/Refraction/spa.jl index 53d4629..07e5239 100644 --- a/src/Refraction/spa.jl +++ b/src/Refraction/spa.jl @@ -13,9 +13,9 @@ Solar Position Algorithm (SPA). $(TYPEDFIELDS) # Constructor -- `SPARefraction()`: Uses default parameters: pressure = 101325 Pa, temperature = 12 °C, refraction_limit = -0.5667° -- `SPARefraction(pressure, temperature)`: Specify custom pressure [Pa] and temperature [°C], uses default refraction_limit -- `SPARefraction(pressure, temperature, refraction_limit)`: Also specify refraction limit [degrees] +- `SPARefraction()`: Uses default parameters: pressure = 101325 Pa, temperature = 12 °C, atmos_refract = -0.5667° +- `SPARefraction(pressure, temperature)`: Specify custom pressure [Pa] and temperature [°C], uses default atmos_refract +- `SPARefraction(pressure, temperature, atmos_refract)`: Also specify refraction limit [degrees] # Notes The equation to calculate the refraction correction is given by: @@ -53,16 +53,16 @@ refraction_correction = refraction(spa, elevation) apparent_elevation = elevation + refraction_correction ``` """ -struct SPARefraction{T} <: RefractionAlgorithm where {T<:AbstractFloat} +@kwdef struct SPARefraction{T<:AbstractFloat} <: RefractionAlgorithm "Annual average atmospheric pressure [Pascal]" - pressure::T + pressure::T = 101325.0 "Annual average temperature [°C]" - temperature::T + temperature::T = 12.0 "Minimum elevation angle for refraction correction [degrees]" - refraction_limit::T + atmos_refract::T = -0.5667 end -SPARefraction() = SPARefraction{Float64}(101325.0, 12.0, -0.5667) +# Positional constructor for 2 arguments (3-argument constructor is already created by @kwdef) SPARefraction(pressure::T, temperature::T) where {T<:AbstractFloat} = SPARefraction{T}(pressure, temperature, T(-0.5667)) @@ -70,11 +70,8 @@ function _refraction(model::SPARefraction{T}, elevation_deg::T) where {T<:Abstra # Convert pressure from Pascal to hPa/mbar pressure_hPa = model.pressure / T(100.0) - # Check if sun is above horizon (elevation >= -0.26667 + refraction_limit) - # The sun diameter of 0.26667 degrees is added to the refraction limit - above_horizon = elevation_deg >= (T(-0.26667) + model.refraction_limit) - - if !above_horizon + # Only apply correction when sun is above horizon accounting for refraction + if elevation_deg < model.atmos_refract - T(0.26667) return T(0.0) end diff --git a/test/positioning/test-interface.jl b/test/positioning/test-interface.jl index 5b70b69..e88f560 100644 --- a/test/positioning/test-interface.jl +++ b/test/positioning/test-interface.jl @@ -87,7 +87,8 @@ using Dates: Hour, @dateformat_str @test length(pos) == n_dts # test a second time to ensure there are minimal allocations - alloc_limit = alg isa SPA ? 300 : 48 + # alloc_limit = alg isa SPA ? 300 : 48 + alloc_limit = 48 @test @allocated(solar_position!(pos, obs, dts, alg)) ≤ alloc_limit @test all(pos.azimuth .!= 0.0) @test pos[1] == single_result diff --git a/test/refraction/test-refraction.jl b/test/refraction/test-refraction.jl index 8b7997b..dfdbf2c 100644 --- a/test/refraction/test-refraction.jl +++ b/test/refraction/test-refraction.jl @@ -113,13 +113,13 @@ end ref1 = SPARefraction() @test ref1.pressure == 101325.0 @test ref1.temperature == 12.0 - @test ref1.refraction_limit == -0.5667 + @test ref1.atmos_refract == -0.5667 # with pressure and temperature ref2 = SPARefraction(100000.0, 15.0) @test ref2.pressure == 100000.0 @test ref2.temperature == 15.0 - @test ref2.refraction_limit == -0.5667 + @test ref2.atmos_refract == -0.5667 # refraction works obs = Observer(45.0, 10.0, 100.0)