Skip to content

Correct accounting for eq_11 term in surface derivatives#931

Merged
pgbrodrick merged 2 commits into
isofit:devfrom
evan-greenbrg:OE/eq_11
Apr 20, 2026
Merged

Correct accounting for eq_11 term in surface derivatives#931
pgbrodrick merged 2 commits into
isofit:devfrom
evan-greenbrg:OE/eq_11

Conversation

@evan-greenbrg

@evan-greenbrg evan-greenbrg commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

The previous location of the eq_11_term correction in the RT.calc_rdn function meant that the L_x_x values were inconsistently scaled between calc_rdn and drdn_dsurface.

This PR moves the eq_11_term accounting into the get_L_coupled function (consistent with the hays model).

This does have some visible impact. Testing on a snow covered shady pixel (bright, but with high proportion of L_dif) Images courtesy of @brentwilder.

In reflectance space:
image

In derivative space:
image

Other note to keep track of that was discussed:

Introducing the eq_11 term into the forward model is another step towards more atmosphere-surface coupling within the model. This may be more accurate physics, but it potentially makes the code organization a bit more confusing. The radiative_transfer module is increasingly in charge of forward model physics that incorporate surface-atmosphere coupling despite the name implying that it is principally responsible for the radiative transfer component. The fuzziness continues with #915, a necessary change, but would further muddy the distinction and purpose of a separate radiative_transfer_engine module.

@brentwilder

brentwilder commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

I want to raise a small concern just to be sure we are treating eq_11_term correctly .. Looking at EQ-11 and EQ-12 in Guanter et al. (2009) they have,

$$L_{diff}^* = L_{diff}(0) / (1 - s_{alb} \rho_{22})$$

and

$$L_{tot}^* = L_{tot}(0) / (1 - s_{alb} \rho_{22})$$

Which is interesting because this means that,

$$L_{tot}^* \ != \ L_{11} \ \ + \ \ L_{12}/(1 - s_{alb} \rho_{22}) \ \ + L_{21} \ + \ \ L_{22}/(1 - s_{alb} \rho_{22})$$

And so, I believe we were incorrect yesterday then in our discussion... And the current way eqn_11_term within calc_rdn is applied is indeed correct. Because we currently compute $L_{tot}(0)$ in get_L_coupled(), and then we apply this scattering term in the calc_rdn call...

And so, for the derivative drdn_drfl(), I believe this is already correct as well for the case of the homogenous background because the TOA formulation simplifies to EQ-15. And the partial of this matches what we currently have. As you discussed yesterday though, I think this will be another story for the partials for the heterogeneous background... And this will need a closer look in #815 .

@evan-greenbrg

Copy link
Copy Markdown
Collaborator Author

Very interesting, thanks, Brent! It took me a bit, but I see your point. If we make the change proposed here, we are, in efect, "double-counting" the $1 - S\rho$ denominator in the multi-scattering term.

For self-consistency with the derivatives, aren't we only simplifying to Eq. 15 in the 3c-case where we set the atm_surface_scattering = 1 and the equation reduces? I must be missing something, but I'm having a hard time seeing how the derivitves wrt $\rho$ would reduce to the same thing between the 3c and 6c if the $1 - S\rho$ scaling is used on the diffuse radiance terms.

@evan-greenbrg evan-greenbrg marked this pull request as ready for review March 30, 2026 16:20
Comment thread isofit/inversion/inverse_simple.py Outdated
L_dif_dif,
) = RT.calc_RT_quantities(x_RT, geom)
) = RT.calc_RT_quantities(
x_RT, geom, rho_dif_dif=0 # Assume no surface-atmosphere coupling

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brentwilder @pgbrodrick This is the only assumption to double check.

In the algebraic inversion we assume no atmosphere-surface coupling, equation 11 term (1 - s * bfrfl) -> 1.

Otherwise, we only have access to rho_init, which we could use as well.

Comment thread isofit/core/forward.py
Comment thread isofit/core/forward.py Outdated
Comment thread isofit/core/forward.py
rho_dir_dif_hi = (
self.upsample(self.surface.wl, geom.bg_rfl)
if isinstance(geom.bg_rfl, np.ndarray)
else rho_dir_dir_hi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may be able to reduce the repeated adjacency effect code in forward, but it could wait until after 815, where we introduce a config entry self.use_background_rfl which would make it cleaner to read to just check this bool each time within forward.py.

@brentwilder brentwilder Apr 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, you could bring in the config in this PR too and I can hook it up in 815. see line 43-44, https://github.com/brentwilder/isofit/blob/bg_rfl/isofit/configs/sections/surface_config.py#L33-L47

...

As I write this though, perhaps that actually does not decrease the amount of times because you still need to call self.upsample...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you're saying here. Would a reasonable strategy be to leave as is for now and then update this to fit with #815 within #815?

I like the check being independent of a config key, but I don't love the type-check.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that the type check is risky in the long run, but I think we can catch this up in the refactor. Let's leave for now.

Moving L_tot calc into get_L_coupled
Simplifying coupled run path

Using geom to seed background in invert_simple functions

Small cleanup
@github-actions

Copy link
Copy Markdown
📊 Generated results:

URL: isofit/isofit-test-results#26
SHA: 8354cad

@evan-greenbrg

Copy link
Copy Markdown
Collaborator Author

Summary of results from Apply OE scale tests:

Magnitude 0.001 differences in reflectance solutions primarily driven by differences in aerosol solutions and Cos (i) issues.

image

Reflectance residuals at blue-end follow aerosol residuals.

image

Cosine angle issues are consistent:

image

@pgbrodrick

Copy link
Copy Markdown
Collaborator

For last check today, but I'm happy with the complexity level (given pending refactor), and comfortable with this level of AOD-based discrepancy. With concurrence on team-call, for merge.

@pgbrodrick pgbrodrick merged commit ef15fc5 into isofit:dev Apr 20, 2026
43 of 81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants