示例#1
0
    def ft_even_diffuse_reflection_matrix(self, frequency, eps_1, mu_s, mu_i,
                                          m_max, npol):

        assert mu_s is mu_i

        if isinstance(self.backscattering_coefficient,
                      dict):  # we have a dictionary with polarization
            diffuse_refl_coeff = smrt_matrix.zeros(
                (npol, m_max + 1, len(mu_i)))

            for m in range(m_max + 1):
                if m == 0:
                    coef = 0.5
                elif (m % 2) == 1:
                    coef = -1.0
                else:
                    coef = 1.0
                coef /= 4 * np.pi * mu_i  # SMRT requires scattering coefficient / 4 * pi

                coef /= m_max + 0.5  # ad hoc normalization to get the right backscatter. This is a trick to deal with the dirac.

                diffuse_refl_coeff[0, m, :] += coef * self._get_refl(
                    self.backscattering_coefficient['VV'], mu_i)
                diffuse_refl_coeff[1, m, :] += coef * self._get_refl(
                    self.backscattering_coefficient['HH'], mu_i)

        elif self.backscattering_coefficient is not None:
            raise SMRTError(
                "backscattering_coefficient must be a dictionary with keys VV and HH"
            )
        else:
            return smrt_matrix(0)

        return diffuse_refl_coeff
示例#2
0
def fresnel_transmission_matrix(eps_1, eps_2, mu1, npol):
    """compute the fresnel reflection matrix for/in medium 1 laying above medium 2.

    :param npol: number of polarizations to return.
    :param eps_1: permittivity of medium 1.
    :param eps_2: permittivity of medium 2.
    :param mu1: cosine zenith angle in medium 1.

    :returns: a matrix or the diagional depending on `return_as_diagonal`
"""

    mu1 = np.atleast_1d(mu1)
    assert len(mu1.shape) == 1  # 1D array

    transmission_coefficients = smrt_matrix.zeros((npol, len(mu1)))

    rv, rh, mu2 = fresnel_coefficients(eps_1, eps_2, mu1)

    transmission_coefficients[0] = 1 - abs2(rv)
    transmission_coefficients[1] = 1 - abs2(rh)
    if npol >= 3:
        transmission_coefficients[2] = mu2 / mu1 * (
            (1 + rv) * np.conj(1 + rh)).real  # TsangI  Eq 7.2.95
    if npol == 4:
        raise Exception(
            "to be implemented, the matrix is not diagonal anymore")

    return transmission_coefficients
示例#3
0
    def ft_even_diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s,
                                          mu_i, m_max, npol):

        assert mu_s is mu_i

        diffuse_refl_coeff = smrt_matrix.zeros((npol, m_max + 1, len(mu_i)))

        gamma = self.diffuse_reflection_matrix(frequency,
                                               eps_1,
                                               eps_2,
                                               mu_s,
                                               mu_i,
                                               dphi=np.pi,
                                               npol=npol)

        for m in range(m_max + 1):
            if m == 0:
                coef = 0.5
            elif (m % 2) == 1:
                coef = -1.0
            else:
                coef = 1.0
            coef /= (
                m_max + 0.5
            )  # ad hoc normalization to get the right backscatter. This is a trick to deal with the dirac.

            diffuse_refl_coeff[:, m, :] = coef * gamma[:, :]

        return diffuse_refl_coeff
示例#4
0
    def phase(self, mu_s, mu_i, dphi, npol=2):
        """Non-scattering phase matrix.

            Returns : null phase matrix

        """

        return smrt_matrix.zeros((npol, npol, len(dphi), len(mu_s), len(mu_i)))
    def ft_even_diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s, mu_i, m_max, npol):
        
        m = smrt_matrix.zeros((npol, m_max + 1, len_atleast_1d(mu_s)))

        # only mode 0, pola 0 and 1, are non-null
        m[0:2, 0, :] = 1.

        return m
