Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Electron-phonon extension #294

Open
wants to merge 74 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
f7310b8
fixed typo
m-baumgarten Feb 9, 2024
4ffbe56
holstein with toyozawa trial, coherent state trial todo
m-baumgarten Feb 9, 2024
fa6f13b
working toyozawa implementation for 1 electron, 1D Holstein
m-baumgarten Feb 16, 2024
caf7a34
multi-electron implementation. toyozawa very dodgy
m-baumgarten Feb 23, 2024
e7507f7
Some einsum cleanup
Mar 3, 2024
bf49a31
added variationcal code to ipie and example run file
Mar 4, 2024
2ef4fb8
holstein propagator cleanup
Mar 4, 2024
f0a10a6
moved files to adhere to addons infrastructure
Mar 5, 2024
582a24e
changed folder name from ipie/addons/ephqmc to ipie/addons/eph
Mar 5, 2024
f9d70d5
Merge branch 'develop' into multiel_holstein
fdmalone Mar 5, 2024
69e1ef5
changed directory name finally
Mar 5, 2024
7925ba9
Merge branch 'multiel_holstein' of github.com:m-baumgarten/ipie_holst…
Mar 5, 2024
ccc2649
Cleanup of HolsteinModel class plus some explanation of the model.
Mar 5, 2024
ce14a30
added __init__ files in new directories
m-baumgarten Mar 5, 2024
d839b23
cleaned up comments and added docstring
m-baumgarten Mar 5, 2024
00870e5
added energy estimator, more or less identical to the one in ipie/est…
m-baumgarten Mar 6, 2024
e2e703b
removed addon imports and dispatch to local_energy_holstein
m-baumgarten Mar 6, 2024
dab3687
enabled AFQMC.build by adding some dummy parameters to HolsteinPropag…
m-baumgarten Mar 6, 2024
ad5c2cd
added docstring to EphWalkers and moved initial trial.calc_overlap fr…
m-baumgarten Mar 6, 2024
e782941
renamed Eph classes to EPh
m-baumgarten Mar 7, 2024
096ea3f
fix optimize position
m-baumgarten Mar 7, 2024
b425c44
Docstrings and renaming of HolsteinPropagatorImportance
m-baumgarten Mar 7, 2024
3a578a2
varaitional clean up, removed comments and moved gab to estimators.py
m-baumgarten Mar 7, 2024
f79e95a
docstrings and type specifications
m-baumgarten Mar 8, 2024
4ea65a6
added licensing header
m-baumgarten Mar 8, 2024
7eec46b
renamed phonon displacements stored in EPhWalkers.x to EPhWalkers.pho…
m-baumgarten Mar 8, 2024
c01760f
docstrings with math
m-baumgarten Mar 10, 2024
e59ead6
removed redundant calculation of greens function
m-baumgarten Mar 10, 2024
a3c3675
added abstract functions, required for every new trial
m-baumgarten Mar 10, 2024
317dcf3
intializes greens functions new and sets overlap in build
m-baumgarten Mar 10, 2024
ee14708
extra layer for propagators from addons
m-baumgarten Mar 11, 2024
eeeb44c
reformatted code
m-baumgarten Mar 11, 2024
58ed7af
Merge branch 'develop' into multiel_holstein
fdmalone Mar 11, 2024
93e6a49
renamed EPhWalkers.total_ovlp to EPhWalkers.ovlp_perm
m-baumgarten Mar 11, 2024
3edb5e8
calc_greens_function and calc_overlap are now "purer", calc_overlap s…
m-baumgarten Mar 11, 2024
4c72ba7
Merge branch 'multiel_holstein' of github.com:m-baumgarten/ipie_holst…
m-baumgarten Mar 11, 2024
d66d467
energy estimator unit test
m-baumgarten Mar 11, 2024
20d86a2
no more hamiltonian needed for trial initialisation. pass w0 instead
m-baumgarten Mar 11, 2024
24a99d5
fixed bug with final reshaping causing dimensions to be mixed up
m-baumgarten Mar 11, 2024
dfb3a4d
added variational_energy to toyozawa
m-baumgarten Mar 11, 2024
a0cfab5
added calc_energy to coherent state trial and made it abstractmethod
m-baumgarten Mar 12, 2024
cf8f379
added unittests for propagation and variational
m-baumgarten Mar 12, 2024
28d40df
utils for unittests
m-baumgarten Mar 12, 2024
298ad97
reformatting
m-baumgarten Mar 12, 2024
51b48a1
added verbosity for toyozawa_variational
m-baumgarten Mar 12, 2024
6fb14af
fixed bug with local_energy, where coherent state expectation value o…
m-baumgarten Mar 12, 2024
5a0a70a
added g_tensor in anticipation of generalization
m-baumgarten Mar 12, 2024
9dfd155
unittests for ephwalkers
m-baumgarten Mar 12, 2024
c355ffa
unittests for trial methods
m-baumgarten Mar 12, 2024
40c5ed5
docstring
m-baumgarten Mar 12, 2024
3b1256f
reformatting
m-baumgarten Mar 12, 2024
27b5365
light reformatting
m-baumgarten Mar 12, 2024
a801b80
removed redundant sqrt(m*w)
m-baumgarten Mar 13, 2024
42faa91
minor bug fixes
m-baumgarten Mar 13, 2024
5d7c560
example for holstein model 4 electrons
m-baumgarten Mar 20, 2024
ee78aad
Merge branch 'develop' into multiel_holstein
fdmalone Mar 30, 2024
92e3620
jax imports in tests guarded
m-baumgarten Apr 16, 2024
1a86cb4
Merge branch 'multiel_holstein' of github.com:m-baumgarten/ipie_holst…
m-baumgarten Apr 16, 2024
9bcb208
removed run_test in holstein example and renamed test_estimators
m-baumgarten Apr 16, 2024
0ebe6f2
Merge branch 'develop' into multiel_holstein
m-baumgarten Jul 22, 2024
705d1e6
removed jax dependency in example
m-baumgarten Aug 4, 2024
44bea2d
Merge branch 'multiel_holstein' of github.com:m-baumgarten/ipie_holst…
m-baumgarten Aug 4, 2024
4963d63
accommodates new Propagator dict
m-baumgarten Aug 4, 2024
e02282c
jax workaround like torch
m-baumgarten Aug 5, 2024
44505b5
fixed pytests
m-baumgarten Sep 6, 2024
fab267b
fixed pylint errors
m-baumgarten Sep 6, 2024
03f7b05
fixed remaining health errors
m-baumgarten Sep 6, 2024
40e9128
Merge branch 'develop' into multiel_holstein
linusjoonho Sep 6, 2024
b73fdd7
fixed examples and black
m-baumgarten Sep 7, 2024
cc4d29d
Merge branch 'multiel_holstein' of github.com:m-baumgarten/ipie_holst…
m-baumgarten Sep 7, 2024
fb69584
fixed example
m-baumgarten Sep 7, 2024
530c5ff
Merge branch 'develop' into multiel_holstein
linusjoonho Nov 5, 2024
42cdff4
Merge branch 'develop' into multiel_holstein
linusjoonho Nov 5, 2024
d9582f7
Merge branch 'develop' into multiel_holstein
linusjoonho Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions examples/13-1d_holstein/run_afqmc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import numpy as np
np.random.seed(125)
from mpi4py import MPI

