예제 #1
0
    def absorption_kick(self, kick_strength):
        self.tddft_init()

        self.timer.start('Kick')

        self.kick_strength = np.array(kick_strength, dtype=float)
        magnitude = np.sqrt(np.sum(self.kick_strength**2))
        direction = self.kick_strength / magnitude

        self.log('----  Applying absorption kick')
        self.log('----  Magnitude: %.8f Hartree/Bohr' % magnitude)
        self.log('----  Direction: %.4f %.4f %.4f' % tuple(direction))

        # Create hamiltonian object for absorption kick
        cef = ConstantElectricField(magnitude * Hartree / Bohr, direction)
        kick_hamiltonian = KickHamiltonian(self, cef)

        # Propagate kick
        self.propagator.kick(kick_hamiltonian, self.time)

        # Call observers after kick
        self.action = 'kick'
        self.call_observers(self.niter)

        self.niter += 1

        self.timer.stop('Kick')
예제 #2
0
def add_efield(fname, efield=0):
    printit('Starting Efield calculation for efiled = {}'.format(efield))
    atom, calc = restart('gs_' + fname + '.gpw')
    calc.set(txt='gs_efield_{}.txt'.format(efield))
    calc.set(external=ConstantElectricField(efield, [0, 0, 1]))
    calc.get_potential_energy()
    calc.write('gs_' + fname + '_{}.gpw'.format(efield), mode='all')
    printit('Efield GS calculation done')
    gap, p1, p2 = get_gap(calc)
    printit("{} {} {} {}".format(efield, gap, p1, p2), fname="gaps.dat")
    printit("efield={} gap={}".format(efield, gap))
def efield(efield=0.05, n=30):
    printit('running GS calculation for {}'.format(efield))
    fname = "sb_relaxed.cif"
    a = read(fname)
    atom = read(fname)
    wire = make_supercell(atom, [[n, 0, 0], [0, 1, 0], [
                          0, 0, 1]], wrap=True, tol=1e-05)
    wire.center(vacuum=15, axis=0)
    a = wire.copy()
    if not os.path.isfile('gs_{}.gpw'.format(efield)):
        calc = GPAW(  # mode='lcao',
            mode='fd',
            basis='szp(dzp)',
            # eigensolver='cg',
            #mixer=Mixer(beta=0.2, nmaxold=3, weight=70.0),
            xc='PBE',
            # poissonsolver=DipoleCorrection(PoissonSolver(relax='GS'), 2),
            mixer=Mixer(beta=0.06, nmaxold=5, weight=100.0),
            occupations=FermiDirac(width=0.1),
            kpts={'density': 4.5},
            txt='gs_output_{}.txt'.format(efield),
            h=0.20,
            external=ConstantElectricField(efield, [0, 0, 1]))

        a.set_calculator(calc)
        a.get_potential_energy()
        calc.write('gs_{}.gpw'.format(efield))

    calc = GPAW('gs_{}.gpw'.format(efield),
                nbands=-100,
                fixdensity=True,
                symmetry='off',
                kpts={'path': 'XGX', 'npoints': 100},
                convergence={'bands': 'CBM+1'},
                txt='gs_output_{}.txt'.format(efield))
    calc.get_potential_energy()
    bs = calc.band_structure()
    bs.plot(filename='bandstructure_{}.png'.format(
        efield), show=False, emax=calc.get_fermi_level()+1, emin=calc.get_fermi_level()-1)
    bs.write('bs_{}.json'.format(
        efield))
    try:
        gap, p1, p2 = get_gap(calc)
        printit("{} {} {} {}".format(efield, gap, p1, p2), fname="gaps.dat")
    except:
        None
예제 #4
0
    def absorption_kick(self, kick_strength):
        self.tddft_init()
        self.timer.start('Kick')
        self.kick_strength = np.array(kick_strength, dtype=float)

        # magnitude
        magnitude = np.sqrt(np.sum(self.kick_strength**2))

        # normalize
        direction = self.kick_strength / magnitude

        self.log('Applying absorption kick')
        self.log('Magnitude: %.8f hartree/bohr' % magnitude)
        self.log('Direction: %.4f %.4f %.4f' % tuple(direction))

        # Create hamiltonian object for absorption kick
        cef = ConstantElectricField(magnitude * Hartree / Bohr, direction)
        kick_hamiltonian = KickHamiltonian(self, cef)
        for k, kpt in enumerate(self.wfs.kpt_u):
            Vkick_MM = self.wfs.eigensolver.calculate_hamiltonian_matrix(
                kick_hamiltonian, self.wfs, kpt, add_kinetic=False, root=-1)
            for i in range(10):
                self.propagate_wfs(kpt.C_nM, kpt.C_nM, kpt.S_MM, Vkick_MM, 0.1)
        self.timer.stop('Kick')
예제 #5
0
    },
    maxiter=1000,
    txt=txt)
a.set_calculator(c)

# Test 2

if test2:
    e = []
    e1s = []
    d = []
    fields = np.linspace(-maxfield, maxfield, nfs)
    for field in fields:
        if rank == 0 and debug:
            print(field)
        c.set(external=ConstantElectricField(field), )
        etot = a.get_potential_energy()
        e += [etot]
        ev0 = c.get_eigenvalues(0)
        ev1 = c.get_eigenvalues(1)
        e1s += [min(ev0[0], ev1[0])]
        dip = c.get_dipole_moment()
        d += [dip[2]]

    pol1, dummy = np.polyfit(fields, d, 1)
    pol2, dummy1, dummy2 = np.polyfit(fields, e1s, 2)

    if rank == 0 and debug:
        print('From shift in 1s-state at constant electric field:')
        print('  alpha = ', -pol2, ' A**2/eV')
        print('  alpha = ', -pol2 * to_au, ' Bohr**3')
