Exemple #1
0
def write_lammps_trajectory(filename, structure):
    if isinstance(filename,str):
        f = open(filename,'w')
    else:
        f = filename
    f.write("ITEM: TIMESTEP\n0\nITEM: NUMBER OF ATOMS\n")
    atoms = AseAtomsAdaptor.get_atoms(structure)
    f.write("{0}\n".format(len(atoms)))
    f.write("ITEM: BOX BOUNDS ")
    pbc = atoms.get_pbc()
    for bound in pbc:
        if bound:
            f.write("pp ")
        else:
            f.write("s ")
    f.write("\n")
    p = prism(atoms.get_cell())
    xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str()

    f.write('0.0 {0}\n'.format(xhi))
    f.write('0.0 {0}\n'.format(yhi))
    f.write('0.0 {0}\n'.format(zhi))
    if p.is_skewed():
        f.write('%s %s %s\n' % (xy, xz, yz))
    f.write('ITEM: ATOMS id type x y z vx vy vz fx fy fz\n')
    syms = sorted(list(set(atoms.get_chemical_symbols())))
    symlist = [one for one in enumerate(syms)]
    for idx in range(len(atoms)):
        type = [ty+1 for ty,sym in symlist if sym==atoms[idx].symbol][0]
        f.write('{0} {1} {2}'.format(idx+1,type, ' '.join([repr(x) for x in atoms[0].position])))
        f.write('0 0 0 0 0 0\n')
    f.close()
    return
Exemple #2
0
def write_lammps_trajectory(filename, structure):
    if isinstance(filename, str):
        f = open(filename, 'w')
    else:
        f = filename
    f.write("ITEM: TIMESTEP\n0\nITEM: NUMBER OF ATOMS\n")
    atoms = AseAtomsAdaptor.get_atoms(structure)
    f.write("{0}\n".format(len(atoms)))
    f.write("ITEM: BOX BOUNDS ")
    pbc = atoms.get_pbc()
    for bound in pbc:
        if bound:
            f.write("pp ")
        else:
            f.write("s ")
    f.write("\n")
    p = prism(atoms.get_cell())
    xhi, yhi, zhi, xy, xz, yz = p.get_lammps_prism_str()

    f.write('0.0 {0}\n'.format(xhi))
    f.write('0.0 {0}\n'.format(yhi))
    f.write('0.0 {0}\n'.format(zhi))
    if p.is_skewed():
        f.write('%s %s %s\n' % (xy, xz, yz))
    f.write('ITEM: ATOMS id type x y z vx vy vz fx fy fz\n')
    syms = sorted(list(set(atoms.get_chemical_symbols())))
    symlist = [one for one in enumerate(syms)]
    for idx in range(len(atoms)):
        type = [ty + 1 for ty, sym in symlist if sym == atoms[idx].symbol][0]
        f.write('{0} {1} {2}'.format(
            idx + 1, type, ' '.join([repr(x) for x in atoms[0].position])))
        f.write('0 0 0 0 0 0\n')
    f.close()
    return
Exemple #3
0
 def forward_final_structure_file(self, childpath, newname="DATA"):
     """Forward the final structure.
         For LAMMPS, this is the Trajectory.
         Args:
             childpath <str>: Path of child ingredient
             newname <str>: new name (default 'POSCAR')
     """
     trajstruct = self.get_structure_from_file("TRAJECTORY")
     trajatoms = AseAtomsAdaptor.get_atoms(trajstruct)
     write_lammps_data("FINAL", trajatoms)
     self.copy_a_file(childpath, "FINAL", newname)
     self.copy_a_file(childpath, "atom_symbols", "atom_symbols")
Exemple #4
0
 def forward_final_structure_file(self, childpath, newname="DATA"):
     """Forward the final structure.
         For LAMMPS, this is the Trajectory.
         Args:
             childpath <str>: Path of child ingredient
             newname <str>: new name (default 'POSCAR')
     """
     trajstruct = self.get_structure_from_file("TRAJECTORY")
     trajatoms = AseAtomsAdaptor.get_atoms(trajstruct)
     write_lammps_data("FINAL",trajatoms)
     self.copy_a_file(childpath, "FINAL", newname)
     self.copy_a_file(childpath, "atom_symbols", "atom_symbols")
