Example #1
0
def do_lattice(bulk, elastic=True):
   tol = 1e-3 # max force tol for relaxation
   n_E_vs_V_steps=10

   # use one of the routines from utilities module to relax the initial
   # unit cell and atomic positions
   bulk = relax_atoms_cell(bulk, tol=tol, traj_file=None, symmetrize=True)

   print "relaxed bulk"
   ase.io.write(sys.stdout, bulk, format='extxyz')

   if elastic:
       # reset calculator to non-symmetrized one (not optimal, but would otherwise need to have optimizer used by fit_elastic_constants to reset symmetry for each relaxation):w
       bulk.set_calculator(model.calculator)
       precon = Exp(3.0)
       opt = lambda atoms, **kwargs: PreconLBFGS(atoms, precon=precon, **kwargs)
       elastic_consts = matscipy.elasticity.fit_elastic_constants(bulk, symmetry='cubic', optimizer=opt)
       c11 = elastic_consts[0][0,0]/GPa
       c12 = elastic_consts[0][0,1]/GPa
       c44 = elastic_consts[0][3,3]/GPa

   V0 = bulk.get_volume()
   dV = bulk.get_volume()*0.025
   E_vs_V=[]

   f = open("relaxed_E_vs_V_configs.xyz", "w")

   for i in range(0, -5-1, -1):
      scaled_bulk = bulk.copy()
      scaled_bulk.set_cell(scaled_bulk.get_cell()*((V0+i*dV)/V0)**(1.0/3.0), scale_atoms=True)
      scaled_bulk = relax_atoms_cell(scaled_bulk, tol=tol, traj_file=None, constant_volume=True, method='cg_n', symmetrize=True)
      # evaluate(scaled_bulk)
      ase.io.write(f, scaled_bulk, format='extxyz')
      E_vs_V.insert(0,  (scaled_bulk.get_volume()/len(scaled_bulk), scaled_bulk.get_potential_energy()/len(bulk)) )

   for i in range(1, 6+1):
      scaled_bulk = bulk.copy()
      scaled_bulk.set_cell(scaled_bulk.get_cell()*((V0+i*dV)/V0)**(1.0/3.0), scale_atoms=True)
      scaled_bulk = relax_atoms_cell(scaled_bulk, tol=tol, traj_file=None, constant_volume=True, method='cg_n', symmetrize=True)
      # evaluate(scaled_bulk)
      ase.io.write(f, scaled_bulk, format='extxyz')
      E_vs_V.append( (scaled_bulk.get_volume()/len(scaled_bulk), scaled_bulk.get_potential_energy()/len(bulk)) )

   for (V, E) in E_vs_V:
     print "EV_final ", V, E

   if elastic:
       return (c11, c12, c44, E_vs_V)
   else:
       return (E_vs_V)
Example #2
0
def defect_energy(a0, e0, filename):

    
    tmp = ase.io.read(os.path.dirname(__file__)+"/"+filename, index=':', format='extxyz')
    defect = tmp[0]
    
    # adjust lattice constant
    # defect.set_cell([2*a0, 2*a0, 2*a0], scale_atoms=True)
    defect.set_calculator(model.calculator)
    
    # relax atom positions and cell
    # defect.positions += (np.random.rand((66*3))*0.01).reshape([66,3])
    defect = relax_atoms_cell(defect, tol=fmax, traj_file="model-"+model.name+"-diinterstitial-"+filename+"-relaxed.opt.xyz")
    ase.io.write(sys.stdout, defect, format='extxyz')

    edefect  = defect.get_potential_energy()
    print 'defect relaxed cell energy', edefect
    e_form = (edefect-66.0 * e0) 
    print 'defect relaxed formation energy', e_form
    return e_form
def interface_energy(e0, filename):

    interface = ase.io.read(os.path.join(os.path.dirname(__file__),filename), format='extxyz')
    
    # adjust lattice constant
    interface.set_calculator(model.calculator)
    
    # relax atom positions, holding cell fixed
    interface.positions += 0.01*np.random.random_sample((len(interface),3))
    print "pre relax config"
    ase.io.write(sys.stdout, interface, format='extxyz')
    print "BOB doing gb relax"
    interface = relax_atoms_cell(interface, tol=fmax, max_steps=300, traj_file=os.path.splitext(filename)[0]+"-relaxed.opt.xyz")
    print "post relax config"
    ase.io.write(sys.stdout, interface, format='extxyz')

    print "BOB doing gb get pot en"
    einterface  = interface.get_potential_energy()
    print 'interface relaxed cell energy', einterface
    e_form = (einterface-len(interface) * e0) 
    area = np.linalg.norm(np.cross(interface.get_cell()[0,:],interface.get_cell()[1,:]))
    print "got area",area
    print 'interface relaxed formation energy/area', e_form/(2.0*area)
    return e_form/(2.0*area)
