def compute_density_all(data_file, dfile):
	''' Calculate density at all steps in .d file '''
	
	# data_file - LAMMPS .data file 
	# dfile - LAMMPS .d file
	#
	# Returns a list of time steps and a list of corresponding densities
	# time steps are ints, densities are doubles
	#

	# Extract time steps
	time_steps = dsec.extract_all_sections(dfile, 'ITEM: TIMESTEP')

	# Extract box dimensions
	box_dims = dsec.extract_all_sections(dfile, 'ITEM: BOX')

	# Get total system mass in g
	total_mass = utils.compute_total_mass(data_file)

	# Compute densities and convert time steps to ints
	densities = []
	int_steps = []
	for step, box in zip(time_steps, box_dims):

		int_steps.append(int(step[0]))
		
		# Compute volume in cm^3
		flt_box = utils.conv_to_float(box)
		vol = utils.compute_volume(flt_box)

		# Compute and store bulk density in g/cm^3
		densities.append(total_mass/vol)

	return int_steps, densities		
Exemple #2
0
def plot_atom_ID(fname, atomID, colors, time):
    ''' Visualize an atom with given ID during the simulation '''

    # fname - name of the d file
    # atomID - atom ID
    # colors - colors, list of RGB tuples, one per time step
    # time - array with simulation times

    # Extract time steps
    time_steps = dsec.extract_all_sections(fname, 'ITEM: TIMESTEP')

    # Extract atom data
    atoms_all_t = dsec.extract_all_sections(fname, 'ITEM: ATOMS')

    ist = 0
    for step, atoms in zip(time_steps, atoms_all_t):
        if not (int(step[0]) in time):
            continue
        atom_data = []
        for at in atoms:
            at = at.strip().split()
            if at[0] == str(atomID):
                atom_data.append([float(at[2]), float(at[3]), float(at[4])])

        atom_np = np.array(atom_data, dtype=np.float32)
        mlab.points3d(atom_np[:, 0],
                      atom_np[:, 1],
                      atom_np[:, 2],
                      color=colors[ist])
        ist += 1

    mlab.show()
Exemple #3
0
def compute_average_conductivity(dfile, atom_type, atom_charge, efield,
                                 vel_col):
    ''' Computes electric conductivity averaged across all	steps in the d file '''

    # dfile - LAMMPS .d file
    # atom_type - atom type ID as defined in .data file
    # atom_charge - atom charge in C
    # efield - strength of the electric field in V/m
    # vel_col - column number for velocity component parallel
    #				to the electric field direction
    #
    # Returns average conductivity in S/m, time steps in fs, and
    #	a list of conductivities in S/m for each time step

    # Collect all data for this type of atom
    time, data = dsec.extract_atom_type_data(dfile, atom_type)

    # For each time compute average velocity over all atoms
    # convert to m/s
    Afs2ms = 1.0e5
    vel_w_time = []
    natom = len(data[0])
    for step, frame in zip(time, data):
        ave_frame = 0.0
        for line in frame:
            ave_frame += line[vel_col]
        vel_w_time.append(ave_frame / len(frame) * Afs2ms)

    # Average velocity across all time steps
    ave_vel_tot = sum(vel_w_time) / len(vel_w_time)

    # Average volume at each time step
    # Extract box dimensions, compute volumes at each step in m^3
    cm32m3 = 1.0e-6
    box_dims = dsec.extract_all_sections(dfile, 'ITEM: BOX')
    vols = []
    for box in box_dims:
        flt_box = utils.conv_to_float(box)
        vols.append(utils.compute_volume(flt_box) * cm32m3)

    # Average electric conductivities over time steps
    # and within time steps
    cond_w_time = [
        vel / vol * natom * atom_charge / efield
        for vel, vol in zip(vel_w_time, vols)
    ]
    ave_cond = sum(cond_w_time) / len(cond_w_time)

    return ave_cond, time, cond_w_time