Exemple #5
0
def read_xyz(fileobj,n=-1,data=False):
    """
    Function to read multi-atom xyz file with data
    Inputs:
        fileobj = String containing file name or file object
        n = Integer indicating number for structure from xyz file
            to read. Default is last structure in file.
            Or String=='All' which will output all structures in file
        data = True/False boolean indicating whether or not to output 
            any data strings read from xyz file
    Outputs:
        atmslist = ASE Atoms class object containing structure from file
            or list of Atoms objects if n=='All'
        datalist(Optional) = String of data read from xyz file or list 
            of data strings read from xyz file
    """
    try:
        from pymatgen.io.vaspio import Poscar
        mystructure = Poscar.from_file(fileobj).structure
        from pymatgen.io.aseio import AseAtomsAdaptor
        myatoms = AseAtomsAdaptor.get_atoms(mystructure)
        return myatoms
    except:
        if isinstance(fileobj, str):
            fileobj = open(fileobj,'r')
        lines = fileobj.readlines()
        atmslist = []
        datalist = []
        while len(lines)>0:
            natoms = int(lines[0])
            datalist.append(lines[1])
            atm1 = Atoms()
            i =- 1
            for i in range(natoms):
                a = lines[i+2].split()
                sym = a[0]
                position = [float(a[1]),float(a[2]),float(a[3])]
                atm1.append(Atom(symbol=sym,position=position))
            atmslist.append(atm1)
            lines = lines[i+3::]
        if n == 'All':
            if data == True:
                return atmslist, datalist
            else:
                return atmslist
        else:
            if data == True:
                return atmslist[n],datalist[n]
            else:
                return atmslist[n]
Exemple #6
0
 def _lammps_data_setup(self):
     """Set up the DATA file for a single LAMMPS run.
     """
     name = self.keywords['name']
     datapath = os.path.join(name, "DATA")
     if os.path.isfile(datapath):
         my_data_structure = self.get_structure_from_file(datapath) 
         #parent should have given a structure
     else: #this is an originating run; mast should give it a structure
         my_data_structure = self.keywords['structure']
         self.logger.info("No DATA file found from a parent; base structure used for %s" % self.keywords['name'])
     if 'mast_coordinates' in self.keywords['program_keys'].keys():
         sxtend = StructureExtensions(struc_work1=my_data_structure, name=self.keywords['name'])
         coordstrucs=self.get_coordinates_only_structure_from_input()
         newstruc = sxtend.graft_coordinates_onto_structure(coordstrucs[0])
         my_data_structure=newstruc.copy()
     #dirutil.lock_directory(name)
     my_data_atoms = AseAtomsAdaptor.get_atoms(my_data_structure)
     write_lammps_data(datapath, my_data_atoms)
     #dirutil.unlock_directory(name)
     return datapath
Exemple #7
0
 def _lammps_data_setup(self):
     """Set up the DATA file for a single LAMMPS run.
     """
     name = self.keywords['name']
     datapath = os.path.join(name, "DATA")
     if os.path.isfile(datapath):
         my_data_structure = self.get_structure_from_file(datapath)
         #parent should have given a structure
     else:  #this is an originating run; mast should give it a structure
         my_data_structure = self.keywords['structure']
         self.logger.info(
             "No DATA file found from a parent; base structure used for %s"
             % self.keywords['name'])
     if 'mast_coordinates' in self.keywords['program_keys'].keys():
         sxtend = StructureExtensions(struc_work1=my_data_structure,
                                      name=self.keywords['name'])
         coordstrucs = self.get_coordinates_only_structure_from_input()
         newstruc = sxtend.graft_coordinates_onto_structure(coordstrucs[0])
         my_data_structure = newstruc.copy()
     #dirutil.lock_directory(name)
     my_data_atoms = AseAtomsAdaptor.get_atoms(my_data_structure)
     write_lammps_data(datapath, my_data_atoms)
     #dirutil.unlock_directory(name)
     return datapath
