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		
예제 #2
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
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