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 dynamical_matrix_mass(mlat): """Compute the dynamical matrix for d^2 u/ dt^2 = D u. This code handles periodic or open boundary conditions Parameters ---------- mlat Returns ------- matrix : 2N x 2N float array The dynamical matrix for the positions of masses in the mass-spring network """ lat = mlat.lattice NP, NN = lat.NL.shape M1 = np.zeros((2 * NP, 2 * NP)) M2 = np.zeros((2 * NP, 2 * NP)) if 'kpin' in mlat.lp: if np.abs(mlat.lp['kpin']) > 1e-10: add_pinning = True else: add_pinning = False else: add_pinning = False m2_shape = M2.shape # Unpack periodic boundary vectors if lat.PVx is not None and lat.PVy is not None: PVx = lat.PVx PVy = lat.PVy elif lat.PVxydict: PVx, PVy = le.PVxydict2PVxPVy(lat.PVxydict, lat.NL) else: PVx = np.zeros((NP, NN), dtype=float) PVy = np.zeros((NP, NN), dtype=float) for i in range(NP): for nn in range(NN): ni = lat.NL[i, nn] k = np.abs(mlat.kk[i, nn]) # true connection? diffx = lat.xy[ni, 0] - lat.xy[i, 0] + PVx[i, nn] diffy = lat.xy[ni, 1] - lat.xy[i, 1] + PVy[i, nn] # This is Lisa's original version # rij_mag = np.sqrt(diffx**2+diffy**2) # if k!=0: # alphaij = np.arccos( diffx /rij_mag) # else: alphaij=0 # if diffy<0 : # alphaij=2*np.pi-alphaij # if lat.NK[i,nn] < 0 : alphaij = (np.pi + alphaij)%(2*np.pi) # This is my version (05-28-16) if abs(k) > 0: alphaij = np.arctan2(diffy, diffx) Cos = np.cos(alphaij) Sin = np.sin(alphaij) if abs(Cos) < 10E-8: Cos = 0 else: Cos = Cos if abs(Sin) < 10E-8: Sin = 0 Cos2 = Cos ** 2 Sin2 = Sin ** 2 CosSin = Cos * Sin # Real equations (x components) massi = mlat.mass[i] if massi == 0 or massi < 0: raise RuntimeError('Encountered zero or negative mass: mass[' + str(i) + '] = ' + str(massi)) M1[2 * i, 2 * i] += k * Cos2 / massi M1[2 * i, 2 * i + 1] += k * CosSin / massi M1[2 * i, 2 * ni] += -k * Cos2 / massi M1[2 * i, 2 * ni + 1] += -k * CosSin / massi # Imaginary equations (y components) M1[2 * i + 1, 2 * i] += k * CosSin / massi M1[2 * i + 1, 2 * i + 1] += k * Sin2 / massi M1[2 * i + 1, 2 * ni] += -k * CosSin / massi M1[2 * i + 1, 2 * ni + 1] += -k * Sin2 / massi if add_pinning: # pinning M2[2 * i, 2 * i] = pin[i] M2[2 * i + 1, 2 * i + 1] = pin[i] matrix = - M1 - M2 return matrix
def build_isostatic(lp): """Build a network by manually tuning coordination of jammed packing (lets you tune through isostatic point) Parameters ---------- lp Returns ------- """ # Manually tune coordination of jammed packing (lets you tune through isostatic point) networkdir = lp['rootdir'] + 'networks/' print( 'Loading isostatic: get jammed point set to build lattice with new bonds...' ) number = '{0:03d}'.format(int(lp['conf'])) if lp['source'] == 'hexner': # Use Daniel Hexner - supplied networks points, BL, LLv, numberstr, sizestr, lp = load_hexner_jammed( lp, BL_load=False) LL = (LLv, LLv) print 'LL = ', LL sourcestr = '_hexner' else: zindex = '{0:03d}'.format(int(lp['loadlattice_z'])) points = np.loadtxt(networkdir + 'isostatic_source/isostatic_homog_z' + zindex + '_conf' + number + '_nodes.txt') points -= np.mean(points, axis=0) # DO initial cropping to speed up triangulation keep1 = np.logical_and( abs(points[:, 0]) < lp['NH'] * 0.5 + 8, abs(points[:, 1]) < lp['NV'] * 0.5 + 8) xy = points[keep1] if lp['periodicBC']: xy, NL, KL, BL, PVxydict = \ le.delaunay_rect_periodic_network_from_pts(xy, LL, target_z=lp['target_z'], zmethod=lp['cutz_method'], check=check) PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL) periodicstr = '_periodic' else: xy, NL, KL, BL, BM = le.delaunay_lattice_from_pts( xy, trimbound=False, target_z=lp['target_z'], zmethod=lp['cutz_method'], check=check) # 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 print('Trimming lattice to be NH x NV...') keep = np.logical_and( abs(xy[:, 0]) < lp['NH'] * 0.5, abs(xy[:, 1]) < lp['NV'] * 0.5) xy, NL, KL, BL = le.remove_pts(keep, xy, BL, NN='min', check=lp['check']) PVxydict = {} PVx = [] PVy = [] periodicstr = '' le.movie_plot_2D(xy, BL, bs=0.0 * BL[:, 0], PVx=PVx, PVy=PVy, PVxydict=PVxydict, colormap='BlueBlackRed', title='Output during isostatic build', show=True) plt.close('all') # Calculate coordination number z = le.compute_bulk_z(copy.deepcopy(xy), copy.deepcopy(NL), copy.deepcopy(KL), copy.deepcopy(BL)) print 'FOUND z = ', z lattice_exten = 'isostatic_' + lp['shape'] + periodicstr + sourcestr + '_z' + '{0:0.03f}'.format(z) + '_conf' + \ numberstr + '_zmethod' + lp['cutz_method'] 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]]) LV = 'none' UC = 'none' LVUC = 'none' plt.close('all') return xy, NL, KL, BL, PVx, PVy, PVxydict, LVUC, BBox, LL, LV, UC, lattice_exten, lp
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 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 calc_boundary_inner(mglat, check=False): """ Parameters ---------- mglat: MagneticGyroLattice instance check: bool Returns ------- boundary_inner : M x 1 int array the idices of mglat.xy that mark the boundary of mglat.xy_inner """ # First check if there is an outer boundary to be ignored if len(mglat.outer_indices) == 0: # All particles are inner particles boundary_inner = mglat.lattice.get_boundary() else: # First remove the outer boundary print 'mgfns: removing outer boundary for tmp lattice' xytmp, NLtmp, KLtmp, BLtmp = le.remove_pts( mglat.inner_indices, mglat.xy, mglat.lattice.BL, NN='min', check=check, PVxydict=mglat.lattice.PVxydict, PV=mglat.lattice.PV) if mglat.lattice.PV is not None: PVxydict_tmp = le.BL2PVxydict(BLtmp, xytmp, mglat.lattice.PV) PVxtmp, PVytmp = le.PVxydict2PVxPVy(PVxydict_tmp, NLtmp, KLtmp, check=check) if mglat.lp['periodic_strip']: # Special case: if the entire strip is a boundary, then get boundary = le.extract_1d_boundaries(xytmp, NLtmp, KLtmp, BLtmp, PVxtmp, PVytmp, check=check) elif mglat.lp['periodicBC']: boundary = None raise RuntimeError( 'periodic boundary conditions and not periodic strip, yet outer_indices are nonempty' ) elif 'annulus' in mglat.lp['LatticeTop'] or mglat.lp[ 'shape'] == 'annulus': print 'here' outer_boundary = le.extract_boundary(xytmp, NLtmp, KLtmp, BLtmp, check=check) inner_boundary = le.extract_inner_boundary(xytmp, NLtmp, KLtmp, BLtmp, check=check) boundary = (outer_boundary, inner_boundary) else: boundary = le.extract_boundary(xytmp, NLtmp, KLtmp, BLtmp, check=check) # Now determine which particles are the same as xytmp[boundary] boundary_inner = dh.match_points(mglat.xy, xytmp[boundary]) if check: print 'mgfns: boundary_inner = ', boundary_inner import matplotlib.pyplot as plt plt.plot(mglat.xy[:, 0], mglat.xy[:, 1], 'b.') plt.plot(xytmp[boundary, 0], xytmp[boundary, 1], 'go') plt.plot(mglat.xy[boundary_inner, 0], mglat.xy[boundary_inner, 1], 'r.') plt.show() return boundary_inner
def build_huvoronoi(lp): if lp['NP_load'] == 0: points = np.loadtxt( lp['rootdir'] + 'networks/hyperuniform_source/hyperuniform_N400/out_d' + str(int(lp['conf'])) + '_xy.txt') points -= np.mean(points, axis=0) + lp['origin'] keep = np.logical_and( abs(points[:, 0]) < (8 + lp['NH'] * 0.5), abs(points[:, 1]) < (8 + lp['NV'] * 0.5)) xytmp = points[keep] if lp['check']: plt.plot(points[:, 0], points[:, 1], 'b.') plt.title('Point set before initial cutting') plt.show() polygon = blf.auto_polygon(lp['shape'], lp['NH'], lp['NV'], eps=0.00) xy, NL, KL, BL = le.voronoi_lattice_from_pts(xytmp, polygon=polygon, NN=3, kill_outliers=True, check=lp['check']) if lp['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') periodicstr = '' else: lp['periodicBC'] = True sizestr = '{0:03d}'.format(lp['NP_load']) print 'sizestr = ', sizestr points = np.loadtxt(lp['rootdir'] + 'networks/hyperuniform_source/hyperuniform_N' + sizestr + '/out_d' + str(int(lp['conf'])) + '_xy.txt') print 'points = ', points points -= np.mean(points, axis=0) # 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 xy, NL, KL, BL, PVxydict = le.voronoi_rect_periodic_from_pts( points, LL, BBox='auto', check=lp['check']) PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL) originstr = '' periodicstr = '_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['NP_load'] != 0: PVx *= scale PVy *= scale PVxydict.update((key, val * scale) for key, val in PVxydict.items()) lattice_exten = 'huvoronoi_' + lp[ 'shape'] + periodicstr + '_d' + '{0:02d}'.format(int( lp['conf'])) + originstr return xy, NL, KL, BL, PVx, PVy, PVxydict, LL, BBox, lattice_exten
def build_kagome_huvor(lp): """Construct a kagomized network from hyperuniform point set and voronoize it with Wigner-Seitz Parameters ---------- lp : dict Lattice parameters dictionary, with keys: rootdir, conf, origin, shape, NH, NV, check, NP_load (if periodic) """ if lp['NP_load'] == 0: points = np.loadtxt( dio.prepdir(lp['rootdir']) + 'networks/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(lp['shape'], lp['NH'] + 7, lp['NV'] + 7, points, [], eps=addpc) polygon = blf.auto_polygon(lp['shape'], lp['NH'], lp['NV'], eps=0.00) xy, NL, KL, BL = blf.kagomevoronoi_network_from_pts(xytmp, polygon=polygon, kill_outliers=True, check=lp['check']) LL = (np.max(xy[:, 0]) - np.min(xy[:, 0]), np.max(xy[:, 1]) - np.min(xy[:, 1])) PVxydict, PVx, PVy = {}, [], [] BBox = polygon if lp['check']: le.display_lattice_2D( xy, BL, NL=NL, KL=KL, title='Cropped centroid lattice, before dilation') # 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( dio.prepdir(lp['rootdir']) + 'networks/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.kagomevoronoi_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 = 'kagome_huvor_' + lp[ 'shape'] + periodicBCstr + '_d{0:02d}'.format(int( lp['conf'])) + originstr return xy, NL, KL, BL, PVx, PVy, PVxydict, LL, BBox, lattice_exten
def load(lat, meshfn='auto', load_polygons=False, load_LVUC=False, load_gxy=False, check=False): """Load a saved lattice into the lattice instance. If meshfn is specified, loads that lattice. Otherwise, attempts to load lattice based on parameter lat.lp['meshfn']. If that is also unavailable, loads from lp[rootdir]/networks/lat.LatticeTop/lat.lp[lattice_exten]_NH_x_NV. """ print '\n\n\n\nLoading network: meshfn == ', meshfn if meshfn == 'auto': fn = lat.automeshfn() else: fnglob = sorted(glob.glob(meshfn)) print 'lattice_functions: globbing meshfn: fnglob = ', fnglob is_a_dir = np.where(np.array([os.path.isdir(ii) for ii in fnglob]))[0] print 'lattice_functions: meshfn = ', meshfn fn = fnglob[is_a_dir[0]] # print 'is_a_dir = ', is_a_dir # print 'np.size(is_a_dir) = ', np.size(is_a_dir) # print 'fn = ', fn if np.size(is_a_dir) > 1: print 'lattice_functions: Found multiple lattices matching meshfn in lattice.load(). Using the first matching lattice.' fn = fn[0] lat.lp['meshfn'] = fn if fn[-1] == '/': fn = fn[:-1] lat.lp = le.load_params(fn + '/', params=lat.lp, paramsfn='lattice_params', ignore=physics_to_ignore()) if not glob.glob(lat.lp['meshfn']): print "\n\nlattice_class: Warning: could not find lp[meshfn] = \n" + \ lat.lp['meshfn'] + '\nso instead replacing lp[meshfn] with --->\n' + fn + '\n\n' lat.lp['meshfn'] = fn # Fix up the lattice parameters dictionary by adding any necessary key-vals that aren't already in there lat.lp = complete_lp(lat.lp) lat.xy = np.loadtxt(fn + '_xy.txt', delimiter=',') lat.NL = np.loadtxt(fn + '_NL.txt', delimiter=',', dtype=int) lat.KL = np.loadtxt(fn + '_KL.txt', delimiter=',', dtype=int) try: lat.BL = np.loadtxt(fn + '_BL.txt', delimiter=',', dtype=int) except IOError: lat.BL = le.NL2BL(lat.NL, lat.KL) # Make sure that BL is 2D, even if only one row if len(np.shape(lat.BL)) < 2: lat.BL = np.array([lat.BL]) name = fn.split('/')[-1] try: print 'lattice_functions.load(): loading ' + name + '_PVxydict/Pvx/Pvy.txt ...' lat.PVxydict = le.load_evaled_dict(fn + '/', filename=name + '_PVxydict.txt') lat.PVx = np.loadtxt(fn + '/' + name + '_PVx.txt', delimiter=',', dtype=float) lat.PVy = np.loadtxt(fn + '/' + name + '_PVy.txt', delimiter=',', dtype=float) if (lat.PVx == lat.PVy).all(): print 'lattice_functions:PVx and PVy are identical (this was a bug in early versions of the code), need to trash one: ' \ 'overwriting then exiting.' lat.PVx, lat.PVy = le.PVxydict2PVxPVy(lat.PVxydict, lat.NL) header = 'PVx: ijth element of PVx are the x-components of the vector taking NL[i,j] to ' + \ 'its image as seen by particle i' np.savetxt(fn + '/' + name + '_PVx.txt', lat.PVx, delimiter=',', header=header) header = 'PVy: ijth element of PVy are the y-components of the vector taking NL[i,j] to ' + \ 'its image as seen by particle i' np.savetxt(fn + '/' + name + '_PVy.txt', lat.PVy, delimiter=',', header=header) print 'lattice_class: exiting here' sys.exit() # load periodic vectors if they exists try: lat.load_PV(meshfn=fn) print 'lattice_functions: loaded PV' except IOError: print 'lattice_functions.load(): no PV file exists, saving it...' lat.PV = le.PVxydict2PV(lat.PVxydict, periodic_strip=lat.lp['periodic_strip']) lat.save_PV() # print 'lattice_functions: exiting here for debug' except: print 'lattice_functions.load(): Could not load PVx and PVy, loading PVxydict to calculate them...' # print ' --> actually, just exiting since this should not happen anymore!' # sys.exit() try: lat.PVxydict = le.load_evaled_dict(fn + '/', filename=name + '_PVxydict.txt') lat.PVx, lat.PVy = le.PVxydict2PVxPVy(lat.PVxydict, lat.NL, lat.KL) header = 'PVx: ijth element of PVx are the x-components of the vector taking NL[i,j] to ' + \ 'its image as seen by particle i' np.savetxt(fn + '/' + name + '_PVx.txt', lat.PVx, delimiter=',', header=header) header = 'PVy: ijth element of PVy are the y-components of the vector taking NL[i,j] to ' + \ 'its image as seen by particle i' np.savetxt(fn + '/' + name + '_PVy.txt', lat.PVy, delimiter=',', header=header) try: lat.load_PV(meshfn=fn) except IOError: lat.PV = le.PVxydict2PV(lat.PVxydict) except IOError: print 'lattice_functions: No periodic vectors stored for this lattice, assuming not periodic.' # Load the boundary of the sample, since that is cheap (sqrt(N) at most) single_bndy = glob.glob(fn + '/' + name + '_boundary.txt') double_bndy = glob.glob(fn + '/' + name + '_boundary0.txt') if single_bndy: boundary = np.loadtxt(fn + '/' + name + '_boundary.txt', delimiter=',', dtype=int) lat.boundary = boundary elif double_bndy: boundary0 = np.loadtxt(fn + '/' + name + '_boundary0.txt', delimiter=',', dtype=int) boundary1 = np.loadtxt(fn + '/' + name + '_boundary1.txt', delimiter=',', dtype=int) boundary = (boundary0, boundary1) lat.boundary = boundary else: if not lat.lp['periodicBC'] or lat.lp['periodic_strip']: print 'lattice_functions: No boundary file found for (partially/fully) openBC network, saving the boundary to file...' bndry = lat.get_boundary(attribute=True, check=check) print 'lattice_functions: bndry = ', bndry if isinstance(bndry, tuple): np.savetxt(fn + '/' + name + '_boundary0.txt', bndry[0], fmt='%d', header="indices of one of the network's boundaries -- boundary zero") np.savetxt(fn + '/' + name + '_boundary1.txt', bndry[1], fmt='%d', header="indices of one of the network's boundaries -- boundary one") else: np.savetxt(fn + '/' + name + '_boundary.txt', bndry, fmt='%d', header='indices of the network boundary') # print image of the boundaries try: lat.plot_boundary(show=False, save=True, outdir=fn + '/', outname=name + '_boundary.png') except: print('Could not save boundary as png. Skipping...') if load_LVUC: lat.load_LUVC() if load_polygons: lat.load_polygons() if load_gxy: lat.load_gxy() # Convert some floats to ints if isinstance(lat.lp['NH'], float): lat.lp['NH'] = int(lat.lp['NH']) if isinstance(lat.lp['NV'], float): lat.lp['NV'] = int(lat.lp['NV'])
def build_hyperuniform(lp): """Build a network from a triangulated hyperuniform pointset Parameters ---------- lp Returns ------- """ networkdir = dio.prepdir(lp['rootdir']) + 'networks/' NH = lp['NH'] NV = lp['NV'] shape = lp['shape'] 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'] # make lattice larger than final cut keep = np.logical_and( abs(points[:, 0]) < NH * 1.5 + 8, abs(points[:, 1]) < NV * 1.5 + 8) xy = points[keep] xytri, NL, KL, BL, BM = le.delaunay_lattice_from_pts( xy, trimbound=False, target_z=lp['target_z']) # Crop lattice down to size 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, xytri, BL, NN='min') # 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') periodicstr = '' LL = (NH, NV) BBox = 0.5 * np.array([[-LL[0], -LL[1]], [LL[0], -LL[1]], [LL[0], LL[1]], [-LL[0], LL[1]]], dtype=float) PVx = [] PVy = [] PVxydict = {} else: # Unlike in the jammed case, we can't load a periodic bond list! We must make it. 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) # 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 xy, NL, KL, BL, PVxydict = le.delaunay_rect_periodic_network_from_pts( points, LL, BBox='auto', check=lp['check'], zmethod=lp['cutz_method'], target_z=lp['target_z']) print 'Building periodicBC PVs...' PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL) originstr = '' periodicstr = '_periodic' 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() lattice_exten = 'hyperuniform_' + shape + periodicstr + '_d' + '{0:02d}'.format(int(lp['conf'])) + \ '_z{0:0.3f}'.format(lp['target_z']) + originstr LV = 'none' UC = 'none' LVUC = 'none' return xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten
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_kagome_hucent(lp): 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 = blf.kagomecentroid_lattice_from_pts(xytmp, polygon=polygon, trimbound=False, check=check) 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 = 'kagome_hucent_' + shape + periodicBCstr + '_d{0:02d}'.format( int(lp['conf'])) + originstr LV = 'none' LVUC = 'none' UC = 'none' return xy, NL, KL, BL, PVxydict, PVx, PVy, LL, LVUC, LV, UC, BBox, lattice_exten
def build_hucentroid(lp): """Load the proper hyperuniform point set, given the parameters in dict lp Parameters ---------- lp : dict lattice parameters dictionary Returns ------- xy, NL, KL, BL, PVxydict, PVx, PVy, LVUC, BBox, LL, LV, UC, lattice_exten """ check = lp['check'] networkdir = lp['rootdir'] + 'networks/' print('Loading hyperuniform to build lattice...') 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 # Note: below we crop a large region so that if the network has shape==circle, we dont cut off the sides if lp['shape'] == 'circle': keep = np.logical_and( abs(points[:, 0]) < (10 + lp['NH'] * (1 + addpc)), abs(points[:, 1]) < (10 + lp['NV'] * (1 + addpc))) else: # it will speed things up to crop more, so do so if the shape is not a circle keep = np.logical_and( abs(points[:, 0]) < (5 + lp['NH'] * (1 + addpc) * 0.5), abs(points[:, 1]) < (5 + lp['NV'] * (1 + addpc)) * 0.5) xytmp = points[keep] if check: plt.plot(points[:, 0], points[:, 1], 'b.') plt.title('Point set before initial cutting') plt.show() polygon = blf.auto_polygon(lp['shape'], lp['NH'], lp['NV'], eps=0.00) xy, NL, KL, BL = le.delaunay_centroid_lattice_from_pts(xytmp, polygon=polygon, trimbound=False, check=check) 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') periodicstr = '' stripstr = '' else: if lp['periodic_strip']: lp['periodicBC'] = True sizestr = '{0:03d}'.format(lp['NP_load']) print 'sizestr = ', sizestr points = np.loadtxt(networkdir + 'hyperuniform_source/hyperuniform_N' + sizestr + '/out_d' + str(int(lp['conf'])) + '_xy.txt') print 'points = ', points points -= 0.5 * np.array([lp['NH'], lp['NV']]) # Ensuring that origin param is centered (since using entire lattice) lp['origin'] = np.array([0.0, 0.0]) if lp['NH'] != lp['NP_load']: raise RuntimeError( 'NP_load should be equal to NH for a periodicstrip geometry!' ) LL = (lp['NH'], lp['NV']) polygon = 0.5 * np.array([[-LL[0], -LL[1]], [LL[0], -LL[1]], [LL[0], LL[1]], [-LL[0], LL[1]]]) BBox = polygon keep = dh.inds_in_polygon(points, polygon) points = points[keep] xy, NL, KL, BL, PVxydict = le.delaunay_centroid_periodicstrip_from_pts( points, LL, BBox='auto', check=check) PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL) originstr = '' periodicstr = '_periodicstrip' stripstr = '_NH{0:06d}'.format(lp['NH']) + '_NV{0:06d}'.format( lp['NV']) else: lp['periodicBC'] = True sizestr = '{0:03d}'.format(lp['NP_load']) print 'sizestr = ', sizestr points = np.loadtxt(networkdir + 'hyperuniform_source/hyperuniform_N' + sizestr + '/out_d' + str(int(lp['conf'])) + '_xy.txt') print 'points = ', points points -= np.mean(points, axis=0) # 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 xy, NL, KL, BL, PVxydict = le.delaunay_centroid_rect_periodic_network_from_pts( points, LL, BBox='auto', check=check) PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL) originstr = '' periodicstr = '_periodic' stripstr = '' # 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['NP_load'] != 0: PVx *= scale PVy *= scale PVxydict.update((key, val * scale) for key, val in PVxydict.items()) lattice_exten = 'hucentroid_' + lp['shape'] + periodicstr + '_d' +\ '{0:02d}'.format(int(lp['conf'])) + stripstr + originstr LVUC = 'none' LV = 'none' UC = 'none' return xy, NL, KL, BL, PVxydict, PVx, PVy, LVUC, BBox, LL, LV, UC, lattice_exten