Example #4
0
from ase import Atoms
from utilities import relax_atoms_cell, phonons
import numpy as np

# set up cell

try:
    with open("../model-{}-test-bulk_diamond-properties.json".format(
            model.name)) as f:
        j = json.load(f)
    a0 = j["diamond_a0"]
    bulk = Atoms(diamond2(a0, 14, 14))
except:
    bulk = Atoms(diamond2(5.43, 14, 14))
    bulk.set_calculator(model.calculator)
    bulk = relax_atoms_cell(bulk, tol=1.0e-4, traj_file=None)
    a0 = bulk.get_cell_lengths_and_angles()[0] * np.sqrt(2.0)
    bulk = Atoms(diamond2(a0, 14, 14))

supercell = [[4, 0, 0], [0, 4, 0], [0, 0, 4]]

dx = 0.03

mesh = [16, 16, 16]

points = np.array([[0, 0, 0], [0, 0.5, 0.5], [1, 1, 1], [0.5, 0.5, 0.5]])

n_points = 50

phonon_properties = phonons(model,
                            bulk,
Example #5
0
# the current model
import model

a0 = 5.44  # initial guess at lattice constant, cell will be relaxed below
fmax = 0.01  # maximum force following relaxtion [eV/A]

if not hasattr(model, 'bulk_reference'):
    # set up the a
    bulk = Diamond(symbol='Si', latticeconstant=a0)

    # specify that we will use model.calculator to compute forces, energies and stresses
    bulk.set_calculator(model.calculator)

    # use one of the routines from utilities module to relax the initial
    # unit cell and atomic positions
    bulk = relax_atoms_cell(bulk, tol=fmax, traj_file=None)
else:
    bulk = model.bulk_reference.copy()
    bulk.set_calculator(model.calculator)

a0 = bulk.cell[0, 0]  # get lattice constant from relaxed bulk
print "got a0 ", a0
bulk = Diamond(symbol="Si",
               latticeconstant=a0,
               directions=[[1, -1, 0], [1, 0, -1], [1, 1, 1]])
bulk.set_calculator(model.calculator)

# set up supercell
bulk *= (1, 1, 10)

Example #6
0
    at.set_scaled_positions(np.random.rand(n_at, 3))
    while too_close(at, hard_sphere_dist):
        at.set_scaled_positions(np.random.rand(n_at, 3))
    print "initial config"
    ase.io.write(sys.stdout, at, format="extxyz")

    at.set_calculator(model.calculator)

    if os.path.basename(os.path.dirname(model.__file__)) == 'CASTEP_file':
        model.geom_method = 'tpsd'
        model.geom_force_tol = tol
        model.geom_stress_tol = tol
        model.geom_energy_tol = 1.0e8
        model.geom_disp_tol = 1.0e8
        print "BOB relax atoms"
        at = relax_atoms_cell(at, tol=tol)
        i_minim = -1
        converged = True
    else:
        config_minim = UnitCellFilter(at)
        x = config_minim.get_positions()
        converged = False
        for i_minim in range(500):
            config_minim.set_positions(x)
            grad_f = -config_minim.get_forces()
            E = config_minim.get_potential_energy()
            try:
                pred_err = predictive_error(config_minim.atoms)
            except:
                pred_err = None
            if isinstance(config_minim, UnitCellFilter):
Example #7
0
a0 = 5.44  # initial guess at lattice constant, cell will be relaxed below
tol = 1e-3  # maximum force following relaxtion [eV/A]
N = 2  # number of unit cells in each direction

if not hasattr(model, 'bulk_reference_216'):
    # set up the a
    bulk = Diamond(symbol='Si', latticeconstant=a0)

    # specify that we will use model.calculator to compute forces, energies and stresses
    bulk.set_calculator(model.calculator)

    # use one of the routines from utilities module to relax the initial
    # unit cell and atomic positions
    print "JOE test relaxing bulk"
    bulk = relax_atoms_cell(bulk, tol=tol, traj_file=None, method='lbfgs')
    print "JOE test done relaxing bulk"
    bulk *= (N, N, N)
    print "JOE test reading bulk E"
    bulk_energy = bulk.get_potential_energy()
    print "JOE test done reading bulk E"
else:
    bulk = model.bulk_reference_216
    bulk_energy = bulk.get_potential_energy()


def fourfold_defect_energy(bulk):
    Nat = bulk.get_number_of_atoms()
    defect = bulk.copy()
    defect.set_calculator(bulk.get_calculator())
Example #8
0
def do_lattice(bulk, use_precon=True, elastic=True, tol=1.0e-3):

    print "unrelaxed bulk"
    ase.io.write(sys.stdout, bulk, format='extxyz')

    # use one of the routines from utilities module to relax the initial
    # unit cell and atomic positions
    if use_precon:
        bulk = relax_atoms_cell(bulk,
                                tol=tol,
                                traj_file="bulk.relax.extxyz",
                                symmetrize=True)
    else:
        bulk = relax_atoms_cell(bulk,
                                tol=tol,
                                traj_file=None,
                                method='cg_n',
                                symmetrize=True)

    print "relaxed bulk"
    ase.io.write(sys.stdout, bulk, format='extxyz')

    print "calculating elastic constants"
    precon = None
    if use_precon:
        precon = Exp(3.0)
    opt = lambda atoms, **kwargs: PreconLBFGS(atoms, precon=precon, **kwargs)
    if elastic:
        # reset calculator to non-symmetrized one (not optimal, but would otherwise need to have optimizer used by fit_elastic_constants to reset symmetry for each relaxation):w
        bulk.set_calculator(model.calculator)
        try:
            elastic_consts = matscipy.elasticity.fit_elastic_constants(
                bulk,
                symmetry='tetragonal_high',
                optimizer=opt,
                logfile=sys.stdout)
        except RuntimeError:
            # fallback on FIRE if we get a linesearch failure with LBFGS
            opt = FIRE
            elastic_consts = matscipy.elasticity.fit_elastic_constants(
                bulk,
                symmetry='tetragonal_high',
                optimizer=opt,
                logfile=sys.stdout)

        c11 = elastic_consts[0][0, 0] / GPa
        c33 = elastic_consts[0][2, 2] / GPa
        c12 = elastic_consts[0][0, 1] / GPa
        c13 = elastic_consts[0][0, 2] / GPa
        c44 = elastic_consts[0][3, 3] / GPa
        c66 = elastic_consts[0][5, 5] / GPa

    print "calculating E vs. V"
    V0 = bulk.get_volume()
    dV = bulk.get_volume() * 0.025
    E_vs_V = []
    scaled_bulk = bulk.copy()
    print "bulk going into E vs. V"
    ase.io.write(sys.stdout, scaled_bulk, format='extxyz')
    f = open("relaxed_E_vs_V_configs.xyz", "w")

    scaled_bulk = bulk.copy()
    constraints = []
    # scaled_bulk.arrays["move_mask_3"] = np.zeros((len(scaled_bulk),3), dtype=np.int)
    # scaled_bulk.arrays["move_mask_3"][:,0] = 1
    # for i in range(len(scaled_bulk)):
    # constraints.append(FixedLine_forces_only(i, (0.0, 0.0, 1.0)))
    # scaled_bulk.set_constraint(constraints)
    for i in range(0, -5 - 1, -1):
        print "doing volume step", i
        vcur = scaled_bulk.get_volume()
        scaled_bulk.set_cell(scaled_bulk.get_cell() *
                             ((V0 + i * dV) / vcur)**(1.0 / 3.0),
                             scale_atoms=True)
        try:
            scaled_bulk = relax_atoms_cell(scaled_bulk,
                                           tol=tol,
                                           traj_file=None,
                                           constant_volume=True,
                                           method='cg_n',
                                           symmetrize=True,
                                           max_steps=500)
        except:
            break
        print "done relaxing step", i
        ase.io.write(f, scaled_bulk, format='extxyz')
        f.flush()
        E_vs_V.insert(0, (scaled_bulk.get_volume() / len(bulk),
                          scaled_bulk.get_potential_energy() / len(bulk)))
        evaluate(scaled_bulk)
        print "done evaluate step", i
        print "EV ", i, scaled_bulk.get_volume(
        ), scaled_bulk.get_potential_energy(), scaled_bulk.get_stress()

    scaled_bulk = bulk.copy()
    # scaled_bulk.arrays["move_mask_3"] = np.zeros((len(scaled_bulk),3), dtype=np.int)
    # scaled_bulk.arrays["move_mask_3"][:,0] = 1
    # scaled_bulk.set_constraint(constraints)
    for i in range(1, 6 + 1):
        print "doing volume step", i
        vcur = scaled_bulk.get_volume()
        scaled_bulk.set_cell(scaled_bulk.get_cell() *
                             ((V0 + i * dV) / vcur)**(1.0 / 3.0),
                             scale_atoms=True)
        try:
            scaled_bulk = relax_atoms_cell(scaled_bulk,
                                           tol=tol,
                                           traj_file=None,
                                           constant_volume=True,
                                           method='cg_n',
                                           symmetrize=True,
                                           max_steps=500)
        except:
            break
        print "done relaxing step", i
        ase.io.write(f, scaled_bulk, format='extxyz')
        f.flush()
        E_vs_V.append((scaled_bulk.get_volume() / len(bulk),
                       scaled_bulk.get_potential_energy() / len(bulk)))
        evaluate(scaled_bulk)
        print "done evaluate step", i
        print "EV ", i, scaled_bulk.get_volume(
        ), scaled_bulk.get_potential_energy(), scaled_bulk.get_stress()

    for (V, E) in E_vs_V:
        print "EV_final ", V, E

    if elastic:
        return (c11, c33, c12, c13, c44, c66, E_vs_V)
    else:
        return (E_vs_V)
Example #9
0
def sf_calc(bulk,
            n_steps,
            z_offset,
            p0=None,
            p1=None,
            relax_from_configs=None):
    global bulk_energy

    p0 = np.array(p0)
    p1 = np.array(p1)
    E0 = bulk_energy
    surf_unrelaxed = np.zeros((n_steps, n_steps), dtype=(float, 3))
    surf_relaxed = np.zeros((n_steps, n_steps), dtype=(float, 3))
    path_unrelaxed = []
    path_relaxed = []

    sf = bulk.copy()
    pos = sf.get_positions()
    pos[:, 2] += z_offset
    sf.set_positions(pos)

    pos = sf.get_scaled_positions()
    pos -= np.floor(pos)
    sf.set_scaled_positions(pos)

    if p0 is not None and p1 is not None:  # paths

        # unrelaxed
        for i in range(n_steps):
            print "start path unrelaxed step", i
            sys.stdout.flush()
            p = p0 + (p1 - p0) * i / float(n_steps - 1)
            sf_cur = sf.copy()

            sf_cur.arrays['move_mask_3'] = np.zeros((len(sf_cur), 3),
                                                    dtype=int)
            sf_cur.arrays['move_mask_3'][:, 2] = 1

            sf_cur.set_calculator(model.calculator)
            cell = sf_cur.get_cell()
            cell[2, :] += cell[0, :] * p[0] + cell[1, :] * p[1]
            sf_cur.set_cell(cell)

            E = (sf_cur.get_potential_energy() - E0) / np.linalg.norm(
                np.cross(cell[0, :], cell[1, :]))
            path_unrelaxed.append((i / float(n_steps - 1), p[0], p[1], E))

        # relaxed
        sf_cur = sf.copy()
        sf_cur.arrays['move_mask_3'] = np.zeros((len(sf_cur), 3), dtype=int)
        sf_cur.arrays['move_mask_3'][:, 2] = 1
        sf_cur.set_calculator(model.calculator)
        dp = (p1 - p0) / float(n_steps - 1)
        p = p0.copy()
        cell = sf_cur.get_cell()
        cell[2, :] += cell[0, :] * p[0] + cell[1, :] * p[1]
        sf_cur.set_cell(cell)
        relax_from_configs_i = 0
        for i in range(n_steps):
            print "start path relaxed step", i
            sys.stdout.flush()

            if model.name == 'CASTEP_file':
                sf_cur.calc.fix_all_cell = False
                sf_cur.set_constraint(
                    [FixCartesian(j, [1, 1, 0]) for j in range(len(sf_cur))])
                sf_cur.calc.cell_constraints = ["0 0 1", "0 0 0"]
                sf_cur.calc._old_atoms = None
            if debug:
                ase.io.write(file_unrelaxed, sf_cur, "extxyz")
                file_unrelaxed.flush()

            try:
                sf_cur.set_cell(
                    relax_from_configs[relax_from_configs_i].get_cell(), False)
                sf_cur.set_positions(
                    relax_from_configs[relax_from_configs_i].get_positions())
                print "got sf_cur from 'relax_from_configs'"
                sys.stdout.flush()
            except:
                pass
            sf_cur_rel = relax_atoms_cell(
                sf_cur,
                tol=tol,
                method='cg_n',
                max_steps=500,
                traj_file=None,
                mask=[False, False, True, False, False, False])
            relax_from_configs_i += 1
            if debug:
                ase.io.write(file_relaxed, sf_cur, "extxyz")
                file_relaxed.flush()
            print "done relaxation"
            sys.stdout.flush()

            E = (sf_cur.get_potential_energy() - E0) / np.linalg.norm(
                np.cross(cell[0, :], cell[1, :]))
            path_relaxed.append((i / float(n_steps - 1), p[0], p[1], E))

            cell = sf_cur.get_cell()
            cell[2, :] += cell[0, :] * dp[0] + cell[1, :] * dp[1]
            sf_cur.set_cell(cell)
            p += dp

        return (path_unrelaxed, path_relaxed)

    else:  # surfaces

        # unrelaxed
        j_doffset = sf.get_cell()[1, :] * (1.0 / float(n_steps - 1))
        for i in range(n_steps):
            x_i = float(i) / float(n_steps - 1)
            sf_cur = sf.copy()

            sf_cur.arrays['move_mask_3'] = np.zeros((len(sf_cur), 3),
                                                    dtype=int)
            sf_cur.arrays['move_mask_3'][:, 2] = 1

            sf_cur.set_calculator(model.calculator)
            cell = sf_cur.get_cell()
            cell[2, :] += cell[0, :] * x_i
            sf_cur.set_cell(cell)
            for j in range(n_steps - i):
                x_j = float(j) / float(n_steps - 1)
                print(i, j, x_i, x_j)
                if debug:
                    ase.io.write(file_unrelaxed, sf_cur, "extxyz")
                    file_unrelaxed.flush()
                E = (sf_cur.get_potential_energy() - E0) / np.linalg.norm(
                    np.cross(cell[0, :], cell[1, :]))
                surf_unrelaxed[i, j] = (x_i, x_j, E)
                if i + j != n_steps - 1:
                    surf_unrelaxed[n_steps - j - 1,
                                   n_steps - i - 1] = (1.0 - x_j, 1.0 - x_i, E)
                cell = sf_cur.get_cell()
                cell[2, :] += j_doffset
                sf_cur.set_cell(cell, scale_atoms=False)

        # relaxed
        relax_from_configs_i = 0
        j_doffset = sf.get_cell()[1, :] * (1.0 / float(n_steps - 1))
        for i in range(n_steps):
            x_i = float(i) / float(n_steps - 1)
            sf_cur = sf.copy()

            # set constraints
            # cs = []
            # for i_at in range(len(bulk)):
            # cs.append(FixCartesian(i_at, mask=[0,0,1]))
            # sf_cur.set_constraint(cs)
            sf_cur.arrays['move_mask_3'] = np.zeros((len(sf_cur), 3),
                                                    dtype=int)
            sf_cur.arrays['move_mask_3'][:, 2] = 1

            sf_cur.set_calculator(model.calculator)
            cell = sf_cur.get_cell()
            cell[2, :] += cell[0, :] * x_i
            sf_cur.set_cell(cell)
            for j in range(n_steps - i):
                x_j = float(j) / float(n_steps - 1)
                print(i, j, x_i, x_j)
                try:
                    sf_cur.set_cell(
                        relax_from_configs[relax_from_configs_i].get_cell(),
                        False)
                    sf_cur.set_positions(
                        relax_from_configs[relax_from_configs_i].get_positions(
                        ))
                except:
                    pass
                sf_cur_rel = relax_atoms_cell(
                    sf_cur,
                    tol=tol,
                    method='cg_n',
                    max_steps=500,
                    traj_file=None,
                    mask=[False, False, True, False, False, False])
                relax_from_configs_i += 1
                if debug:
                    ase.io.write(file_relaxed, sf_cur_rel, "extxyz")
                    file_relaxed.flush()
                E = (sf_cur_rel.get_potential_energy() - E0) / np.linalg.norm(
                    np.cross(cell[0, :], cell[1, :]))
                surf_relaxed[i, j] = (x_i, x_j, E)
                if i + j != n_steps - 1:
                    surf_relaxed[n_steps - j - 1,
                                 n_steps - i - 1] = (1.0 - x_j, 1.0 - x_i, E)
                cell = sf_cur.get_cell()
                cell[2, :] += j_doffset
                sf_cur.set_cell(cell, scale_atoms=False)

        return (surf_unrelaxed, surf_relaxed)
Example #10
0
def struct_energy(e0_per_atom, filename):
    V_unrel = []
    V_rel = []
    E_unrel = []
    E_rel = []

    ats = ase.io.read(os.path.dirname(__file__) + "/" + filename,
                      index=':',
                      format='extxyz')
    for (i, at_orig) in enumerate(ats):
        at = at_orig.copy()
        at.set_calculator(model.calculator)
        # # The commented out bit that follows seems to break CASTEP_file - no minimization runs are set up, apparently because call to relax_atoms_cell doesn't actually trigger a calculate()
        # unrelaxed_e_per_atom  = at.get_potential_energy()/len(at)
        # print 'at unrelaxed energy per atom', unrelaxed_e_per_atom
        # E_unrel.append(unrelaxed_e_per_atom-e0_per_atom)

        # relax fully
        print "BOB: calling relax_atoms_cell"
        if os.path.basename(os.path.dirname(model.__file__)) == 'CASTEP_file':
            at = relax_atoms_cell(at,
                                  tol=fmax,
                                  traj_file="model-" + model.name +
                                  "-RSS-{}-".format(i) + filename +
                                  "-relaxed.opt.xyz")
        else:
            n_at = len(at)
            config_minim = UnitCellFilter(at)
            x = config_minim.get_positions()
            converged = False
            for i_minim in range(500):
                config_minim.set_positions(x)
                grad_f = -config_minim.get_forces()
                E = config_minim.get_potential_energy()
                try:
                    pred_err = predictive_error(config_minim.atoms)
                except:
                    pred_err = None
                if isinstance(config_minim, UnitCellFilter):
                    print i, "SD2: {} {} {} {}".format(
                        i_minim, E, np.max(np.abs(grad_f[:n_at])),
                        np.max(np.abs(grad_f[n_at:])))
                else:
                    print i, "SD2: {} {} {}".format(
                        i_minim, E, np.max(np.abs(grad_f[:n_at])))
                if np.max(np.abs(grad_f[:n_at])) < fmax and np.max(
                        np.abs(grad_f[n_at:])) < fmax:
                    converged = True
                    break
                if i_minim == 0:
                    alpha = 1.0e-6
                else:
                    alpha = np.sum(
                        (x - x_old) * (grad_f - grad_f_old)) / np.sum(
                            (grad_f - grad_f_old)**2)
                x_old = x.copy()
                grad_f_old = grad_f.copy()
                x -= np.abs(alpha) * grad_f
        print "BOB: done relax_atoms_cell"
        ase.io.write(sys.stdout, at, format='extxyz')

        print "BOB: calling get_potential_energy for relaxed"
        relaxed_e_per_atom = at.get_potential_energy() / len(at)
        print "BOB: done get_potential_energy for relaxed"
        print 'at relaxed energy per atom', relaxed_e_per_atom
        E_rel.append(relaxed_e_per_atom - e0_per_atom)

        V_rel.append(at.get_volume() / len(at))

    # This is a workaround for the problem mentioned above
    ats = ase.io.read(os.path.dirname(__file__) + "/" + filename,
                      index=':',
                      format='extxyz')
    for (i, at) in enumerate(ats):
        at.set_calculator(model.calculator)

        # relax fully
        print "BOB: calling get_potential_energy for unrelaxed"
        unrelaxed_e_per_atom = at.get_potential_energy() / len(at)
        print "BOB: done get_potential_energy for unrelaxed"
        print 'at unrelaxed energy per atom', unrelaxed_e_per_atom
        E_unrel.append(unrelaxed_e_per_atom - e0_per_atom)
        V_unrel.append(at.get_volume() / len(at))
    # end of workaround

    return (V_unrel, E_unrel, V_rel, E_rel)