示例#6
0
    def ft_even_phase(self, mu_s, mu_i, m_max, npol=None):
        """ Non-scattering phase matrix.

            Returns : null phase matrix

        """
        if npol is None:
            npol = 2 if m_max == 0 else 3

        return smrt_matrix.zeros((npol, npol, m_max + 1, len(mu_s), len(mu_i)))
示例#7
0
    def specular_reflection_matrix(self, frequency, eps_1, eps_2, mu1, npol):
        """compute the reflection coefficients for the azimuthal mode m
           and for an array of incidence angles (given by their cosine)
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mhu1: array of cosine of incident angles
        :param npol: number of polarization

"""
        assert len(mu1.shape) == 1  # 1D array

        return smrt_matrix.zeros((npol, len(mu1)))
示例#8
0
    def emissivity_matrix(self, frequency, eps_1, mu1, npol):

        if self.specular_reflection is None and self.backscatter_coefficient is None:
            self.specular_reflection = 1

        if npol > 2:
            raise NotImplementedError("active model is not yet implemented, need modification for the third compunant")

        emissivity = smrt_matrix.zeros((npol, len(mu1)))
        if isinstance(self.specular_reflection, dict):  # we have a dictionary with polarization
            emissivity[0] = 1 - self._get_refl(self.specular_reflection['V'], mu1)
            emissivity[1] = 1 - self._get_refl(self.specular_reflection['H'], mu1)
        else:  # we have a scalar, both polarization are the same
            emissivity[0] = emissivity[1] = 1 - self._get_refl(self.specular_reflection, mu1)

        return emissivity
示例#9
0
    def specular_reflection_matrix(self, frequency, eps_1, mu1, npol):

        if npol > 2 and not hasattr(Reflector, "stop_pol2_warning"):
            print("active model is not yet fully implemented, need modification for the third component")  # !!!
            Reflector.stop_pol2_warning = True

        if self.specular_reflection is None and self.backscattering_coefficient is None:
            self.specular_reflection = 1

        spec_refl_coeff = smrt_matrix.zeros((npol, len(mu1)))
        if isinstance(self.specular_reflection, dict):  # we have a dictionary with polarization
            spec_refl_coeff[0] = self._get_refl(self.specular_reflection['V'], mu1)
            spec_refl_coeff[1] = self._get_refl(self.specular_reflection['H'], mu1)
        else:  # we have a scalar, both polarization are the same
            spec_refl_coeff[0] = spec_refl_coeff[1] = self._get_refl(self.specular_reflection, mu1)

        return spec_refl_coeff
示例#10
0
    def diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s, mu_i,
                                  dphi, npol):
        """compute the reflection coefficients for an array of incident, scattered and azimuth angles 
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu1: array of cosine of incident angles
        :param npol: number of polarization

        :return: the reflection matrix
"""
        mu_s = np.atleast_1d(mu_s)
        mu_i = np.atleast_1d(mu_i)

        if not np.allclose(mu_s, mu_i) or not np.allclose(dphi, np.pi):
            raise NotImplementedError(
                "Only the backscattering coefficient is implemented at this stage. This is a very preliminary implementation"
            )

        if len(np.atleast_1d(dphi)) != 1:
            raise NotImplementedError(
                "Only the backscattering coefficient is implemented at this stage. "
            )

        R_normal, _, _ = fresnel_coefficients(eps_1, eps_2, np.ones(1))

        tantheta_i2 = 1 / mu_i**2 - 1

        smrt_norm = 1 / (4 * np.pi)

        gamma = smrt_norm / (2 * self.mean_square_slope) * np.abs(
            R_normal)**2 / mu_i**5 * np.exp(-tantheta_i2 /
                                            (2 * self.mean_square_slope))

        if self.shadow_correction:
            gamma *= 1 / (1 + shadow_function(self.mean_square_slope,
                                              1 / np.sqrt(tantheta_i2)))

        reflection_coefficients = smrt_matrix.zeros((npol, len(mu_i)))
        reflection_coefficients[0] = gamma
        reflection_coefficients[1] = gamma

        return reflection_coefficients
    def coherent_transmission_matrix(self, frequency, eps_1, eps_2, mu1, npol):
        """compute the transmission coefficients for an array of incidence angles (given by their cosine)
           in medium 1. Medium 2 is where the beam is transmitted. While Geometrical Optics, we here consider that power not reflected
           is scattered in the specular transmitted direction. This is an approximation which is reasonable in the context of a "1st order"
           geometrical optics.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu1: array of cosine of incident angles
        :param npol: number of polarization

        :return: the transmission matrix
"""
        go = GeometricalOptics(mean_square_slope=self.mean_square_slope, shadow_function=self.shadow_correction)
        total_reflection = go.reflection_coefficients(frequency, eps_1, eps_2, mu1)

        transmission_matrix = smrt_matrix.zeros((npol, len_atleast_1d(mu1)))
        transmission_matrix[0] = 1 - total_reflection[0]
        transmission_matrix[1] = 1 - total_reflection[1]

        return transmission_matrix
