Ejemplo n.º 1
0
def add_ads(surf, facet, ads, site, fixed_line=True):
    """
    Add ads (string) to surf. Bonding atom is assumed to be the first in the ads string.
    e.g. CO means binding through C, OC means binding through O.
    if fixed_line == True: add fixed_line constraint to binding atom.
    """
    ads_atoms = read('%s/%s.traj' % (ads_prototype_dir, ads))
    bonding_atoms = [
        atom for atom in ads_atoms if atom.symbol == string2symbols(ads)[0]
    ]
    assert len(bonding_atoms) == 1, ""
    bonding_atom = bonding_atoms[0]
    bonding_atom_ind = bonding_atoms[0].index + len(surf)

    #figure out bonding atom position based n facet, site#
    try:  #use ase builtin method if possible
        add_adsorbate(surf, 'X', bond_lengths[site], site)
        bonding_atom_pos = surf[-1].position
        del surf[-1]
    except TypeError:
        #find top layer
        top_z = sorted(set([atom.z for atom in surf]))[-1]
        #find first atom in top layer
        top_atom_inds = [atom.index for atom in surf if atom.z == top_z]
        top_atom = surf[top_atom_inds.pop(np.argmin(
            top_atom_inds))]  #surface atom in top layer w/ lowest index
        top_atom2 = surf[top_atom_inds[np.argmin(
            surf.get_distances(top_atom.index,
                               top_atom_inds))]]  #1st NN to top_atom
        if facet == '211' and site == 'ontop':
            bonding_atom_pos = top_atom.position + np.array(
                [0, 0, bond_lengths[site]])
        elif facet == '211' and site == 'bridge':
            bonding_atom_pos = (top_atom.position +
                                top_atom2.position) / 2. + np.array(
                                    [0, 0, bond_lengths[site]])
        elif facet == '10m10' and site == 'bridge':
            bonding_atom_pos = (top_atom.position +
                                top_atom2.position) / 2. + np.array(
                                    [0, 0, bond_lengths[site]])
        else:
            raise Exception(
                "Cannot add adsorbate to %s-%s (not in ase.build.surface.add_adsorbate or custom definitions)"
                % (facet - site))

    surf += ads_atoms
    delta_vec = bonding_atom_pos - surf[bonding_atom_ind].position
    for i in range(len(surf) - len(ads_atoms), len(surf)):
        surf[i].position += delta_vec

    if fixed_line:
        surf.constraints.append(FixedLine(bonding_atom_ind, [0, 0, 1]))
    return surf
Ejemplo n.º 2
0
def test_siesta_zmat():
    import os
    from ase.calculators.siesta.siesta import Siesta
    from ase.constraints import FixAtoms, FixedLine, FixedPlane
    from ase import Atoms

    pseudo_path = 'pseudos'
    if not os.path.exists(pseudo_path): os.makedirs(pseudo_path)

    # Make dummy pseudopotentials.
    for symbol in 'HCO':
        with open('{0}/{1}.lda.psf'.format(pseudo_path, symbol), 'w') as fd:
            fd.close()

    atoms = Atoms('CO2', [(0.0, 0.0, 0.0), (-1.178, 0.0, 0.0),
                          (1.178, 0.0, 0.0)])

    c1 = FixAtoms(indices=[0])
    c2 = FixedLine(1, [0.0, 1.0, 0.0])
    c3 = FixedPlane(2, [1.0, 0.0, 0.0])

    atoms.set_constraint([c1, c2, c3])

    custom_dir = './dir1/'

    # Test simple fdf-argument case.
    siesta = Siesta(label=custom_dir + 'test_label',
                    symlink_pseudos=False,
                    atomic_coord_format='zmatrix',
                    fdf_arguments={
                        'MD.TypeOfRun': 'CG',
                        'MD.NumCGsteps': 1000
                    })

    atoms.set_calculator(siesta)
    siesta.write_input(atoms, properties=['energy'])

    assert os.path.isfile(os.path.join(custom_dir, 'C.lda.1.psf'))
    assert os.path.isfile(os.path.join(custom_dir, 'O.lda.2.psf'))

    with open(os.path.join(custom_dir, 'test_label.fdf'), 'r') as fd:
        lines = fd.readlines()
    lsl = [line.split() for line in lines]
    assert ['cartesian'] in lsl
    assert ['%block', 'Zmatrix'] in lsl
    assert ['%endblock', 'Zmatrix'] in lsl
    assert ['MD.TypeOfRun', 'CG'] in lsl
    assert any(
        [line.split()[4:9] == ['0', '0', '0', '1', 'C'] for line in lines])
    assert any(
        [line.split()[4:9] == ['0', '1', '0', '2', 'O'] for line in lines])
    assert any(
        [line.split()[4:9] == ['0', '1', '1', '3', 'O'] for line in lines])
Ejemplo n.º 3
0
def test_siesta_zmat(siesta_factory):
    atoms = Atoms('CO2', [(0.0, 0.0, 0.0), (-1.178, 0.0, 0.0),
                          (1.178, 0.0, 0.0)])

    c1 = FixAtoms(indices=[0])
    c2 = FixedLine(1, [0.0, 1.0, 0.0])
    c3 = FixedPlane(2, [1.0, 0.0, 0.0])

    atoms.set_constraint([c1, c2, c3])

    custom_dir = './dir1/'

    # Test simple fdf-argument case.
    siesta = siesta_factory.calc(label=custom_dir + 'test_label',
                                 symlink_pseudos=False,
                                 atomic_coord_format='zmatrix',
                                 fdf_arguments={
                                     'MD.TypeOfRun': 'CG',
                                     'MD.NumCGsteps': 1000
                                 })

    atoms.calc = siesta
    siesta.write_input(atoms, properties=['energy'])

    with open(os.path.join(custom_dir, 'test_label.fdf'), 'r') as fd:
        lines = fd.readlines()
    lsl = [line.split() for line in lines]
    assert ['cartesian'] in lsl
    assert ['%block', 'Zmatrix'] in lsl
    assert ['%endblock', 'Zmatrix'] in lsl
    assert ['MD.TypeOfRun', 'CG'] in lsl
    assert any(
        [line.split()[4:9] == ['0', '0', '0', '1', 'C'] for line in lines])
    assert any(
        [line.split()[4:9] == ['0', '1', '0', '2', 'O'] for line in lines])
    assert any(
        [line.split()[4:9] == ['0', '1', '1', '3', 'O'] for line in lines])