from ipie.qmc.afqmc import AFQMC
from ipie.estimators.energy import EnergyEstimator
from ipie.systems import Generic
from ipie.addons.eph.hamiltonians.holstein import HolsteinModel
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
from ipie.addons.eph.trial_wavefunction.toyozawa import ToyozawaTrial
from ipie.addons.eph.trial_wavefunction.variational.toyozawa_variational import variational_trial_toyozawa
from ipie.addons.eph.walkers.eph_walkers import EphWalkers
from ipie.addons.eph.propagation.holstein import HolsteinPropagatorImportance
from ipie.qmc.options import QMCParams

#System Parameters
nup = 2
ndown = 2
nelec = [nup, ndown]

#Hamiltonian Parameters
g = 2.
t = 1.
w0 = 4.
nsites = 4
pbc = True

#Walker Parameters & Setup
comm = MPI.COMM_WORLD
nwalkers = 1000 // comm.size

#Setup initial guess for variational optimization
initial_electron = np.random.random((nsites, nup + ndown))
initial_phonons = np.ones(nsites) * 0.1

#System and Hamiltonian setup
system = Generic(nelec)
ham = HolsteinModel(g=g, t=t, w0=w0, nsites=nsites, pbc=pbc)
ham.build()

#Variational procedure
etrial, beta_shift, el_trial = variational_trial_toyozawa(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you settings this and not just recomputing it as a check?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this is a good unit test.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying I should load beta_shift and el_trial instead of computing them in the run script (and have a unites for variational_trial_toyozawa)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, computing them in the script is fine. I was saying the trial wavefunction should recompute the energy given your optimized orbitals / parameters. This is a useful sanity check when running jobs as we typically generate trials externally so it's a form of handshake to make sure everything is formatted / interpreted correctly. Here you're just setting them rather than recalculating them via the trial.

The unit test is separate and is just a simple assertion that building a trial wavefunction from your optimized parameters reproduces the variational energy.

initial_phonons, initial_electron, ham, system
)
wavefunction = np.column_stack([beta_shift, el_trial])