示例#12
0
    def diffuse_transmission_matrix(self, frequency, eps_1, eps_2, mu_t, mu_i,
                                    dphi, npol):
        """compute the transmission coefficients for an array of incident, scattered and azimuth angles
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu_i: array of cosine of incident angles
        :param mu_t: array of cosine of transmitted wave angles
        :param npol: number of polarization

        :return: the transmission matrix
"""
        n_2 = np.sqrt(eps_2)
        n_1 = np.sqrt(eps_1)

        eta1_eta = n_1 / n_2  # eta1 is the impedance in medium 2 and eta in medium 1. Impedance is sqrt(permeability/permittivity)

        if abs(eta1_eta - 1) < 1e-6:
            raise NotImplementedError(
                "the case of successive layers with identical index (%g) is not implemented"
                % n_2)
            return 1 / (
                4 * np.pi
            )  # return the identity matrix. The coef is to be checked.

        mu_i = np.atleast_1d(self.clip_mu(mu_i))[np.newaxis, np.newaxis, :]
        mu_t = np.atleast_1d(self.clip_mu(mu_t))[np.newaxis, :, np.newaxis]
        dphi = np.atleast_1d(dphi)[:, np.newaxis, np.newaxis]

        sin_i = np.sqrt(1 - mu_i**2)
        sin_t = np.sqrt(1 - mu_t**2)

        cos_phi = np.cos(dphi)
        sin_phi = np.sin(dphi)

        ki = vector3.from_xyz(sin_i, 0, -mu_i)
        kt = vector3.from_xyz(sin_t * cos_phi, sin_t * sin_phi, -mu_t)

        # compute the local transmission Fresnel coefficient
        ktd = ki * n_1.real - kt * n_2.real  # Eq 2.1.87

        n = ktd / (np.sign(ktd.z) * ktd.norm)  # Eq 2.1.128

        n_kt = -vector3.dot(n, kt)
        n_ki = -vector3.dot(n, ki)

        # compute Fresnel coefficients at stationary point
        Rh = (n_1.real * n_ki - n_2.real * n_kt) / (
            n_1.real * n_ki + n_2.real * n_kt)  # Eq. 2.1.132a
        Rv = (n_2.real * n_ki - n_1.real * n_kt) / (
            n_2.real * n_ki + n_1.real * n_kt)  # Eq. 2.1.132b

        no_compatible_slopes = (n_kt < 0) | (n_ki < 0)

        Rh[no_compatible_slopes] = -1
        Rv[no_compatible_slopes] = -1

        # define polarizations
        ht = vector3.from_xyz(-sin_phi, cos_phi, 0)
        vt = vector3.from_xyz(-mu_t * cos_phi, -mu_t * sin_phi, -sin_t)

        hi = vector3.from_xyz(0, 1, 0)
        vi = vector3.from_xyz(-mu_i, 0, -sin_i)

        # compute the cosines
        cross_ki_kt_norm = vector3.cross(ki, kt).norm
        colinear = cross_ki_kt_norm < 1e-4
        # avoid warning due to divide error, the colinear case is solved independantly:
        cross_ki_kt_norm[colinear] = 1

        ht_ki = vector3.dot(ht, ki) / cross_ki_kt_norm
        ht_ki[colinear] = -1  # checked with sympy

        vt_ki = vector3.dot(vt, ki) / cross_ki_kt_norm
        vt_ki[colinear] = 0  # checked with sympy

        hi_kt = vector3.dot(hi, kt) / cross_ki_kt_norm
        hi_kt[colinear] = 1  # checked with sympy
        vi_kt = vector3.dot(vi, kt) / cross_ki_kt_norm
        vi_kt[colinear] = 0  # checked with sympy

        Wvv = abs2(ht_ki * hi_kt * (1 + Rh) + vt_ki * vi_kt *
                   (1 + Rv) * eta1_eta)  # Eqs 2.1.130 in Tsang_tomeIII
        Whh = abs2(vt_ki * vi_kt * (1 + Rh) + ht_ki * hi_kt *
                   (1 + Rv) * eta1_eta)

        Whv = abs2(-vt_ki * hi_kt * (1 + Rh) + ht_ki * vi_kt *
                   (1 + Rv) * eta1_eta)
        Wvh = abs2(ht_ki * vi_kt * (1 + Rh) - vt_ki * hi_kt *
                   (1 + Rv) * eta1_eta)

        transmission_coefficients = smrt_matrix.zeros(
            (npol, npol, dphi.shape[0], mu_t.shape[1], mu_i.shape[2]))

        transmission_coefficients[0, 0] = Wvv
        transmission_coefficients[0, 1] = Wvh
        transmission_coefficients[1, 0] = Whv
        transmission_coefficients[1, 1] = Whh

        smrt_norm = 1 / (4 * np.pi
                         )  # SMRT requires scattering coefficient / 4 * pi

        coef = smrt_norm * 2 * eps_2 * ktd.norm2 * n_kt**2 / (eta1_eta * self.mean_square_slope * mu_i * ktd.z**4) * \
            np.exp(-(ktd.x**2 + ktd.y**2) / (2 * ktd.z**2 * self.mean_square_slope))   # Eq. 2.1.130   NB: k1^2 -> eps_2

        if self.shadow_correction:
            # this hack to avoid division-by-zero is safe, because the shadow_function is only important for large angles
            sin_i[sin_i < 1e-3] = 1e-3
            sin_t[sin_t < 1e-3] = 1e-3
            s = 1 / (1 + shadow_function(self.mean_square_slope, mu_i / sin_i)
                     + shadow_function(self.mean_square_slope, mu_t / sin_t))
            coef *= s

        return transmission_coefficients * coef.real