Ejemplo n.º 4
0
atoms = bulk('NaCl', crystalstructure='rocksalt', a=5) * (2, 1, 1)
atoms.set_initial_magnetic_moments([1.1] * len(atoms))
l = SPARC(atoms=atoms,
          h=0.1,
          label='in1',
          xc='GGA',
          spin_typ=1,
          pseudo_dir='.')
l.write_input(atoms=atoms, h=0.1, spin_typ=1, pseudo_dir='.', SPIN_TYP=1)

print('input writing functional')
# check reading and writing .ion files
atoms.set_constraint(
    [FixAtoms([0]),
     FixedLine(1, [0, 1, 0]),
     FixedPlane(2, [1, 0, 0])])
write_ion(open('in1.ion', 'w'), atoms, pseudo_dir='.')
recovered_atoms = read_ion(open('in1.ion', 'r'))
assert compare_atoms(atoms, recovered_atoms) == []

calc = SPARC(atoms=atoms, pseudo_dir='.', SPIN_TYP=1)
try:  # check that `h` is required
    calc.write_input()
    raise Exception('test failed')
except CalculatorSetupError:
    pass

print('.ion reading test passed')

calc = SPARC.read('read_input')
Ejemplo n.º 5
0
#mpirun = spawn.find_executable('mpirun')
#vasp = spawn.find_executable('vasp')
#vasp = '/home/eng/essswb/vasp5/vasp.5.3.new/vasp'
mpirun = '/usr/bin/cobalt-mpirun'
vasp = '/projects/SiO2_Fracture/iron/vasp.bgq'
npj = 512  # nodes per job
ppn = 4
njobs = 1
nodes = npj * njobs

job_xyz = glob.glob('feb*.xyz')[0]
bulk = Atoms(job_xyz)

line = []
for at in bulk:
    line.append(FixedLine(at.index, (0, 0, 1)))
bulk.set_constraint(line)

hostname, ip = get_hostname_ip()
partsize, partition, job_name = get_cobalt_info()
blocks = get_bootable_blocks(partition, nodes)
print('Available blocks: %s' % blocks)
boot_blocks(blocks)

block, corner, shape = list(block_corner_iter(blocks, npj))[0]
print block, corner, shape

