[bug fix] Correction of fresnel_polarized for complex IORs (metallic) #1161
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix the imaginary part of cosine refracted angles for complex IORs (metallic) in
fresnel_polarized()
Description
1. Motivation
First of all, note that there are two conventions:$\exp\left(+i\omega t\right)$ and $\exp\left(-i\omega t\right)$ formulations to express waves. Mitsuba 3 uses the former one ( $\exp\left(+i\omega t\right)$ ), which yields $\eta = n - ik$ formulation for complex refractive indices.
I would not discuss this background since it has already been discussed in Issue #1113 and PR #1150 with @tizian .
This PR fixes the remained problem raised in Issue #1113 . The current Mitsuba 3 produces wrong sign of imaginary parts of$\cos\tilde{\theta}_t$ ($\tilde\theta_t$ denotes a complex refracted angle) for complex IORs.
Concretely, with the$\exp\left(+i\omega t\right)$ convention, my claim is that $\Im \cos \tilde\theta_t \le 0$ , as best of my knowledge.
However current implementation of
fresnel_polarized(Float cos_theta_i, dr::Complex<Float> eta)
produces inconsistent signs forcos_theta_t
depending on ranges of arguments.While a technical reasoning for my claim$\Im \cos \tilde\theta_t \le 0$ is contained in Issue #1113, I would like to focus on concrete outputs for
fresnel_polarized()
here.2. Discontinuous outputs for
fresnel_polarized
As the above code, let's imagine Fresnel refectance values for slightly different two refractive indices.
It will be nature that two results would be almost equal, but the current Mitsuba 3 implementation produces sign flippling for
a_s
anda_p
as follows.BEFORE:
After bug fix by this PR, the results have changed as follows.
AFTER:
3. Reproducing plots in the documentation
I also provide a verification through reproducing plots of reflectance and phase delay in the Mitsuba 3 documentation.$\Im \cos\theta_t\le 0$ is correct and $\Im \cos\theta_t\ge 0$ is not relavant to the convention which Mitsuba 3 relies on.
Mitsuba function
fresnel_polarized()
does not returns complex values ofcos_theta_t
(it returns only the real part), so also implemented a short numpy code to showFigure 1.
Let's compare it with Figure 12 in the documentation. From the first and second column in Figure 1, we can see$\Im \cos\theta_t \le 0$ produces the same plots as the documentation. Current Mitsuba 3 implementaion of
fresnel_polarized(Float, Float)
also produces the same results as the second column, so I did not modifiedfresnel_polarized(Float, Float)
. Figure 1 does not changed by this PR.On the other hand, for another overloaded function
fresnel_polarized(Float, dr::Complex<Float>)
, it yields wrong values but this error is somewhat obscure since it produces correct value for0.183-3.43j
but incorrect one for0.5-1e-8j
.I provide a diagram to show how the current implementation has a bug.
Figure 2.
(a) shows ranges of the complex IOR. By our convention, we focus on the region of orange and red colors.$\cos\theta_t$ with a negative real part of a IOR (Sec. 17.3.1 in [Modern Electrodynamics - Andrew Zangwill]). However, I cannot handle such cases due to my limited knowledge. Thus I would like to focus on cases with $\Re\eta \ge 0$ , which covers all materials implemented in Mitsuba 3)
(I consider we need a much more sophisticated careful discussion for signs for complex IORs and
In (a) there are two markers for specific IORs: i) and ii). I will show plots like Figure 1 for cases of the two markers later.
(b) shows$\cos^2\theta_t$ . Note that due to the range of $\sin\theta_i$ (0 to 1), specific IOR values i) and ii) have been changed into lines. For i) $\eta=0.5-10^{-8}i$ , a circle marker indicates a specific value of $\cos\theta_i=0.5$ , which is the case reported above (2. Discontinuous outputs for
fresnel_polarized
).(c) indicates correct values of$\cos\theta_t$ . Choosing the $\exp\left(+i\omega t\right)$ convention, we should choose the lower half-infinite red line on $\Re = 0$ .
While directly applying$\Re = 0$ . It can be corrected by (f) (= this PR).
sqrt
(in Dr.Jit and most of other scientific computing library), the resulting value shown in (d) has wrong sign of the imaginary part whenHowever, current Mitsuba 3 implementation uses (e), which produces incorrect values depending on arguments. For instance, the IOR ii)$\eta=0.183-3.43i$ (Figure 14 of the documentation) yields correct values.
Figure 3. (Applying this PR still yields the same result)
However, the IOR ii)$\eta=0.5-10^{-8}i$ yields flipped signs in $\Im \cos\theta_t$ .
Figure 4. (Applying this commit changes the results in the third column. I manually attached the third column of the changed result as the forth column of this figure.)
Though this PR,$\cos\theta_t$ with consistent negative signs for imaginary parts.
fresnel_polarized
will produces correct values ofChecklist
cuda_*
andllvm_*
variants. If you can't test this, please leave below