示例#13
0
    def diffuse_transmission_matrix(self, frequency, eps_1, eps_2, mu_t, mu_i, dphi, npol):
        """compute the transmission coefficients for an array of incident, scattered and azimuth angles 
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu_i: array of cosine of incident angles
        :param mu_t: array of cosine of transmitted wave angles
        :param npol: number of polarization

        :return: the transmission matrix
"""
        n_2 = np.sqrt(eps_2)
        n_1 = np.sqrt(eps_1)

        eta1_eta = n_1 / n_2  # eta1 is the impedance in medium 2 and eta in medium 1. Impedance is sqrt(permeability/permittivity)

        mu_i = np.atleast_1d(mu_i)[np.newaxis, np.newaxis, :]
        mu_t = np.atleast_1d(mu_t)[np.newaxis, :, np.newaxis]
        dphi = np.atleast_1d(dphi)[:, np.newaxis, np.newaxis]

        sin_i = np.sqrt(1 - mu_i**2)
        sin_t = np.sqrt(1 - mu_t**2)

        cos_phi = np.cos(dphi)
        sin_phi = np.sin(dphi)

        ki = vector3.from_xyz(sin_i, 0, -mu_i)
        kt = vector3.from_xyz(sin_t * cos_phi, sin_t * sin_phi, -mu_t)

        # compute the local transmission Fresnel coefficient
        ktd = n_1.real * ki - n_2.real * kt   # Eq 2.1.87

        n = ktd / (np.sign(ktd.z) * ktd.norm)  # Eq 2.1.128

        mu_local = -vector3.dot(n, ki)

        Rv, Rh, _ = fresnel_coefficients(eps_1, eps_2, mu_local)

        n_kt = vector3.dot(n, kt)
        n_kt[mu_local < 0] = 0
 
        # define polarizations
        ht = vector3.from_xyz(-sin_phi, cos_phi, 0)
        vt = vector3.from_xyz(-mu_t * cos_phi, -mu_t * sin_phi, -sin_t)

        hi = vector3.from_xyz(0, 1, 0)
        vi = vector3.from_xyz(-mu_i, 0, -sin_i)

        # compute the cosines

        ht_ki = vector3.dot(ht, ki)
        vt_ki = vector3.dot(vt, ki)

        hi_kt = vector3.dot(hi, kt)
        vi_kt = vector3.dot(vi, kt)

        Wvv = abs2( ht_ki * hi_kt * (1 + Rh) + vt_ki * vi_kt * (1 + Rv) * eta1_eta)   # Eqs 2.1.130 in Tsang_tomeIII
        Whh = abs2( vt_ki * vi_kt * (1 + Rh) + ht_ki * hi_kt * (1 + Rv) * eta1_eta)

        Whv = abs2(-vt_ki * hi_kt * (1 + Rh) + ht_ki * vi_kt * (1 + Rv) * eta1_eta)
        Wvh = abs2( ht_ki * vi_kt * (1 + Rh) - vt_ki * hi_kt * (1 + Rv) * eta1_eta)
        
        transmission_coefficients = smrt_matrix.zeros((npol, npol, dphi.shape[0], mu_t.shape[1], mu_i.shape[2]))

        transmission_coefficients[0, 0] = Wvv
        transmission_coefficients[0, 1] = Wvh
        transmission_coefficients[1, 0] = Whv
        transmission_coefficients[1, 1] = Whh

        smrt_norm = 1 / (4 * np.pi)   # SMRT requires scattering coefficient / 4 * pi

        coef = smrt_norm * 2 * eps_2 / (eta1_eta * self.mean_square_slope) / mu_i * \
                ktd.norm2 * n_kt**2 / (vector3.cross(ki, kt).norm2**2 * ktd.z**4) * \
                np.exp(-(ktd.x**2 + ktd.y**2) / (2 * ktd.z**2 * self.mean_square_slope))   # Eq. 2.1.130   NB: k1^2 -> eps_2

        if self.shadow_correction:
            s = 1 / (1 + shadow_function(self.mean_square_slope, mu_i/sin_i) + shadow_function(self.mean_square_slope, mu_t/sin_t))
            coef *= s

        return transmission_coefficients * coef.real
