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
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
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
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
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
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
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
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
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]
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
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
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
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
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
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
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
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