vasp_client = VaspClient(client_id=0,
                         kpts=[16, 16, 1],
                         amix=0.01,
                         amin=0.001,
Ejemplo n.º 6
0
def shearDyn(width, edge, save = False):
    
    ratio   =   8
    atoms   =   create_stucture(ratio, width, edge, key = 'top')
    
    
    # FIXES
    constraints     =   []
    top, bot        =   get_topInds(atoms)
    rend            =   get_rightInds(atoms, top)
    fix_bot         =   FixAtoms(indices = bot)
    
    view(atoms)
    constraints.append(fix_bot)
    for i in rend:
        constraints.append(FixedLine(i, (1,0,0)))
    
    # KC
    params          =   get_params(atoms)
    params['top_inds']  \
                    =   top
    add_kc          =   KC_potential_p(params)
    constraints.append(add_kc)
    # END FIXES
    
    
    
    # CALCULATOR LAMMPS 
    parameters = {'pair_style':'rebo',
                  'pair_coeff':['* * CH.airebo C H'],
                  'mass'      :['1 12.0', '2 1.0'],
                  'units'     :'metal', 
                  'boundary'  :'p p f'}
    
    calc    =   LAMMPS(parameters=parameters) 
    atoms.set_calculator(calc)
    # END CALCULATOR
    
    
    # TRAJECTORY
    mdfile, mdlogfile, mdrelax  =   get_fileName(edge, width, ratio, v, taito = False)
    
    if save:    traj    =   PickleTrajectory(mdfile, 'w', atoms)
    else:       traj    =   None
    
    #data    =   np.zeros((M/interval, 5))
    
    # RELAX
    atoms.set_constraint(add_kc)
    dyn     =   BFGS(atoms, trajectory = mdrelax)
    dyn.run(fmax=0.05)
    
    # FIX AFTER RELAXATION
    atoms.set_constraint(constraints)
    
    # DYNAMICS
    dyn     =   Langevin(atoms, dt*units.fs, T*units.kB, fric)
    n       =   0
    header  =   '#t [fs], d [Angstrom], epot_tot [eV], ekin_tot [eV], etot_tot [eV] \n'
    log_f   =   open(mdlogfile, 'w')
    log_f.write(header)            
    log_f.close()

    if T != 0:
        # put initial MaxwellBoltzmann velocity distribution
        mbd(atoms, T*units.kB)
    
    
    for i in range(0, M):
        
        if tau < i*dt:
            hw   =   i*dy
            for ind in rend:
                atoms[ind].position[1] += dy 
        
        dyn.run(1)
        
        if i%interval == 0:

            epot, ekin  =   saveAndPrint(atoms, traj, False)[:2]
            
            if T != 0:
                if tau < i*dt:  hw   =   i*dy - tau*v
                else: hw =   0
            else:   hw = i*dy
                
            data        =   [i*dt, hw, epot, ekin, epot + ekin]
            
            if save:
                log_f   =   open(mdlogfile, 'a')
                stringi =   ''
                for k,d in enumerate(data):
                    if k == 0:           
                        stringi += '%.2f ' %d
                    elif k == 1:
                        stringi += '%.6f ' %d
                    else:
                        stringi += '%.12f ' %d
                
                log_f.write(stringi +  '\n')
                log_f.close()
                  

            n += 1
        
        
        if save and T != 0 and i*dt == tau:
            log_f   =   open(mdlogfile, 'a')
            log_f.write('# Thermalization complete. ' +  '\n')
            log_f.close()
            
            
        if 1e2 <= M:    
            if i%(int(M/100)) == 0: print 'ready = %.1f' %(i/(int(M/100))) + '%' 
Ejemplo n.º 7
0
def delete_single_atom_with_constraint(atoms=None, indice_to_delete=None):
    if indice_to_delete is None:
        return # nothing to delete
    elif indice_to_delete > len(atoms)-1:
        raise RuntimeError("try too remove too many atoms?")

    # I have to teach each fix objects individually, how can I make it smarter?
    hookean_pairs = []
    fix_atoms_indices = []
    fix_bondlengths_indices = None
    never_delete_indices = []
    fix_lines_indices = []
    for c in atoms.constraints:
        if isinstance(c, FixAtoms):
            fix_atoms_indices.append(c.get_indices())
        elif isinstance(c, Hookean):
            hookean_pairs.append([c.get_indices(), c.threshold, c.spring])
        elif isinstance(c, FixBondLengths):
            if fix_bondlengths_indices is not None:
                raise RuntimeError("Do you have more than one FixBondLengths?")
            fix_bondlengths_indices = c.pairs.copy()
        elif isinstance(c, NeverDelete):
            for ind in c.get_indices():
                never_delete_indices.append(ind)
        elif isinstance(c, FixedLine):
            fix_lines_indices.append([c.a, c.dir])
        else:
            try:
                cn = c.__class__.__name__
            except AttributeError:
                cn = "Unknown"
            raise RuntimeError("constraint type %s is not supported" % cn)

    new_constraints = []
    for old_inds in fix_atoms_indices:
        new_inds = []
        for ind in old_inds:
            if ind < indice_to_delete:
                new_inds.append(ind)
            elif ind > indice_to_delete:
                new_inds.append(ind - 1)
            else:
                continue
        if len(new_inds) > 0:
            new_constraints.append(FixAtoms(indices=new_inds))
    for old_inds, rt, k in hookean_pairs:
        if indice_to_delete in old_inds:
            continue
        new_inds = []
        for ind in old_inds:
            if ind < indice_to_delete:
                new_inds.append(ind)
            else:
                new_inds.append(ind-1)
        new_constraints.append(Hookean(a1=new_inds[0], a2=new_inds[1], rt=rt, k=k))
    for ind, direction in fix_lines_indices:
        if ind == indice_to_delete:
            continue
        elif ind < indice_to_delete:
            new_constraints.append(FixedLine(ind, direction=direction))
        else:
            new_constraints.append(FixedLine(ind-1,direction=direction))

    if fix_bondlengths_indices is not None:
        number_of_cons, ncols = fix_bondlengths_indices.shape
        assert ncols == 2
        new_inds = []
        for ic in range(number_of_cons):
            ind1, ind2 = fix_bondlengths_indices[ic][0], fix_bondlengths_indices[ic][1]
            if ind1 == indice_to_delete or ind2 == indice_to_delete:
                continue
            else:
                pairs = []
                if ind1 < indice_to_delete:
                    pairs.append(ind1)
                else:
                    pairs.append(ind1-1)
                if ind2 < indice_to_delete:
                    pairs.append(ind2)
                else:
                    pairs.append(ind2-1)
                new_inds.append(pairs)
        if len(new_inds) > 0:
            new_constraints.append(FixBondLengths(pairs=new_inds))
    if len(never_delete_indices) > 0:
        new_inds = []
        for ind in never_delete_indices:
            if ind < indice_to_delete:
                new_inds.append(ind)
            elif ind > indice_to_delete:
                new_inds.append(ind - 1)
        if len(new_inds) > 0:
            new_constraints.append(NeverDelete(indices=new_inds))

    # remove all the constraints
    atoms.set_constraint()
    del atoms[indice_to_delete]

    # add back the constraints
    atoms.set_constraint(new_constraints)
    return
Ejemplo n.º 8
0
from ase.calculators.siesta.siesta import Siesta
from ase.constraints import FixAtoms, FixedLine, FixedPlane
from ase import Atoms

pseudo_path = 'pseudos'
if not os.path.exists(pseudo_path): os.makedirs(pseudo_path)

# Make dummy pseudopotentials.
for symbol in 'HCO':
    with open('{0}/{1}.lda.psf'.format(pseudo_path, symbol), 'w') as fd:
        fd.close()

atoms = Atoms('CO2', [(0.0, 0.0, 0.0), (-1.178, 0.0, 0.0), (1.178, 0.0, 0.0)])

c1 = FixAtoms(indices=[0])
c2 = FixedLine(1, [0.0, 1.0, 0.0])
c3 = FixedPlane(2, [1.0, 0.0, 0.0])

atoms.set_constraint([c1, c2, c3])

custom_dir = './dir1/'

# Test simple fdf-argument case.
siesta = Siesta(label=custom_dir + 'test_label',
                symlink_pseudos=False,
                atomic_coord_format='zmatrix',
                fdf_arguments={
                    'MD.TypeOfRun': 'CG',
                    'MD.NumCGsteps': 1000
                })
Ejemplo n.º 9
0
def constrained_minim(atoms,
                      method='LBFGS',
                      vacuum=20.0,
                      k_spring=0.6,
                      clamp_mask=None,
                      initial_positions=None,
                      fmax=0.05,
                      spring='point'):
    c = np.ptp(atoms.positions, axis=0)
    c += vacuum
    atoms.set_cell(np.diag(c))

    if clamp_mask is None:
        at_help = Atoms('crack.xyz')
        clamp_mask = at_help.get_array('clamp_mask')
    if initial_positions is None:
        at_help = Atoms('crack.xyz')
        at_help.get_array('pos_orig')

    if spring == 'plane':
        springs = [
            Hookean(a1=i,
                    a2=[0, -1, 0, initial_positions[i, 1]],
                    k=k_spring,
                    rt=0) for i in np.where(clamp_mask)[0]
        ]
    else:
        springs = [
            Hookean(a1=i, a2=initial_positions[i], k=k_spring, rt=0)
            for i in np.where(clamp_mask)[0]
        ]

    from quippy.io import AtomsWriter
    out = AtomsWriter("traj-relax_structure.xyz")
    trajectory_write = lambda: out.write(atoms)

    if method == "LBFGS":
        pot = atoms.calc
        cc = ConstraintCalculator(springs)
        sc = SumCalculator(pot, cc)

        left, bottom, _ = initial_positions.min(axis=0)
        fix_line_mask = (initial_positions[:, 0] < left + 6.5)
        fix_line = FixAtoms(mask=fix_line_mask)
        atoms.set_array('fix_line_mask', fix_line_mask)
        atoms.set_constraint(fix_line)
        atoms.set_calculator(sc)
        opt = LBFGS(atoms, use_armijo=False)

    elif method == "FIRE":
        right, top, _ = initial_positions.max(axis=0)
        left, bottom, _ = initial_positions.min(axis=0)
        fix_line_mask = np.logical_or(initial_positions[:, 0] > right - 6.5,
                                      initial_positions[:, 0] < left + 6.5)
        fix_line_idx = np.where(fix_line_mask)[0]
        fix_line = [FixedLine(i, np.array([0, 1, 0])) for i in fix_line_idx]
        atoms.set_array('fix_line_mask', fix_line_mask)

        atoms.set_constraint(fix_line + springs)

        opt = FIRE(atoms, dtmax=2.5, maxmove=0.5)

    elif method == "mix":
        # do a first opt by keeping vertical edges fixed, then make them move along y
        right, top, _ = initial_positions.max(axis=0)
        left, bottom, _ = initial_positions.min(axis=0)
        fix_line_mask = np.logical_or(initial_positions[:, 0] > right - 6.5,
                                      initial_positions[:, 0] < left + 6.5)
        fix_line_idx = np.where(fix_line_mask)[0]

        pot = atoms.calc
        cc = ConstraintCalculator(springs)
        sc = SumCalculator(pot, cc)

        atoms.set_constraint(FixAtoms(mask=fix_line_mask))
        atoms.set_calculator(sc)
        LBFGS(atoms, use_armijo=False).run(fmax=0.2)

        fix_line = [FixedLine(i, np.array([0, 1, 0])) for i in fix_line_idx]
        atoms.set_array('fix_line_mask', fix_line_mask)

        atoms.set_constraint(fix_line + springs)
        atoms.set_calculator(pot)
        opt = vanillaLBFGS(atoms)

    else:
        print("Method not understood")
        return

    opt.attach(trajectory_write, interval=5)
    opt.run(fmax=fmax)
    return
# print('==> natoms = {0}'.format(natoms))

ASE_Atoms.set_cell(ASE_Atoms.cell[:] / a0)
ASE_Atoms.set_positions(atoms_pos / a0,
                        apply_constraint=False)  # fuking important!

if len(sys.argv) == 1:
    filename2 = 'POSCAR_Cartesian'

elif len(sys.argv) == 2:
    if sys.argv[1] == '-FFT':
        filename2 = 'POSCAR_Cartesian_FFT'
        constrained_atoms = np.arange(natoms)  # apply constraint to all atoms
        relax_direction = ASE_Atoms.cell[
            2, :]  # relax only in the a3 direction
        constraint_a3only = FixedLine(constrained_atoms, relax_direction)
        ASE_Atoms.set_constraint(constraint_a3only)

write_vasp(filename2, ASE_Atoms, label='system_name', direct=False)

with open(filename2) as f:
    lines = f.readlines()

lines[1] = ' %.16f \n' % (a0)

with open('file_temp', "w") as f:
    f.writelines(lines)

os.replace('file_temp', filename2)

# check
Ejemplo n.º 11
0
vasp_args = dict(xc='PBE', amix=0.22, amin=0.02, bmix=0.6, amix_mag=1.0, bmix_mag=0.9, lorbit=11,
                 kpts=[1, 6, 6], kpar=args.kpar, lreal='auto', nelmdl=-15, ispin=2, prec='Accurate', ediff=1.e-4,
                 encut=420, nelm=100, algo='VeryFast', lplane=False, lwave=False, lcharg=False, istart=0,
                 magmom=magmoms, maxmix=25, #https://www.vasp.at/vasp-workshop/slides/handsonIV.pdf #for badly behaved clusters.
                 voskown=0, ismear=1, sigma=0.1, isym=2, iwavpr=11) 

mpirun = spawn.find_executable('mpirun')
vasp = '/home/mmm0007/vasp/vasp.5.4.1/bin/vasp_std'

vasp_client = VaspClient(client_id=0, npj=96, ppn=1,
                         exe=vasp, mpirun=mpirun, parmode='mpi',
                         ibrion=13, nsw=1000000,
                         npar=6, **vasp_args)

traj = io.Trajectory('relaxation.traj','a', gam_cell)

qm_pot = SocketCalculator(vasp_client)
gam_cell.set_calculator(qm_pot)

fixed_line=[]
for at in gam_cell:
    fixed_line.append(FixedLine(at.index, (1,0,0)))
gam_cell.set_constraint(fixed_line)
opt = PreconLBFGS(Atoms(gam_cell))
#opt.attach(traj_writer, interval=1)
opt.attach(traj.write, interval=1)
opt.run(fmax=0.01)
traj.close()

Ejemplo n.º 12
0
def test_pot():
    
    edge    =   'ac'
    width   =   5
    ratio   =   1
    bond    =   1.39695
    acc     =   100
    
    # Initial atoms graphite:
    #atoms_init              =   make_graphene_slab(a,h,width,length,N, (True, True, False))[3]
    atoms_init                  =   create_stucture(ratio, width, edge, key = 'top', a = bond)[0]

    _, _, _, rend_b, _ =   \
                get_constraints(atoms_init, edge, bond, None, \
                            key = 'twist_p', pot = 'KC')
    trans   =   trans_atomsKC(atoms_init.positions[rend_b], edge, bond)
    atoms_init.translate(trans) 
    
    plot_posits(atoms_init, edge, bond)
    
    natoms  =   0
    for atom in atoms_init:
        if atom.number == 6:
            natoms   +=  1
    
    
    view(atoms_init)
    params  =   {}
    params['positions']         =   atoms_init.positions
    params['chemical_symbols']  =   atoms_init.get_chemical_symbols()   
    params['ia_dist']           =   10
    params['edge']              =   edge
    params['bond']              =   bond    
    params['ncores']            =   2
    
    
    # This controls how far the upper layer is pulled:
    hmax                        =   5
    
    # FIX
    # Certain fixes are imposed. Note the KC and LJ - potential are as constraints
    # added to the atom system. The bottom layer is held fixed:
    
    constraints =   []
    for i in range(len(atoms_init)):
        fix_l   =   FixedLine(i, [0., 0., 1.])
        constraints.append(fix_l)
    
    # The constraints for LJ nad KC - potentials:
    add_KC_p        =   KC_potential_p(params)
    add_LJ          =   LJ_potential_smooth(atoms_init, params['bond'])
    
    
    # Different constraint sets for different calculations:
    constraint_KC_p =   [constraints, add_KC_p]
    constraint_LJ   =   [constraints, add_LJ]
    # END FIX
    
    
    # DEF CALC AND RELAX
    # Define proper calculator rebo when LJ or KC and airebe else:
    # Note! The potential files (CH.airebo etc.) have to be set as Enviromental variables
    # in order for lammps to find them!
    params_rebo         =   {'pair_style':'rebo',
                             'pair_coeff':['* * CH.airebo C H'],
                             'mass'      :['1 12.0', '2 1.0'],
                             'units'     :'metal', 
                             'boundary'  :'f f f'}   
   

    
    constraint_param_sets   = [['rebo_KC_p', constraint_KC_p, params_rebo],
                               ['rebo_LJ', constraint_LJ, params_rebo]] 
    
    data_adh    =   {}
    data_corr   =   {}
    
    indents     =   []
    
    for const_params in constraint_param_sets: 
        
        # Name for the method:
        indent          =   const_params[0]
        indents.append(indent)
        print indent
        
        if indent != 'LJ':
            constraints =   const_params[1]
            parameters  =   const_params[2]
        
            atoms       =   atoms_init.copy()
            init_posits =   atoms.positions.copy()
            
            # Caculator:
            calc        =   LAMMPS(parameters=parameters) #, files=['lammps.data'])
            atoms.set_calculator(calc)
            atoms.set_constraint(constraints)
            

            # SLAB IS RELAXED
            #
            
            print 'Adhesion'
            
            adh                 =   get_adhesion_energy(atoms, hmax, acc, natoms)
            adh[:,1]            =   adh[:,1] - np.min(adh[:,1])
            data_adh[indent]    =   adh - np.min(adh)   
            
            print 'run_moldy'
            atoms.positions     =   init_posits
            
            print 'Corrugation'
            
            data_corr[indent]   =   get_corrugation_energy(atoms, bond, natoms, edge, acc)
            
            '''
            atoms.positions     =   init_posits
            
            data_corr_s[indent] =   get_corrugation_energy_surf(atoms, constraints, \
                                                           bond, bottom, top, indent, acc)
            '''
        #else:
        #    data_adh['LJ']      =   get_adhesion_LJ(data_adh['rebo_KC'][:,0], CperArea) 
    
    #PLOT and save
    
    CperArea    =   4. / (3 * np.sqrt(3) * bond**2)
    ecc         =   0.002843732471143
    sigmacc     =   3.4
    zset        =   np.linspace(3, 10, 100)
    LJ          =   lambda z: 2./5*np.pi*CperArea*ecc*(2*(sigmacc**6/z**5)**2 - 5*(sigmacc**3/z**2)**2)
    LJset       =   LJ(zset) - np.min(LJ(zset))
     
    plt.plot(data_adh['rebo_KC_p'][:,0], data_adh['rebo_KC_p'][:,1])
    plt.plot(data_adh['rebo_LJ'][:,0], data_adh['rebo_LJ'][:,1])
    plt.plot(zset, LJset)
    
    plt.show() 

    plt.plot(data_corr['rebo_KC_p'][:,0], data_corr['rebo_KC_p'][:,2])
    plt.plot(data_corr['rebo_LJ'][:,0], data_corr['rebo_LJ'][:,2])
    
    plt.show() 

#test_pot()
Ejemplo n.º 13
0
at_order = np.argsort(dists)[:120]

# ***** Setup constraints *****
# springs = [Hookean(a1=i, a2=[0,-1,0,initial_positions[i,1]], k=k_spring, rt=0) for i in np.where(clamp_mask)[0]]
springs = [
    Hookean(a1=i, a2=initial_positions[i], k=params.k_spring, rt=0)
    for i in np.where(clamp_mask)[0]
]

from ase.constraints import FixedLine
left = initial_positions[:, 0].min()
right = initial_positions[:, 0].max()
fix_line_mask = np.logical_or(initial_positions[:, 0] > right - 5.,
                              initial_positions[:, 0] < left + 5.)
fix_line_idx = np.where(fix_line_mask)[0]
fix_line = [FixedLine(i, np.array([0, 1, 0])) for i in fix_line_idx]

# apply constraints
at.set_constraint(springs + fix_line)

# general cleanup of Atoms object
for k in at.arrays.keys():
    if k not in ['species', 'positions', 'momenta', 'numbers']:
        at.set_array(k, None)
for k in at.info.keys():
    if k not in ['energy', 'strain']:
        del at.info[k]

# ***** Setup and run MD *****

# Initialise the dynamical system
Ejemplo n.º 14
0
def gamma_surf(h_pos=np.array([1.41, 1.500, 22.48])):
    """
    :method:`gamma_surf` generates a set of directories with the upper
    half unit cell displaced along a certain distance
    along a particular lattice vector. Hydrogens can be added by
    setting vector in h_pos.

    TODO:
      h_pos should be a list of vectors and atom type for this to be more general.
    """

    vasp_exe = '/projects/SiO2_Fracture/iron/vasp.bgq'
    crack_geom = {
        'cleavage_plane': (1, 1, 0),
        'crack_front': (1, -1, 0),
        'crack_direction': (0, 0, 1)
    }

    crack_direction = crack_geom['crack_direction']
    crack_front = crack_geom['crack_front']
    cleavage_plane = crack_geom['cleavage_plane']
    fe_unit = BodyCenteredCubic(
        directions=[crack_direction, crack_front, cleavage_plane],
        size=(1, 1, 1),
        symbol='Fe',
        pbc=(1, 1, 1),
        latticeconstant=2.83)
    nunits = 8
    fe_bulk = BodyCenteredCubic(
        directions=[crack_direction, crack_front, cleavage_plane],
        size=(2, 2, nunits),
        symbol='Fe',
        pbc=(1, 1, 1),
        latticeconstant=2.83)
    fe_unit = Atoms(fe_unit)
    fe_bulk = Atoms(fe_bulk)

    ycut = 5.0 + float(nunits) / 2.0 * fe_unit.lattice[2, 2]
    fe_bulk.center(vacuum=5.0, axis=2)
    print 'lattice', fe_bulk.lattice[1, 1]
    print 'ycut', ycut

    a1 = fe_unit.lattice[0, 0]
    a2 = fe_unit.lattice[1, 1]

    POT_DIR = os.environ['POTDIR']
    eam_pot = os.path.join(POT_DIR, 'PotBH.xml')
    r_scale = 1.00894848312
    #eam_pot = os.path.join(POT_DIR, 'iron_mish.xml')
    #r_scale = 1.0129007626
    pot = Potential(
        'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale),
        param_filename=eam_pot)
    fe_bulk.set_calculator(pot)
    print 'Bulk Energy', fe_bulk.get_potential_energy()
    refen = fe_bulk.get_potential_energy()
    A = fe_bulk.get_volume() / fe_bulk.lattice[2, 2]

    vasp_args = dict(
        xc='PBE',
        amix=0.01,
        amin=0.001,
        bmix=0.001,
        amix_mag=0.01,
        bmix_mag=0.001,
        kpts=[8, 8, 1],
        kpar=32,
        lreal='auto',
        ibrion=2,
        nsw=40,
        nelmdl=-15,
        ispin=2,
        nelm=100,
        algo='VeryFast',
        npar=8,
        lplane=False,
        lwave=False,
        lcharg=False,
        istart=0,
        voskown=1,
        ismear=1,
        sigma=0.1,
        isym=2)  # possibly try iwavpr=12, should be faster if it works

    dir_name = 'b111shiftsym'
    #dir_name  = 'b001shiftsym'
    f = open('_patdon123{0}H1.dat'.format(dir_name), 'w')
    WRITEVASP = True
    a0 = 2.83
    for inum, ashift in enumerate(np.arange(0, 1.10, 0.10)):
        try:
            os.mkdir('{0}{1}'.format(dir_name, ashift))
        except:
            pass
        print 'Directory already exists'

        os.chdir('{0}{1}'.format(dir_name, ashift))
        fe_shift = fe_bulk.copy()
        fe_shift.set_calculator(pot)
        for at in fe_shift:
            if at.position[2] > ycut:
                #[00-1](110)
                #  at.position += ashift*np.array([-a1,0,0])
                #[1-11](110)
                at.position += 0.5 * ashift * np.array([a1, a2, 0])
    #  print >> fil1, ashift, (units.m**2/units.J)*(fe_shift.get_potential_energy()-refen)/A
        line = []
        for at in fe_shift:
            line.append(FixedLine(at.index, (0, 0, 1)))
    #Now add Hydrogen
    # fe_shift.add_atoms(np.array([0.53*a0, 0.53*a0, 21.0+a0/2]),1)
    # at relaxed position:
        fe_shift.add_atoms(h_pos, 1)
        fix_atoms_mask = [at.number == 1 for at in fe_shift]
        fixedatoms = FixAtoms(mask=fix_atoms_mask)
        fe_shift.set_constraint(line + [fixedatoms])
        opt = LBFGS(fe_shift)
        opt.run(fmax=0.1, steps=1000)
        if inum == 0:
            print 'Setting Reference Energy'
            refen = fe_shift.get_potential_energy()
        print >> f, ashift, (units.m**2 / units.J) * (
            fe_shift.get_potential_energy() - refen) / A
        fe_shift.write('feb{0}.xyz'.format(ashift))
        if WRITEVASP:
            vasp = Vasp(**vasp_args)
            vasp.initialize(fe_shift)
            write_vasp('POSCAR',
                       vasp.atoms_sorted,
                       symbol_count=vasp.symbol_count,
                       vasp5=True)
            vasp.write_incar(fe_shift)
            vasp.write_potcar()
            vasp.write_kpoints()
        os.chdir('../')
    f.close()
Ejemplo n.º 15
0
    def add_displacement_energy(self, displacement):
        """Add the groundstate energy for a displacements along the
        translational path, and adds it to an_mode['displacement_energies'].

        Args:
            displacement (float): How much to follow translational path.
        """

        # Will otherwise do a groundstate calculation at initial positions
        if displacement:
            if displacement != self.an_mode['transition_path_length']:
                self.atoms.set_positions(
                    self.get_translation_positions(displacement))

                # Do 1D optimization
                fix_environment = FixAtoms(mask=[
                    i not in self.an_mode['indices']
                    for i in range(len(self.atoms))
                ])

                axis_relax = self.an_mode.get('relax_axis')
                if axis_relax:
                    if self.use_forces:
                        warnings.warn(' '.join([
                            "relax along axis and force_consistent",
                            "should only be used with ase releases after",
                            "Jan 2017. See",
                            "https://gitlab.com/ase/ase/merge_requests/354"
                        ]))
                    c = []
                    for i in self.an_mode['indices']:
                        c.append(FixedLine(i, axis_relax))
                    # Fixing everything that is not the vibrating part
                    c.append(fix_environment)
                    self.atoms.set_constraint(c)

                    # Optimization
                    dyn = QuasiNewton(self.atoms, logfile='/dev/null')
                    dyn.run(fmax=self.settings.get('fmax', 0.05))

                    self.atoms.set_constraint(fix_environment)

        if not self.an_mode.get('displacement_energies'):
            self.an_mode['displacement_energies'] = list()

        if self.use_forces:
            e = self.atoms.get_potential_energy(force_consistent=True)

            # For the forces, we need the projection of the forces
            # on the normal mode of the rotation at the current angle
            v_force = self.atoms.get_forces()[self.an_mode['indices']].reshape(
                -1)

            f = float(np.dot(v_force, self.an_mode['mode_tangent']))

            if not self.an_mode.get('displacement_forces'):
                self.an_mode['displacement_forces'] = [f]
            else:
                self.an_mode['displacement_forces'].append(f)
        else:
            e = self.atoms.get_potential_energy()

        if self.traj is not None:
            self.traj.write(self.atoms)

        self.an_mode['displacement_energies'].append(e)

        # adding to trajectory:
        if self.traj is not None:
            self.traj.write(self.atoms)

        self.atoms.set_positions(self.groundstate_positions)

        # save to backup file:
        if self.an_filename:
            self.save_to_backup()
Ejemplo n.º 16
0
def corr_KC(width, edge):
    #width   =   5
    #edge    =   'ac'
    params0 = get_simulParams(edge)[-1]
    bond = params0['bond']

    atoms = create_stucture(1, width, edge, key='top', a=bond)[0]

    atoms.set_cell([40, 40, 20])
    atoms.center()
    atoms.positions[:, 2] = 3.4

    h_t = []
    for i in range(len(atoms)):
        if atoms[i].number == 1:
            h_t.append(i)

    del atoms[h_t]

    params = {}
    params['positions'] = atoms.positions
    params['chemical_symbols'] = atoms.get_chemical_symbols()
    params['ia_dist'] = 10
    params['edge'] = edge
    params['bond'] = bond
    params['ncores'] = 2
    add_KC = KC_potential_p(params)

    constraints = []
    for i in range(len(atoms)):
        fix_l = FixedLine(i, [0., 0., 1.])
        constraints.append(fix_l)

    constraints.append(add_KC)

    lamp_parameters = get_lammps_params(H=False)
    calc = LAMMPS(parameters=lamp_parameters)  #, files=['lammps.data'])
    atoms.set_calculator(calc)
    atoms.set_constraint(constraints)

    #dyn     =   BFGS(atoms, trajectory = 'test.traj')
    #dyn.run(fmax=0.05)

    trans_vec = trans_atomsKC(atoms.positions[0], edge, bond)
    atoms.translate(trans_vec)

    init_pos = atoms.positions.copy()
    middle = [
        np.average(init_pos[:, 0]),
        np.average(init_pos[:, 1]),
        np.average(init_pos[:, 2])
    ]

    thetas = np.linspace(np.pi / 2, np.pi, 91)
    L = 4 * bond
    ds = .05
    n = int(L / ds)

    for i, theta in enumerate(thetas):
        fname = path + 'corr_w=%02d_%s_theta=%.2f.data' % (width, edge, theta /
                                                           (2 * np.pi) * 360)
        if not os.path.isfile(fname):
            print 'Calculating w=%i, theta = %.2f' % (width, theta /
                                                      (2 * np.pi) * 360)

            atoms.positions = init_pos
            atoms.rotate([0, 0, 1], theta, center=middle)
            trans_vec = np.array([-np.sin(theta), np.cos(theta), 0])
            data = np.zeros((n, 3))

            for j in range(n):
                atoms.translate(ds * trans_vec)
                emin, hmin = get_optimal_h(atoms, len(atoms), dyn=False)
                data[j, :] = [j * ds, emin, hmin]
                #plot_posits(atoms, edge, bond)

            header = '%s runs along x-dir, angle measured from x-axis, natoms = %i. x (Angs), e (eV/atom), hmin' % (
                edge, len(atoms))
            np.savetxt(fname, data, header=header)
Ejemplo n.º 17
0
def corr_KC(width, edge):

    params0 = get_simulParams(edge)[-1]
    bond = params0['bond']
    '''
    atoms   =   graphene_nanoribbon(1, 1, type= 'armchair', C_C=bond, saturated = False)
    atoms.rotate([1,0,0], np.pi/2, rotate_cell = True)
    atoms.rotate([0,0,1], -np.pi/2, rotate_cell = True)
    atoms.set_cell([20, 20, 10])
    atoms.center()
    del atoms[[2,3]]
    '''
    atoms = create_stucture(2, width, edge, key='top', a=bond)[0]

    atoms.set_cell([70, 70, 20])
    atoms.center()
    atoms.positions[:, 2] = 3.4

    h_t = []
    for i in range(len(atoms)):
        if atoms[i].number == 1:
            h_t.append(i)

    del atoms[h_t]

    #view(atoms)
    params = {}
    params['positions'] = atoms.positions
    params['chemical_symbols'] = atoms.get_chemical_symbols()
    params['ia_dist'] = 10
    params['edge'] = edge
    params['bond'] = bond
    params['ncores'] = 2
    params['no_edge_neigh'] = True
    add_KC = KC_potential_p(params)

    constraints = []
    for i in range(len(atoms)):
        fix_l = FixedLine(i, [0., 0., 1.])
        constraints.append(fix_l)

    constraints.append(add_KC)

    lamp_parameters = get_lammps_params(H=False)
    calc = LAMMPS(parameters=lamp_parameters)  #, files=['lammps.data'])
    atoms.set_calculator(calc)
    atoms.set_constraint(constraints)

    #dyn     =   BFGS(atoms, trajectory = 'test.traj')
    #dyn.run(fmax=0.05)

    #plot_posits(atoms, edge, bond)

    trans_vec = trans_atomsKC(atoms.positions[0], edge, bond)
    atoms.translate(trans_vec)

    #plot_posits(atoms, edge, bond)
    #exit()
    init_pos = atoms.positions.copy()
    r_around = init_pos[1]

    thetas = np.linspace(0, np.pi / 3, 61)
    n = 15

    lat_vec1 = np.array([3. / 2 * bond, np.sqrt(3) / 2 * bond, 0.])
    lat_vec2 = np.array([3. / 2 * bond, -np.sqrt(3) / 2 * bond, 0.])

    for i, theta in enumerate(thetas):
        fname = path + 'corr_%s_theta=%.2f.data' % (edge, theta /
                                                    (2 * np.pi) * 360)
        #if not os.path.isfile(fname):
        print 'Calculating theta = %.2f' % (theta / (2 * np.pi) * 360)
        atoms.positions = init_pos
        atoms.rotate([0, 0, 1], theta, center=r_around)

        R = np.array([[np.cos(theta), -np.sin(theta), 0.],
                      [np.sin(theta), np.cos(theta), 0.], [0., 0., 1.]])

        lat_vec_theta1 = np.dot(R, lat_vec1.copy())
        lat_vec_theta2 = np.dot(R, lat_vec2.copy())

        #trans_vec1      =   lat_vec_theta1.copy()/n
        trans_vec2 = lat_vec_theta2.copy() / n

        data = np.zeros((n, n))
        #plot_posits(atoms, edge, bond, vecs =  [lat_vec_theta1, lat_vec_theta2])

        for k in range(n):
            atoms.positions = init_pos
            atoms.translate(lat_vec_theta1 * float(k) / n)
            #plot_posits(atoms, edge, bond, vecs =  [lat_vec_theta1, lat_vec_theta2])
            #print trans_vec1*float(k)/n, k, n, float(k)/n

            for l in range(n):
                atoms.translate(trans_vec2)
                emin, hmin = get_optimal_h(atoms, len(atoms), dyn=False)
                #data[k,l,:]  =   [emin, hmin]
                data[k, l] = emin  #atoms.get_potential_energy()/len(atoms)

        header  =   '%s runs along x-dir, angle measured from x-axis, natoms = %i. x (Angs), e (eV/atom), hmin \n\
the lattice vectors are l1 = [%.5f, %.5f, %.5f] and l2 = [%.5f, %.5f, %.5f], they are divided in %i parts. data[i,j,:] \n\
-> atoms pos += l1/n*i + l2/n*j, initial position is such that atom1 is in middle if hexagon.' \
    %(edge, len(atoms), lat_vec_theta1[0], lat_vec_theta1[1], lat_vec_theta1[2], \
      lat_vec_theta2[0], lat_vec_theta2[1], lat_vec_theta2[2], n)
        np.savetxt(fname, data, header=header)
Ejemplo n.º 18
0
def corr_KC():

    atoms = graphene_nanoribbon(1,
                                1,
                                type='armchair',
                                C_C=bond,
                                saturated=False)
    atoms.rotate([1, 0, 0], np.pi / 2, rotate_cell=True)

    if edge == 'ac':
        atoms.rotate([0, 0, 1], -np.pi / 2, rotate_cell=True)
        del atoms[[0, 3]]
        trans_idx = 1
    elif edge == 'zz':
        del atoms[[1, 0]]
        trans_idx = 0

    atoms.set_cell([20, 20, 10])
    atoms.center()

    params = {}
    params['positions'] = atoms.positions
    params['chemical_symbols'] = atoms.get_chemical_symbols()
    params['ia_dist'] = 10
    params['edge'] = edge
    params['bond'] = bond
    params['ncores'] = 2
    add_KC = KC_potential_p(params, True)

    constraints = []
    for i in range(len(atoms)):
        fix_l = FixedLine(i, [0., 0., 1.])
        constraints.append(fix_l)

    constraints.append(add_KC)

    lamp_parameters = get_lammps_params(H=False)
    calc = LAMMPS(parameters=lamp_parameters)  #, files=['lammps.data'])
    atoms.set_calculator(calc)
    atoms.set_constraint(constraints)

    #dyn     =   BFGS(atoms, trajectory = 'test.traj')
    #dyn.run(fmax=0.05)

    #plot_posits(atoms, edge, bond)
    trans_vec = trans_atomsKC(atoms.positions[trans_idx], edge, bond)
    atoms.translate(trans_vec)

    #plot_posits(atoms, edge, bond)
    init_pos = atoms.positions.copy()
    r_around = init_pos[trans_idx]

    #thetas      =   np.linspace(0, np.pi/3, 7) #, endpoint = False)
    #thetas_deg  =   np.array([1,3,5,7,9,11,12,13,15,17,43,45,47,48,49,51,57,55,57,59])
    thetas_deg = np.array([
        .5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5,
        13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5
    ])

    traj        =   PickleTrajectory(path + '%s_corr_twist_thetas_(%.1f-%.1f).traj' \
                                     %(edge, np.min(thetas_deg),
                                       np.max(thetas_deg)), 'w', atoms)

    n = 100

    for i, theta_deg in enumerate(thetas_deg):
        fname = path + 'corr_%s_theta=%.2f.data' % (edge, theta_deg)
        print 'Calculating theta = %.2f' % (theta_deg)
        theta = theta_deg / 360 * np.pi * 2
        print 'time ' + str(datetime.now().time())
        atoms.positions = init_pos
        atoms.rotate([0, 0, 1], theta, center=r_around)
        rot_init_pos = atoms.positions.copy()

        lat_vec_theta1 = lat_vec1.copy()
        lat_vec_theta2 = lat_vec2.copy()

        trans_vec2 = lat_vec_theta2.copy() / n

        data = np.zeros((n, n))

        for k in range(n):
            atoms.positions = rot_init_pos
            atoms.translate(lat_vec_theta1 * float(k) / n)
            #plot_posits(atoms, edge, bond, vecs =  [lat_vec_theta1, lat_vec_theta2])
            print '%.1f percent done' % (100 * float(k) / n)
            for l in range(n):
                atoms.translate(trans_vec2)
                emin = get_optimal_h(atoms, len(atoms), dyn=False)[0]
                data[
                    k,
                    l] = emin  #atoms.get_potential_energy()/len(atoms) #emin #
                saveAndPrint(atoms, traj, False)


        header  =   '%s runs along x-dir, angle measured from x-axis, natoms = %i. x (Angs), e (eV/atom), hmin \n\
the lattice vectors are l1 = [%.5f, %.5f, %.5f] and l2 = [%.5f, %.5f, %.5f], they are divided in %i parts. data[i,j,:] \n\
-> atoms pos += l1/n*i + l2/n*j, initial position is such that atom1 is in middle if hexagon.' \
    %(edge, len(atoms), lat_vec_theta1[0], lat_vec_theta1[1], lat_vec_theta1[2], \
      lat_vec_theta2[0], lat_vec_theta2[1], lat_vec_theta2[2], n)
        np.savetxt(fname, data, header=header)
Ejemplo n.º 19
0
def get_constraints(atoms, edge, bond, idxs, key='shear_p', pot='LJ'):

    if key == 'shear':
        # FIXES
        constraints = []
        if edge == 'zz': fixL = np.sqrt(3) * bond * .51  #1.05
        if edge == 'ac': fixL = 1.01 * bond

        rend_b, rend_t = get_posInds(atoms, 'redge')[1:]
        lend_s, lend_h = get_posInds(atoms, 'ledge', fixL)

        #view(atoms)
        if idxs == None:
            for i in lend_s:
                constraints.append(FixedLine(i, (0, 0, 1)))
            constraints.append(FixAtoms(indices=lend_h))
        else:
            for i in idxs:
                constraints.append(FixedLine(i, (0, 0, 1)))

        for i in rend_b:
            constraints.append(FixedPlane(i, (0, 1, 0)))

        # KC
        add_LJ = LJ_potential_smooth(bond)
        constraints.append(add_LJ)
        # END FIXES

        return constraints, add_LJ, rend_b, rend_t

    elif key == 'twist_F':

        # FIXES
        constraints = []
        if edge == 'zz': fixL = np.sqrt(3) * bond * 2.05
        if edge == 'ac': fixL = 5 * bond

        rend_b, rend_t = get_posInds(atoms, 'redge')[1:]
        lend_s, lend_h = get_posInds(atoms, 'ledge', fixL)

        #view(atoms)
        if idxs == None:
            for i in lend_s:
                constraints.append(FixedLine(i, (0, 0, 1)))
            constraints.append(FixAtoms(indices=lend_h))
        else:
            for i in idxs:
                constraints.append(FixedLine(i, (0, 0, 1)))

        # KC
        add_LJ = LJ_potential_smooth(bond)
        if len(rend_b) != len(rend_t) != 1: raise
        twist = twist_const_F(rend_b[0], rend_t[0], np.zeros(3))

        constraints.append(FixedPlane(rend_b[0], (0, 0, 1)))
        constraints.append(FixedPlane(rend_t[0], (0, 0, 1)))

        constraints.append(add_LJ)
        constraints.append(twist)
        # END FIXES

        return constraints, add_LJ, twist, rend_b, rend_t

    elif key == 'twist_p':

        # FIXES
        constraints = []
        if edge == 'zz': fixL = np.sqrt(3) * bond * .51
        if edge == 'ac': fixL = 1.1 * bond

        rend_b, rend_t = get_posInds(atoms, 'redge')[1:]
        lend_s, lend_h = get_posInds(atoms, 'ledge', fixL)

        #view(atoms)
        if idxs == None:
            for i in lend_s:
                constraints.append(FixedLine(i, (0, 0, 1)))
            constraints.append(FixAtoms(indices=lend_h))
        else:
            for i in idxs:
                constraints.append(FixedLine(i, (0, 0, 1)))

        # KC
        if pot == 'KC':
            params = {}
            params['positions'] = atoms.positions
            params['chemical_symbols'] = atoms.get_chemical_symbols()
            params['ia_dist'] = 10
            params['edge'] = edge
            params['bond'] = bond
            params['ncores'] = 1
            add_pot = KC_potential_p(params)

        elif pot == 'LJ':
            add_pot = LJ_potential_smooth(atoms, bond)

        if len(rend_b) != len(rend_t) != 1: raise

        #dist            =   np.linalg.norm(atoms.positions[rend_b[0]] - atoms.positions[rend_t[0]])
        #twist           =   twistConst_Rod(rend_b[0], rend_t[0], dist)
        twist = twistConst_Rod(atoms, 4, edge, bond)

        constraints.append(FixedPlane(rend_b[0], (0, 0, 1)))

        constraints.append(add_pot)
        constraints.append(twist)
        # END FIXES

        return constraints, add_pot, twist, rend_b[0], rend_t[0]