def aspect_ratio(): D_arr = np.exp(np.linspace(np.log(100e-6), np.log(3000e-6), 100)) with open("../aggregation/dendrite_grid.dat") as f: grid = pickle.load(f) rot = rotator.UniformRotator() grid_res = 40.0e-6 def ar(D): cry = crystal.Dendrite(D, hex_grid=grid) gen = generator.MonodisperseGenerator(cry, rot, grid_res) agg = aggregate.Aggregate(gen) m = agg.X.mean(0) X_c = agg.X - m cov = np.dot(X_c.T, X_c) (l, v) = np.linalg.eigh(cov) size = np.sqrt(l / X_c.shape[0] + (1. / (2 * np.sqrt(3)) * grid_res)**2) width = np.sqrt(0.5 * (size[1]**2 + size[2]**2)) height = size[0] print D, size, width, height return height / width ratios = np.array([ar(D) for D in D_arr]) return (D_arr, ratios)
def generate_rosette(D, min_grid_res=40e-6): grid_res = min(D / 20, min_grid_res) rot = rotator.UniformRotator() cry = crystal.Rosette(D) gen = generator.MonodisperseGenerator(cry, rot, grid_res) agg = aggregate.Aggregate(gen) return (agg, grid_res)
def polydisp_dendrite(N=5, grid=None, align=True): #cry = crystal.Column(0.3e-3) agg = [] psd = stats.expon(scale=1.0e-3) rot = rotator.UniformRotator() for i in xrange(N): D = 1e3 while D > 0.3e-2 or D < 0.2e-3: D = psd.rvs() print "D: " + str(D) cry = crystal.Dendrite(D, alpha=0.705, beta=0.5, gamma=0.0001, num_iter=2500, hex_grid=grid) gen = generator.MonodisperseGenerator(cry, rot, 0.02e-3) agg.append(aggregate.Aggregate(gen, levels=5)) aggregate.t_i = 0 aggregate.t_o = 0 while len(agg) > 1: r = array([((a.extent[0][1] - a.extent[0][0]) + (a.extent[1][1] - a.extent[1][0])) / 4.0 for a in agg]) m_r = numpy.sqrt(array([a.X.shape[0] for a in agg]) / r) r_mat = (numpy.tile(r, (len(agg), 1)).T + r)**2 mr_mat = abs(numpy.tile(m_r, (len(agg), 1)).T - m_r) p_mat = r_mat * mr_mat p_max = p_mat.max() p_mat /= p_mat.max() collision = False while not collision: i = random.randint(len(agg)) j = random.randint(len(agg)) rnd = random.rand() if rnd < p_mat[i][j]: print i, j agg_top = agg[i] if (m_r[i] > m_r[j]) else agg[j] agg_btm = agg[i] if (m_r[i] <= m_r[j]) else agg[j] collision = agg_top.add_particle(particle=agg_btm.X, required=True) if collision: if align: agg_top.align() else: agg_top.rotate(rot) agg.pop(i if (m_r[i] <= m_r[j]) else j) print aggregate.t_i, aggregate.t_o if align: agg[0].align() agg[0].rotate(rotator.HorizontalRotator()) return agg[0]
def monodisp_demo(N=5): #cry = crystal.Plate(0.3e-3) #cry = crystal.Rosette(0.6e-3) cry = crystal.Spheroid(0.6e-3, 0.6) rot = rotator.UniformRotator() gen = generator.MonodisperseGenerator(cry, rot, 0.01e-3) agg = aggregate.Aggregate(gen) for i in xrange(N - 1): print i agg.add_particle(required=True, pen_depth=0.02e-3) agg.align() return agg
def gen_monomer(psd="monodisperse", size=1.0, min_size=1e-3, max_size=10, mono_type="dendrite", grid_res=0.02e-3, rimed=False): def make_cry(D): if mono_type == "dendrite": grid = pickle.load(file("dendrite_grid.dat")) cry = crystal.Dendrite(D, hex_grid=grid) elif mono_type == "plate": cry = crystal.Plate(D) elif mono_type == "needle": cry = crystal.Needle(D) elif mono_type == "rosette": cry = crystal.Rosette(D) elif mono_type == "bullet": cry = crystal.Bullet(D) elif mono_type == "spheroid": cry = crystal.Spheroid(D, 0.6) return cry rot = rotator.UniformRotator() def gen(): if psd == "monodisperse": D = size elif psd == "exponential": psd_f = stats.expon(scale=size) D = max_size + 1 while (D < min_size) or (D > max_size): D = psd_f.rvs() cry = make_cry(D) gen = generator.MonodisperseGenerator(cry, rot, grid_res) if rimed: agg = aggregate.RimedAggregate(gen) else: agg = aggregate.Aggregate(gen) return agg return gen
def generate_aggregate(monomer_generator, N=5, align=True): align_rot = rotator.PartialAligningRotator(exp_sig_deg=40) uniform_rot = rotator.UniformRotator() agg = [monomer_generator() for i in xrange(N)] while len(agg) > 1: r = array([((a.extent[0][1] - a.extent[0][0]) + (a.extent[1][1] - a.extent[1][0])) / 4.0 for a in agg]) m_r = np.sqrt(array([a.X.shape[0] for a in agg]) / r) r_mat = (np.tile(r, (len(agg), 1)).T + r)**2 mr_mat = abs(np.tile(m_r, (len(agg), 1)).T - m_r) p_mat = r_mat * mr_mat p_mat /= p_mat.max() collision = False while not collision: i = random.randint(len(agg)) j = random.randint(len(agg)) rnd = random.rand() if rnd < p_mat[i][j]: print i, j agg_top = agg[i] if (m_r[i] > m_r[j]) else agg[j] agg_btm = agg[i] if (m_r[i] <= m_r[j]) else agg[j] agg_btm.rotate(uniform_rot) collision = agg_top.add_particle(particle=agg_btm.X, required=True, pen_depth=80e-6) if collision: if align: agg_top.align() agg_top.rotate(align_rot) else: agg_top.rotate(uniform_rot) agg.pop(i if (m_r[i] <= m_r[j]) else j) if align: agg[0].align() agg[0].rotate(align_rot) agg[0].rotate(rotator.HorizontalRotator()) return agg[0]
def monodisp_pseudo(N=5, grid=None, sig=1.0): cry = crystal.Dendrite(0.5e-3, alpha=0.705, beta=0.5, gamma=0.0001, num_iter=2500, hex_grid=grid) rot = rotator.UniformRotator() gen = generator.MonodisperseGenerator(cry, rot, 0.02e-3) """ p_agg = aggregate.PseudoAggregate(gen, sig=0.1e-2) rho_i = 916.7 #kg/m^3 N_dip = p_agg.grid().shape[0] m = 0.02e-3**3 * N_dip * N * rho_i sig = (m/20.3)**(1.0/2.35) print N_dip, sig """ p_agg = aggregate.PseudoAggregate(gen, sig=sig) aggs = [aggregate.Aggregate(gen, levels=5) for i in xrange(N - 1)] for agg in aggs: p_agg.add_particle(particle=agg.X, required=False) return p_agg
def monodisp_demo2(N=5): #cry = crystal.Column(0.3e-3) cry = crystal.Dendrite(0.3e-3, 0.705, 0.5, 0.0001, num_iter=2500) rot = rotator.UniformRotator() gen = generator.MonodisperseGenerator(cry, rot, 0.01e-3) agg = [aggregate.Aggregate(gen) for i in xrange(N)] aggregate.t_i = 0 aggregate.t_o = 0 while len(agg) > 1: r = array([((a.extent[0][1] - a.extent[0][0]) + (a.extent[1][1] - a.extent[1][0])) / 4.0 for a in agg]) m_r = numpy.sqrt(array([a.X.shape[0] for a in agg]) / r) r_mat = (numpy.tile(r, (len(agg), 1)).T + r)**2 mr_mat = abs(numpy.tile(m_r, (len(agg), 1)).T - m_r) p_mat = r_mat * mr_mat p_max = p_mat.max() p_mat /= p_mat.max() collision = False while not collision: i = random.randint(len(agg)) j = random.randint(len(agg)) rnd = random.rand() if rnd < p_mat[i][j]: print i, j agg_top = agg[i] if (m_r[i] > m_r[j]) else agg[j] agg_btm = agg[i] if (m_r[i] <= m_r[j]) else agg[j] collision = agg_top.add_particle(particle=agg_btm.X, required=True) agg_top.align() agg.pop(i if (m_r[i] <= m_r[j]) else j) print aggregate.t_i, aggregate.t_o return agg[0]
def gen_monomer(psd="monodisperse", size=1e-3, min_size=0.1e-3, max_size=20e-3, mono_type="dendrite", grid_res=0.02e-3, rimed=False, debug=False): """Make a monomer crystal generator. Args: psd: "monodisperse" or "exponential". size: If psd="monodisperse", this is the diameter of the ice crystals. If psd="exponential", this is the inverse of the slope parameter (usually denoted as lambda). min_size, max_size: Minimum and maximum allowed size for generated crystals. mono_type: The type of crystals used. The possible values are "dendrite", "plate", "needle", "rosette", "bullet", "column", "spheroid". grid_res: The volume element size. rimed: True if a rimed aggregate should be generated, False otherwise. debug: If True, debug information will be printed. """ def make_cry(D): if mono_type=="dendrite": current_dir = os.path.dirname(os.path.realpath(__file__)) grid = pickle.load(file(current_dir+"/dendrite_grid.dat")) cry = crystal.Dendrite(D, hex_grid=grid) elif mono_type=="plate": cry = crystal.Plate(D) elif mono_type=="needle": cry = crystal.Needle(D) elif mono_type=="rosette": cry = crystal.Rosette(D) elif mono_type=="bullet": cry = crystal.Bullet(D) elif mono_type=="column": cry = crystal.Column(D) elif mono_type=="spheroid": cry = crystal.Spheroid(D,1.0) return cry rot = rotator.UniformRotator() def gen(ident=0): if psd=="monodisperse": D = size elif psd=="exponential": psd_f = stats.expon(scale=size) D=max_size+1 while (D<min_size) or (D>max_size): D = psd_f.rvs() cry = make_cry(D) if debug: print D gen = generator.MonodisperseGenerator(cry, rot, grid_res) if rimed: agg = aggregate.RimedAggregate(gen, ident=ident) else: agg = aggregate.Aggregate(gen, ident=ident) return agg return gen
def generate_rimed_aggregate_iter(monomer_generator, N=5, align=True, riming_lwp=0.0, riming_eff=1.0, riming_mode="simultaneous", rime_pen_depth=120e-6, seed=None, lwp_div=10, compact_dist=0., debug=False): """Generate a rimed aggregate particle. Refer to the generate_rimed_aggregate function for details. """ random.seed(seed) align_rot = rotator.PartialAligningRotator(exp_sig_deg=40, random_flip=True) uniform_rot = rotator.UniformRotator() agg = [monomer_generator(ident=i) for i in xrange(N)] yield agg while len(agg) > 1: r = np.array([((a.extent[0][1]-a.extent[0][0])+ (a.extent[1][1]-a.extent[1][0]))/4.0 for a in agg]) m_r = np.sqrt(np.array([a.X.shape[0] for a in agg])/r) r_mat = (np.tile(r,(len(agg),1)).T+r)**2 mr_mat = abs(np.tile(m_r,(len(agg),1)).T - m_r) p_mat = r_mat * mr_mat p_mat /= p_mat.max() collision = False while not collision: i = random.randint(len(agg)) j = i while j == i: j = random.randint(len(agg)) rnd = random.rand() if rnd < p_mat[i][j]: if debug: print i, j agg_top = agg[i] if (m_r[i] > m_r[j]) else agg[j] agg_btm = agg[i] if (m_r[i] <= m_r[j]) else agg[j] agg_btm.rotate(uniform_rot) collision = agg_top.add_particle(particle=agg_btm.X,ident=agg_btm.ident, required=True,pen_depth=80e-6) if collision: if align: agg_top.align() agg_top.rotate(align_rot) else: agg_top.rotate(uniform_rot) agg.pop(i if (m_r[i] <= m_r[j]) else j) if riming_mode == "simultaneous": for a in agg: generate_rime(a, align_rot if align else uniform_rot, riming_lwp/float(N-1), riming_eff=riming_eff, pen_depth=rime_pen_depth, lwp_div=lwp_div, compact_dist=compact_dist) if len(agg) > 1: yield agg if (riming_mode == "subsequent") or (N==1): for a in generate_rime(agg[0], align_rot if align else uniform_rot, riming_lwp, riming_eff=riming_eff, pen_depth=rime_pen_depth, lwp_div=lwp_div, iter=True, compact_dist=compact_dist): yield [a] if align: agg[0].align() agg[0].rotate(align_rot) agg[0].rotate(rotator.HorizontalRotator()) yield agg