示例#14
0
    def diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s, mu_i, dphi, npol):
        """compute the reflection coefficients for an array of incident, scattered and azimuth angles 
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu1: array of cosine of incident angles
        :param npol: number of polarization

        :return: the reflection matrix
"""
        mu_i = np.atleast_1d(mu_i)[np.newaxis, np.newaxis, :]
        mu_s = np.atleast_1d(mu_s)[np.newaxis, :, np.newaxis]
        dphi = np.atleast_1d(dphi)[:, np.newaxis, np.newaxis]

        sin_i = np.sqrt(1 - mu_i**2)
        sin_s = np.sqrt(1 - mu_s**2)

        cos_phi = np.cos(dphi)
        sin_phi = np.sin(dphi)

        ki = vector3.from_xyz(sin_i, 0, -mu_i)
        ks = vector3.from_xyz(sin_s * cos_phi, sin_s * sin_phi, mu_s)

        # compute the local reflection Fresnel coefficient
        kd = ki - ks   # in principe: *sqrt(eps_1), but in the following it appears everywhere as a ratio

        n = kd / (np.sign(kd.z) * kd.norm)  # EQ 2.1.223 #equivalent to np.vector3(kd_x / kd_z, kd_y / kd_z, 1)

        mu_local = -vector3.dot(n, ki)

        Rv, Rh, _ = fresnel_coefficients(eps_1, eps_2, mu_local)
 
        # define polarizations
        hs = vector3.from_xyz(-sin_phi, cos_phi, 0)
        vs = vector3.from_xyz(mu_s * cos_phi, mu_s * sin_phi, -sin_s)

        hi = vector3.from_xyz(0, 1, 0)
        vi = vector3.from_xyz(-mu_i, 0, -sin_i)

        # compute the dot products
        hs_ki = vector3.dot(hs, ki)
        vs_ki = vector3.dot(vs, ki)

        hi_ks = vector3.dot(hi, ks)
        vi_ks = vector3.dot(vi, ks)

        fvv = abs2( hs_ki * hi_ks * Rh + vs_ki* vi_ks * Rv)   # Eqs 2.1.122 in Tsang_tomeIII
        fhh = abs2( vs_ki * vi_ks * Rh + hs_ki* hi_ks * Rv)

        fhv = abs2( vs_ki * hi_ks * Rh - hs_ki* vi_ks * Rv)
        fvh = abs2( hs_ki * vi_ks * Rh + vs_ki* hi_ks * Rv)
        
        reflection_coefficients = smrt_matrix.zeros((npol, npol, dphi.shape[0], mu_s.shape[1], mu_i.shape[2]))
        reflection_coefficients[0, 0] = fvv
        reflection_coefficients[0, 1] = fvh
        reflection_coefficients[1, 0] = fhv
        reflection_coefficients[1, 1] = fhh

        smrt_norm = 1 / (4 * np.pi)  #  divide by 4*pi because this is the norm for SMRT

        coef = smrt_norm / (2 * self.mean_square_slope) / mu_i * kd.norm2**2 / (vector3.cross(ki, ks).norm2**2 * kd.z**4) * \
                         np.exp( - (kd.x**2 + kd.y**2)/ (2 * kd.z**2 * self.mean_square_slope))  # Eq. 2.1.124 

        if self.shadow_correction:

            backward = dphi == np.pi
            higher_thetas = mu_s <= mu_i
            zero_i = backward & higher_thetas
            zero_s = backward & ~higher_thetas

            s = 1 / (1 + zero_i * shadow_function(self.mean_square_slope, mu_i/sin_i) + zero_s * shadow_function(self.mean_square_slope, mu_s/sin_s))
            coef *= s

        return reflection_coefficients * coef
