コード例 #1
0
ファイル: smps.py プロジェクト: fanmei/atm-py
        def xfer(dp, qa, qs):
            """
            Return the full-width, half-max of the transfer function in diameter space.
            This implementation ignores diffusion broadening.

            Parameters
            -----------
            dp: float
                particle size in nm
            qa: float
                aerosol flow rate in lpm
            qs: float
                aerosol flow rate in lpm

            Returns
            -------
            Width of transfer function in nm.
            """
            beta = float(qa)/float(qs)

            # Retrieve the center mobility
            zc = aerosol.z(dp, self.air, 1)

            # Upper bound of the mobility
            zm = (1-beta/2)*zc

            # Lower bound of the mobility
            zp = (1+beta/2)*zc

            return aerosol.z2d(zm, self.air, 1) - aerosol.z2d(zp, self.air, 1)
コード例 #2
0
        def xfer(dp, qa, qs):
            """
            Return the full-width, half-max of the transfer function in diameter space.
            This implementation ignores diffusion broadening.

            Parameters
            -----------
            dp: float
                particle size in nm
            qa: float
                aerosol flow rate in lpm
            qs: float
                aerosol flow rate in lpm

            Returns
            -------
            Width of transfer function in nm.
            """
            beta = float(qa) / float(qs)

            # Retrieve the center mobility
            zc = aerosol.z(dp, self.air, 1)

            # Upper bound of the mobility
            zm = (1 - beta / 2) * zc

            # Lower bound of the mobility
            zp = (1 + beta / 2) * zc

            return aerosol.z2d(zm, self.air, 1) - aerosol.z2d(zp, self.air, 1)
コード例 #3
0
ファイル: smps.py プロジェクト: fanmei/atm-py
    def __chargecorr__(diam, dn, gas, n=3, pos_neg=-1):
        """
        Correct the input concentrations for multiple charges.

        When running in SMPS mode, we must keep in mind that each size of particles can carry multiple charges.
        Particles with more charges will appear to be SMALLER than those with less.  So, we will index through the
        diameters backwards, get the number of the current selected size that would have charge n, and remove those
        from the lower bins to the upper bins.

        Parameters
        ----------
        diam:       array of float
                    array of diameters in nm
        dn:         array of integers
                    Array of particle concentrations corresponding to diameter 'diam'
        gas:        gas object
                    Gas object that defines the properties of the gas
        n:          int, optional
                    Number of charges to consider.  Default is 3.
        pos_neg:    int, optional
                    Positive or negative one indicating whether to consider positive or negative charges.
                    Default is -1.

        Returns
        -------
        None

        Notes
        ------
        The charge correction loops from top to bottom in the size distribution.
        This assumes that there are no particles beyond the probed distribution.
        If there are, there will be noticeable steps in the charge corrected distribution.

        Regarding the algorithm, we can solve for each bin by using the charging efficiency
        ala Gunn or Wiedensohler.  To solve, we use the following algorithm:

        1. Assume that the current bin holds ONLY singly charged particles.

        2. Calculate the fraction of particles that are expected to be singly charged
        at the current diameter, :math:'f_1\left(D_p\right)'.

        3. For each charge beyond 1:

            a) Get the charging efficiency of the current particle size for :math:'i' charges
            :math:'f_i \left(D_p\right)'

            b)

        """
        # Flip the incoming diamter array
        rdiam = np.copy(diam[::-1])

        # We are working backwards, so we need to have the length to get this all right...
        l = len(dn)-1

        # Inline function for finding the value closest to diameter d in the array diam
        fmin = lambda nd: (np.abs(np.asarray(diam) - nd)).argmin()

        for i, d in enumerate(rdiam):

            # Get the fraction of particles that are singly charged
            f1 = aerosol.ndistr(d, pos_neg, gas.t)

            for j in reversed(range(2, n+1)):  # Loop through charges 2 and higher backwards

                ne = j*pos_neg
                fi = aerosol.ndistr(d, ne, gas.t)

                # Mobility of multiply charged particles
                z_mult = abs(ne * aerosol.z(d, gas, pos_neg))

                # Diameter bin which contains the multiply charged particles
                d_mult = aerosol.z2d(z_mult, gas, 1)

                # Continue while the diameter specified is larger than the minimum diameter
                if d_mult >= diam[0]:

                    # Find the index of the multiple charges
                    k = fmin(d_mult)

                    # Remove the particles in bin k that belong in the current bin, but don't remove more
                    # particles than there are in the bin
                    dn[k] -= min(dn[l-i]*fi/f1, dn[k])

                # The total number of particlesi n the current bin is simply the number of singly charged
                # particles divided by the singly charged charging efficiency.
            dn[l-i] /= f1

        return None