Exemple #8
0
def readable_lammps_parameters(parameters, structure):
    atoms = AseAtomsAdaptor.get_atoms(structure)
    atomlist = sorted(list(set(atoms.get_chemical_symbols())))
    masslist = [Atom(sym).mass for sym in atomlist]
    if 'potential_file' in parameters:
        if parameters['potential_file']:
            parameters['pot_file'] = os.path.basename(
                parameters['potential_file'])
    if parameters['pair_style'] == 'tersoff':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff += ' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
        parameters['mass'] = mass
    elif parameters['pair_style'] == 'eam':
        pair_coeff = ['* * {0}'.format(parameters['pot_file'])]
        parameters['pair_coeff'] = pair_coeff
    elif parameters['pair_style'] == 'eam/fs':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff += ' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
    elif parameters['pair_style'] == 'eam/cd':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff += ' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
    elif parameters['pair_style'] == 'edip':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff += ' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
        parameters['mass'] = mass
        parameters['newton'] = 'on'
    elif parameters['pair_style'] == 'bop':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff += ' {0}'.format(one[0])
        parcoff += '\ncommunicate single cutoff {0}'.format(
            parameters['bopcutoff'])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
        parameters['mass'] = mass
        parameters['newton'] = 'on'
    elif parameters['pair_style'] == 'buck':
        pairstyle = '{0} {1}'.format(parametes['pair_style'],
                                     parameters['buckcutoff'])
        pair_coeff = parameters['buckparameters']
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
        parameters['pair_style'] = pairstyle
        parameters['pair_coeff'] = pair_coeff
        parameters['mass'] = mass
        parameters['potential_file'] = None
    elif parameters['pair_style'] == 'other':
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist) - 1):
                mass.append('{0} {1}'.format(i + 2, masslist[i + 1]))
        if 'charges' in parameters:
            cs = parameters['charges']
            parameters['mass'][len(parameters['mass']) - 1] += cs[1]
            parameters['newton'] += '\natom_style charge'
    else:
        parameters = {'potential_file': None}
        print 'WARNING: No LAMMPS potential recognized. Assuming Lennard Jones Potential'
    return parameters
Exemple #9
0
    def _lammps_input_setup(self,
                            lammps_input_file="INPUT",
                            lammps_data_file="DATA",
                            lammps_trajectory_file="TRAJECTORY"):
        """Function to write a lammps input file
        Input:
            lammps_input_file = file to write lammps input to
            lammps_data_file = file to load lammps data from
            lammps_trajectory_file = file to write lammps trajectory to
        """
        if isinstance(lammps_input_file, str):
            f = open(lammps_input_file, 'w')
        else:
            f = lammps_input_file

        # Write file variable names
        f.write('clear\n' +
                ('variable dump_file string "%s"\n' % lammps_trajectory_file) +
                ('variable data_file string "%s"\n' % lammps_data_file))
        f.write('units metal \n')

        #Write to specified log file
        #logname = os.path.join(os.path.dirname(lammps_data_file),"LOG")
        #f.write('log %s append\n' % logname)

        #Get keyword parameters
        parameters = dict()
        parameters = self._lammps_input_get_non_mast_keywords()
        #Copy potential file to current working directory
        if 'potential_file' in parameters:
            if parameters['potential_file']:
                newlocation = os.path.join(
                    os.path.dirname(lammps_data_file),
                    os.path.basename(parameters['potential_file']))
                shutil.copyfile(parameters['potential_file'], newlocation)
                self.potential_file = newlocation

        atoms = AseAtomsAdaptor.get_atoms(self.keywords['structure'])
        pbc = atoms.get_pbc()
        if ('boundary' in parameters):
            f.write('boundary %s \n' % parameters['boundary'])
        else:
            f.write('boundary %c %c %c \n' % tuple('sp'[x] for x in pbc))
        f.write('atom_modify sort 0 0.0 \n')
        if ('neighbor' in parameters):
            f.write('neighbor %s \n' % parameters['neighbor'])
        if ('newton' in parameters):
            f.write('newton %s \n' % parameters['newton'])

        f.write('\n')

        f.write('read_data %s\n' % lammps_data_file)

        # Write pair potential information
        f.write('\n### interactions \n')
        if (('pair_style' in parameters) and ('pair_coeff' in parameters)):
            pair_style = parameters['pair_style']
            f.write('pair_style %s \n' % pair_style)
            if not isinstance(parameters['pair_coeff'], list):
                try:
                    parameters['pair_coeff'] = eval(parameters['pair_coeff'])
                except:
                    parameters['pair_coeff'] = [parameters['pair_coeff']]
            for pair_coeff in parameters['pair_coeff']:
                f.write('pair_coeff %s \n' % pair_coeff)
            if 'mass' in parameters:
                if not isinstance(parameter['mass'], list):
                    try:
                        parameters['mass'] = eval(parameters['mass'])
                    except:
                        parameters['mass'] = [parameters['mass']]
                for mass in parameters['mass']:
                    f.write('mass %s \n' % mass)
        else:  # Use simple leonnard jones calculation
            f.write('pair_style lj/cut 2.5 \n' + 'pair_coeff * * 1 1 \n' +
                    'mass * 1.0 \n')
        #Set up min_style if appropriate
        if 'min_style' in parameters:
            f.write('min_style %s \n' % parameters['min_style'])

        #Write line for thermo arguments and stemps
        thermo_args = [
            'step', 'temp', 'press', 'cpu', 'pxx', 'pyy', 'pzz', 'pxy', 'pxz',
            'pyz', 'ke', 'pe', 'etotal', 'vol', 'lx', 'ly', 'lz', 'atoms'
        ]
        thermo_mark = ' '.join([x.capitalize() for x in thermo_args[0:3]])
        if 'thermosteps' not in parameters:
            parameters['thermosteps'] = '1'

        f.write('\n### run\n' + 'fix fix_nve all nve\n' +
                ('dump dump_all all custom {0} {1}'.format(
                    parameters['thermosteps'], lammps_trajectory_file)) +
                ' id type x y z vx vy vz fx fy fz' + '\n')
        f.write(('thermo_style custom %s\n' + 'thermo_modify flush yes\n' +
                 'thermo ' + repr(parameters['thermosteps']) + '\n') %
                (' '.join(thermo_args)))

        if 'minimize' in parameters:
            f.write('minimize %s\n' % parameters['minimize'])
        if 'run' in parameters:
            f.write('run %s\n' % parameters['run'])
        if not (('minimize' in parameters) or ('run' in parameters)):
            f.write('run 0\n')

        f.write('print "CALCULATION HAS FINISHED"\n')
        f.write('log /dev/stdout\n')  # Force LAMMPS to flush log
        f.write('undump dump_all\n')  # Force LAMMPS to flush trj
        f.close()
        return lammps_input_file