示例#15
0
    def diffuse_reflection_matrix(self,
                                  frequency,
                                  eps_1,
                                  eps_2,
                                  mu_s,
                                  mu_i,
                                  dphi,
                                  npol,
                                  debug=False):
        """compute the reflection coefficients for an array of incident, scattered and azimuth angles 
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu1: array of cosine of incident angles
        :param npol: number of polarization

        :return: the reflection matrix
"""
        mu_s = np.atleast_1d(mu_s)
        mu_i = np.atleast_1d(mu_i)

        if not np.allclose(mu_s, mu_i) or not np.allclose(dphi, np.pi):
            raise NotImplementedError(
                "Only the backscattering coefficient is implemented at this stage. This is a very preliminary implementation"
            )

        if len(np.atleast_1d(dphi)) != 1:
            raise NotImplementedError(
                "Only the backscattering coefficient is implemented at this stage. "
            )

        mu = mu_i[None, :]
        k = vector3.from_angles(
            2 * np.pi * frequency / C_SPEED * np.sqrt(eps_1).real, mu, 0)
        eps_r = eps_2 / eps_1

        # check validity
        warning = None
        ks = abs(k.norm * self.roughness_rms)
        if ks > 3:
            warning = "Warning, roughness_rms is too high for the given wavelength. Limit is ks < 3. Here ks=%g" % ks

        kskl = abs(ks * k.norm * self.corr_length)
        if kskl > np.sqrt(eps_r):
            warning = "Warning, roughness_rms or correlation_length are too high for the given wavelength. Limit is ks * kl < sqrt(eps_r). Here ks*kl=%g and sqrt(eps_r)=%g" % (
                kskl, np.sqrt(eps_r))

        if warning:
            if self.warning_handling == "print":
                print(warning)
            elif self.warning_handling == "nan":
                return smrt_matrix.full((npol, len(mu_i)), np.nan)
        # chekc validity done

        Rv, Rh, _ = fresnel_coefficients(eps_1, eps_2, mu_i)

        fvv = 2 * Rv / mu  # Eq 44 in Fung et al. 1992
        fhh = -2 * Rh / mu  # Eq 45 in Fung et al. 1992

        # prepare the series
        N = self.series_truncation
        n = np.arange(1, N + 1, dtype=np.float64)[:, None]

        rms2 = self.roughness_rms**2

        # Kirchoff term
        Iscalar_n = (2 * k.z)**n * np.exp(-rms2 * k.z**2)
        Ivv_n = Iscalar_n * fvv  # Eq 82 in Fung et al. 1992
        Ihh_n = Iscalar_n * fhh

        # Complementary term
        mu2 = mu**2
        sin2 = 1 - mu2
        tan2 = sin2 / mu2
        Ivv_n += k.z**n * (
            sin2 / mu * (1 + Rv)**2 * (1 - 1 / eps_r) * (1 + tan2 / eps_r)
        )  # part of Eq 91. We don't use all the simplification because we want validity for n>1, especially not np.exp(-rms2*k.z**2)=1
        Ihh_n += -k.z**n * (sin2 / mu * (1 + Rh)**2 *
                            (eps_r - 1) / mu2)  # part of Eq 95.

        # compute the series
        rms2_over_fractorial = np.cumprod(rms2 / n)[:, None]

        # Eq 82 in Fung et al. 1992
        coef = k.norm2 / 2 * np.exp(-2 * rms2 * k.z**2)
        coef_n = rms2_over_fractorial * self.W_n(n, -2 * k.x)

        sigma_vv = coef * np.sum(coef_n * abs2(Ivv_n), axis=0)
        sigma_hh = coef * np.sum(coef_n * abs2(Ihh_n), axis=0)

        #if debug:
        #    self.sigma_vv_1 = ( 8*k.norm2**2*rms2*abs2(Rv*mu2 + (1-mu2)*(1+Rv)**2 / 2 * (1 - 1 / eps_r)) * self.W_n(1, -2 * k.x) ).flat
        #    self.sigma_hh_1 = ( 8*k.norm2**2*rms2*abs2(Rh*mu2) * self.W_n(1, -2 * k.x) ).flat

        reflection_coefficients = smrt_matrix.zeros((npol, len(mu_i)))
        reflection_coefficients[0] = sigma_vv / (4 * np.pi * mu_i)
        reflection_coefficients[1] = sigma_hh / (4 * np.pi * mu_i)

        return reflection_coefficients