#Setup trial
trial = ToyozawaTrial(
wavefunction=wavefunction,
hamiltonian=ham,
num_elec=[nup, ndown],
num_basis=nsites
)
trial.set_etrial(etrial)

fdmalone marked this conversation as resolved.
Show resolved Hide resolved
#Setup walkers
walkers = EphWalkers(
initial_walker=wavefunction,
nup=nup,
ndown=ndown,
nbasis=nsites,
nwalkers=nwalkers
)
walkers.build(trial)

timestep = 0.01
propagator = HolsteinPropagatorImportance(timestep)
propagator.build(ham)

num_steps_per_block = 10
num_blocks = 10000
add_est = {
"energy": EnergyEstimator(
system=system, ham=ham, trial=trial
)
}

stabilize_freq = 5
pop_control_freq = 5
seed = 125
params = QMCParams(
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
num_walkers=nwalkers,
total_num_walkers=nwalkers * comm.size,
num_blocks=num_blocks,
num_steps_per_block=num_steps_per_block,
timestep=timestep,
num_stblz=stabilize_freq,
pop_control_freq=pop_control_freq,
rng_seed=seed,
)

ephqmc = AFQMC(system, ham, trial, walkers, propagator, params)
trial.calc_overlap(walkers) #Sets ovlp, ph and el overlaps
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
ephqmc.run(additional_estimators=add_est, verbose=False)

56 changes: 56 additions & 0 deletions ipie/addons/ephqmc/estimators/local_energy_holstein.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import numpy as np

from ipie.addons.eph.hamiltonians.holstein import HolsteinModel
from ipie.addons.eph.trial_wavefunction.eph_trial_base import EphTrialWavefunctionBase
from ipie.addons.eph.walkers.eph_walkers import EphWalkers
from ipie.systems.generic import Generic
from ipie.utils.backend import arraylib as xp


def local_energy_holstein(
system: Generic,
hamiltonian: HolsteinModel,
walkers: EphWalkers,
trial: EphTrialWavefunctionBase
):
"""Computes the local energy for the Holstein model."""
# energy = xp.zeros((walkers.nwalkers, 5), dtype=xp.complex128)
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved

# gf = trial.calc_greens_function(walkers)

# energy[:, 1] = np.sum(hamiltonian.T[0] * gf[0], axis=(1,2))
# if system.ndown > 0:
# energy[:, 1] += np.sum(hamiltonian.T[1] * gf[1], axis=(1,2))

# energy[:, 2] = np.sum(np.diagonal(gf[0], axis1=1, axis2=2) * walkers.x, axis=1)
# if system.ndown > 0:
# energy[:, 2] += np.sum(np.diagonal(gf[1], axis1=1, axis2=2) * walkers.x, axis=1)
# energy[:, 2] *= hamiltonian.const

# energy[:, 3] = 0.5 * hamiltonian.m * hamiltonian.w0**2 * np.sum(walkers.x**2, axis=1)
# energy[:, 3] -= 0.5 * hamiltonian.nsites * hamiltonian.w0
# energy[:, 4] = -0.5 * trial.calc_phonon_laplacian_locenergy(walkers) / hamiltonian.m

# energy[:, 0] = np.sum(energy[:,1:], axis=1)
##
energy = xp.zeros((walkers.nwalkers, 5), dtype=xp.complex128)

#get greens_function from estimators
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
gf = trial.calc_greens_function(walkers)

#TODO make this nicer
for n in range(walkers.nwalkers):
energy[n, 1] = np.einsum('ij->', hamiltonian.T[0] * gf[0][n] + hamiltonian.T[1] * gf[1][n])

#TODO this performs too many summations
energy[:, 2] = hamiltonian.const * np.einsum('nii,ni->n', gf[0] + gf[1], walkers.x)