Exemple #4
0
def compute_coordination_number_all(dfile,
                                    atom_type_1,
                                    atom_type_2,
                                    dR=0.1,
                                    Rmax=10,
                                    steps=None):
    ''' Compute coordination number as a function of distance between 
			two types of atoms at all time steps '''

    #
    # dfile - LAMMPS .d file
    # atom_type_1, atom_type_2 - integer atom type IDs as specified in the Masses part of .data file
    # 	atom_type_1 is the type which coordination numbers will be returned (the central atom)
    # dR - width of a single shell for counting atoms at a given distance
    # Rmax - max radius around the central atom to consider
    # steps - optional list of timesteps to consider, all if not specified
    #
    # Returns a list of time steps and a list of lists of corresponding coordination numbers
    # with first list being radial distance, and second list the coordination number for
    # that distance; the radial distance is the center of each shell considered a
    # single position.
    #
    # Time steps and coordination numbers are ints, radial distances are doubles
    #

    # Extract time steps
    time_steps = dsec.extract_all_sections(dfile, 'ITEM: TIMESTEP')

    # Extract atom data
    atom_data = dsec.extract_all_sections(dfile, 'ITEM: ATOMS')

    # Compute coordination numbers as function of position
    # and convert time steps to ints
    cn_all = []
    int_steps = []

    for step, atom in zip(time_steps, atom_data):

        step_int = int(step[0])
        # If selected steps, then skip ones not needed
        if steps:
            if not (step_int in steps):
                continue
        int_steps.append(step_int)

        # Retrieve all data for these atom types
        at_data_1 = utils.get_atom_i_data(atom, atom_type_1, 1, [2, 3, 4])
        if atom_type_1 == atom_type_2:
            at_data_2 = at_data_1
        else:
            at_data_2 = utils.get_atom_i_data(atom, atom_type_2, 1, [2, 3, 4])

        # Compute and store distances between each atom in 1 and each atom in 2
        # One sublist per atom from atom type 1
        dist_12 = []
        for at1 in at_data_1:
            temp_dist = []
            for at2 in at_data_2:
                temp_dist.append(utils.compute_distance(at1, at2))
            dist_12.append(temp_dist)

        # Compute coordination numbers
        ri, ci = compute_cn(dist_12, dR, Rmax)
        cn_all.append([ri, ci])

    return int_steps, cn_all
def compute_spatial_stress(fname,
                           time,
                           nbins,
                           idir,
                           wpos=[],
                           all_steps=False,
                           av_per_atom=False):
    ''' Compute spatial distribution of stress '''

    #
    # fname - name of the d file
    # time - array with simulation times to plot
    # nbins - number of bins in the target direction
    # idir - string representing direction
    # wpos - positions of walls in a non-periodic system
    # all_steps - include all time steps
    # av_per_atom - return average stress per atom rather than total
    #

    # Extract time steps
    time_steps = dsec.extract_all_sections(fname, 'ITEM: TIMESTEP')

    # Extract atom data
    atoms_all_t = dsec.extract_all_sections(fname, 'ITEM: ATOMS')

    # Extract box dimensions
    box_all_t = dsec.extract_all_sections(fname, 'ITEM: BOX')

    # Direction settings
    # b_ind - index of coordinates in the BOX data
    # d_ind - column with atom positions in that direction in the .d file
    if idir == 'x':
        b_ind = 0
        d_ind = 2
    elif idir == 'y':
        b_ind = 1
        d_ind = 3
    elif idir == 'z':
        b_ind = 2
        d_ind = 4
    else:
        raise RuntimeError('Wrong direction: ' + idir)

    # Stress components
    directions = ['xx', 'yy', 'zz', 'xy', 'xz', 'yz']
    # ..and their position in d file (starts from 0)
    columns = [8, 9, 10, 11, 12, 13]

    stress = []
    for step, atoms, box in zip(time_steps, atoms_all_t, box_all_t):

        if (not (int(step[0]) in time)) and (all_steps == False):
            continue

        # Spatial bins
        dims = box[b_ind].strip().split()
        if wpos:
            L_0 = wpos[0]
            L_tot = wpos[1] - wpos[0]
        else:
            L_0 = float(dims[0])
            L_tot = float(dims[1]) - L_0
        bin_width = L_tot / nbins
        atoms_in_bins = [0] * nbins

        # Compute volume in A^3
        flt_box = utils.conv_to_float(box)
        # Compute volume in cm^3 then convert to A^3
        cm32A3 = 1.0e24
        vol = utils.compute_volume(flt_box) * cm32A3
        bin_vol = vol / nbins

        # All stress components
        temp_stress = {}
        for key in directions:
            temp_stress[key] = [0] * nbins

        # Sum stresses in each bin and each direction
        for at in atoms:
            at = at.strip().split()
            # So that the binning is simple
            # Shifted the interval to 0->L_tot
            norm_pos = float(at[d_ind]) - L_0
            ind = max(min(math.floor(norm_pos / bin_width), nbins - 1), 0)
            atoms_in_bins[ind] += 1
            for key, col in zip(directions, columns):
                temp_stress[key][ind] += float(at[col])

        if av_per_atom:
            # Divide by number of atoms in each bin
            for key, value in temp_stress.items():
                temp_stress[key] = [
                    x / max(y, 1) for x, y in zip(value, atoms_in_bins)
                ]
        else:
            for key, value in temp_stress.items():
                temp_stress[key] = [x / bin_vol for x in value]

        stress.append(temp_stress)

    return stress