示例#16
0
    def diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s, mu_i,
                                  dphi, npol):
        """compute the reflection coefficients for an array of incident, scattered and azimuth angles 
           in medium 1. Medium 2 is where the beam is transmitted.

        :param eps_1: permittivity of the medium where the incident beam is propagating.
        :param eps_2: permittivity of the other medium
        :param mu1: array of cosine of incident angles
        :param npol: number of polarization

        :return: the reflection matrix
"""
        mu_i = np.atleast_1d(self.clip_mu(mu_i))[np.newaxis, np.newaxis, :]
        mu_s = np.atleast_1d(self.clip_mu(mu_s))[np.newaxis, :, np.newaxis]
        dphi = np.atleast_1d(dphi)[:, np.newaxis, np.newaxis]

        sin_i = np.sqrt(1 - mu_i**2)
        sin_s = np.sqrt(1 - mu_s**2)

        cos_phi = np.cos(dphi)
        sin_phi = np.sin(dphi)

        ki = vector3.from_xyz(sin_i, 0, -mu_i)
        ks = vector3.from_xyz(sin_s * cos_phi, sin_s * sin_phi, mu_s)

        # compute the local reflection Fresnel coefficient
        kd = ki - ks  # in principe: *sqrt(eps_1), but in the following it appears everywhere as a ratio

        n = kd / (
            np.sign(kd.z) * kd.norm
        )  # EQ 2.1.123 #equivalent to np.vector3(kd_x / kd_z, kd_y / kd_z, 1)

        mu_local = -vector3.dot(n, ki)
        assert (np.all(mu_local >= 0))
        assert (np.all(mu_local <= 1.0001))  # compare with some tolerance
        Rv, Rh, _ = fresnel_coefficients(eps_1, eps_2, self.clip_mu(mu_local))

        # define polarizations
        hs = vector3.from_xyz(-sin_phi, cos_phi, 0)
        vs = vector3.from_xyz(mu_s * cos_phi, mu_s * sin_phi, -sin_s)

        hi = vector3.from_xyz(0, 1, 0)
        vi = vector3.from_xyz(-mu_i, 0, -sin_i)

        # compute the dot products
        cross_ki_ks_norm = vector3.cross(ki, ks).norm
        colinear = cross_ki_ks_norm < 1e-4
        # avoid warning due to divide error, the colinear case is solved independantly:
        cross_ki_ks_norm[colinear] = 1

        hs_ki = vector3.dot(hs, ki) / cross_ki_ks_norm
        hs_ki[colinear] = -1
        vs_ki = vector3.dot(vs, ki) / cross_ki_ks_norm
        vs_ki[colinear] = 0

        hi_ks = vector3.dot(hi, ks) / cross_ki_ks_norm
        hi_ks[colinear] = 1

        vi_ks = vector3.dot(vi, ks) / cross_ki_ks_norm
        vi_ks[colinear] = 0

        fvv = abs2(hs_ki * hi_ks * Rh +
                   vs_ki * vi_ks * Rv)  # Eqs 2.1.122 in Tsang_tomeIII
        fhh = abs2(vs_ki * vi_ks * Rh + hs_ki * hi_ks * Rv)

        fhv = abs2(vs_ki * hi_ks * Rh - hs_ki * vi_ks * Rv)
        fvh = abs2(hs_ki * vi_ks * Rh - vs_ki * hi_ks * Rv)

        reflection_coefficients = smrt_matrix.zeros(
            (npol, npol, dphi.shape[0], mu_s.shape[1], mu_i.shape[2]))
        reflection_coefficients[0, 0] = fvv
        reflection_coefficients[0, 1] = fvh
        reflection_coefficients[1, 0] = fhv
        reflection_coefficients[1, 1] = fhh

        smrt_norm = 1 / (4 * np.pi
                         )  # divide by 4*pi because this is the norm for SMRT

        coef = smrt_norm / (2 * self.mean_square_slope) / mu_i * kd.norm2**2 / kd.z**4 * \
            np.exp(-(kd.x**2 + kd.y**2) / (2 * kd.z**2 * self.mean_square_slope))  # Eq. 2.1.124

        if self.shadow_correction:
            backward = dphi == np.pi
            higher_thetas = mu_s <= mu_i
            zero_i = backward & higher_thetas
            zero_s = backward & ~higher_thetas
            # this hack to avoid division-by-zero is safe, because the shadow_function is only important for large angles
            sin_i[sin_i < 1e-3] = 1e-3
            sin_s[sin_s < 1e-3] = 1e-3

            s = 1 / (1 + (~zero_i) *
                     shadow_function(self.mean_square_slope, mu_i / sin_i) +
                     (~zero_s) *
                     shadow_function(self.mean_square_slope, mu_s / sin_s))
            coef *= s

        return reflection_coefficients * coef
示例#17
0
    def diffuse_reflection_matrix(self, frequency, eps_1, eps_2, mu_s, mu_i, dphi, npol):

        m = smrt_matrix.zeros((npol, len_atleast_1d(dphi), len_atleast_1d(mu_i)))
        m[0:2, :, :] = 1.

        return m