Ejemplo n.º 1
0
def gulp_wolf(base_name,
              base_file,
              gulp_exec,
              xi_min=0.05,
              xi_max=0.40,
              rcut_min=10.0,
              rcut_max=25.0,
              dxi=0.01,
              dr=0.1):
    '''Runs a series of single-point calculations in GULP with Wolf summation
    parameters given in dampRange and cutRange. Extracts optimum parameters.
    '''

    xi_range = np.arange(xi_min, xi_max + dxi, dxi)
    rcut_range = np.arange(rcut_min, rcut_max + dr, dr)

    for xi in xi_range:
        print('Setting \\xi = %.2f:' % xi)
        for rcut in rcut_range:
            print('r = %.1f' % rcut)
            # create GULP input file for this combination of damping parameter
            # \xi and cutoff radius r_{cut}
            root_name = '%s.wolf.%.2f.%.1f' % (base_name, xi, rcut)
            outstream = open('%s.gin' % root_name, 'w')
            for line in base_file:
                outstream.write('%s\n' % line)

            put_wolf(lambda in_line: outstream.write(in_line), xi, rcut)
            outstream.close()

            # perform calculation
            gulp.run_gulp(gulp_exec, root_name)
    return
Ejemplo n.º 2
0
def calculate_impurity_energies(site_list,
                                gulpexec,
                                in_parallel=False,
                                nprocesses=1,
                                suffix='gin'):
    '''Calculates energies for dislocation clusters containing a single impurity
    previously constructed using the <calculate_impurity> function.
    '''

    if not in_parallel:
        for site in site_list:
            i = site.split('.')[-1]
            print('Relaxing structure with defect at site {}...'.format(i))
            gulp.run_gulp(gulpexec, site, in_suffix=suffix)
    else:
        pool = Pool(processes=nprocesses)
        for site in site_list:
            i = site.split('.')[-1]
            msg = 'Relaxing structure with defect at site {}...'.format(i)
            pool.apply_async(gulp.gulp_process,
                             args=(site, gulpexec),
                             kwds=dict(message=msg, in_suffix=suffix))

        pool.close()
        pool.join()

    return
def transition_rfo(strucname, rI, rII, maxiter=2500, executable=None):
    '''Takes a defect structure produced by the constrained minimization routine
    and sets up a transition state calculation using the RFO algorithm to find the
    saddle point. <maxiter> is large because of the slow convergence of the 
    l-BFGS algorithm used by GULP to find the transition state. 
    '''

    # produce input file for transition state calculation
    cluster, sysinfo = gulp.cluster_from_grs('{}.grs'.format(strucname), rI,
                                             rII)
    ostream = open('rfo.{}.gin'.format(strucname), 'w')
    gulp.write_gulp(ostream,
                    cluster,
                    sysinfo,
                    prop=False,
                    maxiter=maxiter,
                    transition=True,
                    do_relax=False,
                    add_constraints=True)

    # run the calculation if an executable has been provided
    if executable is not None:
        gulp.run_gulp(executable, 'rfo.{}'.format(strucname))

    return
def calculate_migration_points(site_pairs,
                               executable,
                               npoints,
                               noisy=False,
                               in_parallel=False,
                               np=1):
    '''Optimize structures and calculate energies for all <n> points along the 
    migration paths with endpoints defined in <site_pairs>.
    '''

    if not in_parallel:
        for pair in site_pairs:
            for n in range(npoints):
                if noisy:
                    i, j = pair.split('.')[-2:]
                    print(
                        "Calculating barrier for migrationfrom site {} to site {}"
                        .format(i, j))

                prefix = 'disp.{}.{}'.format(n, pair)
                gulp.run_gulp(executable, prefix)
    else:
        pool = Pool(processes=np)
        files_to_calc = [
            'disp.{}.{}'.format(ni, prefix) for ni in range(npoints)
            for prefix in site_pairs
        ]
        for disp_file in files_to_calc:
            if noisy:
                i, j = disp_file.split('.')[-2:]
                ni = disp_file.split('.')[1]
                if int(ni) == 0:
                    message = "Calculating barrier for migration from site {} to site {}".format(
                        i, j)
                else:
                    message = None
            else:
                message = None

            pool.apply_async(gulp.gulp_process,
                             (disp_file, executable, message))

        pool.close()
        pool.join()
