test_earthRadiationModel
Unit tests for earthRadiationModel.
Test geometry (all tests unless noted)
Earth at origin (planet-fixed = inertial, J20002Pfix = I) Sun at (+AU, 0, 0) → sunlit side: +x hemisphere Satellite at (0, REQ+600 [km], 0) → visible side: +y hemisphere Overlap (first quadrant lon 0-90°) → albedoFlux > 0, irFlux > 0
Physics expected values (approximate, for sanity-check only)
irFlux ~ OLR/(pi) * solid_angle_of_Earth ~ O(50) W/m^2 albedoFlux > 0 (sunlit + visible patches exist) Both direction vectors are unit vectors when flux > 0
- test_earthRadiationModel.test_earthRadiation_albedoAvg_physicsChecks()[source]
albedoFlux and irFlux are positive; direction vectors are unit vectors.
- test_earthRadiationModel.test_earthRadiation_albedoData_nonzero()[source]
With CERES albedo data, albedoFlux must remain positive.
- test_earthRadiationModel.test_earthRadiation_albedoDir_geometry()[source]
In the standard geometry (Sun +x, satellite +y), albedoDir_N must point roughly toward the satellite (+y component > 0).
Illuminated patches are in the +x hemisphere; visible patches from the +y satellite are near the (lat=0°, lon~65°-90°) band. The flux-weighted direction from these patches to the satellite has a dominant +y component.
- test_earthRadiationModel.test_earthRadiation_analytical_ir()[source]
Validate irFlux against the exact Lambertian-sphere closed form.
Derivation (integrating the patch kernel over the visible hemisphere):
F_IR = (OLR/pi) * integral_{visible} cos_sat * dA / d^2 = 2 * OLR * (1 - sqrt(1 - (R_aut/D)^2))This result is independent of the albedo model since OLR is spatially uniform in both avg and CERES-data configurations.
Note
The far-field approximation
OLR*(R/D)^2is only valid forD >> R. At 600 km LEO,R/D ~ 0.91so the far-field error is ~30 %; the exact formula above is used here.A fine grid (
nLat=180,nLon=360, 1-degree resolution) is used so that the midpoint-rule discretisation error is < 0.3 %, well below the assertion tolerance of 1 %.
- test_earthRadiationModel.test_earthRadiation_direction_toward_earth()[source]
The net force direction from ERP points roughly from satellite toward Earth (i.e. the radiation comes from Earth). With the satellite on the +y axis, irDir_N should have a dominant negative-y component.
- test_earthRadiationModel.test_earthRadiation_eclipseCase_applied()[source]
P2 regression:
eclipseCase=Truemust be applied inEarthRadiationModel.Before the fix,
isPatchEclipsed()in the base class always returnedFalseregardless of the flag, soeclipseCase=Truehad no effect on ERM output. After the fix, the base-class implementation runs the Knocke penumbra model when the flag is set.Properties verified:
eclipseCase=Trueruns without error.Monotonicity: eclipse can only reduce albedo flux, never increase it —
albedo_eclipse <= albedo_no_eclipse.- IR is unaffected: eclipse shadows apply only to the albedo channel;
the IR channel is independent of solar illumination and must not change.
- Small magnitude: for the standard geometry (satellite well outside
the terminator zone), nearly all visible patches are clearly sunlit so the penumbra correction is negligible (< 1 % relative).
- test_earthRadiationModel.test_earthRadiation_invalid_albedo_file(tmp_path)[source]
Providing a nonexistent albedo file must raise an error in Reset().
- test_earthRadiationModel.test_earthRadiation_numpy_reference(useAlbedoData)[source]
Cross-check EarthRadiationModel against a pure-NumPy reimplementation of the same Lambertian patch algorithm.
What this test validates (and does not validate)
_python_lambertian mirrors
planetRadiationBase.cppandearthRadiationModel.cppline-by-line in a different language. Because it replicates the same model, it cannot catch physics errors shared by both implementations. Its value is:Arithmetic correctness — catches mistakes in the C++/Eigen indexing, DCM convention (
Eigen::Mapcolumn-major transpose of row-major C array, seeavsEigenSupport.cpp), normArea formula, or accumulation loop.CERES CSV loading — verifies that the C++ CSV parser produces the same per-patch albedo values as
np.loadtxt. The albedo grid is loaded from BasilisksupportData(DataFile.AlbedoData.Earth_ALB_2018_CERES_All_1x1) and fed identically into both sides.
Physics correctness (the model converges to the right integral) is covered by test_earthRadiation_analytical_ir.
Tolerance:
1e-7relative, accounting for accumulated floating-point differences between Eigen and NumPy across the 180x360 patch loop.
- test_earthRadiationModel.test_earthRadiation_solar_flux_distance_scaling()[source]
albedoFlux must scale as (AU / d_sun)^2; irFlux must be independent of d_sun.
Moving the Sun from 1 AU to 2 AU (same direction) halves the solar flux S_sun = S0*(AU/d)^2, so albedoFlux must drop by factor 4. The IR formula uses the constant OLR and does not contain S_sun, so irFlux must be unchanged.
- test_earthRadiationModel.test_earthRadiation_unlinked_messages()[source]
Reset() must raise BSK_ERROR (BasiliskError) when messages are unlinked.
- test_earthRadiationModel.test_earthRadiation_zero_albedo_direction_is_zero()[source]
When no patches are both sunlit and visible (albedoFlux = 0), albedoDir_N must be [0, 0, 0].
Geometry: Sun on +x, satellite on -x. Sunlit patches (outward normal toward +x) are on the far side from the satellite; visible patches (outward normal toward -x) face away from the Sun. The two sets are disjoint → albedoFlux = 0. IR flux must still be positive (emitted regardless of illumination).