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