energy[:, 3] = 0.5 * hamiltonian.m * hamiltonian.w0**2 * np.einsum('ni->n', walkers.x**2)
energy[:, 3] -= 0.5 * hamiltonian.nsites * hamiltonian.w0
energy[:, 4] = -0.5 * trial.calc_phonon_laplacian_locenergy(walkers) / hamiltonian.m
energy[:, 0] = np.sum(energy[:,1:], axis=1)

return energy



11 changes: 11 additions & 0 deletions ipie/addons/ephqmc/hamiltonians/generic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import numpy
from ipie.hamiltonians.generic_base import GenericBase
from ipie.utils.backend import arraylib as xp


class GenericElphBase(GenericBase):
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
""""""

def __init__(self, ):
pass

31 changes: 31 additions & 0 deletions ipie/addons/ephqmc/hamiltonians/holstein.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import numpy
from ipie.hamiltonians.generic_base import GenericBase
from ipie.utils.backend import arraylib as xp


class HolsteinModel(GenericBase):
"""Class for Holstein model carrying elph tensor and system parameters
"""
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, g: float, t: float, w0: float, nsites: int, pbc: bool):
self.g = g
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
self.t = t
self.w0 = w0
self.m = 1/self.w0
self.nsites = nsites
self.pbc = pbc
self.T = None
self.const = -self.g * numpy.sqrt(2. * self.m * self.w0)

def build(self):
self.T = numpy.diag(numpy.ones(self.nsites-1), 1)
self.T += numpy.diag(numpy.ones(self.nsites-1), -1)

if self.pbc:
self.T[0,-1] = self.T[-1,0] = 1.

self.T *= -self.t

self.T = [self.T.copy(), self.T.copy()]


182 changes: 182 additions & 0 deletions ipie/addons/ephqmc/propagation/holstein.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import numpy
import time
import scipy.linalg

from ipie.addons.eph.hamiltonians.holstein import HolsteinModel
from ipie.propagation.operations import propagate_one_body
from ipie.utils.backend import synchronize, cast_to_device
from ipie.propagation.continuous_base import PropagatorTimer

def construct_one_body_propagator(hamiltonian: HolsteinModel, dt: float):
""""""
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
H1 = hamiltonian.T
expH1 = numpy.array(
[scipy.linalg.expm(-0.5 * dt * H1[0]), scipy.linalg.expm(-0.5 * dt * H1[1])]
)
return expH1


class HolsteinPropagatorFree():
""""""
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, time_step, verbose=False):
self.dt = time_step
self.verbose = verbose
self.timer = PropagatorTimer()

self.sqrt_dt = self.dt**0.5
self.dt_ph = 0.5 * self.dt
self.mpi_handler = None

def build(self, hamiltonian) :
self.expH1 = construct_one_body_propagator(hamiltonian, self.dt)
self.const = hamiltonian.g * numpy.sqrt(2. * hamiltonian.m * hamiltonian.w0) * self.dt
self.w0 = hamiltonian.w0
self.m = hamiltonian.m
self.scale = numpy.sqrt(self.dt_ph / self.m)
self.nsites = hamiltonian.nsites

def propagate_walkers_one_body(self, walkers):
start_time = time.time()
walkers.phia = propagate_one_body(walkers.phia, self.expH1[0])
if walkers.ndown > 0 and not walkers.rhf:
walkers.phib = propagate_one_body(walkers.phib, self.expH1[1])
synchronize()
self.timer.tgemm += time.time() - start_time

def propagate_phonons(self, walkers):
start_time = time.time()

pot = 0.25 * self.m * self.w0**2 * numpy.sum(walkers.x**2, axis=1)
pot = numpy.real(pot)
walkers.weight *= numpy.exp(-self.dt_ph * pot)

N = numpy.random.normal(loc=0.0, scale=self.scale,
size=(walkers.nwalkers, self.nsites))
walkers.x = walkers.x + N
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved

pot = 0.25 * self.m * self.w0**2 * numpy.sum(walkers.x**2, axis=1)
pot = numpy.real(pot)
walkers.weight *= numpy.exp(-self.dt_ph * pot)

walkers.weight *= numpy.exp(self.dt_ph * self.nsites * self.w0 / 2) #doesnt matter for estimators

synchronize()
self.timer.tgemm += time.time() - start_time

