def moments(path): """ Computes and prints moments 0-2 to stdout. """ g = from_file(path) h = 1.0 - g m1 = bgy3d.moments1(h) # Get the center of distribution center = m1[1:4] / m1[0] # Use center to compute 2nd momenta m2 = bgy3d.moments2nd(h, center) print "Moments from", path print "<1> = ", m1[0] print "<x> = ", m1[1] / m1[0] print "<y> = ", m1[2] / m1[0] print "<z> = ", m1[3] / m1[0] print "<xy> = ", m2[0] / m1[0] print "<yz> = ", m2[1] / m1[0] print "<zx> = ", m2[2] / m1[0] print "<z^2 - 1/3 * r^2> = ", m2[3] / m1[0] print "<x^2 - y^2> = ", m2[4] / m1[0] print "<r^2> = ", m2[5] / m1[0]
def get_plane(g, plane=3): ''' Get the plane in which the center point of grid box locates 1 : plane x = 0 2 : plane y = 0 3 : plane z = 0 (default) ''' # Get the zero and first moments m = bgy.moments1(1.0 - g) # Round the center of the grid to the nearest integer center = np.empty(3, dtype='float') gcenter = np.empty(3, dtype='int') center = m[1:4] / m[0] for i in range(3): gcenter[i] = int(np.round(center[i])) if plane == 3: # z plane pd = g[:, :, gcenter[2]] elif plane == 2: # y plane pd = g[:, gcenter[1], :] elif plane == 1: # x plane pd = g[gcenter[0], :, :] else: print "unknown plane." exit() return pd
def get_plane(g, plane = 3): ''' Get the plane in which the center point of grid box locates 1 : plane x = 0 2 : plane y = 0 3 : plane z = 0 (default) ''' # Get the zero and first moments m = bgy.moments1(1.0 - g) # Round the center of the grid to the nearest integer center = np.empty(3,dtype='float') gcenter = np.empty(3, dtype='int') center = m[1:4] / m[0] for i in range(3): gcenter[i] = int(np.round(center[i])) if plane == 3: # z plane pd = g[:, :, gcenter[2]] elif plane == 2: # y plane pd = g[:, gcenter[1], :] elif plane == 1: # x plane pd = g[gcenter[0], :, :] else: print "unknown plane." exit() return pd
def get_rdf(g, dr, interval=(-10, 10)): ''' Return shell radius spacing with dr and radial components of distribution functions. The interval of grid box is (-10, 10) by default which is often used in BGY3D code. >>> N, R, dR = 20, 2.0, 1.0 >>> g3 = bgy.sinc_hole(N, R=R) >>> rs, gs = get_rdf(g3, dr=dR) FIXME: the interface of get_rdf() is somewhat cryptic, why do the following two arrays show no sign of similarity? #>> gs #>> 1.0 - np.sinc(rs / R) ''' # Number of grids in each direction N = bgy.root3(np.size(g)) # Get the zero and first moments m = bgy.moments1(1.0 - g) # Get the center of the grid center = m[1:4] / m[0] # print "center=", center # Get the coordinate distances from each grid point to the center rgrid = grid_distance(N, center) # Size of each grid point gsize = (interval[1] - interval[0]) / float(N) # Now convert rgrid to REAL unit rgrid *= gsize # volume of each grid point gvol = gsize * gsize * gsize # Set the maximum shell radius equal to half of grid box length Rmax = (interval[1] - interval[0]) / 2.0 # Arrays to store shell radius Rshell = np.empty(int(Rmax / dr)) # Array to store accumulated g in each layer # acc_g = np.zeros(int(Rmax / dr)) # import time # print "A", time.time() # FIXME: why stopping with array operations here? ind = np.empty(rgrid.shape, dtype='int') # fill an integer array with data, converted to integer: ind[:, :, :] = np.floor(rgrid / dr) acc = np.zeros(1 + np.max(ind)) for i, gi in zip(ind.flat, g.flat): acc[i] += gi # print "B", time.time() # Loop over the grid storing g and accumulate the value in each layer # for i in xrange(N): # for j in xrange(N): # for k in xrange(N): # R = rgrid[i, j, k] # # Ensure we'are still in the max shell # if R <= Rmax: # # r<= R < r + dr # R_interval = layer_interval(R, dr) # # assert R_interval == bins[i, j, k] # # Accumulate the value of g in this layer # acc_g[R_interval] += g[i, j, k] # print "C", time.time() # print "1=", acc_g # print "2=", acc # First mutiply accumulated g by volume of each grid occupy # acc_g *= gvol acc *= gvol # Then divide it by the volume of the layer between two shells for ii in range(int(Rmax / dr)): # Get the radius of each shell Rshell[ii] = ii * dr # acc_g[ii] /= delta_V(Rshell[ii], dr) acc[ii] /= delta_V(Rshell[ii], dr) # return Rshell, acc_g return Rshell, acc
def get_one(g, vec=[1, 1, 1], interval=(-10, 10)): ''' Return radial components of distribution function along with relevant distances in a single direction determined by vec, which defaulted as [1, 1, 1] >>> N, R = 20, 2.0 >>> g3 = bgy.sinc_hole(N, R=R) >>> rs, gs = get_one(g3) >>> gs array([ 0.28111293, 1.19780139, 0.92713167, 1.01024038, 1.02594318, 0.95473599, 1.05195458, 0.95099858, 1.03919611, 0.97466649]) >>> 1.0 - np.sinc(rs / R) array([ 0.28111293, 1.19780139, 0.92713167, 1.01024038, 1.02594318, 0.95473599, 1.05195458, 0.95099858, 1.03919611, 0.97466649]) ''' # Number of grids in each direction N = bgy.root3(np.size(g)) # Get the zero and first moments m = bgy.moments1(1.0 - g) # Get the center of the grid center = np.empty(3, dtype='float') center = m[1:4] / m[0] center = [round(center[i], 1) for i in range(3)] # Get the coordinate distances from each grid point to the center rgrid = grid_distance(N, center) # Size of each grid point gsize = (interval[1] - interval[0]) / float(N) # Now convert rgrid to REAL unit rgrid *= gsize # Get GCD of three component of direction vector v_gcd = GCD_List(vec) # Then get the reduced direction vector vec_new = [vec[i] / v_gcd for i in range(3)] # cor_ini: initial grid for iteration in each direction # Nmax: max iterations times in each direction # if the center looks like: # center = [10, 9.5, 10] # and shape(g) = [20, 20, 20] # then we have different strategies for vec = [1, 1, 1] and vec = [1, -1, 1] # if vec = [1, 1, 1], iteration begins from [10, 10, 10], and ends after 20 - 10 = 10 times # if vec = [1, -1, 1], iteration begins from [10, 9, 10], and ends after 9 - 0 + 1 = 10 times cor_ini = np.empty(3) Nmax = np.empty(3) # Get initial grid and max iteration times in each direction for i in range(3): # center coordinate is fractional if center[i] % 1 != 0: # begins from the left nearest grid if vec[i] < 0 if vec_new[i] < 0: cor_ini[i] = np.round(center[i] - 0.5, 1) Nmax[i] = abs(int((cor_ini[i] + 1) / vec_new[i])) # begins from the right nearest grid if vec[i] > 0 elif vec_new[i] > 0: cor_ini[i] = np.round(center[i] + 0.5, 1) Nmax[i] = abs(int((N - cor_ini[i]) / vec_new[i])) # always begins from the left nearest grid if vec[i] = 0 else: cor_ini[i] = np.round(center[i], 1) Nmax[i] = float("inf") else: # simpler if center coordinates is integers, but iteration times in different directions might vary cor_ini[i] = center[i] if vec_new[i] < 0: Nmax[i] = abs(int((cor_ini[i] + 1) / vec_new[i])) elif vec_new[i] > 0: Nmax[i] = abs(int((N - cor_ini[i]) / vec_new[i])) else: Nmax[i] = float("inf") # Actual iteration times is the mininum of those in three direction # Might improve this if PBS applied N_iter = int(min(Nmax)) # rs: distances # gs: value of distribution function rs = np.empty(N_iter) gs = np.empty(N_iter) for ii in range(N_iter): # Get grid coordinates in each direction cor_xx = cor_ini[0] + ii * vec_new[0] cor_yy = cor_ini[1] + ii * vec_new[1] cor_zz = cor_ini[2] + ii * vec_new[2] rs[ii] = rgrid[cor_xx, cor_yy, cor_zz] gs[ii] = g[cor_xx, cor_yy, cor_zz] return rs, gs