コード例 #4
0
    def __chargecorr__(diam, dn, gas, n=3, pos_neg=-1):
        """
        Correct the input concentrations for multiple charges.

        When running in SMPS mode, we must keep in mind that each size of particles can carry multiple charges.
        Particles with more charges will appear to be SMALLER than those with less.  So, we will index through the
        diameters backwards, get the number of the current selected size that would have charge n, and remove those
        from the lower bins to the upper bins.

        Parameters
        ----------
        diam:       array of float
                    array of diameters in nm
        dn:         array of integers
                    Array of particle concentrations corresponding to diameter 'diam'
        gas:        gas object
                    Gas object that defines the properties of the gas
        n:          int, optional
                    Number of charges to consider.  Default is 3.
        pos_neg:    int, optional
                    Positive or negative one indicating whether to consider positive or negative charges.
                    Default is -1.

        Returns
        -------
        None

        Notes
        ------
        The charge correction loops from top to bottom in the size distribution.
        This assumes that there are no particles beyond the probed distribution.
        If there are, there will be noticeable steps in the charge corrected distribution.

        Regarding the algorithm, we can solve for each bin by using the charging efficiency
        ala Gunn or Wiedensohler.  To solve, we use the following algorithm:

        1. Assume that the current bin holds ONLY singly charged particles.

        2. Calculate the fraction of particles that are expected to be singly charged
        at the current diameter, :math:'f_1\left(D_p\right)'.

        3. For each charge beyond 1:

            a) Get the charging efficiency of the current particle size for :math:'i' charges
            :math:'f_i \left(D_p\right)'

            b)

        """
        # Flip the incoming diamter array
        rdiam = np.copy(diam[::-1])

        # We are working backwards, so we need to have the length to get this all right...
        l = len(dn) - 1

        # Inline function for finding the value closest to diameter d in the array diam
        fmin = lambda nd: (np.abs(np.asarray(diam) - nd)).argmin()

        for i, d in enumerate(rdiam):

            # Get the fraction of particles that are singly charged
            f1 = aerosol.ndistr(d, pos_neg, gas.t)

            for j in reversed(range(2, n + 1)):  # Loop through charges 2 and higher backwards

                ne = j * pos_neg
                fi = aerosol.ndistr(d, ne, gas.t)

                # Mobility of multiply charged particles
                z_mult = abs(ne * aerosol.z(d, gas, pos_neg))

                # Diameter bin which contains the multiply charged particles
                d_mult = aerosol.z2d(z_mult, gas, 1)

                # Continue while the diameter specified is larger than the minimum diameter
                if d_mult >= diam[0]:
                    # Find the index of the multiple charges
                    k = fmin(d_mult)

                    # Remove the particles in bin k that belong in the current bin, but don't remove more
                    # particles than there are in the bin
                    dn[k] -= min(dn[l - i] * fi / f1, dn[k])

                    # The total number of particlesi n the current bin is simply the number of singly charged
                    # particles divided by the singly charged charging efficiency.
            dn[l - i] /= f1

        return None