예제 #6
0
"""A proton in an electric field."""
from ase import Atoms
from ase.units import Hartree, Bohr

from gpaw import GPAW
from gpaw.external import ConstantElectricField

h = Atoms('H')
h.center(vacuum=2.5)
h.calc = GPAW(external=ConstantElectricField(1.0),  # 1 eV / Ang
              charge=1,
              txt='h.txt')
e = h.get_potential_energy()
f1 = h.get_forces()[0, 2]
h[0].z += 0.001
de = h.get_potential_energy() - e
f2 = -de / 0.001
print(f1, f2)
assert abs(f1 - 1) < 1e-4
assert abs(f2 - 1) < 5e-3

# Check writing and reading:
h.calc.write('h')
vext = GPAW('h', txt=None).hamiltonian.vext
assert abs(vext.field_v[2] - 1.0 * Bohr / Hartree) < 1e-13
예제 #7
0
    def initialize(self, paw, min_occdiff=1e-3, only_ia=True):
        if self.has_initialized:
            return
        paw.initialize_positions()
        # paw.set_positions()

        if self.wfs.gd.pbc_c.any():
            self.C0_dtype = complex
        else:
            self.C0_dtype = float

        # Take quantities
        self.fermilevel = paw.occupations.get_fermi_level()
        self.S_uMM = []
        self.C0_unM = []
        self.eig_un = []
        self.occ_un = []
        for kpt in self.wfs.kpt_u:
            S_MM = kpt.S_MM
            assert np.max(np.absolute(S_MM.imag)) == 0.0
            S_MM = S_MM.real
            self.S_uMM.append(S_MM)

            C_nM = kpt.C_nM
            if self.C0_dtype == float:
                assert np.max(np.absolute(C_nM.imag)) == 0.0
                C_nM = C_nM.real
            self.C0_unM.append(C_nM)

            self.eig_un.append(kpt.eps_n)
            self.occ_un.append(kpt.f_n)

        # TODO: do the rest of the function with K-points

        # Construct p = (i, a) pairs
        u = 0
        Nn = self.wfs.bd.nbands
        eig_n = self.eig_un[u]
        occ_n = self.occ_un[u]

        self.only_ia = only_ia
        f_p = []
        w_p = []
        i_p = []
        a_p = []
        ia_p = []
        i0 = 0
        for i in range(i0, Nn):
            if only_ia:
                a0 = i + 1
            else:
                a0 = 0
            for a in range(a0, Nn):
                f = occ_n[i] - occ_n[a]
                if only_ia and f < min_occdiff:
                    continue
                w = eig_n[a] - eig_n[i]
                f_p.append(f)
                w_p.append(w)
                i_p.append(i)
                a_p.append(a)
                ia_p.append((i, a))
        f_p = np.array(f_p)
        w_p = np.array(w_p)
        i_p = np.array(i_p, dtype=int)
        a_p = np.array(a_p, dtype=int)
        ia_p = np.array(ia_p, dtype=int)

        # Sort according to energy difference
        p_s = np.argsort(w_p)
        f_p = f_p[p_s]
        w_p = w_p[p_s]
        i_p = i_p[p_s]
        a_p = a_p[p_s]
        ia_p = ia_p[p_s]

        Np = len(f_p)
        P_p = []
        for p in range(Np):
            P = np.ravel_multi_index(ia_p[p], (Nn, Nn))
            P_p.append(P)
        P_p = np.array(P_p)

        dm_vMM = []
        for v in range(3):
            direction = np.zeros(3, dtype=float)
            direction[v] = 1.0
            magnitude = 1.0
            cef = ConstantElectricField(magnitude * Hartree / Bohr, direction)
            kick_hamiltonian = KickHamiltonian(paw, cef)
            dm_MM = self.wfs.eigensolver.calculate_hamiltonian_matrix(
                kick_hamiltonian,
                paw.wfs,
                self.wfs.kpt_u[u],
                add_kinetic=False,
                root=-1)
            tri2full(dm_MM)  # TODO: do not use this
            dm_vMM.append(dm_MM)

        C0_nM = self.C0_unM[u]
        dm_vnn = []
        for v in range(3):
            dm_vnn.append(np.dot(C0_nM.conj(), np.dot(dm_vMM[v], C0_nM.T)))
        dm_vnn = np.array(dm_vnn)
        dm_vP = dm_vnn.reshape(3, -1)

        dm_vp = dm_vP[:, P_p]

        self.w_p = w_p
        self.f_p = f_p
        self.ia_p = ia_p
        self.P_p = P_p
        self.dm_vp = dm_vp

        self.has_initialized = True
예제 #8
0
"""A proton in an electric field."""
from ase import Atoms
from ase.units import Hartree, Bohr

from gpaw import GPAW
from gpaw.external import ConstantElectricField

h = Atoms('H')
h.center(vacuum=2.5)
h.calc = GPAW(
    external=ConstantElectricField(1.0),  # 1 V / Ang
    charge=1,
    txt='h.txt')
e = h.get_potential_energy()
f1 = h.get_forces()[0, 2]
h[0].z += 0.001
de = h.get_potential_energy() - e
f2 = -de / 0.001
print(f1, f2)
assert abs(f1 - 1) < 1e-4
assert abs(f2 - 1) < 5e-3

# Check writing and reading:
h.calc.write('h')
vext = GPAW('h', txt=None).hamiltonian.vext
assert abs(vext.field_v[2] - 1.0 * Bohr / Hartree) < 1e-13