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