Exemple #10
0
def readable_lammps_parameters(parameters, structure):
    atoms = AseAtomsAdaptor.get_atoms(structure)
    atomlist = sorted(list(set(atoms.get_chemical_symbols())))
    masslist = [Atom(sym).mass for sym in atomlist]
    if 'potential_file' in parameters:
        if parameters['potential_file']:
            parameters['pot_file'] = os.path.basename(parameters['potential_file'])
    if parameters['pair_style']=='tersoff':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff+=' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2,masslist[i+1]))
        parameters['mass'] = mass
    elif parameters['pair_style']=='eam':
        pair_coeff = [ '* * {0}'.format(parameters['pot_file'])]
        parameters['pair_coeff'] = pair_coeff
    elif parameters['pair_style']=='eam/fs':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff+=' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2,masslist[i+1]))
    elif parameters['pair_style']=='eam/cd':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff+=' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
    elif parameters['pair_style']=='edip':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff+=' {0}'.format(one[0])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2,masslist[i+1]))
        parameters['mass'] = mass
        parameters['newton'] = 'on'
    elif parameters['pair_style']=='bop':
        parcoff = '* * {0}'.format(parameters['pot_file'])
        for one in atomlist:
            parcoff+=' {0}'.format(one[0])
        parcoff+='\ncommunicate single cutoff {0}'.format(parameters['bopcutoff'])
        parameters['pair_coeff'] = [parcoff]
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2,masslist[i+1]))
        parameters['mass'] = mass
        parameters['newton'] = 'on'
    elif parameters['pair_style']=='buck':
        pairstyle='{0} {1}'.format(parametes['pair_style'], parameters['buckcutoff'])
        pair_coeff=parameters['buckparameters']
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2, masslist[i+1]))	
        parameters['pair_style'] = pairstyle
        parameters['pair_coeff'] = pair_coeff
        parameters['mass'] = mass
        parameters['potential_file'] = None
    elif parameters['pair_style']=='other':
        mass = ['1 {0}'.format(masslist[0])]
        if len(masslist) > 1:
            for i in range(len(masslist)-1):
                mass.append('{0} {1}'.format(i+2,masslist[i+1]))
        if 'charges' in parameters:
            cs = parameters['charges']
            parameters['mass'][len(parameters['mass'])-1] +=cs[1]
            parameters['newton']+='\natom_style charge'
    else:
        parameters={'potential_file':None}
        print 'WARNING: No LAMMPS potential recognized. Assuming Lennard Jones Potential'
    return parameters
