def problem_1(container, special_particles, **extra_params): """Create a triangular (hex) lattice with N = 64 particles. The dimensions of the lattice should be Lx and Ly = sqrt(3)/2*Lx """ N = 8 # this is 8x8 = 64 particles Lx = extra_params.get('Lx', None) Lx = Lx or container.bounds[0] # error here would indicate bounds haven't been set Ly = math.sqrt(3)/2 * Lx container.bounds = (Lx, Ly) dx = Lx / float(N) dy = Ly / float(N) moldyn.add_triangle_lattice(container, N, N, dx, dy) return container, special_particles
def hourglass(funnel_width, hole_width, d_angle_from_horizon_to_wall, dist_between_anchors, diam, grain_height, **kwargs_ignore): """ Make a container with "anchor" particles set up as walls of an hourglass :param kwargs_ignore: ignored extra args so you can use an exploded dictionary (**myargdict) for arg input :param diam: diameter of each grain and anchor :returns: container, y_funnel_bottom """ # Do calculations for funnel r_angle = math.radians(d_angle_from_horizon_to_wall) tan_over_2 = math.tan(r_angle)/2.0 height_funnel = funnel_width * tan_over_2 hole_width += diam # trick to allow space so bottom anchors don't overlap, e.g. so a zero-width hole actually places anchors with their borders touching instead of with their centers touching height_hole = hole_width * tan_over_2 xdist = dist_between_anchors * math.cos(r_angle) ydist = dist_between_anchors * math.sin(r_angle) # Centers of wall particles def get_anchor_centers(xstart, xend, xdist, left_side=True): # np.arange doesn't let you go from a greater to a lesser value, so invert twice to get that behavior if xstart > xend: dx = (xstart - xend) ## xs = -np.arange(-xstart, -xend, xdist) else: dx = (xend - xstart) ## xs = np.arange(xstart, xend, xdist) num_anchors = math.ceil(dx / xdist) xs = np.linspace(xstart, xend, num_anchors) return xs # Right wall equation: goes from ( (wf + wh)/2, hh - hf ) to (wf, 0) #m = (height_funnel - height_hole) / (funnel_width - (funnel_width + hole_width)/2.0) extra_funnel_extension = 0 # messes up hole alignment y_funnel_bottom = height_hole - height_funnel # y is negative xrs = get_anchor_centers((funnel_width + hole_width)/2.0, funnel_width + extra_funnel_extension, xdist) yrs = get_anchor_centers(y_funnel_bottom, extra_funnel_extension, ydist, False) # Left wall goes from (0, 0) to ( (wf - wh)/2, hh - hf) xls = get_anchor_centers(-extra_funnel_extension, (funnel_width - hole_width)/2.0, xdist) yls = get_anchor_centers(extra_funnel_extension, y_funnel_bottom, ydist, False) # Place anchors # NOTE: the order of adding matters when plotting anchor forces, so try to add from left to right c = Container() # Make side walls/anchors # NOTE: The anchors at y = 0 are placed by other code wall_ys = np.arange(diam, grain_height + diam, diam) for y in reversed(wall_ys): # high to low c.add_particle([0, y]) def add_anchors(xs, ys): for x, y in zip(xs, ys): c.add_particle([x, y]) add_anchors(xls, yls) add_anchors(xrs, yrs) # KLUDGE repeating sucks, but I want the anchor ixs in the right order for y in wall_ys: # low to high c.add_particle([funnel_width, y]) anchor_ixs = range(c.num_particles) # Finally, add sand moldyn.add_triangle_lattice(c, (diam, funnel_width-diam), (diam, grain_height), diam, diam) return c, y_funnel_bottom, anchor_ixs