Ejemplo n.º 5
0
def main():
    '''Controller program.
    '''
    
    if not sys.argv[1:]:
        # test to see if command line options have been passed. If they have
        # not, start interactive prompt
        args = manual_options()
    elif len(sys.argv[1:]) == 1:
        # assume that the user is providing the name of an input file
        args = read_control(sys.argv[1])
    else:
        # parse arguments
        options = command_line_options()
        args = options.parse_args()
        if args.control:
            # read simulation parameters from control file
            args = read_control(args.control)
        else:
            pass
            
    # make sure that the atomic simulation code specified by the user is supported
    if args.prog.lower() in supported_codes:
        pass
    else:
        raise ValueError("{} is not a supported atomistic simulation code." +
                         "Supported codes are: GULP; QE; CASTEP.")

    # extract unit cell and GULP run parameters from file <cell_name>
    ab_initio = False   
    if 'gulp' == args.prog.lower():
        unit_cell = cry.Crystal()
        parse_fn = gulp.parse_gulp
    elif 'qe' == args.prog.lower():
        unit_cell = cry.Crystal()
        parse_fn = qe.parse_qe
        ab_initio = True
    elif 'castep' == args.prog.lower():
        unit_cell = castep.CastepCrystal()
        parse_fn = castep.parse_castep
        ab_initio = True
        
    sys_info = parse_fn(args.cell_name, unit_cell)

    # if the calculation uses an ab initio solver, scale the k-point grid
    if ab_initio:
        if 'qe' == args.prog.lower():
            atm.scale_kpoints(sys_info['cards']['K_POINTS'], 
                              np.array([1., 1., args.n]))
            qe.scale_nbands(sys_info['namelists']['&system'], np.array([1., 1., args.n]))
        elif 'castep' == args.prog.lower():
            atm.scale_kpoints(sys_info['mp_kgrid'], np.array([1., 1., args.n]))
    
    # shift origin of cell
    unit_cell.translate_cell(np.array([0., 0., -1*args.shift]), modulo=True)
    
    # select output mode appropriate for the atomistic calculator used, together
    # with the correct suffix for the input files (may be better to let the 
    # output functions determine the suffix?)
    if 'gulp' == args.prog.lower():
        write_fn = gulp.write_gulp
        suffix = 'gin'
        relax = None
    elif 'qe' == args.prog.lower():
        write_fn = qe.write_qe
        suffix = 'in'
        relax = 'relax'
    elif 'castep' == args.prog.lower():
        write_fn = castep.write_castep
        suffix = 'cell'
        relax = None
    
    # make the slab and construct the gamma surface/line
    new_slab = gsf.make_slab(unit_cell, args.n, args.vac, d_fix=args.d_fix, 
                                                 free_atoms=args.free_atoms)
    if args.simulation_type == 'gsurface':
        limits = (args.max_x, args.max_y)          
        gsf.gamma_surface(new_slab, args.res, write_fn, sys_info, suffix=suffix,
                          limits=limits, basename=args.sim_name, vacuum=args.vac,
                                                                    relax=relax)    
        
        # run the calculations, if an executable has been provided. Otherwise,
        # assume that that the input files will be transferred to another machine
        # and run by the user.
        if not (args.progexec is None):
            # extract increments
            N, M = gsf.gs_sampling(new_slab.getLattice(), args.res, limits)
            for n in range(0, N+1):
                for m in range(0, M+1):
                    print("Relaxing cell with generalized stacking fault vector" +
                            " ({}, {})...".format(n, m), end="")
                    basename = '{}.{}.{}'.format(args.sim_name, n, m)
                    if 'gulp' == args.prog.lower():
                        gulp.run_gulp(args.progexec, basename) 
                    elif 'qe' == args.prog.lower():
                        qe.run_qe(args.progexec, basename)
                    elif 'castep' == args.prog.lower():
                        castep.run_castep(args.progexec, basename)
                    
                    print("complete.") 
        else:
            pass
    elif args.simulation_type == 'gline':      
        gsf.gamma_line(new_slab, np.array(args.line_vec), args.res, write_fn,  
                           sys_info, suffix=suffix, limits=args.max_x,  
                           basename=args.sim_name, vacuum=args.vac, relax=relax)
        
        if not (args.progexec is None):
            # extract limits
            N = gsf.gl_sampling(new_slab.getLattice(), resolution=args.res, 
                            vector=np.array(args.line_vec), limits=args.max_x)
            # run calculations
            for n in range(0, N+1):
                print("Relaxing cell {}...".format(n), end="")
                basename = '{}.{}'.format(args.sim_name, n)
                if 'gulp' == args.prog.lower():
                    gulp.run_gulp(args.progexec, basename)
                elif 'qe' == args.prog.lower():
                    qe.run_qe(args.progexec, basename)
                elif 'castep' == args.prog.lower():
                    castep.run_castep(args.progexec, basename)

                print("complete.")
        else:
            pass
    else:
        pass          