Exemple #11
0
    def _lammps_input_setup(self, lammps_input_file="INPUT", lammps_data_file="DATA", lammps_trajectory_file="TRAJECTORY"):
        """Function to write a lammps input file
        Input:
            lammps_input_file = file to write lammps input to
            lammps_data_file = file to load lammps data from
            lammps_trajectory_file = file to write lammps trajectory to
        """
        if isinstance(lammps_input_file, str):
            f = open(lammps_input_file, 'w')
        else:
            f = lammps_input_file
        
        # Write file variable names
        f.write('clear\n' +
                ('variable dump_file string "%s"\n' % lammps_trajectory_file) +
                ('variable data_file string "%s"\n' % lammps_data_file))
        f.write('units metal \n')
        
        #Write to specified log file
        #logname = os.path.join(os.path.dirname(lammps_data_file),"LOG")
        #f.write('log %s append\n' % logname)
        
        #Get keyword parameters
        parameters = dict()
        parameters = self._lammps_input_get_non_mast_keywords()
        #Copy potential file to current working directory
        if 'potential_file' in parameters:
            if parameters['potential_file']:
                newlocation = os.path.join(os.path.dirname(lammps_data_file),os.path.basename(parameters['potential_file']))
                shutil.copyfile(parameters['potential_file'],newlocation)
                self.potential_file = newlocation
        
        atoms = AseAtomsAdaptor.get_atoms(self.keywords['structure'])
        pbc = atoms.get_pbc()
        if ('boundary' in parameters):
            f.write('boundary %s \n' % parameters['boundary'])
        else:
            f.write('boundary %c %c %c \n' % tuple('sp'[x] for x in pbc))
        f.write('atom_modify sort 0 0.0 \n')
        if ('neighbor' in parameters):
            f.write('neighbor %s \n' % parameters['neighbor'])
        if ('newton' in parameters):
            f.write('newton %s \n' % parameters['newton'])
                
        f.write('\n')
        
        f.write('read_data %s\n' % lammps_data_file)
        
        # Write pair potential information
        f.write('\n### interactions \n')
        if ( ('pair_style' in parameters) and ('pair_coeff' in parameters) ):
            pair_style = parameters['pair_style']
            f.write('pair_style %s \n' % pair_style)
            if not isinstance(parameters['pair_coeff'],list):
                try:
                    parameters['pair_coeff'] = eval(parameters['pair_coeff'])
                except:
                    parameters['pair_coeff'] = [ parameters['pair_coeff'] ]
            for pair_coeff in parameters['pair_coeff']:
                f.write('pair_coeff %s \n' % pair_coeff)
            if 'mass' in parameters:
                if not isinstance(parameter['mass'],list):
                    try:
                        parameters['mass'] = eval(parameters['mass'])
                    except:
                        parameters['mass'] = [ parameters['mass'] ]
                for mass in parameters['mass']:
                    f.write('mass %s \n' % mass)
        else:# Use simple leonnard jones calculation
            f.write('pair_style lj/cut 2.5 \n' +
                    'pair_coeff * * 1 1 \n' +
                    'mass * 1.0 \n')
        #Set up min_style if appropriate
        if 'min_style' in parameters:
            f.write('min_style %s \n' % parameters['min_style'])
        
        #Write line for thermo arguments and stemps
        thermo_args = ['step', 'temp', 'press', 'cpu', 
                            'pxx', 'pyy', 'pzz', 'pxy', 'pxz', 'pyz',
                            'ke', 'pe', 'etotal',
                            'vol', 'lx', 'ly', 'lz', 'atoms']
        thermo_mark = ' '.join([x.capitalize() for x in thermo_args[0:3]])
        if 'thermosteps' not in parameters:
            parameters['thermosteps'] = '1'
        
        f.write('\n### run\n' + 
                 'fix fix_nve all nve\n'+
                ('dump dump_all all custom {0} {1}'.format(parameters['thermosteps'], lammps_trajectory_file))+
                ' id type x y z vx vy vz fx fy fz'+
                '\n')
        f.write(('thermo_style custom %s\n' +
                'thermo_modify flush yes\n' +
                'thermo '+repr(parameters['thermosteps'])+
                '\n') % (' '.join(thermo_args)))

        if 'minimize' in parameters:
            f.write('minimize %s\n' % parameters['minimize'])
        if 'run' in parameters:
            f.write('run %s\n' % parameters['run'])
        if not (('minimize' in parameters) or ('run' in parameters)):
            f.write('run 0\n')

        f.write('print "CALCULATION HAS FINISHED"\n')
        f.write('log /dev/stdout\n') # Force LAMMPS to flush log
        f.write('undump dump_all\n') # Force LAMMPS to flush trj
        f.close()
        return lammps_input_file