コード例 #1
0
def compute_mass_rate_derivative_AS_num(w_s, R_p, T_p, rho_p, T_amb, p_amb,
                                        S_amb, e_s_amb, L_v, K, D_v, sigma_p):
    m_p = mp.compute_mass_from_radius_jit(R_p, rho_p)
    m_s = w_s * m_p

    h = m_p * machine_epsilon_sqrt

    m_p1 = m_p + h
    w_s1 = m_s / m_p1
    rho_p1 = mp.compute_density_AS_solution(w_s1, T_p)
    R_p1 = mp.compute_radius_from_mass_jit(m_p1, rho_p1)
    sigma_p1 = mp.compute_surface_tension_AS(w_s1, T)

    gamma = mp.compute_mass_rate_AS(w_s1, R_p1, T_p, rho_p1, T_amb, p_amb,
                                    S_amb, e_s_amb, L_v, K, D_v, sigma_p1)
    m_p2 = m_p - h
    w_s2 = m_s / m_p2
    rho_p2 = mp.compute_density_AS_solution(w_s2, T_p)
    R_p2 = mp.compute_radius_from_mass_jit(m_p2, rho_p2)
    sigma_p2 = mp.compute_surface_tension_AS(w_s2, T)

    gamma -= mp.compute_mass_rate_AS(w_s2, R_p2, T_p, rho_p2, T_amb, p_amb,
                                     S_amb, e_s_amb, L_v, K, D_v, sigma_p2)

    return gamma / (m_p1 - m_p2)
コード例 #2
0
def compute_kernel_Long_Bott_m(m_i, m_j, mass_density):
    R_i = compute_radius_from_mass_jit(m_i, mass_density)
    R_j = compute_radius_from_mass_jit(m_j, mass_density)
    return compute_kernel_Long_Bott_R(R_i, R_j)
