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)
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)
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
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