def compute_spatial_density(fname,
                            typeID,
                            time,
                            nbins,
                            idir,
                            wpos=[],
                            all_steps=False,
                            den=False):
    ''' Compute spatial density distribution of given atom type '''

    #
    # fname - name of the d file
    # typeID - atom type as defined in .data file
    # time - array with simulation times to plot
    # nbins - number of bins in the target direction
    # idir - string representing direction
    # wpos - positions of walls in a non-periodic system
    #

    # Extract time steps
    time_steps = dsec.extract_all_sections(fname, 'ITEM: TIMESTEP')

    # Extract atom data
    atoms_all_t = dsec.extract_all_sections(fname, 'ITEM: ATOMS')

    # Extract box dimensions
    box_all_t = dsec.extract_all_sections(fname, 'ITEM: BOX')

    # Direction settings
    # b_ind - index of coordinates in the BOX data
    # d_ind - column with atom positions in that direction in the .d file
    if idir == 'x':
        b_ind = 0
        d_ind = 2
    elif idir == 'y':
        b_ind = 1
        d_ind = 3
    else:
        b_ind = 2
        d_ind = 4

    densities = []
    for step, atoms, box in zip(time_steps, atoms_all_t, box_all_t):

        if (not (int(step[0]) in time)) and (all_steps == False):
            continue

        # Spatial bins
        dims = box[b_ind].strip().split()
        if wpos:
            L_0 = wpos[0]
            L_tot = wpos[1] - wpos[0]
        else:
            L_0 = float(dims[0])
            L_tot = float(dims[1]) - L_0
        bin_width = L_tot / nbins
        number_density = [0] * nbins

        # Calculate how many atoms in each bin
        atom_data = []
        for at in atoms:
            at = at.strip().split()
            if at[1] == str(typeID):
                # So that the binning is simple
                # Shifted the interval to 0->L_tot
                norm_pos = float(at[d_ind]) - L_0
                number_density[max(
                    min(math.floor(norm_pos / bin_width), nbins - 1), 0)] += 1

        # Compute volume in cm^3 then convert to A^3
        cm32A3 = 1.0e24
        flt_box = utils.conv_to_float(box)

        vol = utils.compute_volume(flt_box) * cm32A3
        bin_vol = vol / nbins

        if den:
            # Divide by bin volumes (all volumes equal)
            densities.append([x / bin_vol for x in number_density])
        else:
            densities.append([x for x in number_density])

    return densities