Beispiel #1
0
def generate_circle_lattice(N):
    """Generate lattice as a circle of points connected by nearest neighbors.
    """
    theta = np.linspace(0, 2. * np.pi, N + 1)
    theta = theta[:-1]
    # The radius, given the length of a side is:
    # radius = s/(2 * sin(2 pi/ n)), where n is number of sides, s is length of each side
    # We set the length of a side to be 1 (the rest length of each bond)
    R = 1. / (2. * np.sin(np.pi / float(N)))
    # print '(2.* np.sin(2.*np.pi/float(N))) = ', (2.* np.sin(np.pi/float(N)))
    # print 'R = ', R
    xtmp = R * np.cos(theta)
    ytmp = R * np.sin(theta)
    xy = np.dstack([xtmp, ytmp])[0]
    if N == 1:
        BL = np.array([[]])
    elif N == 2:
        BL = np.array([[0, 1]])
    else:
        BL = np.array([[i, (i + 1) % N] for i in np.arange(N)])
    # print 'BL = ', BL
    # print 'NP = ', len(xtmp)
    NL, KL = le.BL2NLandKL(BL, NP=len(xtmp), NN=2)
    LV = np.array([[0, 0], [0, 0]], dtype=int)
    UC = xy
    ztmp = np.zeros(len(xy), dtype=int)
    LVUC = np.dstack((ztmp, ztmp, np.arange(len(xy), dtype=int)))[0]
    print LVUC
    lattice_exten = 'circlebonds'
    return xy, NL, KL, BL, LV, UC, LVUC, lattice_exten
Beispiel #2
0
def build_hex_kagperframe(lp):
    """Build a hyperuniform centroidal lattice with partially kagomized points beyond a distance
    alph*Radius/Halfwidth of sample. "per" here means "percolation", referring to the randomly added kagomized elements.

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    xy, NL, KL, BL, LVUC, LV, UC, PVxydict, PVx, PVy, PV, lattice_exten = bhex.generate_honeycomb_lattice(
        lp)
    max_x = np.max(xy[:, 0])
    max_y = np.max(xy[:, 1])
    min_x = np.min(xy[:, 0])
    min_y = np.min(xy[:, 1])
    LL = (max_x - min_x, max_y - min_y)
    BBox = np.array([[min_x, min_y], [min_x, max_y], [max_x, max_y],
                     [max_x, min_y]])

    # Grab indices (vertices) to kagomize: select the ones farther than alph*characteristic length from center
    if lp['shape'] == 'square':
        lenscaleX = np.max(BBox[:, 0]) * lp['alph']
        lenscaleY = np.max(BBox[:, 1]) * lp['alph']
        kaginds = np.where(
            np.logical_or(
                np.abs(xy[:, 0]) > lenscaleX,
                np.abs(xy[:, 1]) > lenscaleY))[0]
    elif lp['shape'] == 'circle':
        # todo: handle circles
        pass
    elif lp['hexagon'] == 'hexagon':
        # todo: handle hexagons
        pass

    # Select some fraction of vertices (which are points) --> xypick gives Nkag of the vertices (xy)
    Nkag = round(lp['percolation_density'] * len(kaginds))
    ind_shuffled = np.random.permutation(np.arange(len(kaginds)))
    xypick = np.sort(ind_shuffled[0:Nkag])

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          kaginds[xypick],
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])
    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        # todo: make this work
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        PV = np.array([])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # If the meshfn going to overwrite a previous realization?
    lattice_exten = 'hex_kagperframe' + lattice_exten[9:] +\
                    '_perd' + sf.float2pstr(lp['percolation_density'], ndigits=2) +\
                    '_alph' + sf.float2pstr(lp['alph'], ndigits=2)
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #3
0
def build_isocent_kagframe(lp):
    """Build a hyperuniform centroidal lattice with kagomized points beyond distance alph*Radius/Halfwidth of sample

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    from lepm.build import build_iscentroid
    # if lp['NP_load'] < 1:
    #     lp['NH'] += 5
    #     lp['NV'] += 5

    xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten = build_iscentroid.build_iscentroid(
        lp)
    # Grab indices (vertices) to kagomize: select the ones farther than alph*characteristic length from center
    if 'kagframe' in lp['LatticeTop']:
        lenscaleX = np.max(BBox[:, 0]) * lp['alph']
        lenscaleY = np.max(BBox[:, 1]) * lp['alph']
        kaginds = np.where(
            np.logical_or(
                np.abs(xy[:, 0]) > lenscaleX,
                np.abs(xy[:, 1]) > lenscaleY))[0]
    elif 'kagcframe' in lp['LatticeTop']:
        eps = 1e-9
        lenscale = np.max(
            np.sqrt(xy[:, 0]**2 + xy[:, 1]**2)) * lp['alph'] + eps
        kaginds = np.where(np.sqrt(xy[:, 0]**2 + xy[:, 1]**2) > lenscale)[0]
    elif lp['hexagon'] == 'hexagon':
        # todo: handle hexagons
        pass

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          kaginds,
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])

    # if trim_after:
    #     print 'trim here'

    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        # todo: make this work
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        PV = np.array([])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # name the output network
    lattice_exten = lp['LatticeTop'] + lattice_exten[
        10:] + '_alph' + sf.float2pstr(lp['alph'], ndigits=2)
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #4
0
def build_hex_kagframe(lp):
    """Build a hyperuniform centroidal lattice with kagomized points beyond distance alph*Radius/Halfwidth of sample

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    xy, NL, KL, BL, LVUC, LV, UC, PVxydict, PVx, PVy, PV, lattice_exten = bhex.generate_honeycomb_lattice(
        lp)
    max_x = np.max(xy[:, 0])
    max_y = np.max(xy[:, 1])
    min_x = np.min(xy[:, 0])
    min_y = np.min(xy[:, 1])
    LL = (max_x - min_x, max_y - min_y)
    BBox = np.array([[min_x, min_y], [min_x, max_y], [max_x, max_y],
                     [max_x, min_y]])

    # Grab indices (vertices) to kagomize: select the ones farther than alph*characteristic length from center
    eps = 1e-9
    if lp['shape'] == 'square':
        lenscaleX = np.max(np.abs(BBox[:, 0])) * lp['alph'] + eps
        lenscaleY = np.max(np.abs(BBox[:, 1])) * lp['alph'] + eps
        kaginds = np.where(
            np.logical_or(
                np.abs(xy[:, 0]) > lenscaleX,
                np.abs(xy[:, 1]) > lenscaleY))[0]
    elif lp['shape'] == 'circle':
        # todo: handle circles
        pass
    elif lp['hexagon'] == 'hexagon':
        # todo: handle hexagons
        pass

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          kaginds,
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])
    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        # todo: make this work
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        PV = np.array([])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # If the meshfn going to overwrite a previous realization?
    lattice_exten = 'hex_kagframe' + lattice_exten[9:] +\
                    '_alph' + sf.float2pstr(lp['alph'], ndigits=2)
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #5
0
def build_kaghu_centframe(lp):
    """Build a hyperuniform centroidal lattice with kagomized points inside distance alph*Radius/Halfwidth of sample

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten = bhex.build_hucentroid(
        lp)

    # Grab indices (vertices) to kagomize: select the ones farther than alph*characteristic length from center
    if lp['shape'] == 'square':
        lenscaleX = np.max(BBox[:, 0]) * lp['alph']
        lenscaleY = np.max(BBox[:, 1]) * lp['alph']
        kaginds = np.where(
            np.logical_and(
                np.abs(xy[:, 0]) < lenscaleX,
                np.abs(xy[:, 1]) < lenscaleY))[0]
    elif lp['shape'] == 'circle':
        # todo: handle circles
        pass
    elif lp['hexagon'] == 'hexagon':
        # todo: handle hexagons
        pass

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          kaginds,
                                          NL=NL,
                                          PVxydict=PVxydict,
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])
    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        # The ith row of PV is the vector taking the ith side of the polygon (connecting polygon[i] to
        # polygon[i+1 % len(polygon)]
        PV = np.array([[LL[0], 0.0], [LL[0], LL[1]], [LL[0], -LL[1]],
                       [0.0, 0.0], [0.0, LL[1]], [0.0, -LL[1]], [-LL[0], 0.0],
                       [-LL[0], LL[1]], [-LL[0], -LL[1]]])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # If the meshfn going to overwrite a previous realization?
    lattice_exten = 'kaghu_centframe' + lattice_exten[10:] +\
                    '_alph' + sf.float2pstr(lp['alph'], ndigits=2)
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #6
0
def generate_zigzag_lattice(NH, theta, eta=0.):
    """Creates a zigzag (linear) lattice, with angle theta and randomization eta
    """
    LV = np.array([[np.cos(theta), np.sin(theta)],
                   [np.cos(theta), -np.sin(theta)]])

    xy = np.array([
        np.ceil(i * 0.5) * LV[0] + np.ceil((i - 1) * 0.5) * LV[1]
        for i in range(NH)
    ])
    xy -= np.array([np.mean(xy[:, 0]), np.mean(xy[:, 1])])
    print 'xy = ', xy

    # Connectivity
    BL = np.zeros((NH - 1, 2), dtype=int)
    for i in range(0, NH - 1):
        BL[i, 0] = i
        BL[i, 1] = i + 1

    print 'BL = ', BL

    TRI = le.BL2TRI(BL, xy)

    # scale lattice down to size
    if eta == 0:
        xypts = xy
    else:
        print 'Randomizing lattice by eta=', eta
        jitter = eta * np.random.rand(np.shape(xy)[0], np.shape(xy)[1])
        xypts = np.dstack(
            (xy[:, 0] + jitter[:, 0], xy[:, 1] + jitter[:, 1]))[0]

    # Naming
    etastr = '{0:.3f}'.format(eta).replace('.', 'p')
    thetastr = '{0:.3f}'.format(theta / np.pi).replace('.', 'p')
    exten = '_line_theta' + thetastr + 'pi_eta' + etastr

    # BL = latticevec_filter(BL,xy, C, CBL)
    NL, KL = le.BL2NLandKL(BL, NP=NH, NN=2)
    lattice_exten = 'linear' + exten
    print 'lattice_exten = ', lattice_exten
    return xypts, NL, KL, BL, LV, lattice_exten