def propagate_electron(self, walkers, trial):
start_time = time.time()
ovlp = trial.calc_greens_function(walkers)
synchronize()
self.timer.tgf += time.time() - start_time

expEph = numpy.exp(self.const * walkers.x)

walkers.phia = propagate_one_body(walkers.phia, self.expH1[0])
walkers.phia = numpy.einsum('ni,nie->nie', expEph, walkers.phia)
walkers.phia = propagate_one_body(walkers.phia, self.expH1[0])

if walkers.ndown > 0:
walkers.phib = propagate_one_body(walkers.phib, self.expH1[1])
walkers.phib = numpy.einsum('ni,nie->nie', expEph, walkers.phib)
walkers.phib = propagate_one_body(walkers.phib, self.expH1[1])

def propagate_walkers(self, walkers, hamiltonian, trial, eshift=None):
synchronize()
start_time = time.time()
ovlp = trial.calc_overlap(walkers)
synchronize()
self.timer.tgf += time.time() - start_time

# 2. Update Walkers
# 2.a DMC for phonon degrees of freedom
self.propagate_phonons(walkers)

# 2.b One-body propagation for electrons
self.propagate_electron(walkers, trial)

# 2.c DMC for phonon degrees of freedom
self.propagate_phonons(walkers)

# Update weights (and later do phaseless for multi-electron)
start_time = time.time()
ovlp_new = trial.calc_overlap(walkers)
synchronize()
self.timer.tovlp += time.time() - start_time

start_time = time.time()
self.update_weight(walkers, ovlp, ovlp_new)
synchronize()
self.timer.tupdate += time.time() - start_time


def update_weight(self, walkers, ovlp, ovlp_new):
walkers.weight *= ovlp_new / ovlp


class HolsteinPropagatorImportance(HolsteinPropagatorFree):
""""""
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, time_step, verbose=False):
super().__init__(time_step, verbose=verbose)

def propagate_phonons(self, walkers, hamiltonian, trial):
"""Propagates phonons via DMC"""
start_time = time.time()
#no ZPE in pot -> cancels with ZPE of etrial, wouldn't affect estimators anyways
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
ph_ovlp_old = trial.calc_phonon_overlap(walkers)

pot = 0.5 * hamiltonian.m * hamiltonian.w0**2 * numpy.sum(walkers.x**2, axis=1)
pot -= 0.5 * trial.calc_phonon_laplacian_importance(walkers) / hamiltonian.m
pot = numpy.real(pot)
walkers.weight *= numpy.exp(-self.dt_ph * pot / 2)

N = numpy.random.normal(loc=0.0, scale=self.scale, size=(walkers.nwalkers, self.nsites))
drift = trial.calc_phonon_gradient(walkers)
walkers.x = walkers.x + N + self.dt_ph * drift / hamiltonian.m

ph_ovlp_new = trial.calc_phonon_overlap(walkers)

pot = 0.5 * hamiltonian.m * hamiltonian.w0**2 * numpy.sum(walkers.x**2, axis=1)
pot -= 0.5 * trial.calc_phonon_laplacian_importance(walkers) / hamiltonian.m
pot = numpy.real(pot)
walkers.weight *= numpy.exp(-self.dt_ph * pot / 2)

walkers.weight *= ph_ovlp_old / ph_ovlp_new
walkers.weight *= numpy.exp(self.dt_ph * trial.energy)

synchronize()
self.timer.tgemm += time.time() - start_time


def propagate_walkers(self, walkers, hamiltonian, trial, eshift=None):
""""""
m-baumgarten marked this conversation as resolved.
Show resolved Hide resolved
synchronize()
start_time = time.time()

ovlp = trial.calc_overlap(walkers).copy()

synchronize()
self.timer.tgf += time.time() - start_time

# 2. Update Walkers
# 2.a DMC for phonon degrees of freedom
self.propagate_phonons(walkers, hamiltonian, trial)

# 2.b One-body propagation for electrons
self.propagate_electron(walkers, trial)

# 2.c DMC for phonon degrees of freedom
self.propagate_phonons(walkers, hamiltonian, trial)

start_time = time.time()

ovlp_new = trial.calc_overlap(walkers)
synchronize()
self.timer.tovlp += time.time() - start_time

start_time = time.time()

self.update_weight(walkers, ovlp, ovlp_new)

synchronize()
self.timer.tupdate += time.time() - start_time

Loading