Ejemplo n.º 6
0
def iterateOverRI(startRI, finalRI, dRI, baseName, gulpExec, thick, 
                                     use_eregion=True, E_atoms=None):
    '''Decreases the radius of region I from <startRI> to <finalRI> by
    decrementing by dRI (> 0). <baseName> gives the root name for both .grs
    files and the .sysInfo file. <gulpExec> is the path to the GULP 
    executable. If <explicitRegions>, gulp can calculate the total energy of
    the dislocation explicitly (E(RI)+0.5*E(RI-RII)). 
    '''
    
    # if atomic energies have been supplied, record that we are using the 
    # edge method
    if not (E_atoms is None):
        using_edge = True
    else:
        using_edge = False
    
    # open the output file to stream energy data to
    outStream = open(baseName + '.energies', 'w')
    sysInfo = readSystemInfo(baseName)
   
    # get bits for output names
    systemName, RIIval = nameBits(baseName)
    
    # initialise <Basis> objects to hold input regions
    rIPerfect = cry.Basis()
    rIIPerfect = cry.Basis()
    rIDislocated = cry.Basis()
    rIIDislocated = cry.Basis()
    
    # populate the bases for regions I and II of the dislocated cell
    gulp.extractRegions('dis.{}.grs'.format(baseName), rIDislocated, rIIDislocated)
    
    # unless atomic energies have been supplied (in which case the energy will
    # be calculated using those instead of a reference, perfect cluster), read
    # in the associated undislocated cluster.
    if not using_edge:
        gulp.extractRegions('ndf.{}.grs'.format(baseName), rIPerfect, rIIPerfect)

    # ensure that dRI is > 0
    dRI = abs(dRI)
    if (dRI - 0.) < 1e-10:
        print('Error: Decrement interval must be nonzero.')
        sys.exit(1)
    elif startRI < finalRI:
        print('Error: Initial radius is lower than final radius.')
        sys.exit(1)
    elif finalRI <= 0.:
        print('Error: Final radius must be >= 0.')
        sys.exit(1)

    currentRI = startRI
        
    while currentRI >= finalRI:
    
        print('Setting RI = {:.1f}...'.format(currentRI))
        print('Calculating energy', end=' ') 
        
        [newRI, newRII, newRIPerfect, newRIIPerfect] = newRegions(rIPerfect,
                             rIDislocated, rIIPerfect, rIIDislocated, currentRI,
                                                            edge=using_edge)

        derivedName = 'sp.{}.{:.1f}.{}'.format(systemName, currentRI, RIIval)
        
        if using_edge:
            print('using edge.')
            writeSPSections(newRI, newRII, sysInfo, derivedName, True)
            
            # run single-point calculations
            for regionsUsed in ('RI', 'RII', 'BOTH'):
                gulp.run_gulp(gulpExec, '{}.{}'.format(derivedName, regionsUsed))
            
            eDis = dislocation_energy_edge(derivedName, outStream, currentRI, 
                                                        newRI, E_atoms) 
        elif use_eregion: # use GULP's eregion functionality     
            print('using eregion.')              
            writeSinglePoint(newRI, newRII, sysInfo, derivedName+'.dislocated',
                                                                        True)
            writeSinglePoint(newRIPerfect, newRIIPerfect, sysInfo, derivedName 
                                                         + '.perfect', False)
                                                         
            # run single point calculations and extract dislocation energy
            for cellType in ('dislocated', 'perfect'):
                gulp.run_gulp(gulpExec, '{}.{}'.format(derivedName, cellType))
                                                
            eDis = dislocationEnergyEregion(derivedName, outStream, currentRI) 
            
        else: # calculate energy of region I by calculating energies of regions
            print ('using sections.')
            writeSPSections(newRI, newRII, sysInfo, derivedName + '.dislocated',
                                                                        True)
            writeSPSections(newRIPerfect, newRIIPerfect, sysInfo, derivedName 
                                                         + '.perfect', False)
                                                         
            # run single point calculations and extract dislocation energy
            for cellType in ('dislocated', 'perfect'):
                for regionsUsed in ('RI', 'RII', 'BOTH'):
                    gulp.run_gulp(gulpExec, '{}.{}.{}'.format(derivedName, cellType,
                                                            regionsUsed))
                                                          
            eDis = dislocationEnergySections(derivedName, outStream, currentRI) 
         
        # convert <eDis> to energy_units/angstrom and write to output streams
        eDis /= thick    
        print('Energy is {:.6f} eV/ang.'.format(eDis))  
        outStream.write('{} {:.6f}\n'.format(currentRI, eDis))  
                                                         
        currentRI = currentRI - dRI        
        
    return