Beispiel #7
0
def build_kagper_hucent(lp):
    """Build a hyperuniform centroidal lattice with some density of kagomization (kagper = kagome percolation)

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten = build_hucentroid(
        lp)

    # Select some fraction of vertices (which are points) --> xypick gives Nkag of the vertices (xy)
    Nkag = round(lp['percolation_density'] * len(xy))
    ind_shuffled = np.random.permutation(np.arange(len(xy)))
    xypick = np.sort(ind_shuffled[0:Nkag])

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          xypick,
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])
    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        PV = np.array([])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # If the meshfn going to overwrite a previous realization?
    mfok = le.meshfn_is_used(le.build_meshfn(lp)[0])
    while mfok:
        lp['subconf'] += 1
        mfok = le.meshfn_is_used(le.build_meshfn(lp)[0])

    lattice_exten = 'kagper_hucent' + lattice_exten[10:] + \
                    '_perd' + sf.float2pstr(lp['percolation_density'], ndigits=2) + \
                    '_r' + '{0:02d}'.format(int(lp['subconf']))
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #8
0
def build_hex_kagcframe(lp):
    """Build a hyperuniform centroidal lattice with kagomized points beyond distance alph*Radius/Halfwidth of sample

    Parameters
    ----------
    lp : dict
        lattice parameters dictionary
    """
    hclp = copy.deepcopy(lp)
    hclp['eta'] = 0.0
    xy, tr1, tr2, BL, tr3, tr4, tr5, PVxydict, PVx, PVy, PV, lattice_exten = bhex.generate_honeycomb_lattice(
        hclp)
    max_x = np.max(xy[:, 0])
    max_y = np.max(xy[:, 1])
    min_x = np.min(xy[:, 0])
    min_y = np.min(xy[:, 1])
    LL = (max_x - min_x, max_y - min_y)
    BBox = np.array([[min_x, min_y], [min_x, max_y], [max_x, max_y],
                     [max_x, min_y]])

    # Grab indices (vertices) to kagomize: select the ones farther than alph*characteristic length from center
    eps = 1e-9
    lenscale = np.max(np.sqrt(xy[:, 0]**2 + xy[:, 1]**2)) * lp['alph'] + eps
    print "lp['alph'] = ", lp['alph']
    print "lp['alph'] * np.abs(BBox[:, 0])) = ", lp['alph'] * np.abs(BBox[:,
                                                                          0])
    print 'lenscale = ', lenscale
    kaginds = np.where(np.sqrt(xy[:, 0]**2 + xy[:, 1]**2) > lenscale)[0]

    xy, BL = blf.decorate_kagome_elements(xy,
                                          BL,
                                          kaginds,
                                          viewmethod=lp['viewmethod'],
                                          check=lp['check'])
    NL, KL = le.BL2NLandKL(BL)
    if (BL < 0).any():
        # todo: make this work
        print 'Creating periodic boundary vector dictionary for kagper_hucent network...'
        PV = np.array([])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

    # Only randomly displace the gyros in frame, and only if eta >0
    if lp['eta'] > 0.0:
        if 'eta_alph' not in lp:
            lp['eta_alph'] = lp['alph']
        eta_lenscale = np.max(
            np.sqrt(xy[:, 0]**2 + xy[:, 1]**2)) * lp['eta_alph'] + eps
        print '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\neta_lenscale = ', eta_lenscale
        print '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\neta_alph = ', lp['eta_alph']
        etainds = np.where(
            np.sqrt(xy[:, 0]**2 + xy[:, 1]**2) > eta_lenscale)[0]
        displ = lp['eta'] * (np.random.rand(len(etainds), 2) - 0.5)
        xy[etainds, :] += displ
        addstr = '_eta' + sf.float2pstr(lp['eta'], ndigits=3)
        addstr += '_etaalph' + sf.float2pstr(lp['eta_alph'], ndigits=3)
    else:
        addstr = ''

    # If the meshfn going to overwrite a previous realization?
    lattice_exten = 'hex_kagcframe' + lattice_exten[9:] +\
                    '_alph' + sf.float2pstr(lp['alph'], ndigits=2) + addstr
    LV = 'none'
    UC = 'none'
    LVUC = 'none'
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #9
0
def generate_square_lattice(shape, NH, NV, eta=0., theta=0., check=False):
    """Create a square lattice NH wide and NV tall, with sites randomized by eta and rotated by theta.

    Parameters
    ----------
    shape : string
        overall shape of the mesh: 'circle' 'hexagon' 'square'
    NH : int
        Number of pts along horizontal before boundary is cut
    NV : int
        Number of pts along vertical before boundary is cut
    eta : float
        randomization or jitter in the positions of the particles
    theta : float
        orientation of the lattice vectors (rotation) in units of radians
    check : bool
        Whether to view intermediate results

    Results
    ----------
    """
    # Establish square lattice, rotated by theta

    if abs(theta) < 1e-6:
        latticevecs = [[1., 0.], [0., 1.]]
        # todo: SHOULD MODIFY TO INCLUDE LVUC
        # xypts_tmp, LVUC = generate_lattice_LVUC([NH,NV], latticevecs)
        xypts_tmp = blf.generate_lattice([NH, NV], latticevecs)
    else:
        latticevecs = [[np.cos(theta), np.sin(theta)],
                       [np.sin(theta), np.cos(theta)]]
        xypts_tmp, LVUC = blf.generate_lattice([2 * NH, 2 * NV], latticevecs)
    if NH < 3 and NV < 3:
        if NH == NV == 2:
            xypts_tmp = np.array(
                [[0., 0.],
                 np.array(latticevecs[0]),
                 np.array(latticevecs[1]),
                 np.array(latticevecs[0]) + np.array(latticevecs[1])],
                dtype=float)
            xypts_tmp -= np.mean(xypts_tmp)
        elif NH == 1 and NV == 1:
            '''making single point'''
            xypts_tmp = np.array([[0., 0.]])

    print 'xypts_tmp =', xypts_tmp

    if eta == 0. or eta == '':
        etastr = ''
    else:
        etastr = '_eta{0:.3f}'.format(eta).replace('.', 'p')

    if theta == 0. or theta == '':
        thetastr = ''
    else:
        thetastr = '_theta{0:.3f}'.format(theta / np.pi).replace('.',
                                                                 'p') + 'pi'

    if shape == 'square':
        tmp2 = xypts_tmp  # shorten name for clarity
        xy = tmp2  # [np.logical_and(tmp2[:,0]<(NH) , tmp2[:,1]<NV) ,:]
    elif shape == 'circle':
        print 'assuming NH == NV since cutting out a circle...'
        tmp2 = xypts_tmp  # shorten name for clarity
        xy = tmp2[tmp2[:, 0]**2 + tmp2[:, 1]**2 < NH**2, :]
    elif shape == 'hexagon':
        tmp2 = xypts_tmp  # shorten name for clarity
        # xy = tmp2[tmp2[:,0]**2+tmp2[:,1]**2 < (NH)**2 ,:]
        print 'cropping to: ', shape
        # NH, NV = shape['hexagon']
        # Modify below to allow different values of NH and NV on the horiz and vertical sides of the hexagon
        a = NH + 0.5
        polygon = np.array([[-a * 0.5, -np.sqrt(a**2 - (0.5 * a)**2)],
                            [a * 0.5, -np.sqrt(a**2 - (0.5 * a)**2)], [a, 0.],
                            [a * 0.5, np.sqrt(a**2 - (0.5 * a)**2)],
                            [-a * 0.5, np.sqrt(a**2 - (0.5 * a)**2)], [-a, 0.],
                            [-a * 0.5, -np.sqrt(a**2 - (0.5 * a)**2)]])
        bpath = mplpath.Path(polygon)
        keep = bpath.contains_points(tmp2)
        xy = tmp2[keep]

        # Check'
        if check:
            codes = [
                mplpath.Path.MOVETO,
                mplpath.Path.LINETO,
                mplpath.Path.LINETO,
                mplpath.Path.LINETO,
                mplpath.Path.LINETO,
                mplpath.Path.LINETO,
                mplpath.Path.CLOSEPOLY,
            ]
            path = mplpath.Path(polygon, codes)
            ax = plt.gca()
            patch = mpatches.PathPatch(path, facecolor='orange', lw=2)
            ax.add_patch(patch)
            ax.plot(polygon[:, 0], polygon[:, 1], 'bo')
            ax.plot(tmp2[:, 0], tmp2[:, 1], 'r.')
            plt.show()
    else:
        xy = xypts_tmp

    print('Triangulating points...\n')
    print 'xy =', xy

    tri = Delaunay(xy)
    TRItmp = tri.vertices

    print('Computing bond list to remove cross braces...\n')
    BL = le.Tri2BL(TRItmp)
    thres = np.sqrt(2.0) * .99  # cut off everything as long as a diagonal
    print('thres = ' + str(thres))
    print('Trimming bond list...\n')
    orig_numBL = len(BL)
    BL = le.cut_bonds(BL, xy, thres)
    print('Trimmed ' + str(orig_numBL - len(BL)) + ' bonds.')

    # print('Recomputing TRI...\n')
    # TRI = le.BL2TRI(BL, xy)

    # Randomize by eta
    if eta == 0:
        xypts = xy
    else:
        print 'Randomizing lattice by eta=', eta
        jitter = eta * np.random.rand(np.shape(xy)[0], np.shape(xy)[1])
        xypts = np.dstack(
            (xy[:, 0] + jitter[:, 0], xy[:, 1] + jitter[:, 1]))[0]

    # Naming
    exten = '_' + shape + etastr + thetastr

    # BL = latticevec_filter(BL,xy, C, CBL)
    NL, KL = le.BL2NLandKL(BL, NN=4)
    lattice_exten = 'square' + exten
    print 'lattice_exten = ', lattice_exten
    return xypts, NL, KL, BL, lattice_exten
def movie_plot_2D(xy,
                  BL,
                  bs=None,
                  fname='none',
                  title='',
                  NL=[],
                  KL=[],
                  BLNNN=[],
                  NLNNN=[],
                  KLNNN=[],
                  PVx=[],
                  PVy=[],
                  PVxydict={},
                  nljnnn=None,
                  kljnnn=None,
                  klknnn=None,
                  ax=None,
                  fig=None,
                  axcb='auto',
                  cbar_ax=None,
                  cbar_orientation='vertical',
                  xlimv='auto',
                  ylimv='auto',
                  climv=0.1,
                  colorz=True,
                  ptcolor=None,
                  figsize='auto',
                  colorpoly=False,
                  bondcolor=None,
                  colormap='seismic',
                  bgcolor=None,
                  axis_off=False,
                  axis_equal=True,
                  text_topleft=None,
                  lw=-1.,
                  ptsize=10,
                  negative_NNN_arrows=False,
                  show=False,
                  arrow_alpha=1.0,
                  fontsize=8,
                  cax_label='Strain',
                  zorder=0,
                  rasterized=False):
    """Plots (and saves if fname is not 'none') a 2D image of the lattice with colored bonds and particles colored by
    coordination (both optional).

    Parameters
    ----------
    xy : array of dimension nx2
        2D lattice of points (positions x,y)
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    bs : array of dimension #bonds x 1 or None
        Strain in each bond
    fname : string
        Full path including name of the file (.png, etc), if None, will not save figure
    title : string
        The title of the frame
    NL : NP x NN int array (optional, for speed)
        Specify to speed up computation, if colorz or colorpoly or if periodic boundary conditions
    KL : NP x NN int array (optional, for speed)
        Specify to speed up computation, if colorz or colorpoly or if periodic boundary conditions
    BLNNN :
    NLNNN :
    KLNNN :
    PVx : NP x NN float array (optional, for periodic lattices and speed)
        ijth element of PVx is the x-component of the vector taking NL[i,j] to its image as seen by particle i
        If PVx and PVy are specified, PVxydict need not be specified.
    PVy : NP x NN float array (optional, for periodic lattices and speed)
        ijth element of PVy is the y-component of the vector taking NL[i,j] to its image as seen by particle i
        If PVx and PVy are specified, PVxydict need not be specified.
    PVxydict : dict (optional, for periodic lattices)
        dictionary of periodic bonds (keys) to periodic vectors (values)
    nljnnn : #pts x max(#NNN) int array or None
        nearest neighbor array matching NLNNN and KLNNN. nljnnn[i, j] gives the neighbor of i such that NLNNN[i, j] is
        the next nearest neighbor of i through the particle nljnnn[i, j]
    kljnnn : #pts x max(#NNN) int array or None
        bond array describing periodicity of bonds matching NLNNN and KLNNN. kljnnn[i, j] describes the bond type
        (bulk -> +1, periodic --> -1) of bond connecting i to nljnnn[i, j]
    klknnn : #pts x max(#NNN) int array or None
        bond array describing periodicity of bonds matching NLNNN and KLNNN. klknnn[i, j] describes the bond type
        (bulk -> +1, periodic --> -1) of bond connecting nljnnn[i, j] to NLNNN[i, j]
    ax: matplotlib figure axis instance
        Axis on which to draw the network
    fig: matplotlib figure instance
        Figure on which to draw the network
    axcb: matplotlib colorbar instance
        Colorbar to use for strains in bonds
    cbar_ax : axis instance
        Axis to use for colorbar. If colorbar instance is not already defined, use axcb instead.
    cbar_orientation : str ('horizontal' or 'vertical')
        Orientation of the colorbar
    xlimv: float or tuple of floats
    ylimv: float or tuple of floats
    climv : float or tuple
        Color limit for coloring bonds by bs
    colorz: bool
        whether to color the particles by their coordination number
    ptcolor: string color spec or tuple color spec or None
        color specification for coloring the points, if colorz is False. Default is None (no coloring of points)
    figsize : tuple
        w,h tuple in inches
    colorpoly : bool
        Whether to color in polygons formed by bonds according to the number of sides
    bondcolor : color specification (hexadecimal or RGB)
    colormap : if bondcolor is None, uses bs array to color bonds
    bgcolor : hex format string, rgb color spec, or None
        If not None, sets the bgcolor. Often used is '#d9d9d9'
    axis_off : bool
        Turn off the axis border and canvas
    axis_equal : bool
    text_topleft : str or None
    lw: float
        line width for plotting bonds. If lw == -1, then uses automatic line width to adjust for bond density..
    ptsize: float
        size of points passed to absolute_sizer
    negative_NNN_arrows : bool
        make positive and negative NNN hoppings different color
    show : bool
        whether to show the plot after creating it
    arrow_alpha : float
        opacity of the arrow
    fontsize : int (default=8)
        fontsize for all labels
    cax_label : int (default='Strain')
        Label for the colorbar
    zorder : int
        z placement on axis (higher means bringing network to the front, lower is to the back

    Returns
    ----------
    [ax,axcb] : stuff to clear after plotting

    """
    if fig is None or fig == 'none':
        fig = plt.gcf()
    if ax is None or ax == 'none':
        if figsize == 'auto':
            plt.clf()
        else:
            fig = plt.figure(figsize=figsize)
        ax = plt.axes()

    if bs is None:
        bs = np.zeros_like(BL[:, 0], dtype=float)

    if colormap not in plt.colormaps():
        lecmaps.register_colormaps()

    NP = len(xy)
    if lw == -1:
        if NP < 10000:
            lw = 0.5
            s = leplt.absolute_sizer()
        else:
            lw = (10 / np.sqrt(len(xy)))

    if NL == [] and KL == []:
        if colorz or colorpoly:
            NL, KL = le.BL2NLandKL(BL, NP=NP, NN='min')
            if (BL < 0).any():
                if len(PVxydict) == 0:
                    raise RuntimeError(
                        'PVxydict must be supplied to display_lattice_2D() when periodic BCs exist, '
                        + 'if NL and KL not supplied!')
                else:
                    PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL, KL)

    if colorz:
        zvals = (KL != 0).sum(1)
        zmed = np.median(zvals)
        # print 'zmed = ', zmed
        under1 = np.logical_and(zvals < zmed - 0.5, zvals > zmed - 1.5)
        over1 = np.logical_and(zvals > zmed + 0.5, zvals < zmed + 1.5)
        Cz = np.zeros((len(xy), 3), dtype=int)
        # far under black // under blue // equal white // over red // far over green
        Cz[under1] = [0. / 255, 50. / 255, 255. / 255]
        Cz[zvals == zmed] = [100. / 255, 100. / 255, 100. / 255]
        Cz[over1] = [255. / 255, 0. / 255, 0. / 255]
        Cz[zvals > zmed + 1.5] = [0. / 255, 255. / 255, 50. / 255]
        # Cz[zvals<zmed-1.5] = [0./255,255./255,150./255] #leave these black

        s = leplt.absolute_sizer()
        sval = min([.005, .12 / np.sqrt(len(xy))])
        sizes = np.zeros(NP, dtype=float)
        sizes[zvals > zmed + 0.5] = sval
        sizes[zvals == zmed] = sval * 0.5
        sizes[zvals < zmed - 0.5] = sval

        # topinds = zvals!=zmed
        ax.scatter(xy[:, 0],
                   xy[:, 1],
                   s=s(sizes),
                   c=Cz,
                   edgecolor='none',
                   zorder=10,
                   rasterized=rasterized)
        ax.axis('equal')
    elif ptcolor is not None and ptcolor != 'none' and ptcolor != '':
        if NP < 10000:
            # if smallish #pts, plot them
            # print 'xy = ', xy
            # plt.plot(xy[:,0],xy[:,1],'k.')
            s = leplt.absolute_sizer()
            ax.scatter(xy[:, 0],
                       xy[:, 1],
                       s=ptsize,
                       alpha=0.5,
                       facecolor=ptcolor,
                       edgecolor='none',
                       rasterized=rasterized)

    if colorpoly:
        # Color the polygons based on # sides
        # First extract polygons. To do that, if there are periodic boundaries, we need to supply as dict
        if PVxydict == {} and len(PVx) > 0:
            PVxydict = le.PVxy2PVxydict(PVx, PVy, NL, KL=KL)

        polygons = le.extract_polygons_lattice(xy,
                                               BL,
                                               NL=NL,
                                               KL=KL,
                                               viewmethod=True,
                                               PVxydict=PVxydict)
        PolyPC = le.polygons2PPC(polygons)
        # number of polygon sides
        Pno = np.array([len(polyg) for polyg in polygons], dtype=int)
        print 'nvis: Pno = ', Pno
        print 'nvis: medPno = ', np.floor(np.median(Pno))
        medPno = np.floor(np.median(Pno))
        uIND = np.where(Pno == medPno - 1)[0]
        mIND = np.where(Pno == medPno)[0]
        oIND = np.where(Pno == medPno + 1)[0]
        loIND = np.where(Pno < medPno - 1.5)[0]
        hiIND = np.where(Pno > medPno + 1.5)[0]
        print ' uIND = ', uIND
        print ' oIND = ', oIND
        print ' loIND = ', loIND
        print ' hiIND = ', hiIND
        if len(uIND) > 0:
            PPCu = [PolyPC[i] for i in uIND]
            pu = PatchCollection(PPCu, color='b', alpha=0.5)
            ax.add_collection(pu)
        if len(mIND) > 0:
            PPCm = [PolyPC[i] for i in mIND]
            pm = PatchCollection(PPCm, color=[0.5, 0.5, 0.5], alpha=0.5)
            ax.add_collection(pm)
        if len(oIND) > 0:
            PPCo = [PolyPC[i] for i in oIND]
            po = PatchCollection(PPCo, color='r', alpha=0.5)
            ax.add_collection(po)
        if len(loIND) > 0:
            PPClo = [PolyPC[i] for i in loIND]
            plo = PatchCollection(PPClo, color='k', alpha=0.5)
            ax.add_collection(plo)
        if len(hiIND) > 0:
            PPChi = [PolyPC[i] for i in hiIND]
            phi = PatchCollection(PPChi, color='g', alpha=0.5)
            ax.add_collection(phi)

    # Efficiently plot many lines in a single set of axes using LineCollection
    # First check if there are periodic bonds
    if BL.size > 0:
        if (BL < 0).any():
            if PVx == [] or PVy == [] or PVx is None or PVy is None:
                raise RuntimeError(
                    'PVx and PVy must be supplied to display_lattice_2D when periodic BCs exist!'
                )
            else:
                # get indices of periodic bonds
                perINDS = np.unique(np.where(BL < 0)[0])
                perBL = np.abs(BL[perINDS])
                # # Check
                # print 'perBL = ', perBL
                # plt.plot(xy[:,0], xy[:,1],'b.')
                # for i in range(len(xy)):
                #     plt.text(xy[i,0]+0.05, xy[i,1],str(i))
                # plt.show()

                # define the normal bonds which are not periodic
                normINDS = np.setdiff1d(np.arange(len(BL)), perINDS)
                BLtmp = BL[normINDS]
                bstmp = bs[normINDS]
                lines = [
                    zip(xy[BLtmp[i, :], 0], xy[BLtmp[i, :], 1])
                    for i in range(len(BLtmp))
                ]

                xy_add = np.zeros((4, 2))
                # Build new strain list bs_out by storing bulk lines first, then recording the strain twice
                # for each periodic bond since the periodic bond is at least two lines in the plot, get bs_out
                # ready for appending
                # bs_out = np.zeros(len(normINDS) + 5 * len(perINDS), dtype=float)
                # bs_out[0:len(normINDS)] = bstmp
                bs_out = bstmp.tolist()

                # Add periodic bond lines to image
                # Note that we have to be careful that a single particle can be connected to another both in the bulk
                # and through a periodic boundary, and perhaps through more than one periodic boundary
                # kk indexes perINDS to determine what the strain of each periodic bond should be
                # draw_perbond_count counts the number of drawn linesegments that are periodic bonds
                kk, draw_perbond_count = 0, 0
                for row in perBL:
                    colA = np.argwhere(NL[row[0]] == row[1]).ravel()
                    colB = np.argwhere(NL[row[1]] == row[0]).ravel()
                    if len(colA) > 1 or len(colB) > 1:
                        # Look for where KL < 0 to pick out just the periodic bond(s) -- ie there
                        # were both bulk and periodic bonds connecting row[0] to row[1]
                        a_klneg = np.argwhere(KL[row[0]] < 0)
                        colA = np.intersect1d(colA, a_klneg)
                        b_klneg = np.argwhere(KL[row[1]] < 0)
                        colB = np.intersect1d(colB, b_klneg)
                        # print 'colA = ', colA
                        # print 'netvis here'
                        # sys.exit()
                        if len(colA) > 1 or len(colB) > 1:
                            # there are multiple periodic bonds connecting one particle to another (in different
                            # directions). Plot each of them.
                            for ii in range(len(colA)):
                                print 'netvis: colA = ', colA
                                print 'netvis: colB = ', colB
                                # columns a and b for this ii index
                                caii, cbii = colA[ii], colB[ii]
                                # add xy points to the network to plot to simulate image particles
                                xy_add[0] = xy[row[0]]
                                xy_add[1] = xy[row[1]] + np.array(
                                    [PVx[row[0], caii], PVy[row[0], caii]])
                                xy_add[2] = xy[row[1]]
                                xy_add[3] = xy[row[0]] + np.array(
                                    [PVx[row[1], cbii], PVy[row[1], cbii]])
                                # Make the lines to draw (dashed lines for this periodic case)
                                lines += zip(xy_add[0:2, 0],
                                             xy_add[0:2, 1]), zip(
                                                 xy_add[2:4, 0], xy_add[2:4,
                                                                        1])
                                bs_out.append(bs[perINDS[kk]])
                                bs_out.append(bs[perINDS[kk]])
                                draw_perbond_count += 1

                            kk += 1
                        else:
                            # print 'row = ', row
                            # print 'NL = ', NL
                            # print 'KL = ', KL
                            # print 'colA, colB = ', colA, colB
                            colA, colB = colA[0], colB[0]
                            xy_add[0] = xy[row[0]]
                            xy_add[1] = xy[row[1]] + np.array(
                                [PVx[row[0], colA], PVy[row[0], colA]])
                            xy_add[2] = xy[row[1]]
                            xy_add[3] = xy[row[0]] + np.array(
                                [PVx[row[1], colB], PVy[row[1], colB]])
                            lines += zip(xy_add[0:2, 0], xy_add[0:2, 1]), zip(
                                xy_add[2:4, 0], xy_add[2:4, 1])
                            # bs_out[2 * kk + len(normINDS)] = bs[perINDS[kk]]
                            # bs_out[2 * kk + 1 + len(normINDS)] = bs[perINDS[kk]]
                            bs_out.append(bs[perINDS[kk]])
                            bs_out.append(bs[perINDS[kk]])
                            draw_perbond_count += 1
                            kk += 1
                    else:
                        colA, colB = colA[0], colB[0]
                        xy_add[0] = xy[row[0]]
                        xy_add[1] = xy[row[1]] + np.array(
                            [PVx[row[0], colA], PVy[row[0], colA]])
                        xy_add[2] = xy[row[1]]
                        xy_add[3] = xy[row[0]] + np.array(
                            [PVx[row[1], colB], PVy[row[1], colB]])
                        lines += zip(xy_add[0:2, 0],
                                     xy_add[0:2,
                                            1]), zip(xy_add[2:4, 0],
                                                     xy_add[2:4, 1])
                        # bs_out[2 * kk + len(normINDS)] = bs[perINDS[kk]]
                        # bs_out[2 * kk + 1 + len(normINDS)] = bs[perINDS[kk]]
                        bs_out.append(bs[perINDS[kk]])
                        bs_out.append(bs[perINDS[kk]])
                        draw_perbond_count += 1
                        kk += 1

                # replace bs by the new bs (bs_out)
                bs = np.array(bs_out)
                # store number of bulk bonds
                nbulk_bonds = len(normINDS)
        else:
            if len(np.shape(BL)) > 1:
                lines = [
                    zip(xy[BL[i, :], 0], xy[BL[i, :], 1])
                    for i in range(np.shape(BL)[0])
                ]
                # store number of bulk bonds
                nbulk_bonds = len(lines)
            else:
                lines = [
                    zip(xy[BL[i][0]], xy[BL[i][1]])
                    for i in range(np.shape(BL)[0])
                ]
                # store number of bulk bonds
                nbulk_bonds = 1

        if isinstance(climv, tuple):
            cmin = climv[0]
            cmax = climv[1]
        elif isinstance(climv, float):
            cmin = -climv
            cmax = climv
        elif climv is None:
            cmin = None
            cmax = None

        if bondcolor is None:
            # draw the periodic bonds as dashed, regular bulk bonds as solid
            line_segments = LineCollection(
                lines[0:nbulk_bonds],  # Make a sequence of x,y pairs
                linewidths=lw,  # could iterate over list
                linestyles='solid',
                cmap=colormap,
                norm=plt.Normalize(vmin=cmin, vmax=cmax),
                zorder=zorder,
                rasterized=rasterized)
            line_segments.set_array(bs[0:nbulk_bonds])
            # draw the periodic bonds as dashed, if there are any
            periodic_lsegs = LineCollection(
                lines[nbulk_bonds:],  # Make a sequence of x,y pairs
                linewidths=lw,  # could iterate over list
                linestyles='dashed',
                cmap=colormap,
                norm=plt.Normalize(vmin=cmin, vmax=cmax),
                zorder=zorder,
                rasterized=rasterized)
            periodic_lsegs.set_array(bs[nbulk_bonds:])
        else:
            line_segments = LineCollection(lines[0:nbulk_bonds],
                                           linewidths=lw,
                                           linestyles='solid',
                                           colors=bondcolor,
                                           zorder=zorder,
                                           rasterized=rasterized)
            # draw the periodic bonds as dashed, if there are any
            periodic_lsegs = LineCollection(lines[nbulk_bonds:],
                                            linewidths=lw,
                                            linestyles='dashed',
                                            colors=bondcolor,
                                            zorder=zorder,
                                            rasterized=rasterized)

        ax.add_collection(line_segments)
        if periodic_lsegs:
            ax.add_collection(periodic_lsegs)
        # If there is only a single bond color, ignore the colorbar specification
        if bondcolor is None or isinstance(bondcolor, np.ndarray):
            if axcb == 'auto':
                if cbar_ax is None:
                    print 'nvis: Instantiating colorbar...'
                    axcb = fig.colorbar(line_segments)
                else:
                    print 'nvis: Using cbar_ax to instantiate colorbar'
                    axcb = fig.colorbar(line_segments,
                                        cax=cbar_ax,
                                        orientation=cbar_orientation)

            if axcb != 'none' and axcb is not None:
                print 'nvis: Creating colorbar...'
                axcb.set_label(cax_label, fontsize=fontsize)
                axcb.set_clim(vmin=cmin, vmax=cmax)
        else:
            # Ignore colorbar axis specification
            axcb = 'none'
    else:
        axcb = 'none'

    if len(BLNNN) > 0:
        # todo: add functionality for periodic NNN connections
        # Efficiently plot many lines in a single set of axes using LineCollection
        lines = [
            zip(xy[BLNNN[i, :], 0], xy[BLNNN[i, :], 1])
            for i in range(len(BLNNN))
        ]
        linesNNN = LineCollection(
            lines,  # Make a sequence of x,y pairs
            linewidths=lw,  # could iterate over list
            linestyles='dashed',
            color='blue',
            zorder=100)
        ax.add_collection(linesNNN, rasterized=rasterized)
    elif len(NLNNN) > 0 and len(KLNNN) > 0:
        factor = 0.8
        if (BL < 0).any():
            print 'nvis: plotting periodic NNN...'
            if nljnnn is None:
                raise RuntimeError(
                    'Must supply nljnnn to plot NNN hoppings/connections')
            for i in range(NP):
                todo = np.where(KLNNN[i, :] > 1e-12)[0]
                for index in todo:
                    kk = NLNNN[i, index]
                    # Ascribe the correct periodic vector based on both PVx[i, NNind] and PVx[NNind, ind]
                    # Note : nljnnn is
                    # nearest neighbor array matching NLNNN and KLNNN. nljnnn[i, j] gives the neighbor of i such that
                    # NLNNN[i, j] is the next nearest neighbor of i through the particle nljnnn[i, j]
                    jj = nljnnn[i, index]
                    if kljnnn[i, index] < 0 or klknnn[i, index] < 0:
                        jind = np.where(NL[i, :] == jj)[0][0]
                        kind = np.where(NL[jj, :] == kk)[0][0]
                        # print 'jj = ', jj
                        # print 'kk = ', kk
                        # print 'jind = ', jind
                        # print 'kind = ', kind
                        # print 'NL[i, :] =', NL[i, :]
                        # print 'NL[jj, :] =', NL[jj, :]
                        # print 'PVx[i, jind] = ', PVx[i, jind]
                        # print 'PVy[i, jind] = ', PVy[i, jind]
                        # print 'PVx[jj, kind] = ', PVx[jj, kind]
                        # print 'PVy[jj, kind] = ', PVy[jj, kind]
                        dx = (xy[kk, 0] + PVx[i, jind] + PVx[jj, kind] -
                              xy[i, 0]) * factor
                        dy = (xy[kk, 1] + PVy[i, jind] + PVy[jj, kind] -
                              xy[i, 1]) * factor
                    else:
                        dx = (xy[kk, 0] - xy[i, 0]) * factor
                        dy = (xy[kk, 1] - xy[i, 1]) * factor
                    ax.arrow(xy[i, 0],
                             xy[i, 1],
                             dx,
                             dy,
                             head_width=0.1,
                             head_length=0.2,
                             fc='b',
                             ec='b',
                             linestyle='dashed')
                    # Check
                    # print 'dx = ', dx
                    # print 'dy = ', dy
                    # for ind in range(NP):
                    #     plt.text(xy[ind, 0]-0.2, xy[ind, 1]-0.2, str(ind))
                    # plt.show()
                    # sys.exit()
        else:
            # amount to offset clockwise nnn arrows
            for i in range(NP):
                todo = np.where(KLNNN[i, :] > 1e-12)[0]

                # Allow for both blue and red arrows (forward/backward), or just blue. If just blue, use no offset and
                # full scale factor
                if negative_NNN_arrows:
                    scalef = 0.3
                else:
                    scalef = 0.8
                offset = np.array([0.0, 0.0])
                for ind in NLNNN[i, todo]:
                    if negative_NNN_arrows:
                        offset = (xy[ind, :] - xy[i, :]) * 0.5
                    ax.arrow(xy[i, 0] + offset[0],
                             xy[i, 1] + offset[1],
                             (xy[ind, 0] - xy[i, 0]) * scalef,
                             (xy[ind, 1] - xy[i, 1]) * scalef,
                             head_width=0.1,
                             head_length=0.2,
                             fc='b',
                             ec='b',
                             alpha=arrow_alpha)

                if negative_NNN_arrows:
                    todo = np.where(KLNNN[i, :] < -1e-12)[0]
                    for ind in NLNNN[i, todo]:
                        offset = (xy[ind, :] - xy[i, :]) * 0.5
                        ax.arrow(xy[i, 0] + offset[0],
                                 xy[i, 1] + offset[1],
                                 (xy[ind, 0] - xy[i, 0]) * 0.3,
                                 (xy[ind, 1] - xy[i, 1]) * 0.3,
                                 head_width=0.1,
                                 head_length=0.2,
                                 fc='r',
                                 ec='r',
                                 alpha=arrow_alpha)

    if bgcolor is not None:
        ax.set_axis_bgcolor(bgcolor)

    # set limits
    ax.axis('scaled')
    if xlimv != 'auto' and xlimv is not None:
        if isinstance(xlimv, tuple):
            ax.set_xlim(xlimv[0], xlimv[1])
        else:
            print 'nvis: setting xlimv'
            ax.set_xlim(-xlimv, xlimv)
    else:
        ax.set_xlim(np.min(xy[:, 0]) - 2.5, np.max(xy[:, 0]) + 2.5)

    if ylimv != 'auto' and ylimv is not None:
        if isinstance(ylimv, tuple):
            print 'nvis: setting ylimv to tuple'
            ax.set_ylim(ylimv[0], ylimv[1])
        else:
            ax.set_ylim(-ylimv, ylimv)
    else:
        print 'nvis: setting', min(xy[:, 1]), max(xy[:, 1])
        ax.set_ylim(np.min(xy[:, 1]) - 2, np.max(xy[:, 1]) + 2)

    if title is not None:
        ax.set_title(title, fontsize=fontsize)
    if text_topleft is not None:
        ax.text(0.05,
                .98,
                text_topleft,
                horizontalalignment='right',
                verticalalignment='top',
                transform=ax.transAxes)
    if axis_off:
        ax.axis('off')

    if fname != 'none' and fname != '' and fname is not None:
        print 'nvis: saving figure: ', fname
        plt.savefig(fname)
    if show:
        plt.show()

    return [ax, axcb]
Beispiel #11
0
def generate_penrose_rhombic_tiling(Num_sub, check=False):
    """Generates penrose rhomus tiling (P3) with given number of subdivisions (scaling method)
    http://preshing.com/20110831/penrose-tiling-explained/
    """
    # ------ Configuration --------
    NUM_SUBDIVISIONS = Num_sub
    # -----------------------------

    goldenRatio = (1.0 + math.sqrt(5.0)) / 2.0

    def subdivide(triangles):
        result = []
        for color, A, B, C in triangles:
            if color == 0:
                # Subdivide red triangle
                P = A + (B - A) / goldenRatio
                result += [(0, C, P, B), (1, P, C, A)]
            else:
                # Subdivide blue triangle
                Q = B + (A - B) / goldenRatio
                R = B + (C - B) / goldenRatio
                result += [(1, R, C, A), (1, Q, R, B), (0, R, Q, A)]
        return result

        # Create wheel of red triangles around the origin
        triangles = []
        for i in xrange(10):
            B = cmath.rect(1, (2*i - 1) * math.pi / 10)
            C = cmath.rect(1, (2*i + 1) * math.pi / 10)
            if i % 2 == 0:
                B, C = C, B # Make sure to mirror every second triangle
            triangles.append((0, B, 0j, C))

    def plot_quasicrystal(triangles):
        ax = plt.gca()
        for color, A, B, C in triangles:
            if color == 0:
                codes = [mplpath.Path.MOVETO,
                        mplpath.Path.LINETO,
                        mplpath.Path.LINETO,
                        mplpath.Path.CLOSEPOLY,
                        ]
                polygon = np.array([[A.real, A.imag], [B.real, B.imag], [C.real, C.imag], [A.real, A.imag]])
                path = mplpath.Path(polygon, codes)
                patch = mpatches.PathPatch(path, facecolor='orange', lw=2)
                ax.add_patch(patch)

            if color == 1:
                codes = [mplpath.Path.MOVETO,
                        mplpath.Path.LINETO,
                        mplpath.Path.LINETO,
                        mplpath.Path.CLOSEPOLY,
                        ]
                polygon = np.array([[A.real, A.imag], [B.real, B.imag], [C.real, C.imag], [A.real, A.imag]])
                path = mplpath.Path(polygon, codes)
                patch = mpatches.PathPatch(path, facecolor='blue', lw=2)
                ax.add_patch(patch)
        return ax

    # Create wheel of red triangles around the origin
    triangles = []
    for i in xrange(10):
        B = cmath.rect(1, (2*i - 1) * math.pi / 10)
        C = cmath.rect(1, (2*i + 1) * math.pi / 10)
        if i % 2 == 0:
            B, C = C, B  # Make sure to mirror every second triangle
        triangles.append((0, 0j, B, C))

    # Perform subdivisions
    for i in xrange(NUM_SUBDIVISIONS):
        triangles = subdivide(triangles)

    # Prepare cairo surface
    # surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMAGE_SIZE[0], IMAGE_SIZE[1])
    # cr = cairo.Context(surface)
    # cr.translate(IMAGE_SIZE[0] / 2.0, IMAGE_SIZE[1] / 2.0)
    # wheelRadius = 1.2 * math.sqrt((IMAGE_SIZE[0] / 2.0) ** 2 + (IMAGE_SIZE[1] / 2.0) ** 2)
    # cr.scale(wheelRadius, wheelRadius)

    # Draw red triangles
    if check:
        plot_quasicrystal(triangles)
        plt.show()

    # Scale points
    tri = np.array(triangles)
    mindist = np.min(abs(tri[:, 1] - tri[:, 0]))
    print 'mindist = ', mindist
    scale = 1./mindist
    tri = tri[:, 1:4] * scale
    if check:
        plot_quasicrystal(triangles)

    # Convert points to numbered points
    # Create dict of locations to indices
    indexd = {}
    xy = np.zeros((len(tri) * 3, 2))
    TRI = np.zeros_like(tri, dtype=int)
    rowIND = 0
    dmyi = 0
    offs = float(np.ceil(np.max(tri.real).ravel())+1)
    for AA, BB, CC in tri:
        # reformat A,B,C
        A = ('{0:0.2f}'.format(AA.real + offs), '{0:0.2f}'.format(AA.imag + offs))
        B = ('{0:0.2f}'.format(BB.real + offs), '{0:0.2f}'.format(BB.imag + offs))
        C = ('{0:0.2f}'.format(CC.real + offs), '{0:0.2f}'.format(CC.imag + offs))
        # print '\n\n\n'
        # print 'A = ', A
        if A not in indexd:
            indexd[A] = dmyi
            xy[dmyi] = [AA.real, AA.imag]
            TRI[rowIND, 0] = dmyi
            dmyi += 1
            # print 'xy[0:dmyi,:] = ', xy[0:dmyi,:]
        else:
            index = indexd[A]
            TRI[rowIND, 0] = index

        # print 'indexd = ', indexd
        # print '\nB = ', B
        if B not in indexd:
            indexd[B] = dmyi
            xy[dmyi] = [BB.real, BB.imag]
            TRI[rowIND, 1] = dmyi
            dmyi += 1
            # print 'xy[0:dmyi,:] = ', xy[0:dmyi,:]
        else:
            index = indexd[B]
            TRI[rowIND, 1] = index

        # print 'indexd = ', indexd
        # print '\nC = ', C
        if C not in indexd:
            indexd[C] = dmyi
            xy[dmyi] = [CC.real, CC.imag]
            TRI[rowIND, 2] = dmyi
            dmyi += 1
            # print 'xy[0:dmyi,:] = ', xy[0:dmyi,:]
        else:
            index = indexd[C]
            TRI[rowIND, 2] = index
        rowIND += 1

    xy = xy[0:dmyi]
    print 'xy = ', xy

    if check:
        # plot_quasicrystal(triangles)
        plt.plot(xy[:, 0], xy[:, 1], 'b.')
        plt.triplot(xy[:, 0], xy[:, 1], TRI, 'ro-')
        plt.show()

    BL = le.TRI2BL(TRI)
    NL, KL = le.BL2NLandKL(BL, NP='auto', NN='min')
    print 'TRI = ', TRI
    print 'BL = ', BL
    if check:
        le.display_lattice_2D(xy, BL, close=False)
        for ii in range(len(xy)):
            plt.text(xy[ii, 0], xy[ii, 1], str(ii))
        plt.show()

    lattice_exten = 'penroserhombTri_div_' + str(Num_sub)
    return xy, NL, KL, BL, TRI, lattice_exten
Beispiel #12
0
def build_lattice(lattice):
    """Build the lattice based on the values stored in the lp dictionary attribute of supplied lattice instance.

    Returns
    -------
    lattice : lattice_class lattice instance
        The instance of the lattice class, with the following attributes populated:
        lattice.xy = xy
        lattice.NL = NL
        lattice.KL = KL
        lattice.BL = BL
        lattice.PVx = PVx
        lattice.PVy = PVy
        lattice.PVxydict = PVxydict
        lattice.PV = PV
        lattice.lp['BBox'] : #vertices x 2 float array
            BBox is the polygon used to crop the lattice or defining the extent of the lattice; could be hexagonal, for instance.
        lattice.lp['LL'] : tuple of 2 floats
            LL are the linear extent in each dimension of the lattice. For ex:
            ( np.max(xy[:,0])-np.min(xy[:,0]), np.max(xy[:,1])-np.min(xy[:,1]) )
        lattice.lp['LV'] = LV
        lattice.lp['UC'] = UC
        lattice.lp['lattice_exten'] : str
            A string specifier for the lattice built
        lattice.lp['slit_exten'] = slit_exten
    """
    # Define some shortcut variables
    lattice_type = lattice.lp['LatticeTop']
    shape = lattice.lp['shape']
    NH = lattice.lp['NH']
    NV = lattice.lp['NV']
    lp = lattice.lp
    networkdir = lattice.lp['rootdir'] + 'networks/'
    check = lattice.lp['check']
    if lattice_type == 'hexagonal':
        from build_hexagonal import build_hexagonal
        xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = build_hexagonal(
            lp)
    elif lattice_type == 'hexmeanfield':
        from build_hexagonal import build_hexmeanfield
        xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = build_hexmeanfield(
            lp)
    elif lattice_type == 'hexmeanfield3gyro':
        from build_hexagonal import build_hexmeanfield3gyro
        xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = build_hexmeanfield3gyro(
            lp)
    elif 'selregion' in lattice_type:
        # amorphregion_isocent or amorphregion_kagome_isocent, for ex
        # Example usage: python ./build/make_lattice.py -LT selregion_randorg_gammakick1p60_cent -spreadt 0.8 -NP 225
        #  python ./build/make_lattice.py -LT selregion_iscentroid -N 30
        #  python ./build/make_lattice.py -LT selregion_hyperuniform -N 80
        from lepm.build.build_select_region import build_select_region
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_select_region(
            lp)
    elif lattice_type == 'frame1dhex':
        from build_hexagonal import build_frame1dhex
        # keep only the boundary of the lattice, eliminate the bulk
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_frame1dhex(
            lp)
    elif lattice_type == 'square':
        import lepm.build.build_square as bs
        print '\nCreating square lattice...'
        xy, NL, KL, BL, lattice_exten = bs.generate_square_lattice(
            shape, NH, NV, lp['eta'], lp['theta'])
        print 'lattice_exten = ', lattice_exten
        PVx = []
        PVy = []
        PVxydict = {}
        LL = (NH + 1, NV + 1)
        LVUC = 'none'
        UC = 'none'
        LV = 'none'
        BBox = np.array([[-LL[0] * 0.5, -LL[1] * 0.5],
                         [LL[0] * 0.5,
                          -LL[1] * 0.5], [LL[0] * 0.5, LL[1] * 0.5],
                         [-LL[0] * 0.5, LL[1] * 0.5]])
    elif lattice_type == 'triangular':
        import lepm.build.build_triangular as bt
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = bt.build_triangular_lattice(
            lp)
    elif lattice_type == 'linear':
        from lepm.build.build_linear_lattices import build_zigzag_lattice
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_zigzag_lattice(
            lp)
        lp['NV'] = 1
    elif lattice_type == 'deformed_kagome':
        from lepm.build.build_kagome import generate_deformed_kagome
        xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = generate_deformed_kagome(
            lp)
    elif lattice_type == 'deformed_martini':
        from lepm.build.build_martini import build_deformed_martini
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_deformed_martini(
            lp)
    elif lattice_type == 'twisted_kagome':
        from lepm.build.build_kagome import build_twisted_kagome
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_twisted_kagome(
            lp)
    elif lattice_type == 'hyperuniform':
        from lepm.build.build_hyperuniform import build_hyperuniform
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_hyperuniform(
            lp)
    elif lattice_type == 'hyperuniform_annulus':
        from lepm.build.build_hyperuniform import build_hyperuniform_annulus
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_hyperuniform_annulus(
            lp)
        lp['shape'] = 'annulus'
    elif lattice_type == 'isostatic':
        from lepm.build.build_jammed import build_isostatic
        # Manually tune coordination of jammed packing (lets you tune through isostatic point)
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_isostatic(
            lp)
    elif lattice_type == 'jammed':
        from lepm.build.build_jammed import build_jammed
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_jammed(
            lp)
    elif lattice_type == 'triangularz':
        from lepm.build.build_triangular import build_triangularz
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_triangularz(
            lp)
    elif lattice_type == 'hucentroid':
        from lepm.build.build_hucentroid import build_hucentroid
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_hucentroid(
            lp)
    elif lattice_type == 'hucentroid_annulus':
        from lepm.build.build_hucentroid import build_hucentroid_annulus
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_hucentroid_annulus(
            lp)
        lp['shape'] = 'annulus'
    elif lattice_type == 'huvoronoi':
        from lepm.build.build_voronoized import build_huvoronoi
        xy, NL, KL, BL, PVx, PVy, PVxydict, LL, BBox, lattice_exten = build_huvoronoi(
            lp)
        LVUC = 'none'
        LV = 'none'
        UC = 'none'
    elif lattice_type == 'kagome_hucent':
        from lepm.build.build_hucentroid import build_kagome_hucent
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_kagome_hucent(
            lp)
    elif lattice_type == 'kagome_hucent_annulus':
        from lepm.build.build_hucentroid import build_kagome_hucent_annulus
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_kagome_hucent_annulus(
            lp)
        lp['shape'] = 'annulus'
    elif lattice_type == 'kagome_huvor':
        from lepm.build.build_voronoized import build_kagome_huvor
        print('Loading hyperuniform to build lattice...')
        xy, NL, KL, BL, PVx, PVy, PVxydict, LL, BBox, lattice_exten = build_kagome_huvor(
            lp)
        LV, LVUC, UC = 'none', 'none', 'none'
    elif lattice_type == 'iscentroid':
        from lepm.build.build_iscentroid import build_iscentroid
        print('Loading isostatic to build lattice...')
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten = build_iscentroid(
            lp)
    elif lattice_type == 'kagome_isocent':
        from lepm.build.build_iscentroid import build_kagome_isocent
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten = build_kagome_isocent(
            lp)
    elif lattice_type == 'overcoordinated1':
        from lepm.build.build_overcoordinated import generate_overcoordinated1_lattice
        xy, NL, KL, BL, SBL, LV, UC, LVUC, lattice_exten = generate_overcoordinated1_lattice(
            NH, NV)
        PVxydict = {}
        PVx = []
        PVy = []
        if lp['check']:
            le.display_lattice_2D(xy, BL)
    elif lattice_type == 'circlebonds':
        from lepm.build.build_linear_lattices import generate_circle_lattice
        xy, NL, KL, BL, LV, UC, LVUC, lattice_exten = generate_circle_lattice(
            NH)
        PVxydict = {}
        PVx = []
        PVy = []
        lp['NV'] = 1
        minx = np.min(xy[:, 0])
        maxx = np.max(xy[:, 0])
        miny = np.min(xy[:, 1])
        maxy = np.max(xy[:, 1])
        BBox = np.array([[minx, miny], [minx, maxy], [maxx, maxy],
                         [maxx, miny]])
        LL = (maxx - minx, maxy - miny)
    elif lattice_type == 'dislocatedRand':
        from lepm.build.build_dislocatedlattice import build_dislocated_lattice
        xy, NL, KL, BL, PVx, PVy, PVxydict, LL, BBox, lattice_exten = build_dislocated_lattice(
            lp)
    elif lattice_type == 'dislocated':
        if lp['dislocation_xy'] != 'none':
            dislocX = lp['dislocation_xy'].split('/')[0]
            dislocY = lp['dislocation_xy'].split('/')[1]
            dislocxy_exten = '_dislocxy_' + dislocX + '_' + dislocY
            pt = np.array([[float(dislocX), float(dislocY)]])
        else:
            pt = np.array([[0., 0.]])
            dislocxy_exten = ''
        if lp['Bvec'] == 'random':
            Bvecs = 'W'
        else:
            Bvecs = lp['Bvec']
        xy, NL, KL, BL, lattice_exten = generate_dislocated_hexagonal_lattice(
            shape, NH, NV, pt, Bvecs=Bvecs, check=lp['check'])
        lattice_exten += dislocxy_exten
        PVx = []
        PVy = []
        PVxydict = {}
        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        BBox = np.array([[np.min(xy[:, 0]), np.min(xy[:, 1])],
                         [np.max(xy[:, 0]), np.min(xy[:, 1])],
                         [np.max(xy[:, 0]), np.max(xy[:, 1])],
                         [np.min(xy[:, 0]), np.max(xy[:, 1])]])
        LV = 'none'
        UC = 'none'
        LVUC = 'none'
    elif lattice_type == 'penroserhombTri':
        if lp['periodicBC']:
            from lepm.build.build_quasicrystal import generate_periodic_penrose_rhombic
            xy, NL, KL, BL, PVxydict, BBox, PV, lattice_exten = generate_periodic_penrose_rhombic(
                lp)
            LL = (PV[0, 0], PV[1, 1])
            PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)
        else:
            from lepm.build.build_quasicrystal import generate_penrose_rhombic_lattice
            xy, NL, KL, BL, lattice_exten, Num_sub = generate_penrose_rhombic_lattice(
                shape, NH, NV, check=lp['check'])
            LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
                  np.max(xy[:, 1]) - np.min(xy[:, 1]))
            BBox = blf.auto_polygon(shape, NH, NV, eps=0.00)
            PVx = []
            PVy = []
            PVxydict = {}

        LVUC = 'none'
        LV = 'none'
        UC = 'none'
    elif lattice_type == 'penroserhombTricent':
        from lepm.build.build_quasicrystal import generate_penrose_rhombic_centroid_lattice
        xy, NL, KL, BL, PVxydict, PV, LL, BBox, lattice_exten = generate_penrose_rhombic_centroid_lattice(
            lp)
        # deepcopy PVxydict to generate new pointers
        PVxydict = copy.deepcopy(PVxydict)
        if lp['periodicBC']:
            PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)
        else:
            PVx, PVy = [], []

        # Rescale so that median bond length is unity
        bL = le.bond_length_list(xy, BL, NL=NL, KL=KL, PVx=PVx, PVy=PVy)
        scale = 1. / np.median(bL)
        xy *= scale
        PV *= scale
        print 'PV = ', PV
        BBox *= scale
        LL = (LL[0] * scale, LL[1] * scale)

        print 'after updating other things: PVxydict = ', PVxydict
        if lp['periodicBC']:
            PVx *= scale
            PVy *= scale
            PVxydict.update(
                (key, val * scale) for key, val in PVxydict.items())
        else:
            PVx = []
            PVy = []

        LVUC = 'none'
        LV = 'none'
        UC = 'none'
    elif lattice_type == 'kagome_penroserhombTricent':
        from build.build_quasicrystal import generate_penrose_rhombic_centroid_lattice
        xy, NL, KL, BL, lattice_exten = generate_penrose_rhombic_centroid_lattice(
            shape, NH + 5, NV + 5, check=lp['check'])

        # Decorate lattice as kagome
        print('Decorating lattice as kagome...')
        xy, BL, PVxydict = blf.decorate_as_kagome(xy, BL)
        lattice_exten = 'kagome_' + lattice_exten

        xy, NL, KL, BL = blf.mask_with_polygon(shape,
                                               NH,
                                               NV,
                                               xy,
                                               BL,
                                               eps=0.00,
                                               check=False)

        # Rescale so that median bond length is unity
        bL = le.bond_length_list(xy, BL)
        xy *= 1. / np.median(bL)

        minx = np.min(xy[:, 0])
        miny = np.min(xy[:, 1])
        maxx = np.max(xy[:, 0])
        maxy = np.max(xy[:, 1])
        BBox = np.array([[minx, miny], [minx, maxy], [maxx, maxy],
                         [maxx, miny]])
        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        PVx = []
        PVy = []
        PVxydict = {}
        LVUC = 'none'
        LV = 'none'
        UC = 'none'
    elif lattice_type == 'random':
        xx = np.random.uniform(low=-NH * 0.5 - 10,
                               high=NH * 0.5 + 10,
                               size=(NH + 20) * (NV + 20))
        yy = np.random.uniform(low=-NV * 0.5 - 10,
                               high=NV * 0.5 + 10,
                               size=(NH + 20) * (NV + 20))
        xy = np.dstack((xx, yy))[0]
        Dtri = Delaunay(xy)
        TRI = Dtri.vertices
        BL = le.Tri2BL(TRI)
        NL, KL = le.BL2NLandKL(BL, NN='min')

        # Crop to polygon (instead of trimming boundaries)
        # NL, KL, BL, TRI = le.delaunay_cut_unnatural_boundary(xy, NL, KL, BL, TRI, thres=lp['trimbound_thres'])
        shapedict = {shape: [NH, NV]}
        keep = blf.argcrop_lattice_to_polygon(shapedict, xy, check=check)
        xy, NL, KL, BL = le.remove_pts(keep, xy, BL, NN='min')

        lattice_exten = lattice_type + '_square_thres' + sf.float2pstr(
            lp['trimbound_thres'])
        polygon = blf.auto_polygon(shape, NH, NV, eps=0.00)
        BBox = polygon
        LL = (np.max(BBox[:, 0]) - np.min(BBox[:, 0]),
              np.max(BBox[:, 1]) - np.min(BBox[:, 1]))
        PVx = []
        PVy = []
        PVxydict = {}
        LVUC = 'none'
        LV = 'none'
        UC = 'none'
    elif lattice_type == 'randomcent':
        from lepm.build.build_random import build_randomcent
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_randomcent(
            lp)
    elif lattice_type == 'kagome_randomcent':
        from lepm.build.build_random import build_kagome_randomcent
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_kagome_randomcent(
            lp)
    elif lattice_type == 'randomspreadcent':
        from lepm.build.build_randomspread import build_randomspreadcent
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_randomspreadcent(
            lp)
    elif lattice_type == 'kagome_randomspread':
        from lepm.build.build_randomspread import build_kagome_randomspread
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_kagome_randomspread(
            lp)
    elif 'randorg_gammakick' in lattice_type and 'kaghi' not in lattice_type:
        # lattice_type is like 'randorg_gamma0p20_cent' and uses Hexner pointsets
        # NH is width, NV is height, NP_load is total number of points. This is different than other conventions.
        from build_randorg_gamma import build_randorg_gamma_spread
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_randorg_gamma_spread(
            lp)
    elif 'randorg_gamma' in lattice_type and 'kaghi' not in lattice_type:
        # lattice_type is like 'randorg_gamma0p20_cent' and uses Hexner pointsets
        from build_randorg_gamma import build_randorg_gamma_spread_hexner
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = \
            build_randorg_gamma_spread_hexner(lp)
    elif 'random_organization' in lattice_type:
        try:
            if isinstance(lp['relax_timesteps'], str):
                relax_tag = lp['relax_timesteps']
            else:
                relax_tag = '{0:02d}'.format(lp['relax_timesteps'])
        except:
            raise RuntimeError(
                'lattice parameters dictionary lp needs key relax_timesteps')

        points = np.loadtxt(
            networkdir +
            'random_organization_source/random_organization/random/' +
            'random_kick_' + relax_tag + 'relax/out_d' +
            '{0:02d}'.format(int(lp['conf'])) + '_xy.txt')
        points -= np.mean(points, axis=0)
        xytmp, trash1, trash2, trash3 = blf.mask_with_polygon(shape,
                                                              NH,
                                                              NV,
                                                              points, [],
                                                              eps=0.00)

        xy, NL, KL, BL = le.delaunay_centroid_lattice_from_pts(xytmp,
                                                               polygon='auto',
                                                               check=check)
        polygon = blf.auto_polygon(shape, NH, NV, eps=0.00)

        if check:
            le.display_lattice_2D(xy, BL)

        # Rescale so that median bond length is unity
        bL = le.bond_length_list(xy, BL, NL=NL, KL=KL, PVx=PVx, PVy=PVy)
        xy *= 1. / np.median(bL)
        polygon *= 1. / np.median(bL)

        lattice_exten = lattice_type + '_relax' + relax_tag + '_' + shape + '_d' + \
                        '{0:02d}'.format(int(lp['loadlattice_number']))
        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        PVxydict = {}
        PVx = []
        PVy = []
        BBox = polygon
    elif lattice_type == 'flattenedhexagonal':
        from lepm.build.build_hexagonal import generate_flattened_honeycomb_lattice
        xy, NL, KL, BL, LVUC, LV, UC, PVxydict, PVx, PVy, lattice_exten = \
            generate_flattened_honeycomb_lattice(shape, NH, NV, lp['aratio'], lp['delta'], lp['phi'], eta=0., rot=0.,
                                                 periodicBC=False, check=check)
    elif lattice_type == 'cairo':
        from lepm.build.build_cairo import build_cairo
        xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = build_cairo(
            lp)
    elif lattice_type == 'kagper_hucent':
        from lepm.build.build_hucentroid import build_kagper_hucent
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagper_hucent(
            lp)
    elif lattice_type == 'hex_kagframe':
        from lepm.build.build_kagcentframe import build_hex_kagframe
        # Use lp['alph'] to determine the beginning of the kagomized frame, surrounding hexagonal lattice
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_hex_kagframe(
            lp)
    elif lattice_type == 'hex_kagcframe':
        from lepm.build.build_kagcentframe import build_hex_kagcframe
        # Use lp['alph'] to determine the beginning of the kagomized frame, surrounding hexagonal lattice
        # as circlular annulus
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_hex_kagcframe(
            lp)
    elif lattice_type in ['hucent_kagframe', 'hucent_kagcframe']:
        from lepm.build.build_kagcentframe import build_hucent_kagframe
        # Use lp['alph'] to determine the beginning of the kagomized frame, surrounding hucentroid decoration
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_hucent_kagframe(
            lp)
    elif lattice_type == 'kaghu_centframe':
        from lepm.build.build_kagcentframe import build_kaghu_centframe
        # Use lp['alph'] to determine the beginning of the centroid frame, surrounding kagomized decoration
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kaghu_centframe(
            lp)
    elif lattice_type in ['isocent_kagframe', 'isocent_kagcframe']:
        from lepm.build.build_kagcentframe import build_isocent_kagframe
        # Use lp['alph'] to determine the beginning of the kagomized frame, surrounding hucentroid decoration
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_isocent_kagframe(
            lp)
    elif lattice_type == 'kagsplit_hex':
        from lepm.build.build_kagome import build_kagsplit_hex
        # Use lp['alph'] to determine what fraction (on the right) is kagomized
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagsplit_hex(
            lp)
    elif lattice_type == 'kagper_hex':
        from lepm.build.build_kagome import build_kagper_hex
        # Use lp['alph'] to determine what fraction of the radius/width (in the center) is kagomized
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagper_hex(
            lp)
    elif lattice_type == 'hex_kagperframe':
        from lepm.build.build_kagcentframe import build_hex_kagperframe
        # Use lp['alph'] to determine what fraction of the radius/width (in the center) is partially kagomized
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_hex_kagperframe(
            lp)
    elif lattice_type == 'kagome':
        from lepm.build.build_kagome import build_kagome
        # lets you make a square kagome
        xy, NL, KL, BL, PVx, PVy, PVxydict, PV, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagome(
            lp)
    elif 'uofc' in lattice_type:
        from lepm.build.build_kagcent_words import build_uofc
        # ['uofc_hucent', 'uofc_kaglow_hucent', 'uofc_kaghi_hucent', 'uofc_kaglow_isocent']:
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_uofc(
            lp)
    elif 'chicago' in lattice_type:
        from lepm.build.build_kagcent_words import build_chicago
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_chicago(
            lp)
    elif 'chern' in lattice_type:
        from lepm.build.build_kagcent_words import build_kagcentchern
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagcentchern(
            lp)
    elif 'csmf' in lattice_type:
        from lepm.build.build_kagcent_words import build_kagcentcsmf
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagcentcsmf(
            lp)
    elif 'thanks' in lattice_type:
        # example:
        # python ./build/make_lattice.py -LT kaghi_isocent_thanks -skip_gyroDOS -NH 300 -NV 70 -thres 5.5 -skip_polygons
        from lepm.build.build_kagcent_words import build_kagcentthanks
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagcentthanks(
            lp)
    elif 'curvys' in lattice_type:
        # for lattice_type in ['kaghi_isocent_curvys', 'kaglow_isocent_curvys',
        #                      'kaghi_hucent_curvys', 'kaglow_hucent_curvys', kaghi_randorg_gammakick1p60_cent_curvys',
        #                      'kaghi_randorg_gammakick0p50_cent_curvys', ... ]
        # example usage:
        # python ./build/make_lattice.py -LT kaghi_isocent_curvys -NH 100 -NV 70 -thres 5.5 -skip_polygons -skip_gyroDOS
        from lepm.build.build_kagcent_words import build_kagcentcurvys
        xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagcentcurvys(
            lp)
    elif 'hexannulus' in lattice_type:
        from lepm.build.build_conformal import build_hexannulus
        xy, NL, KL, BL, lattice_exten, lp = build_hexannulus(lp)
        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        PVxydict = {}
        PVx = []
        PVy = []
        UC = np.array([0, 0])
        LV = 'none'
        LVUC = 'none'
        minx = np.min(xy[:, 0])
        miny = np.min(xy[:, 1])
        maxx = np.max(xy[:, 0])
        maxy = np.max(xy[:, 1])
        BBox = np.array([[minx, miny], [minx, maxy], [maxx, maxy],
                         [maxx, miny]])
    elif 'accordion' in lattice_type:
        # accordionhex accordiony accordionkagy
        # Example usage:
        # python ./build/make_lattice.py -LT accordionkag -alph 0.9 -intparam 2 -N 6 -skip_polygons -skip_gyroDOS
        # nzag controlled by lp['intparam'], and the rotation of the kagome element is controlled by lp['alph']
        if lattice_type == 'accordionhex':
            from lepm.build.build_hexagonal import build_accordionhex
            xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp, xyvx = build_accordionhex(
                lp)
        elif lattice_type == 'accordionkag':
            from lepm.build.build_kagome import build_accordionkag
            xy, NL, KL, BL, PVx, PVy, PVxydict, PV, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_accordionkag(
                lp)
        elif lattice_type == 'accordionkag_hucent':
            from lepm.build.build_hucentroid import build_accordionkag_hucent
            xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = \
                build_accordionkag_hucent(lp)
        elif lattice_type == 'accordionkag_isocent':
            from lepm.build.build_iscentroid import build_accordionkag_isocent
            xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten = \
                build_accordionkag_isocent(lp)
    elif 'spindle' in lattice_type:
        if lattice_type == 'spindle':
            from lepm.build.build_spindle import build_spindle
            xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = build_spindle(
                lp)
    elif lattice_type == 'stackedrhombic':
        from lepm.build.build_rhombic import build_stacked_rhombic
        xy, NL, KL, BL, PVxydict, PVx, PVy, PV, LL, LVUC, LV, UC, BBox, lattice_exten = build_stacked_rhombic(
            lp)
    elif 'junction' in lattice_type:
        # accordionhex accordiony accordionkagy
        if lattice_type == 'hexjunction':
            from lepm.build.build_hexagonal import build_hexjunction
            xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp, xyvx = build_hexjunction(
                lp)
        elif lattice_type == 'kagjunction':
            from lepm.build.build_kagome import build_kagjunction
            xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp = build_kagjunction(
                lp)

    ###########

    # For reference: this is how to change z
    # le.cut_bonds_z(BL,lp['target_z'])
    # ##cut N bonds for z
    # N2cut = int(round((z_start-target_z)*len(BL)/z_start))
    # allrows = range(len(BL))
    # inds = random.sample(allrows, N2cut)
    # keep = np.setdiff1d(allrows,inds)
    # bnd_z = BL[keep]

    # Cut slit
    if lp['make_slit']:
        print('Cuting notch or slit...')
        L = max(xy[:, 0]) - min(xy[:, 0])
        cutL = L * lp['cutLfrac']
        x0 = -L * 0. + cutL * 0.5 - 1.  # 0.25*L+0.5
        BL, xy = blf.cut_slit(BL, xy, cutL + 1e-3, x0, y0=0.2)
        slit_exten = '_cutL' + str(cutL / L) + 'L_x0_' + str(x0)

        print('Rebuilding NL,KL...')
        NP = len(xy)
        if latticetop == 'deformed_kagome':
            nn = 4
        elif lattice_type == 'linear':
            if NP == 1:
                nn = 0
            else:
                nn = 2
        else:
            nn = 'min'

        NL, KL = le.BL2NLandKL(BL, NP=NP, NN=nn)

        # remake BL too
        BL = le.NL2BL(NL, KL)
    else:
        slit_exten = ''
        NP = len(xy)

    if lp['check']:
        print 'make_lattice: Showing lattice before saving...'
        # print 'PVx = ', PVx
        # print 'PVy = ', PVy
        le.display_lattice_2D(xy, BL, PVxydict=PVxydict)
    ################

    lattice.xy = xy
    lattice.NL = NL
    lattice.KL = KL
    lattice.BL = BL
    lattice.PVx = PVx
    lattice.PVy = PVy
    lattice.PVxydict = PVxydict
    lattice.LVUC = LVUC
    lattice.lp = lp
    lattice.lp['BBox'] = BBox
    lattice.lp['LL'] = LL
    lattice.lp['LV'] = LV
    lattice.lp['UC'] = UC
    lattice.lp['lattice_exten'] = lattice_exten
    lattice.lp['slit_exten'] = slit_exten
    lattice.lp['Nparticles'] = NP
    return lattice
Beispiel #13
0
def build_accordionkag_hucent(lp):
    """Create an accordion-bonded kagomized amorphous network from a loaded hyperuniform point set.

    Parameters
    ----------
    lp

    Returns
    -------

    """
    print('Loading hyperuniform to build lattice...')
    networkdir = lp['rootdir'] + 'networks/'
    shape = lp['shape']
    NH = lp['NH']
    NV = lp['NV']
    check = lp['check']
    if lp['NP_load'] == 0:
        points = np.loadtxt(networkdir +
                            'hyperuniform_source/hyperuniform_N400/out_d' +
                            str(int(lp['conf'])) + '_xy.txt')
        points -= np.mean(points, axis=0) + lp['origin']
        addpc = .05
        xytmp, trash1, trash2, trash3 = blf.mask_with_polygon(shape,
                                                              NH + 4,
                                                              NV + 4,
                                                              points, [],
                                                              eps=addpc)
        polygon = blf.auto_polygon(shape, NH, NV, eps=0.00)

        xy, NL, KL, BL = le.delaunay_centroid_lattice_from_pts(
            xytmp, polygon=polygon, trimbound=False)  # check=check)
        #################################################################
        # nzag controlled by lp['intparam'] below
        xyacc, BLacc, LVUC, UC, xyvertices, lattice_exten_add = \
            blf.accordionize_network(xy, BL, lp, PVxydict=None, PVx=None, PVy=None, PV=None)

        print 'BL = ', BL

        # need indices of xy that correspond to xyvertices
        # note that xyvertices gives the positions of the vertices, not their indices
        inRx = np.in1d(xyacc[:, 0], xyvertices[:, 0])
        inRy = np.in1d(xyacc[:, 1], xyvertices[:, 1])
        vxind = np.where(np.logical_and(inRx, inRy))[0]
        print 'vxind = ', vxind

        # Note: beware, do not provide NL and KL to decorate_bondneighbors_elements() since NL,KL need
        # to be recalculated
        xy, BL = blf.decorate_bondneighbors_elements(xyacc,
                                                     BLacc,
                                                     vxind,
                                                     PVxydict=None,
                                                     viewmethod=False,
                                                     check=lp['check'])
        NL, KL = le.BL2NLandKL(BL, NP=len(xy))

        #################################################################
        polygon = blf.auto_polygon(shape, NH, NV, eps=0.00)

        if check:
            le.display_lattice_2D(
                xy,
                BL,
                NL=NL,
                KL=KL,
                title='Cropped centroid lattice, before dilation')

        # Form output bounding box and extent measurement
        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        PVxydict = {}
        PVx = []
        PVy = []
        BBox = polygon

        # make string from origin values
        print 'lp[origin] = ', lp['origin']
        print 'type(lp[origin]) = ', type(lp['origin'])
        if (np.abs(lp['origin']) < 1e-7).all():
            originstr = ''
        else:
            originstr = '_originX' + '{0:0.2f}'.format(lp['origin'][0]).replace('.', 'p') + \
                        'Y' + '{0:0.2f}'.format(lp['origin'][1]).replace('.', 'p')
        periodicBCstr = ''
    else:
        # Ensuring that origin param is centered (since using entire lattice)
        lp['origin'] = np.array([0.0, 0.0])
        LL = (lp['NP_load'], lp['NP_load'])
        polygon = 0.5 * np.array([[-LL[0], -LL[1]], [LL[0], -LL[1]],
                                  [LL[0], LL[1]], [-LL[0], LL[1]]])
        BBox = polygon

        lp['periodicBC'] = True
        sizestr = '{0:03d}'.format(lp['NP_load'])
        points = np.loadtxt(networkdir + 'hyperuniform_source/hyperuniform_N' + sizestr + '/out_d' + \
                            str(int(lp['conf'])) + '_xy.txt')
        points -= np.mean(points, axis=0)
        xy, NL, KL, BL, PVxydict = blf.kagomecentroid_periodic_network_from_pts(
            points, LL, BBox=BBox, check=lp['check'])
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)
        originstr = ''
        periodicBCstr = '_periodic'

    # Rescale so that median bond length is unity
    bL = le.bond_length_list(xy, BL, NL=NL, KL=KL, PVx=PVx, PVy=PVy)
    scale = 1. / np.median(bL)
    xy *= scale
    polygon *= scale
    BBox *= scale
    LL = (LL[0] * scale, LL[1] * scale)
    if lp['periodicBC']:
        PVx *= scale
        PVy *= scale
        PVxydict.update((key, val * scale) for key, val in PVxydict.items())

    lattice_exten = 'accordionkag_hucent_' + shape + periodicBCstr + '_d{0:02d}'.format(int(lp['conf'])) + originstr + \
                    lattice_exten_add
    LV = 'none'
    LVUC = 'none'
    UC = 'none'
    return xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten
Beispiel #14
0
def build_accordionkag_isocent(lp):
    """Create an accordion-bonded kagomized amorphous network from a loaded jammed point set.

    Parameters
    ----------
    lp

    Returns
    -------

    """
    shape = lp['shape']
    check = lp['check']
    NH = lp['NH']
    NV = lp['NV']
    print('Loading isostatic to build kagome-decorated lattice...')
    import lepm.build.build_jammed as build_jammed
    use_hexner = (lp['source'] == 'hexner')
    if use_hexner:
        # Use Daniel Hexner's lattices
        points, BL, LLv, numberstr, sizestr, lp = build_jammed.load_hexner_jammed(
            lp, BL_load=False)
        LL = (LLv, LLv)
    else:
        number = '{0:03d}'.format(int(lp['loadlattice_number']))
        zindex = '{0:03d}'.format(int(lp['loadlattice_z']))
        points = np.loadtxt(lp['rootdir'] + 'networks/' +
                            'isostatic_source/isostatic_homog_z' + zindex +
                            '_conf' + number + '_nodes.txt')
        # LL = NH

    points -= np.mean(points, axis=0)

    # Separate procedure if not using entire lattice
    if lp['NP_load'] == 0:
        # Do initial (generous) cropping if not using entire lattice
        if check:
            plt.plot(points[:, 0], points[:, 1], 'b.')
            plt.title('Point set before initial cutting')
            plt.show()
        xytmp, trash1, trash2, trash3 = blf.mask_with_polygon(shape,
                                                              NH * 1.2 + 8,
                                                              NV * 1.2 + 8,
                                                              points, [],
                                                              eps=0.)
        polygon = blf.auto_polygon(shape, NH, NV, eps=0.00)
        if check:
            plt.plot(xytmp[:, 0], xytmp[:, 1], 'b.')
            plt.title('Point set after initial cutting')
            plt.show()

        xy, NL, KL, BL = le.delaunay_centroid_lattice_from_pts(
            xytmp, polygon=polygon, trimbound=False, check=lp['check'])

        #################################################################
        # nzag controlled by lp['intparam'] below
        xyacc, BLacc, LVUC, UC, xyvertices, lattice_exten_add = \
            blf.accordionize_network(xy, BL, lp, PVxydict=None, PVx=None, PVy=None, PV=None)

        print 'BL = ', BL

        # need indices of xy that correspond to xyvertices
        # note that xyvertices gives the positions of the vertices, not their indices
        inRx = np.in1d(xyacc[:, 0], xyvertices[:, 0])
        inRy = np.in1d(xyacc[:, 1], xyvertices[:, 1])
        vxind = np.where(np.logical_and(inRx, inRy))[0]
        print 'vxind = ', vxind

        # Note: beware, do not provide NL and KL to decorate_bondneighbors_elements() since NL,KL need
        # to be recalculated
        xy, BL = blf.decorate_bondneighbors_elements(xyacc,
                                                     BLacc,
                                                     vxind,
                                                     PVxydict=None,
                                                     viewmethod=False,
                                                     check=lp['check'])
        NL, KL = le.BL2NLandKL(BL, NP=len(xy))

        #################################################################

        LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]),
              np.max(xy[:, 1]) - np.min(xy[:, 1]))
        PVxydict = {}
        PVx = []
        PVy = []
        periodicBCstr = ''
    else:
        polygon = 0.5 * np.array([[-LL[0], -LL[1]], [LL[0], -LL[1]],
                                  [LL[0], LL[1]], [-LL[0], LL[1]]])
        xy, NL, KL, BL, PVxydict = blf.kagomecentroid_periodic_network_from_pts(
            points, LL, BBox='auto', check=lp['check'])
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)
        periodicBCstr = '_periodic'

    # Rescale so that median bond length is unity
    bL = le.bond_length_list(xy, BL, NL=NL, KL=KL, PVx=PVx, PVy=PVy)
    scale = 1. / np.median(bL)
    xy *= scale
    polygon *= scale
    LL = (LL[0] * scale, LL[1] * scale)
    if lp['periodicBC']:
        PVx *= scale
        PVy *= scale
        PVxydict.update((key, val * scale) for key, val in PVxydict.items())

    lattice_exten = 'accordionkag_isocent_' + shape + periodicBCstr + '_d{0:02d}'.format(int(lp['conf'])) + \
                    lattice_exten_add

    if use_hexner:
        lattice_exten = 'accordionkag_isocent_' + shape + periodicBCstr + '_hexner_size' + sizestr + '_conf' + \
                        numberstr + lattice_exten_add
    else:
        lattice_exten = 'accordionkag_isocent_' + shape + periodicBCstr + '_ulrich_homog_zindex' + zindex + \
                        lattice_exten_add
    LV = 'none'
    LVUC = 'none'
    UC = 'none'
    BBox = polygon
    return xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten
def generate_overcoordinated1_lattice(NH, NV, shape='square', check=False):
    """Generates a lattice with a made-up unit cell that is overcoordinated.

    Parameters
    ----------
    NH : int
        Number of pts along horizontal before boundary is cut
    NV : int

    Returns
    ----------
    xy : array of dimension nx3
        Equilibrium positions of all the points for the lattice
    NL : array of dimension n x (max number of neighbors)
        Each row corresponds to a point.  The entries tell the indices of the neighbors.
    KL : array of dimension n x (max number of neighbors)
        Correponds to NL matrix.  1 corresponds to a true connection while 0 signifies that there is not a connection
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    SBL : NP x 1 int array
        Sublattice bond list: 0, 1, 2 for each site of the 3-particle unit cell
    lattice_type : string
        label, lattice type.  For making output directory: for ex, 'overcoordinated1_square'

    """
    print('Setting up unit cell...')
    a0 = 2*np.array([[np.cos(n*np.pi/3+np.pi/6), np.sin(n*np.pi/3+np.pi/6), 0] for n in range(6)])

    a = np.array([a0[:, 0], a0[:, 1]]).T
    A = np.array([0, 0])
    C = np.array([np.cos(-10*np.pi/180), np.sin(-10*np.pi/180)])
    B = 1.2*np.array([np.cos(20*np.pi/180), np.sin(20*np.pi/180)])

    An = A+ a
    Bn = B+a
    Cn = C+a

    nA = np.array([B-A, B+a[3]-A, B+a[4]-A, C-A, C+a[2]-A])
    angsA = np.array([np.arctan2(nA[i, 1], nA[i, 0]) for i in range(len(nA))])

    nB = np.array([A-B, A+a[0]-B, A+a[1]-B, C-B, C+a[1]-B])
    angsB = np.array([np.arctan2(nB[i, 1], nB[i, 0]) for i in range(len(nB))])

    nC = np.array([A-C, A+a[5]-C, B-C, B+a[4]-C])
    angsC = np.array([np.arctan2(nC[i,1], nC[i,0]) for i in range(len(nC))])

    aa = a.copy()
    print 'aa = ', aa
    a1 = aa[1]
    a2 = aa[2]
    a3 = aa[3]

    # nodes at R
    C = np.array([A,#0
                  B,  # 1
                  B + a[3],  # 2
                  B + a[4],  # 3
                  C,  # 4
                  C + a[2],  # 5
                  A+a[0],  # 6
                  A+a[1],  # 7
                  C+a[1],  # 8
                  A+a[5],  # 9

        ])
    CU = np.arange(len(C), dtype='int')

    sbl = np.array([0,#0
               1,#1
               1,#2
               1,#3
               2,#4
               2,#5

               #A
               0, #6
               0, #7
               #C, #4
               2,#8

               #A
               0,#9
               #B,#1
               #B+a[4]#3

        ])

    CBL = np.array([
        [0, 1],
        [0, 2],
        [0, 3],
        [0, 4],
        [0, 5],
        [1, 6],
        [1, 7],
        [1, 4],
        [1, 8],
        [3, 4],
        [4, 9]
        ])

    # translate by Bravais latt vecs
    print('Translating by Bravais lattice vectors...')
    LV  = [-a2-a3, a1]
    inds = np.arange(len(C))
    tmp0 = np.zeros(len(C), dtype='int')
    tmp1 = np.ones(len(C), dtype='int')
    print 'sbl = ', sbl
    for i in np.arange(NV):
        for j in np.arange(NH):
            # bottom row
            if i == 0:
                if j == 0 :
                    Bprev = C
                    R = C
                    SBL = sbl.tolist()
                    LVUC = np.dstack((tmp0, tmp0, CU))[0]

                    # # Check
                    # colorvals = np.linspace(0,1,len(R))
                    # #plt.plot(R[:,0],R[:,1], 'k-') #,c=colorvals, cmap='spectral')
                    # le.display_lattice_2D(R,CBL,close=False)
                    # for ii in range(len(R)):
                    #     plt.text(R[ii,0]+0.05,R[ii,1],str(ii))
                    # plt.arrow(0, 0, a1[0], a1[1], head_width=0.05, head_length=0.1, fc='r', ec='r')
                    # plt.arrow(0, 0, a2[0], a2[1], head_width=0.05, head_length=0.1, fc='b', ec='b')
                    # plt.arrow(0, 0, a3[0], a3[1], head_width=0.05, head_length=0.1, fc='g', ec='g')
                    # plt.show()
                else:
                    R = np.vstack((R, C + j*LV[0]))
                    SBL += sbl.tolist() # np.vstack((SBL, sbl))

                    LVUCadd = np.dstack((j*tmp1, tmp0, CU))[0]
                    # print 'LVUCadd = ', LVUCadd
                    LVUC = np.vstack((LVUC, LVUCadd))

                    # # Check
                    # colorvals = np.linspace(0,1,len(R))
                    # plt.scatter(R[:,0],R[:,1],c=colorvals, cmap='spectral')
                    # for ii in range(len(R)):
                    #     plt.text(R[ii,0]+0.05,R[ii,1],str(ii))
                    # plt.arrow(0, 0, a1[0], a1[1], head_width=0.05, head_length=0.1, fc='r', ec='r')
                    # plt.arrow(0, 0, a2[0], a2[1], head_width=0.05, head_length=0.1, fc='b', ec='b')
                    # plt.arrow(0, 0, a3[0], a3[1], head_width=0.05, head_length=0.1, fc='g', ec='g')
                    # plt.pause(1)
            else:
                # vertical indices to copy over
                vinds = np.array([1,2,5,6,7,8])
                R = np.vstack((R, C[vinds] + j*LV[0] + i*LV[1]))
                SBL += sbl[vinds].tolist()
                LVUCadd = np.dstack((j*tmp1[vinds],i*tmp1[vinds],CU[vinds] ))[0]
                # print 'LVUCadd = ', LVUCadd
                LVUC = np.vstack((LVUC,LVUCadd))

                # # Check
                # sizevals = np.arange(len(R))+10
                # colorvals = np.linspace(0,1,len(R))
                # plt.scatter(R[:,0],R[:,1],s=sizevals,c=colorvals, cmap='afmhot')
                # for ii in range(len(R)):
                #     plt.text(R[ii,0]+0.05,R[ii,1],str(ii))
                # plt.arrow(0, 0, a1[0], a1[1], head_width=0.05, head_length=0.1, fc='r', ec='r')
                # plt.arrow(0, 0, a2[0], a2[1], head_width=0.05, head_length=0.1, fc='b', ec='b')
                # plt.arrow(0, 0, a3[0], a3[1], head_width=0.05, head_length=0.1, fc='g', ec='g')
                # plt.show()
        # if i%2 ==0:
        #     Bprev = Bprev + a2
        # else:
        #     Bprev = Bprev + a3

    SBL = np.asarray(SBL)
    # get rid of repeated points
    print('Eliminating repeated points...')
    #########
    # check
    if check:
        plt.clf()
        sizevals = np.arange(len(R))+10
        colorvals = np.linspace(0,1,len(R))
        plt.scatter(R[:,0],R[:,1],s=sizevals,c=colorvals, cmap='afmhot', alpha=0.2)
        plt.show()
    #########
    print 'R = ', R
    print 'shape(R) = ', np.shape(R)
    R, si, ui = le.args_unique_rows_threshold(R, 0.01)
    print 'shape(R) = ', np.shape(R)
    #########
    # check
    if check:
        sizevals = np.arange(len(R))+50
        colorvals = np.linspace(0, 1, len(R))
        plt.scatter(R[:, 0], R[:, 1], s=sizevals, c=colorvals, cmap='afmhot', alpha=0.2)
        plt.show()
    #########
    BL2 = generate_overcoordinated1_lattice_trip(NH, NV, ui, si, C, CBL)
    SBL = SBL.flatten()
    SBL = SBL[si]
    SBL = SBL[ui]
    # get rid of first row (0,0)a
    xy = le.unique_rows_threshold(R, 0.05) - np.array([np.mean(R[1:, 0]), np.mean(R[1:, 1])])

    # xy = R[ui]
    # Triangulate
    print('Triangulating...')
    Dtri = Delaunay(xy)
    btri = Dtri.vertices

    # C = C-np.array([np.mean(R[1:,0]),np.mean(R[1:,1])])
    # fig = plt.figure()
    # plt.triplot(xy[:,0], xy[:,1], Dtri.simplices.copy())
    # plt.xlim(-10,10)
    # plt.ylim(-10, 10)
    # plt.show()

    # translate btri --> bond list
    BL = le.Tri2BL(btri)

    # remove bonds on the sides and through the hexagons
    print('Removing extraneous bonds from triangulation...')
    # calc vecs from C bonds

    BL = np.array(list(BL)+list(BL2))
    BL = le.unique_rows(BL)

    BL = blf.latticevec_filter(BL, xy, C, CBL)

    NL, KL = le.BL2NLandKL(BL,NN=10)

    UC = C
    lattice_exten = 'overcoordinated1_square'
    return xy, NL, KL, BL, SBL, LV, UC, LVUC, lattice_exten
Beispiel #16
0
def generate_triangular_lattice(shape, NH, NV, periodicBC=False, eta=0., theta=0., check=False):
    """Generate a triangular lattice NH wide and NV tall, with sites randomized by eta and rotated by theta.

    Parameters
    ----------
    shape : dictionary with string key
        key is overall shape of the mesh ('square' 'rectangle2x1' 'rectangle1x2' 'circle' 'hexagon'), value is radius,
        hexagon, sidelength, or array of closed points
    NH : int
        Number of pts along horizontal before boundary is cut
    NV : int
        Number of pts along vertical before boundary is cut
    periodicBC : bool
        make the network periodic
    eta : float
        randomization of the mesh, in units of lattice spacing
    theta : float
        overall rotation of the mesh lattice vectors in radians
    check : bool
        whether to view results at each step
    Returns
    ----------
    xy : array of dimension nx3
        Equilibrium positions of all the points for the lattice
    NL : array of dimension n x (max number of neighbors)
        Each row corresponds to a point.  The entries tell the indices of the neighbors.
    KL : array of dimension n x (max number of neighbors)
        Correponds to NL matrix.  1 corresponds to a true connection while 0 signifies that there is not a connection
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    LVUC : NP x 4 array
        For each particle, gives (lattice vector, unit cell vector) coordinate position of that particle: LV1, LV2, UC
        For instance, xy[0,:] = LV[0]*LVUC[0,0] + LV[1]*LVUC[0,1] + UC[LVUC[0,2]]
    LV : 3 x 2 float array
        Lattice vectors for the kagome lattice with input twist angle
    UC : 6 x 2 float array
        (extended) unit cell vectors
    lattice_type : string
        label, lattice type.  For making output directory
    """
    # If shape is a string, turn it into the appropriate dict
    if isinstance(shape, str):
        # Since shape is a string, give key as str and vals to form polygon mask
        print 'Since shape is a string, give key as str and vals to form polygon mask...'
        vals = [NH, NV]
        shape_string = shape
        NH *= 3
        NV *= 3
        shape = {shape_string: vals}

    # Establish triangular lattice, rotated by theta
    if abs(theta) < 1e-6:
        latticevecs = [[1, 0], [0.5, np.sqrt(3)*0.5]]
    else:
        latticevecs = [[np.cos(theta), np.sin(theta)],
                       [0.5 * np.cos(theta) - np.sqrt(3) * 0.5 * np.sin(theta),
                        np.sqrt(3) * 0.5 * np.cos(theta) + 0.5 * np.sin(theta)]]

    xypts_tmp, LVUC = blf.generate_lattice_LVUC([NH, NV], latticevecs)

    # CHECK
    if check:
        plt.plot(xypts_tmp[:, 0], xypts_tmp[:, 1], 'b.')
        for i in range(len(xypts_tmp)):
            plt.text(xypts_tmp[i, 0], xypts_tmp[i, 1], str(LVUC[i, 0]) + ', ' + str(LVUC[i, 1]))
        plt.title('Pre-cropped lattice')
        plt.show()

    if theta == 0:
        add_exten = ''
    else:
        add_exten = '_theta' + '{0:.3f}'.format(theta / np.pi).replace('.', 'p') + 'pi'
        # ROTATE BY THETA
        print 'Rotating by theta= ', theta, '...'
        xys = copy.deepcopy(xypts_tmp)
        xypts_tmp = np.array([[x*np.cos(theta) - y*np.sin(theta), y*np.cos(theta)+x*np.sin(theta)] for x, y in xys])

    # mask to rectangle
    if 'circle' in shape:
        '''add masking to shape here'''
        tmp2 = xypts_tmp
        NH, NV = shape['circle']
        # Modify below to allow ovals
        R = NH*0.5
        keep = np.logical_and(np.abs(tmp2[:, 0]) < R*1.000000001, np.abs(tmp2[:, 1]) < (2*R*1.0000001))
        xy = tmp2[keep, :]
        LVUC = LVUC[keep, :]
        shape = 'circle'
    elif 'hexagon' in shape:
        print 'cropping to: ', shape
        tmp2 = xypts_tmp
        NH, NV = shape['hexagon']
        # Modify below to allow different values of NH and NV on the horiz and vertical sides of the hexagon
        a = NH + 0.5
        polygon = np.array([[-a*0.5, -np.sqrt(a**2 - (0.5*a)**2)],
            [a*0.5, -np.sqrt(a**2 - (0.5*a)**2)], [a, 0.],
            [a*0.5, np.sqrt(a**2 - (0.5*a)**2)], [-a*0.5, np.sqrt(a**2 - (0.5*a)**2)], [-a, 0.],
            [-a*0.5, -np.sqrt(a**2 - (0.5*a)**2)]])
        bpath = mplpath.Path(polygon)
        keep = bpath.contains_points(tmp2)
        xy = tmp2[keep, :]
        LVUC = LVUC[keep, :]
        shape = 'hexagon'

        # Check'
        if check:
            codes = [mplpath.Path.MOVETO,
                    mplpath.Path.LINETO,
                    mplpath.Path.LINETO,
                    mplpath.Path.LINETO,
                    mplpath.Path.LINETO,
                    mplpath.Path.LINETO,
                    mplpath.Path.CLOSEPOLY,
                    ]
            path = mplpath.Path(polygon, codes)
            ax = plt.gca()
            patch = mpatches.PathPatch(path, facecolor='orange', lw=2)
            ax.add_patch(patch)
            ax.plot(polygon[:, 0], polygon[:, 1], 'bo')
            ax.plot(xy[:, 0], xy[:, 1], 'r.')
            plt.show()
    elif 'square' in shape:
        tmp2 = xypts_tmp
        NH,NV = shape['square']
        if periodicBC:
            keep = np.logical_and(np.abs(tmp2[:, 0]) < NH * .5 + 0.51,
                                  np.abs(tmp2[:, 1]) < (NV * .5 / np.sin(np.pi / 3.) - 0.1))
        else:
            keep = np.logical_and(np.abs(tmp2[:, 0]) < NH*.5 + 0.1, np.abs(tmp2[:, 1]) < (NV*.5/np.sin(np.pi/3.)+0.1))
        xy = tmp2[keep, :]
        LVUC = LVUC[keep, :]
        shape = 'square'
        pass
    elif 'polygon' in shape:
        bpath = mplpath.Path(shape['polygon'])
        keep = bpath.contains_points(xypts_tmp)
        xy = xypts_tmp[keep, :]
        LVUC = LVUC[keep, :]
        shape = 'polygon'
    else:
        raise RuntimeError('Polygon dictionary not specified in generate_triangular_lattice().')

    print('Triangulating points...\n')
    tri = Delaunay(xy)
    TRItmp = tri.vertices

    print('Computing bond list...\n')
    BL = le.Tri2BL(TRItmp)
    # bL = le.bond_length_list(xy,BL)
    thres = 1.1  # cut off everything longer than a diagonal
    print('thres = ' + str(thres))
    print('Trimming bond list...\n')
    BLtrim = le.cut_bonds(BL, xy, thres)
    print('Trimmed ' + str(len(BL) - len(BLtrim)) + ' bonds.')

    # print 'BLtrim =', BLtrim

    print('Recomputing TRI...\n')
    TRI = le.BL2TRI(BLtrim, xy)

    # Randomize if eta >0 specified
    if eta == 0:
        xypts = xy
        eta_exten = ''
    else:
        print 'Randomizing lattice by eta=', eta
        jitter = eta*np.random.rand(np.shape(xy)[0], np.shape(xy)[1])
        xypts = np.dstack((xy[:, 0] + jitter[:, 0], xy[:, 1] + jitter[:, 1]))[0]
        eta_exten = '_eta{0:.3f}'.format(eta).replace('.', 'p')

    # Naming
    exten = '_' + shape + add_exten + eta_exten

    # BL = latticevec_filter(BL,xy, C, CBL)
    NL, KL = le.BL2NLandKL(BLtrim, NN=6)
    lattice_exten = 'triangular' + exten
    print 'lattice_exten = ', lattice_exten
    LV = np.array(latticevecs)
    UC = np.array([0., 0.])
    return xypts, NL, KL, BLtrim, LVUC, LV, UC, lattice_exten
Beispiel #17
0
def build_jammed(lp):
    """Use bonds from jammed packing --> already near isostatic, but can't tune above it, only below.

    Parameters
    ----------
    lp

    Returns
    -------

    """
    # Use bonds from jammed packing --> already near isostatic, but can't tune above it, only below.
    shape = lp['shape']
    nh = lp['NH']
    nv = lp['NV']
    networkdir = dio.ensure_dir(lp['rootdir']) + 'networks/'

    print('Loading isostatic file to build jammed lattice...')
    # Now load
    use_hexner = (lp['source'] == 'hexner')
    if use_hexner:
        print 'lp[periodicBC] = ', lp['periodicBC']
        points, BL, LLv, numberstr, sizestr, lp = load_hexner_jammed(
            lp, BL_load=True)
        sourcestr = '_hexner'
    else:
        # Use Stephan Ulrich's lattices
        if lp['periodicBC']:
            RuntimeError('Not sure if Stephan Ulrich lattices are periodic!')
        zindex = '{0:03d}'.format(int(lp['loadlattice_z']))
        number = '{0:03d}'.format(int(lp['conf']))
        points = np.loadtxt(networkdir + 'isostatic_source/isostatic_homog_z' +
                            zindex + '_conf' + number + '_nodes.txt')
        BL = np.loadtxt(networkdir + 'isostatic_source/isostatic_homog_z' +
                        zindex + '_conf' + number + '_bonds.txt',
                        usecols=(0, 1),
                        dtype=int)
        sourcestr = '_ulrich_homog'
        print 'BL[100] = ', BL[100]
        # Loaded BL uses indexing starting at 1, not 0
        BL -= 1
        print 'BL[100] = ', BL[100]
        numberstr = number[1:]

    if check:
        le.display_lattice_2D(points,
                              np.abs(BL),
                              title='points and bonds loaded, before pruning')
    xy = points - np.mean(points, axis=0)
    NL, KL = le.BL2NLandKL(BL, NN='min')

    # Remove any points with no bonds
    print 'Removing points without any bonds...'
    keep = KL.any(axis=1)
    xy, NL, KL, BL = le.remove_pts(keep, xy, BL, NN='min')
    print 'len(xy) = ', len(xy)

    if check:
        le.display_lattice_2D(
            xy,
            np.abs(BL),
            title='Before tuning z (down) and before fixing PBCs')

    if lp['cutz_method'] == 'random':
        NL, KL, BL = le.cut_bonds_z_random(xy,
                                           NL,
                                           KL,
                                           BL,
                                           lp['target_z'],
                                           bulk_determination='Endpts')
    elif lp['cutz_method'] == 'highest':
        NL, KL, BL = le.cut_bonds_z_highest(xy,
                                            NL,
                                            KL,
                                            BL,
                                            lp['target_z'],
                                            check=check)
    elif lp['cutz_method'] == 'none':
        pass

    if lp['periodicBC'] or lp['NP_load'] > 0:
        print 'Building periodicBC PVs...'
        lp['periodicBC'] = True
        LL = (LLv, LLv)
        polygon = 0.5 * np.array([[-LLv, -LLv], [LLv, -LLv], [LLv, LLv],
                                  [-LLv, LLv]])
        BBox = polygon
        PV = np.array([[LLv, 0.0], [LLv, LLv], [LLv, -LLv], [0.0, 0.0],
                       [0.0, LLv], [0.0, -LLv], [-LLv, 0.0], [-LLv, LLv],
                       [-LLv, -LLv]])
        PVxydict = le.BL2PVxydict(BL, xy, PV)
        PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL)

        if lp['check']:
            le.display_lattice_2D(xy,
                                  BL,
                                  NL=NL,
                                  KL=KL,
                                  PVx=PVx,
                                  PVy=PVy,
                                  title='Checking periodic BCs',
                                  close=False,
                                  colorz=False)
            for ii in range(len(xy)):
                plt.text(xy[ii, 0] + 0.1, xy[ii, 1], str(ii))
            plt.plot(xy[:, 0], xy[:, 1], 'go')
            plt.show()
    else:
        polygon = blf.auto_polygon(shape, nh, nv, eps=0.00)
        BBox = polygon
        print('Trimming lattice to be NH x NV...')
        keep = np.logical_and(
            abs(xy[:, 0]) < nh * 0.5,
            abs(xy[:, 1]) < nv * 0.5)
        print "Check that if lp['NP_load'] !=0 then len(keep) == len(xy):", len(
            keep) == len(xy)
        xy, NL, KL, BL = le.remove_pts(keep, xy, BL, NN='min')
        LL = (nh, nv)
        PVx = []
        PVy = []
        PVxydict = {}

    z = le.compute_bulk_z(xy, NL, KL, BL)
    print 'FOUND z = ', z

    if lp['periodicBC']:
        periodicBCstr = '_periodicBC'
    else:
        periodicBCstr = ''

    print('Defining lattice_exten...')
    lattice_exten = 'jammed_' + shape + sourcestr + periodicBCstr + '_z' + '{0:0.03f}'.format(z) + '_conf' + \
                    numberstr + '_zmethod' + lp['cutz_method']
    LV = 'none'
    UC = 'none'
    LVUC = 'none'
    return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
Beispiel #18
0
def generate_deformed_martini(shape, NH, NV, x1, x2, x3, z, check=False):
    """creates distorted martini lattice as in Kane&Lubensky2014--> Paulose 2015

    Parameters
    ----------
    shape : string
        overall shape of the mesh ('square' 'circle') --> haven't built in functionality yet
    NH : int
        Number of pts along horizontal before boundary is cut
    NV : int
        Number of pts along vertical before boundary is cut
    x1 : float
        symmetrical representation of deformation (sp = xp*(a[p-1]+a[p+1])+yp*a[p])
    x2 : float
        symmetrical representation of deformation (sp = xp*(a[p-1]+a[p+1])+yp*a[p])
    x3 : float
        symmetrical representation of deformation (sp = xp*(a[p-1]+a[p+1])+yp*a[p])
    z : float
        z= y1+y2+y3, symmetrical representation of deformation (sp = xp*(a[p-1]+a[p+1])+yp*a[p])

    Returns
    ----------
    xy : array of dimension nx3
        Equilibrium positions of all the points for the lattice
    NL : array of dimension n x (max number of neighbors)
        Each row corresponds to a point.  The entries tell the indices of the neighbors.
    KL : array of dimension n x (max number of neighbors)
        Correponds to NL matrix.  1 corresponds to a true connection while 0 signifies that there is not a connection
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    LVUCV : NP x 4 array
        For each particle, gives (lattice vector, unit cell vector) coordinate position of that particle: LV1, LV2, UCV1, UCV2
    lattice_type : string
        label, lattice type.  For making output directory
    """
    print('Setting up unit cell...')
    # Bravais primitive unit vecs
    a = np.array([[np.cos(2*np.pi*p/3.), np.sin(2*np.pi*p/3.)] for p in range(3)])
    a1 = a[0]
    a2 = a[1]
    a3 = a[2]

    # make unit cell
    x = np.array([x1, x2, x3])
    y = np.array([z/3. + x[np.mod(i-1, 3)]- x[np.mod(i+1, 3)] for i in [0, 1, 2]])
    s = np.array([x[p]*(a[np.mod(p-1, 3)] - a[np.mod(p+1, 3)]) + y[p]*a[p] for p in range(3)])
    s1 = s[0]
    s2 = s[1]
    d1 = a1/2.+s2
    d2 = a2/2.-s1
    d3 = a3/2.

    # nodes at R (from top to bottom) -- like fig 2a of KaneLubensky2014
    C = np.array([d1+a2,
        d3+a1+a2,
        d2+a1,
        d1,
        d3+a1,
        d2-a2,
        d1+a3,
        d3,
        d2+a3,
        d1+a2+a3,
        d3+a2,
        d2])

    LV = np.array([a1, 2.*a2+a1])
    CU = np.arange(len(C))
    tmp1 = np.ones(len(C), dtype=int)

    # translate by Bravais latt vecs
    print('Translating by Bravais lattice vectors...')
    inds = np.arange(len(C))
    for i in np.arange(NV):
        print 'Building row ', i, ' of ', NV
        for j in np.arange(NH):
            if i == 0:
                if j == 0:
                    # initialize
                    R = C;
                    LVUC = np.dstack(([0*tmp1, 0*tmp1, CU]))[0]
                    # Rename particle 4 as particle 7 of next over in LV0, for martini trimming
                    # LVUC[4] = np.array([1,0,7])
                else:
                    # bottom row (include point 6 in translation)
                    R = np.vstack((R, C[0:7,:] + i*(2*a2+a1) + j*a1))
                    LVUCadd = np.dstack(( (i+j)*tmp1[0:7], (2*i)*tmp1[0:7], CU[0:7] ))[0]
                    print 'LVUC = ', LVUC
                    print 'LVUCadd = ', LVUCadd
                    LVUC = np.vstack((LVUC, LVUCadd))
            else:
                if j == 0:
                    # first cell of row, include all but pt 6
                    R = np.vstack((R, C[inds!=6,:] + i*(2*a2+a1) + j*a1))
                    LVUCadd = np.dstack(( (i+j)*tmp1[inds!=6], (2*i)*tmp1[inds!=6],CU[inds!=6] ))[0]
                    # Rename particle 4 as particle 7 of next over in LV0, for martini trimming
                    # LVUCadd[4] = np.array([1,0,7])
                    LVUC = np.vstack((LVUC, LVUCadd))
                else:
                    # only points 0 through 5 included
                    R = np.vstack((R, C[0:6,:] + i*(2*a2+a1) + j*a1))
                    LVUCadd = np.dstack(( (i+j)*tmp1[0:6], (2*i)*tmp1[0:6], CU[0:6] ))[0]
                    LVUC = np.vstack((LVUC, LVUCadd))

    if check:
        plt.plot(R[:, 0], R[:, 1], '.-')
        plt.show()

    # check for repeated points
    print('Checking for repeated points...')
    print 'len(R) =', len(R)
    Rcheck = le.unique_rows(R)
    print 'len(Rcheck) =', len(Rcheck)
    if len(R)-len(Rcheck) !=0:
        sizes = np.arange(len(xy))
        plt.scatter(xy[:,0],xy[:,1],s=sizes)
        raise RuntimeError('Repeated points!')
    else:
        print 'No repeated points.\n'
    xy = R
    xy -= np.array([np.mean(R[1:,0]),np.mean(R[1:,1])]) ;
    #Triangulate
    print('Triangulating...')
    Dtri = Delaunay(xy)
    btri = Dtri.vertices
    #translate btri --> bond list
    BL = le.Tri2BL(btri)

    #remove bonds on the sides and through the hexagons
    print('Removing extraneous bonds from triangulation...')
    #calc vecs from C bonds
    CBL = np.array([[0,1],[1,11],[0,11],[1,2],[2,3],[3,4],[4,5],[3,5],
        [5,6],[6,7],[7,8],[8,9],[7,9],[9,10],[10,11]])

    BL = latticevec_filter(BL,xy, C, CBL)

    # Now kill bonds between 1-3, 5-7, 9-11
    # Also remove bonds between 4 of left kagome and 5 of right kagome
    BLUC = np.dstack((LVUC[BL[:,0],2], LVUC[BL[:,1],2] ))[0]
    print 'len(BLUC) = ', len(BLUC)
    print len(BL)
    kill1 = le.rows_matching(BLUC, np.array([1,3] ))
    kill2 = le.rows_matching(BLUC, np.array([5,7] ))
    kill3 = le.rows_matching(BLUC, np.array([9,11]))

    # Remove bonds between 4 of left kagome and 5 of right kagome
    in45a = np.in1d(BLUC[:,0], np.array([4,5]))
    in45b = np.in1d(BLUC[:,1], np.array([4,5]))
    BLLV1 = np.dstack((LVUC[BL[:,0],0], LVUC[BL[:,1],0] ))[0]
    kill4 = np.where(np.logical_and( np.logical_and(in45a, in45b), BLLV1[:,0] != BLLV1[:,1]))[0]

    # print 'BLUC = ', BLUC
    # print 'kill1 = ', kill1
    # print 'kill2 = ', kill2
    # print 'kill3 = ', kill3
    keep = np.setdiff1d(np.setdiff1d(np.setdiff1d(np.setdiff1d(np.arange(len(BLUC)), kill1), kill2), kill3), kill4)
    # print 'keep = ', keep

    if check:
        le.display_lattice_2D(xy, BL, close=False)
        for ii in range(len(BL)):
            plt.text( np.mean([xy[BL[ii,0],0], xy[BL[ii,1],0]]), np.mean([xy[BL[ii,0],1],xy[BL[ii,1],1]]), str(BLUC[ii]) )
        for ii in kill1:
            plt.text( np.mean([xy[BL[ii,0],0], xy[BL[ii,1],0]]), np.mean([xy[BL[ii,0],1],xy[BL[ii,1],1]]), str(BLUC[ii]), bbox=dict(facecolor='red', alpha=0.5) )
        for ii in kill2:
            plt.text( np.mean([xy[BL[ii,0],0], xy[BL[ii,1],0]]), np.mean([xy[BL[ii,0],1],xy[BL[ii,1],1]]), str(BLUC[ii]), bbox=dict(facecolor='red', alpha=0.5) )
        for ii in kill3:
            plt.text( np.mean([xy[BL[ii,0],0], xy[BL[ii,1],0]]), np.mean([xy[BL[ii,0],1],xy[BL[ii,1],1]]), str(BLUC[ii]), bbox=dict(facecolor='red', alpha=0.5) )
        for ii in kill4:
            plt.text( np.mean([xy[BL[ii,0],0], xy[BL[ii,1],0]]), np.mean([xy[BL[ii,0],1],xy[BL[ii,1],1]]), str(BLUC[ii]), bbox=dict(facecolor='red', alpha=0.5) )
        for ii in range(len(xy)):
            plt.text( xy[ii,0], xy[ii,1], str(LVUC[ii,2]) )
        plt.show()

    BL = BL[keep,:]
    NL,KL = le.BL2NLandKL(BL, NN=4)
    lattice_exten = 'deformed_martini_' + shape + '_x1_' + '{0:.4f}'.format(x1) + '_x2_' + '{0:.4f}'.format(x2) + \
                    '_x3_' + '{0:.4f}'.format(x3) + '_z_' + '{0:.4f}'.format(z)
    UC = C
    return xy,NL,KL,BL,lattice_exten, LV, UC, LVUC
Beispiel #19
0
def generate_periodic_zigzag_lattice(NH, theta, eta=0.):
    """

    Parameters
    ----------
    NH
    theta
    eta

    Returns
    -------

    """
    LV = np.array([[np.cos(theta), np.sin(theta)],
                   [np.cos(theta), -np.sin(theta)]])

    xy = np.array([
        np.ceil(i * 0.5) * LV[0] + np.ceil((i - 1) * 0.5) * LV[1]
        for i in range(NH)
    ])
    if abs(LV[0, 1]) < 1e-9:
        # There is only one kind of particle
        LVout = np.array([[1., 0.]])
        UC = np.array([0., 0.])
        LVUC = np.array([[np.ceil(i * 0.5),
                          np.ceil((i - 1) * 0.5), 0] for i in range(NH)])
    else:
        # There are two kinds of particles, up and down
        LVout = np.array([[2 * np.cos(theta), 0]])
        UC = LV
        LVUC = np.array([[np.ceil(i * 0.5),
                          np.ceil((i - 1) * 0.5), i % 2] for i in range(NH)])

    xy -= np.array([np.mean(xy[:, 0]), np.mean(xy[:, 1])])
    print 'xy = ', xy

    # Connectivity
    BL = np.zeros((NH, 2), dtype=int)
    for i in range(0, NH - 1):
        BL[i, 0] = i
        BL[i, 1] = i + 1
    # make periodic bond
    BL[NH - 1, 0] = -0
    BL[NH - 1, 1] = -(NH - 1)

    print 'BL = ', BL
    # scale lattice down to size
    if eta == 0:
        xypts = xy
    else:
        print 'Randomizing lattice by eta=', eta
        jitter = eta * np.random.rand(np.shape(xy)[0], np.shape(xy)[1])
        xypts = np.dstack(
            (xy[:, 0] + jitter[:, 0], xy[:, 1] + jitter[:, 1]))[0]

    # Naming
    etastr = '{0:.3f}'.format(eta).replace('.', 'p')
    thetastr = '{0:.3f}'.format(theta / np.pi).replace('.', 'p')
    exten = '_periodic_line_theta' + thetastr + 'pi_eta' + etastr

    # BL = latticevec_filter(BL,xy, C, CBL)
    NL, KL = le.BL2NLandKL(BL, NP=NH, NN=2)

    # Create periodic and lattice info
    print 'xy = ', xy
    minx = np.min(xy[:, 0]) - np.cos(theta) * 0.5
    miny = np.min(xy[:, 1])
    maxx = np.max(xy[:, 0]) + np.cos(theta) * 0.5
    maxy = np.max(xy[:, 1])
    if miny == maxy:
        maxy = 0.5
        miny = -0.5
    LL = (maxx - minx, 1)
    PV = np.array([[LL[0], 0], [0, LL[1]]])
    print 'PV = ', PV
    BBox = np.array([[minx, miny], [minx, maxy], [maxx, maxy], [maxx, miny]])
    PVxydict = le.BL2PVxydict(BL, xy, PV)
    print 'PVxydict = ', PVxydict
    lattice_exten = 'linear' + exten
    print 'lattice_exten = ', lattice_exten
    return xypts, NL, KL, BL, LVUC, LVout, UC, LL, PV, PVxydict, BBox, lattice_exten