コード例 #3
0
def collision_step_Long_Bott_Ecol_const_2D_multicomp_np(
        xis, m_w, m_s, radii, vel, mass_densities, dt_over_dV, E_col_grid,
        no_cols):
    no_SIPs = xis.shape[0]

    rnd = np.random.rand((no_SIPs * (no_SIPs - 1)) // 2)

    #    ind_kernel = create_kernel_index_array(
    #                     radii, no_SIPs,
    #                     R_kernel_low_log, bin_factor_R_log, no_kernel_bins)

    # check each i-j combination for a possible collection event
    cnt = 0
    for i in range(0, no_SIPs - 1):
        for j in range(i + 1, no_SIPs):
            if xis[i] <= xis[j]:
                ind_min = i
                ind_max = j
            else:
                ind_min = j
                ind_max = i
            xi_min = xis[ind_min]  # = nu_i in Unt
            xi_max = xis[ind_max]  # = nu_j in Unt
            m_w_min = m_w[ind_min]  # = mu_i in Unt, not necc. the smaller mass
            m_w_max = m_w[ind_max]  # = mu_j in Unt, not necc. the larger mass
            m_s_min = m_s[ind_min]  # = mu_i in Unt, not necc. the smaller mass
            m_s_max = m_s[ind_max]  # = mu_j in Unt, not necc. the larger mass


            p_crit = xi_max * dt_over_dV \
                     * compute_kernel_hydro(
                           radii[i], radii[j],
                           E_col_grid,
                           # abs difference of 2D vectors
                           math.sqrt( (vel[0,i] - vel[0,j])**2
                                      + (vel[1,i] - vel[1,j])**2 ) )

            if p_crit > 1.0:
                # multiple collection
                xi_col = p_crit * xi_min  # p_crit = xi_col / xi_min
                m_w[ind_min] = m_w_min + p_crit * m_w_max
                m_s[ind_min] = m_s_min + p_crit * m_s_max
                # mass changed: update radius
                # IMPORTANT: need to put (m_w + m_s) in paranthesis for jit
                radii[ind_min] =\
                    compute_radius_from_mass_jit((m_w[ind_min] + m_s[ind_min]),
                                                 mass_densities[ind_min])
                #                radii[ind_min] =\
                #                    compute_radius_from_mass_jit(m_w[ind_min] + m_s[ind_min],
                #                                                 mass_densities[ind_min])
                xis[ind_max] -= xi_col
                # rad of ind_min changed -> update kernel index:
                #                ind_kernel[ind_min] = \
                #                    compute_kernel_index(radii[ind_min], R_kernel_low_log,
                #                                         bin_factor_R_log, no_kernel_bins)
                no_cols[1] += 1
            elif p_crit > rnd[cnt]:
                no_cols[0] += 1
                xi_rel_dev = (xi_max - xi_min) / xi_max
                if xi_rel_dev < 1.0E-5:
                    print("xi_i approx xi_j, xi_rel_dev =", xi_rel_dev,
                          " in collision")
                    xi_ges = xi_min + xi_max
                    m_w[ind_min] = 2.0 * ( xi_min*m_w_min + xi_max*m_w_max ) \
                                      / xi_ges
                    m_s[ind_min] = 2.0 * ( xi_min*m_s_min + xi_max*m_s_max ) \
                                      / xi_ges
                    m_w[ind_max] = m_w[ind_min]
                    m_s[ind_max] = m_s[ind_min]
                    # IMPORTANT: need to put (m_w + m_s) in paranthesis for jit
                    radii[ind_min] =\
                        compute_radius_from_mass_jit((m_w[ind_min] + m_s[ind_min]),
                                                     mass_densities[ind_min])
                    #                    radii[ind_min] =\
                    #                        compute_radius_from_mass_jit(m_w[ind_min]+m_s[ind_min],
                    #                                                     mass_densities[ind_min])
                    radii[ind_max] = radii[ind_min]
                    xis[ind_max] = 0.5 * 0.7 * xi_ges
                    xis[ind_min] = 0.5 * xi_ges - xis[ind_max]
                    # radius of ind_min AND ind_max changed to same radii
                    # -> update kernel ind:
#                    ind_kernel[ind_min] = \
#                        compute_kernel_index(radii[ind_min], R_kernel_low_log,
#                                             bin_factor_R_log, no_kernel_bins)
#                    ind_kernel[ind_max] = ind_kernel[ind_min]
                else:
                    m_w[ind_min] += m_w_max
                    m_s[ind_min] += m_s_max
                    # IMPORTANT: need to put (m_w + m_s) in paranthesis for jit
                    radii[ind_min] =\
                        compute_radius_from_mass_jit((m_w[ind_min] + m_s[ind_min]),
                                                     mass_densities[ind_min])
                    #                    radii[ind_min] =\
                    #                        compute_radius_from_mass_jit(m_w[ind_min]+m_w[ind_min],
                    #                                                     mass_densities[ind_min])
                    xis[ind_max] -= xi_min
                    # rad of ind_min changed -> update kernel index:


#                    ind_kernel[ind_min] = \
#                        compute_kernel_index(radii[ind_min], R_kernel_low_log,
#                                             bin_factor_R_log, no_kernel_bins)
            cnt += 1
コード例 #4
0
def collision_step_Ecol_grid_R_np(xis, masses, radii, vel, mass_densities,
                                  dt_over_dV, E_col_grid, no_kernel_bins,
                                  R_kernel_low_log, bin_factor_R_log, no_cols):
    no_SIPs = xis.shape[0]

    rnd = np.random.rand((no_SIPs * (no_SIPs - 1)) // 2)

    ind_kernel = create_kernel_index_array(radii, no_SIPs, R_kernel_low_log,
                                           bin_factor_R_log, no_kernel_bins)

    # check each i-j combination for a possible collection event
    cnt = 0
    for i in range(0, no_SIPs - 1):
        for j in range(i + 1, no_SIPs):
            if xis[i] <= xis[j]:
                ind_min = i
                ind_max = j
            else:
                ind_min = j
                ind_max = i
            xi_min = xis[ind_min]  # = nu_i in Unt
            xi_max = xis[ind_max]  # = nu_j in Unt
            m_min = masses[
                ind_min]  # = mu_i in Unt, not necc. the smaller mass
            m_max = masses[ind_max]  # = mu_j in Unt, not necc. the larger mass

            p_crit = xi_max * dt_over_dV \
                     * compute_kernel_hydro(
                           radii[i], radii[j],
                           E_col_grid[ind_kernel[i], ind_kernel[j]],
                           abs(vel[i]-vel[j]))

            if p_crit > 1.0:
                # multiple collection
                xi_col = p_crit * xi_min
                masses[ind_min] = (xi_min * m_min + xi_col * m_max) / xi_min
                # mass changed: update radius
                radii[ind_min] =\
                    compute_radius_from_mass_jit(masses[ind_min],
                                                 mass_densities[ind_min])
                xis[ind_max] -= xi_col
                # rad of ind_min changed -> update kernel index:
                ind_kernel[ind_min] = \
                    compute_kernel_index(radii[ind_min], R_kernel_low_log,
                                         bin_factor_R_log, no_kernel_bins)
                no_cols[1] += 1
            elif p_crit > rnd[cnt]:
                no_cols[0] += 1
                xi_rel_dev = (xi_max - xi_min) / xi_max
                if xi_rel_dev < 1.0E-5:
                    print("xi_i approx xi_j, xi_rel_dev =", xi_rel_dev,
                          " in collision")
                    xi_ges = xi_min + xi_max
                    masses[ind_min] = 2.0 * ( xi_min*m_min + xi_max*m_max ) \
                                      / xi_ges
                    masses[ind_max] = masses[ind_min]
                    radii[ind_min] =\
                        compute_radius_from_mass_jit(masses[ind_min],
                                                     mass_densities[ind_min])
                    radii[ind_max] = radii[ind_min]
                    xis[ind_max] = 0.5 * 0.7 * xi_ges
                    xis[ind_min] = 0.5 * xi_ges - xis[ind_max]
                    # radius of ind_min AND ind_max changed to same radii
                    # -> update kernel ind:
                    ind_kernel[ind_min] = \
                        compute_kernel_index(radii[ind_min], R_kernel_low_log,
                                             bin_factor_R_log, no_kernel_bins)
                    ind_kernel[ind_max] = ind_kernel[ind_min]
                else:
                    masses[ind_min] += m_max
                    radii[ind_min] =\
                        compute_radius_from_mass_jit(masses[ind_min],
                                                     mass_densities[ind_min])
                    xis[ind_max] -= xi_min
                    # rad of ind_min changed -> update kernel index:
                    ind_kernel[ind_min] = \
                        compute_kernel_index(radii[ind_min], R_kernel_low_log,
                                             bin_factor_R_log, no_kernel_bins)
            cnt += 1
コード例 #5
0
def analyze_sim_data(kappa, mass_density, dV, no_sims, start_seed, no_bins,
                     load_dir):
    # f"/mnt/D/sim_data/col_box_mod/results/{kernel_name}/{gen_method}/kappa_{kappa}/dt_{int(dt)}/"
    # f"/mnt/D/sim_data/col_box_mod/results/{kernel_name}/{gen_method}/kappa_{kappa}/dt_{int(dt)}/perm/"

    save_times = np.load(load_dir + f"save_times_{start_seed}.npy")

    seed_list = np.arange(start_seed, start_seed + no_sims * 2, 2)

    masses_vs_time = []
    xis_vs_time = []
    for seed in seed_list:
        # convert to kg
        masses_vs_time.append(1E-18 *
                              np.load(load_dir + f"masses_vs_time_{seed}.npy"))
        #        masses_vs_time.append(np.load(load_dir + f"masses_vs_time_{seed}.npy"))
        xis_vs_time.append(np.load(load_dir + f"xis_vs_time_{seed}.npy"))

    masses_vs_time_T = []
    xis_vs_time_T = []

    no_times = len(save_times)

    for time_n in range(no_times):
        masses_ = []
        xis_ = []
        for i, m in enumerate(masses_vs_time):
            masses_.append(m[time_n])
            xis_.append(xis_vs_time[i][time_n])
        masses_vs_time_T.append(masses_)
        xis_vs_time_T.append(xis_)

    f_m_num_avg_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    f_m_num_std_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    g_m_num_avg_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    g_m_num_std_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    g_ln_r_num_avg_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    g_ln_r_num_std_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)

    bins_mass_vs_time = np.zeros((no_times, no_bins + 1), dtype=np.float64)
    bins_mass_width_vs_time = np.zeros((no_times, no_bins), dtype=np.float64)
    bins_rad_width_log_vs_time = np.zeros((no_times, no_bins),
                                          dtype=np.float64)
    bins_mass_centers = []
    bins_rad_centers = []

    m_max_vs_time = np.zeros(no_times, dtype=np.float64)
    m_min_vs_time = np.zeros(no_times, dtype=np.float64)
    bin_factors_vs_time = np.zeros(no_times, dtype=np.float64)

    moments_vs_time = np.zeros((no_times, 4, no_sims), dtype=np.float64)

    last_bin_factor = 1.0
    # last_bin_factor = 1.5
    first_bin_factor = 1.0
    # first_bin_factor = 0.8
    for time_n, masses in enumerate(masses_vs_time_T):
        xis = xis_vs_time_T[time_n]
        masses_sampled = np.concatenate(masses)
        xis_sampled = np.concatenate(xis)
        # print(time_n, xis_sampled.min(), xis_sampled.max())

        m_min = masses_sampled.min()
        m_max = masses_sampled.max()

        # convert to microns
        R_min = compute_radius_from_mass_jit(1E18 * m_min, mass_density)
        R_max = compute_radius_from_mass_jit(1E18 * m_max, mass_density)

        xi_min = xis_sampled.min()
        xi_max = xis_sampled.max()

        print(kappa, time_n, f"{xi_max/xi_min:.3e}",
              xis_sampled.shape[0] / no_sims, R_min, R_max)

        m_min_vs_time[time_n] = m_min
        m_max_vs_time[time_n] = m_max

        bin_factor = (m_max / m_min)**(1.0 / no_bins)
        bin_factors_vs_time[time_n] = bin_factor
        # bin_log_dist = np.log(bin_factor)
        # bin_log_dist_half = 0.5 * bin_log_dist
        # add dummy bins for overflow
        # bins_mass = np.zeros(no_bins+3,dtype=np.float64)
        bins_mass = np.zeros(no_bins + 1, dtype=np.float64)
        bins_mass[0] = m_min
        # bins_mass[0] = m_min / bin_factor
        for bin_n in range(1, no_bins + 1):
            bins_mass[bin_n] = bins_mass[bin_n - 1] * bin_factor
        # the factor 1.01 is for numerical stability: to be sure
        # that m_max does not contribute to a bin larger than the
        # last bin
        # bins_mass[-1] *= 1.0001
        bins_mass[-1] *= last_bin_factor
        # the factor 0.99 is for numerical stability: to be sure
        # that m_min does not contribute to a bin smaller than the
        # 0-th bin
        # bins_mass[0] *= 0.9999
        bins_mass[0] *= first_bin_factor
        # m_0 = m_min / np.sqrt(bin_factor)
        # bins_mass_log = np.log(bins_mass)

        bins_mass_vs_time[time_n] = bins_mass
        # convert to microns
        bins_rad = compute_radius_from_mass_vec(1E18 * bins_mass, mass_density)
        bins_mass_log = np.log(bins_mass)
        bins_rad_log = np.log(bins_rad)

        bins_mass_width = (bins_mass[1:] - bins_mass[:-1])
        bins_rad_width = (bins_rad[1:] - bins_rad[:-1])
        bins_rad_width_log = (bins_rad_log[1:] - bins_rad_log[:-1])
        bins_mass_width_vs_time[time_n] = bins_mass_width
        bins_rad_width_log_vs_time[time_n] = bins_rad_width_log

        f_m_counts = np.histogram(masses_sampled, bins_mass)[0]

        # define centers on lin scale
        bins_mass_center_lin = 0.5 * (bins_mass[:-1] + bins_mass[1:])
        bins_rad_center_lin = 0.5 * (bins_rad[:-1] + bins_rad[1:])

        # define centers on the logarithmic scale
        bins_mass_center_log = np.exp(0.5 *
                                      (bins_mass_log[:-1] + bins_mass_log[1:]))
        bins_rad_center_log = np.exp(0.5 *
                                     (bins_rad_log[:-1] + bins_rad_log[1:]))

        # bins_mass are not equally spaced on log scale because of scaling
        # of the first and last bin
        # bins_mass_center_log = bins_mass[:-1] * np.sqrt(bin_factor)
        # bins_rad_center_log = bins_rad[:-1] * np.sqrt(bin_factor)

        # bins_mass_center_log = bins_mass[:-1] * 10**(1.0/(2.0*kappa))
        # bins_rad_center_log = bins_rad[:-1] * 10**(1.0/(2.0*kappa))

        # define the center of mass for each bin and set it as the "bin center"
        # bins_mass_center_COM = g_m_num_sampled/f_m_num_sampled
        # bins_rad_center_COM =\
        #     compute_radius_from_mass(bins_mass_center_COM*1.0E18,
        #                              c.mass_density_water_liquid_NTP)

        # set the bin "mass centers" at the right spot such that
        # f_avg_i in bin in = f(mm_i), where mm_i is the "mass center"
        m_avg = masses_sampled.sum() / xis_sampled.sum()
        bins_mass_center_exact = bins_mass[:-1] \
                                 + m_avg * np.log(bins_mass_width\
              / (m_avg * (1-np.exp(-bins_mass_width/m_avg))))
        # convert to microns
        bins_rad_center_exact =\
            compute_radius_from_mass_vec(1E18*bins_mass_center_exact,
                                         mass_density)
        bins_mass_centers.append(
            np.array((bins_mass_center_lin, bins_mass_center_log,
                      bins_mass_center_exact)))

        bins_rad_centers.append(
            np.array((bins_rad_center_lin, bins_rad_center_log,
                      bins_rad_center_exact)))

        ### STATISTICAL ANALYSIS OVER no_sim runs
        # get f(m_i) curve for each "run" with same bins for all ensembles
        f_m_num = []
        g_m_num = []
        g_ln_r_num = []

        for sim_n, mass in enumerate(masses):
            # convert to microns
            rad = compute_radius_from_mass_vec(1E18 * mass, mass_density)
            f_m_num.append(np.histogram(mass, bins_mass, weights=xis[sim_n])[0] \
                           / (bins_mass_width * dV))
            g_m_num.append(np.histogram(mass, bins_mass, weights=xis[sim_n]*mass)[0] \
                           / (bins_mass_width * dV))

            # build g_ln_r = 3*m*g_m DIRECTLY from data
            g_ln_r_num.append( np.histogram(rad, bins_rad,
                                            weights=xis[sim_n]*mass)[0] \
                               / (bins_rad_width_log * dV) )

            moments_vs_time[time_n, 0, sim_n] = xis[sim_n].sum() / dV
            for n in range(1, 4):
                moments_vs_time[time_n, n,
                                sim_n] = np.sum(xis[sim_n] * mass**n) / dV

        # f_m_num = np.array(f_m_num)
        # g_m_num = np.array(g_m_num)
        # g_ln_r_num = np.array(g_ln_r_num)

        f_m_num_avg_vs_time[time_n] = np.average(f_m_num, axis=0)
        f_m_num_std_vs_time[time_n] = \
            np.std(f_m_num, axis=0, ddof=1) / np.sqrt(no_sims)
        g_m_num_avg_vs_time[time_n] = np.average(g_m_num, axis=0)
        g_m_num_std_vs_time[time_n] = \
            np.std(g_m_num, axis=0, ddof=1) / np.sqrt(no_sims)
        g_ln_r_num_avg_vs_time[time_n] = np.average(g_ln_r_num, axis=0)
        g_ln_r_num_std_vs_time[time_n] = \
            np.std(g_ln_r_num, axis=0, ddof=1) / np.sqrt(no_sims)
    # convert to microns
    R_min_vs_time = compute_radius_from_mass_vec(1E18 * m_min_vs_time,
                                                 mass_density)
    R_max_vs_time = compute_radius_from_mass_vec(1E18 * m_max_vs_time,
                                                 mass_density)

    moments_vs_time_avg = np.average(moments_vs_time, axis=2)
    moments_vs_time_std = np.std(moments_vs_time, axis=2, ddof=1) \
                          / np.sqrt(no_sims)

    moments_vs_time_Unt = np.zeros_like(moments_vs_time_avg)

    # mom_fac = math.log(10)/(3*kappa)
    for time_n in range(no_times):
        for n in range(4):
            moments_vs_time_Unt[time_n,n] =\
                math.log(bin_factors_vs_time[time_n]) / 3.0 \
                * np.sum( g_ln_r_num_avg_vs_time[time_n]
                                    * (bins_mass_centers[time_n][1])**(n-1) )
            # np.sum( g_ln_r_num_avg_vs_time[time_n]
            #         * (bins_mass_centers[time_n][1])**(n-1)
            #         * bins_rad_width_log_vs_time[time_n] )
            # mom_fac * np.sum( g_m_num_avg_vs_time[time_n]
            #                    * (bins_mass_centers[time_n][1])**(n-1) )

    np.save(
        load_dir +
        f"moments_vs_time_avg_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        moments_vs_time_avg)
    np.save(
        load_dir +
        f"moments_vs_time_std_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        moments_vs_time_std)
    np.save(
        load_dir +
        f"f_m_num_avg_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        f_m_num_avg_vs_time)
    np.save(
        load_dir +
        f"f_m_num_std_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        f_m_num_std_vs_time)
    np.save(
        load_dir +
        f"g_m_num_avg_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        g_m_num_avg_vs_time)
    np.save(
        load_dir +
        f"g_m_num_std_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        g_m_num_std_vs_time)
    np.save(
        load_dir +
        f"g_ln_r_num_avg_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        g_ln_r_num_avg_vs_time)
    np.save(
        load_dir +
        f"g_ln_r_num_std_vs_time_no_sims_{no_sims}_no_bins_{no_bins}.npy",
        g_ln_r_num_std_vs_time)
    np.save(load_dir + f"bins_mass_centers_{no_sims}_no_bins_{no_bins}.npy",
            bins_mass_centers)
    np.save(load_dir + f"bins_rad_centers_{no_sims}_no_bins_{no_bins}.npy",
            bins_rad_centers)
コード例 #6
0
#D_s = 6. # mu = 10 nm
D_s = 10.  # mu = 10 nm
#D_s = 20. # mu = 10 nm
#D_s = 30. # mu = 10 nm
#D_s = 100. # mu = 10 nm

w_s = np.logspace(-5., np.log10(0.78), 10000)

D_s *= 1E-3
R_s = 0.5 * D_s

m_s_AS = mp.compute_mass_from_radius_jit(R_s, c.mass_density_AS_dry)
rho_AS = mp.compute_density_AS_solution(w_s, T_p)
m_p_AS = m_s_AS / w_s
m_w_AS = m_p_AS - m_s_AS
R_p_AS = mp.compute_radius_from_mass_jit(m_p_AS, rho_AS)

m_s_SC = mp.compute_mass_from_radius_jit(R_s, c.mass_density_NaCl_dry)
rho_SC = mp.compute_density_NaCl_solution(w_s, T_p)
m_p_SC = m_s_SC / w_s
m_w_SC = m_p_SC - m_s_SC
R_p_SC = mp.compute_radius_from_mass_jit(m_p_SC, rho_SC)

sigma_AS = mp.compute_surface_tension_AS(w_s, T_p)
sigma_SC = atm.compute_surface_tension_water(T_p)

S_eq_AS = mp.compute_equilibrium_saturation_AS(w_s, R_p_AS, T_p, rho_AS,
                                               sigma_AS)
S_eq_SC = mp.compute_equilibrium_saturation_NaCl(m_w_SC, m_s_SC, w_s, R_p_SC,
                                                 T_p, rho_SC, sigma_SC)