Skip to content
Snippets Groups Projects
Commit 06d1a482 authored by Johanna Zijderveld's avatar Johanna Zijderveld
Browse files

change the optimizer kwargs to make convergence behave better

parent 6d791558
No related branches found
No related tags found
1 merge request!7Examples
Pipeline #179657 passed
...@@ -91,7 +91,7 @@ def compute_sol(U, h_0, nk, filling=2): ...@@ -91,7 +91,7 @@ def compute_sol(U, h_0, nk, filling=2):
} }
guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0])) guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0]))
full_model = pymf.Model(h_0, h_int, filling) full_model = pymf.Model(h_0, h_int, filling)
mf_sol = pymf.solver(full_model, guess, nk=nk) mf_sol = pymf.solver(full_model, guess, nk=nk, optimizer_kwargs={"M":0})
return pymf.add_tb(h_0, mf_sol) return pymf.add_tb(h_0, mf_sol)
......
%% Cell type:code id:cb509096-42c6-4a45-8dc4-a8eed3116e67 tags: %% Cell type:code id:cb509096-42c6-4a45-8dc4-a8eed3116e67 tags:
``` python ``` python
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pymf import pymf
from tqdm import tqdm from tqdm import tqdm
``` ```
%% Cell type:markdown id:396d935c-146e-438c-878b-04ed70aa6d63 tags: %% Cell type:markdown id:396d935c-146e-438c-878b-04ed70aa6d63 tags:
To simulate infinite systems, we provide the corresponding tight-binding model. To simulate infinite systems, we provide the corresponding tight-binding model.
We exemplify this construction by computing the ground state of an infinite spinful chain with onsite interactions. We exemplify this construction by computing the ground state of an infinite spinful chain with onsite interactions.
Because the ground state is an antiferromagnet, so we must build a two-atom cell. We name the two sublattices, $A$ and $B$. The Hamiltonian in is: Because the ground state is an antiferromagnet, so we must build a two-atom cell. We name the two sublattices, $A$ and $B$. The Hamiltonian in is:
$$ $$
H_0 = \sum_i c_{i, B}^{\dagger}c_{i, A} + c_{i, A}^{\dagger}c_{i+1, B} + h.c. H_0 = \sum_i c_{i, B}^{\dagger}c_{i, A} + c_{i, A}^{\dagger}c_{i+1, B} + h.c.
$$ $$
We write down the spinful by simply taking $H_0(k) \otimes \mathbb{1}$. We write down the spinful by simply taking $H_0(k) \otimes \mathbb{1}$.
%% Cell type:code id:5529408c-fb7f-4732-9a17-97b0718dab29 tags: %% Cell type:code id:5529408c-fb7f-4732-9a17-97b0718dab29 tags:
``` python ``` python
hopp = np.kron(np.array([[0, 1], [0, 0]]), np.eye(2)) hopp = np.kron(np.array([[0, 1], [0, 0]]), np.eye(2))
h_0 = {(0,): hopp + hopp.T.conj(), (1,): hopp, (-1,): hopp.T.conj()} h_0 = {(0,): hopp + hopp.T.conj(), (1,): hopp, (-1,): hopp.T.conj()}
``` ```
%% Cell type:markdown id:050f5435-6699-44bb-b31c-8ef3fa2264d4 tags: %% Cell type:markdown id:050f5435-6699-44bb-b31c-8ef3fa2264d4 tags:
To build the tight-binding model, we need to generate a Hamiltonian on a k-point and the corresponding hopping vectors to generate a guess. We then verify the spectrum and see that the bands indeed consistent of two bands due to the Brillouin zone folding. To build the tight-binding model, we need to generate a Hamiltonian on a k-point and the corresponding hopping vectors to generate a guess. We then verify the spectrum and see that the bands indeed consistent of two bands due to the Brillouin zone folding.
%% Cell type:code id:b39a2976-7c35-4670-83ef-12157bd3fc0e tags: %% Cell type:code id:b39a2976-7c35-4670-83ef-12157bd3fc0e tags:
``` python ``` python
# Set number of k-points # Set number of k-points
nk = 100 nk = 100
ks = np.linspace(0, 2*np.pi, nk, endpoint=False) ks = np.linspace(0, 2*np.pi, nk, endpoint=False)
hamiltonians_0 = pymf.tb_to_khamvector(h_0, nk, ks=ks) hamiltonians_0 = pymf.tb_to_khamvector(h_0, nk, ks=ks)
# Perform diagonalization # Perform diagonalization
vals, vecs = np.linalg.eigh(hamiltonians_0) vals, vecs = np.linalg.eigh(hamiltonians_0)
# Plot data # Plot data
plt.plot(ks, vals, c="k") plt.plot(ks, vals, c="k")
plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"]) plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"])
plt.xlim(0, 2 * np.pi) plt.xlim(0, 2 * np.pi)
plt.ylabel("$E - E_F$") plt.ylabel("$E - E_F$")
plt.xlabel("$k / a$") plt.xlabel("$k / a$")
plt.show() plt.show()
``` ```
%% Output %% Output
%% Cell type:markdown id:6ec53b08-053b-4aad-87a6-525dd7f61687 tags: %% Cell type:markdown id:6ec53b08-053b-4aad-87a6-525dd7f61687 tags:
Here, in the workflow to find the ground state, we use a helper function to build the initial guess. because we don't need a dense k-point grid in the self-consistent loop, we compute the spectrum later on a denser k-point grid. Here, in the workflow to find the ground state, we use a helper function to build the initial guess. because we don't need a dense k-point grid in the self-consistent loop, we compute the spectrum later on a denser k-point grid.
%% Cell type:markdown id:dc59e440-1289-4735-9ae8-b04d0d13c94a tags: %% Cell type:markdown id:dc59e440-1289-4735-9ae8-b04d0d13c94a tags:
Finally, we compute the eigen0alues for a set of Ualues of $U$. For this case, since the interaction is onsite only, the interaction matrix is simply Finally, we compute the eigen0alues for a set of Ualues of $U$. For this case, since the interaction is onsite only, the interaction matrix is simply
$$ $$
H_{int} = H_{int} =
\left(\begin{array}{cccc} \left(\begin{array}{cccc}
U & U & 0 & 0\\ U & U & 0 & 0\\
U & U & 0 & 0\\ U & U & 0 & 0\\
0 & 0 & U & U\\ 0 & 0 & U & U\\
0 & 0 & U & U 0 & 0 & U & U
\end{array}\right)~. \end{array}\right)~.
$$ $$
%% Cell type:code id:32b9e7c5-db12-44f9-930c-21e5494404b8 tags: %% Cell type:code id:32b9e7c5-db12-44f9-930c-21e5494404b8 tags:
``` python ``` python
def compute_sol(U, h_0, nk, filling=2): def compute_sol(U, h_0, nk, filling=2):
h_int = { h_int = {
(0,): U * np.kron(np.eye(2), np.ones((2, 2))), (0,): U * np.kron(np.eye(2), np.ones((2, 2))),
} }
guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0])) guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0]))
full_model = pymf.Model(h_0, h_int, filling) full_model = pymf.Model(h_0, h_int, filling)
mf_sol = pymf.solver(full_model, guess, nk=nk) mf_sol = pymf.solver(full_model, guess, nk=nk, optimizer_kwargs={"M":0})
return pymf.add_tb(h_0, mf_sol) return pymf.add_tb(h_0, mf_sol)
def compute_gap_and_vals(full_sol, nk_dense, fermi_energy=0): def compute_gap_and_vals(full_sol, nk_dense, fermi_energy=0):
h_kgrid = pymf.tb_to_khamvector(full_sol, nk_dense) h_kgrid = pymf.tb_to_khamvector(full_sol, nk_dense)
vals = np.linalg.eigvalsh(h_kgrid) vals = np.linalg.eigvalsh(h_kgrid)
emax = np.max(vals[vals <= fermi_energy]) emax = np.max(vals[vals <= fermi_energy])
emin = np.min(vals[vals > fermi_energy]) emin = np.min(vals[vals > fermi_energy])
return np.abs(emin - emax), vals return np.abs(emin - emax), vals
def compute_phase_diagram( def compute_phase_diagram(
Us, Us,
nk, nk,
nk_dense, nk_dense,
): ):
gaps = [] gaps = []
vals = [] vals = []
for U in tqdm(Us): for U in tqdm(Us):
full_sol = compute_sol(U, h_0, nk) full_sol = compute_sol(U, h_0, nk)
gap, _vals = compute_gap_and_vals(full_sol, nk_dense) gap, _vals = compute_gap_and_vals(full_sol, nk_dense)
gaps.append(gap) gaps.append(gap)
vals.append(_vals) vals.append(_vals)
return np.asarray(gaps, dtype=float), np.asarray(vals) return np.asarray(gaps, dtype=float), np.asarray(vals)
``` ```
%% Cell type:code id:6a8c08a9-7e31-420b-b6b4-709abfb26793 tags: %% Cell type:code id:6a8c08a9-7e31-420b-b6b4-709abfb26793 tags:
``` python ``` python
# Interaction strengths # Interaction strengths
Us = np.linspace(0.5, 10, 20, endpoint=True) Us = np.linspace(0.5, 10, 20, endpoint=True)
nk, nk_dense = 40, 100 nk, nk_dense = 40, 100
gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense) gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense)
``` ```
%% Output %% Output
75%|███████▌ | 15/20 [00:02<00:00, 5.07it/s]/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.07651e-17): result may not be accurate. 75%|███████▌ | 15/20 [00:02<00:00, 5.07it/s]/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.07651e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.54968e-17): result may not be accurate. /Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.54968e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.17567e-17): result may not be accurate. /Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.17567e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.88621e-17): result may not be accurate. /Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=8.88621e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.35564e-17): result may not be accurate. /Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.35564e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
/Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.73285e-17): result may not be accurate. /Users/rzijderveld/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py:1072: LinAlgWarning: Ill-conditioned matrix (rcond=9.73285e-17): result may not be accurate.
gamma = solve(self.a, df_f) gamma = solve(self.a, df_f)
85%|████████▌ | 17/20 [00:06<00:01, 2.47it/s] 85%|████████▌ | 17/20 [00:06<00:01, 2.47it/s]
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
NoConvergence Traceback (most recent call last) NoConvergence Traceback (most recent call last)
/var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/1169016709.py in <module> /var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/1169016709.py in <module>
2 Us = np.linspace(0.5, 10, 20, endpoint=True) 2 Us = np.linspace(0.5, 10, 20, endpoint=True)
3 nk, nk_dense = 40, 100 3 nk, nk_dense = 40, 100
----> 4 gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense) ----> 4 gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense)
/var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3682270308.py in compute_phase_diagram(Us, nk, nk_dense) /var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3682270308.py in compute_phase_diagram(Us, nk, nk_dense)
26 vals = [] 26 vals = []
27 for U in tqdm(Us): 27 for U in tqdm(Us):
---> 28 full_sol = compute_sol(U, h_0, nk) ---> 28 full_sol = compute_sol(U, h_0, nk)
29 gap, _vals = compute_gap_and_vals(full_sol, nk_dense) 29 gap, _vals = compute_gap_and_vals(full_sol, nk_dense)
30 gaps.append(gap) 30 gaps.append(gap)
/var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3682270308.py in compute_sol(U, h_0, nk, filling) /var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3682270308.py in compute_sol(U, h_0, nk, filling)
5 guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0])) 5 guess = pymf.generate_guess(frozenset(h_int), len(list(h_0.values())[0]))
6 full_model = pymf.Model(h_0, h_int, filling) 6 full_model = pymf.Model(h_0, h_int, filling)
----> 7 mf_sol = pymf.solver(full_model, guess, nk=nk) ----> 7 mf_sol = pymf.solver(full_model, guess, nk=nk)
8 return pymf.add_tb(h_0, mf_sol) 8 return pymf.add_tb(h_0, mf_sol)
9 9
~/kwant-scf/pymf/solvers.py in solver(Model, mf_guess, nk, optimizer, optimizer_kwargs) ~/kwant-scf/pymf/solvers.py in solver(Model, mf_guess, nk, optimizer, optimizer_kwargs)
60 f = partial(cost, Model=Model, nk=nk) 60 f = partial(cost, Model=Model, nk=nk)
61 result = rparams_to_tb( 61 result = rparams_to_tb(
---> 62 optimizer(f, mf_params, **optimizer_kwargs), list(Model.h_int), shape ---> 62 optimizer(f, mf_params, **optimizer_kwargs), list(Model.h_int), shape
63 ) 63 )
64 fermi = calculate_fermi_energy(add_tb(Model.h_0, result), Model.filling, nk=nk) 64 fermi = calculate_fermi_energy(add_tb(Model.h_0, result), Model.filling, nk=nk)
~/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py in anderson(F, xin, iter, alpha, w0, M, verbose, maxiter, f_tol, f_rtol, x_tol, x_rtol, tol_norm, line_search, callback, **kw) ~/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py in anderson(F, xin, iter, alpha, w0, M, verbose, maxiter, f_tol, f_rtol, x_tol, x_rtol, tol_norm, line_search, callback, **kw)
~/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py in nonlin_solve(F, x0, jacobian, iter, verbose, maxiter, f_tol, f_rtol, x_tol, x_rtol, tol_norm, line_search, callback, full_output, raise_exception) ~/opt/anaconda3/lib/python3.9/site-packages/scipy/optimize/_nonlin.py in nonlin_solve(F, x0, jacobian, iter, verbose, maxiter, f_tol, f_rtol, x_tol, x_rtol, tol_norm, line_search, callback, full_output, raise_exception)
239 else: 239 else:
240 if raise_exception: 240 if raise_exception:
--> 241 raise NoConvergence(_array_like(x, x0)) --> 241 raise NoConvergence(_array_like(x, x0))
242 else: 242 else:
243 status = 2 243 status = 2
NoConvergence: [ 1.86715628e+00 4.47287535e-02 -1.23356829e-04 1.20430729e-03 NoConvergence: [ 1.86715628e+00 4.47287535e-02 -1.23356829e-04 1.20430729e-03
4.47287535e-02 2.63543104e+00 2.63234161e-03 3.71702031e-03 4.47287535e-02 2.63543104e+00 2.63234161e-03 3.71702031e-03
-1.23356829e-04 2.63234161e-03 1.86002862e+00 4.51677226e-02 -1.23356829e-04 2.63234161e-03 1.86002862e+00 4.51677226e-02
1.20430729e-03 3.71702031e-03 4.51677226e-02 2.64245378e+00 1.20430729e-03 3.71702031e-03 4.51677226e-02 2.64245378e+00
0.00000000e+00 1.61192759e-01 -1.51104882e-03 1.47113079e-03 0.00000000e+00 1.61192759e-01 -1.51104882e-03 1.47113079e-03
-1.61192759e-01 0.00000000e+00 5.03808388e-03 1.99828384e-03 -1.61192759e-01 0.00000000e+00 5.03808388e-03 1.99828384e-03
1.51104882e-03 -5.03808388e-03 0.00000000e+00 1.64032886e-01 1.51104882e-03 -5.03808388e-03 0.00000000e+00 1.64032886e-01
-1.47113079e-03 -1.99828384e-03 -1.64032886e-01 0.00000000e+00] -1.47113079e-03 -1.99828384e-03 -1.64032886e-01 0.00000000e+00]
%% Cell type:code id:e17fc96c-c463-4e1f-8250-c254d761b92a tags: %% Cell type:code id:e17fc96c-c463-4e1f-8250-c254d761b92a tags:
``` python ``` python
import xarray as xr import xarray as xr
ds = xr.Dataset( ds = xr.Dataset(
data_vars=dict(vals=(["Us", "ks", "n"], vals), gap=(["Us"], gap)), data_vars=dict(vals=(["Us", "ks", "n"], vals), gap=(["Us"], gap)),
coords=dict( coords=dict(
Us=Us, Us=Us,
ks=np.linspace(0, 2 * np.pi, nk_dense), ks=np.linspace(0, 2 * np.pi, nk_dense),
n=np.arange(vals.shape[-1]) n=np.arange(vals.shape[-1])
), ),
) )
``` ```
%% Cell type:markdown id:5a87dcc1-208b-4602-abad-a870037ec95f tags: %% Cell type:markdown id:5a87dcc1-208b-4602-abad-a870037ec95f tags:
We observe that as the interaction strength increases, a gap opens due to the antiferromagnetic ordering. We observe that as the interaction strength increases, a gap opens due to the antiferromagnetic ordering.
%% Cell type:code id:50f02d06 tags: %% Cell type:code id:50f02d06 tags:
``` python ``` python
plt.scatter(Us, gap) plt.scatter(Us, gap)
``` ```
%% Output %% Output
<matplotlib.collections.PathCollection at 0x7fe0a154a130> <matplotlib.collections.PathCollection at 0x7fe0a154a130>
%% Cell type:code id:868cf368-45a0-465e-b042-6182ff8b6998 tags: %% Cell type:code id:868cf368-45a0-465e-b042-6182ff8b6998 tags:
``` python ``` python
ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5) ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5)
plt.axhline(0, ls="--", c="k") plt.axhline(0, ls="--", c="k")
plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"]) plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"])
plt.xlim(0, 2 * np.pi) plt.xlim(0, 2 * np.pi)
plt.ylabel("$E - E_F$") plt.ylabel("$E - E_F$")
plt.xlabel("$k / a$") plt.xlabel("$k / a$")
plt.show() plt.show()
``` ```
%% Output %% Output
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
AttributeError Traceback (most recent call last) AttributeError Traceback (most recent call last)
/var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3492086229.py in <module> /var/folders/yf/2jcxwgld3l77h6y62fb5ty8ssr_5lq/T/ipykernel_78867/3492086229.py in <module>
----> 1 ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5) ----> 1 ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5)
2 plt.axhline(0, ls="--", c="k") 2 plt.axhline(0, ls="--", c="k")
3 plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"]) 3 plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"])
4 plt.xlim(0, 2 * np.pi) 4 plt.xlim(0, 2 * np.pi)
5 plt.ylabel("$E - E_F$") 5 plt.ylabel("$E - E_F$")
AttributeError: '_PlotMethods' object has no attribute 'scatter' AttributeError: '_PlotMethods' object has no attribute 'scatter'
%% Cell type:markdown id:0761ed33-c1bb-4f12-be65-cb68629f58b9 tags: %% Cell type:markdown id:0761ed33-c1bb-4f12-be65-cb68629f58b9 tags:
The Hartree-Fock dispersion should follow (see [these notes](https://www.cond-mat.de/events/correl11/manuscript/Lechermann.pdf)) The Hartree-Fock dispersion should follow (see [these notes](https://www.cond-mat.de/events/correl11/manuscript/Lechermann.pdf))
$$ $$
\epsilon_{HF}^{\sigma}(\mathbf{k}) = \epsilon(\mathbf{k}) + U \left(\frac{n}{2} + \sigma m\right) \epsilon_{HF}^{\sigma}(\mathbf{k}) = \epsilon(\mathbf{k}) + U \left(\frac{n}{2} + \sigma m\right)
$$ $$
where $m=(\langle n_{i\uparrow} \rangle - \langle n_{i\downarrow} \rangle) / 2$ is the magnetization per atom and $n = \sum_i \langle n_i \rangle$ is the total number of atoms per cell. Thus, for the antiferromagnetic groundstate, $m=1/2$ and $n=2$. The gap thus should be $\Delta=U$. And we can confirm it indeed follows the expected trend. where $m=(\langle n_{i\uparrow} \rangle - \langle n_{i\downarrow} \rangle) / 2$ is the magnetization per atom and $n = \sum_i \langle n_i \rangle$ is the total number of atoms per cell. Thus, for the antiferromagnetic groundstate, $m=1/2$ and $n=2$. The gap thus should be $\Delta=U$. And we can confirm it indeed follows the expected trend.
%% Cell type:code id:ac2eb725-f3bd-4d5b-a509-85d0d0071958 tags: %% Cell type:code id:ac2eb725-f3bd-4d5b-a509-85d0d0071958 tags:
``` python ``` python
ds.gap.plot() ds.gap.plot()
plt.plot(ds.Us, ds.Us) plt.plot(ds.Us, ds.Us)
plt.show() plt.show()
``` ```
%% Output %% Output
%% Cell type:markdown id:06e0d356-558e-40e3-8287-d7d2e0bee8cd tags: %% Cell type:markdown id:06e0d356-558e-40e3-8287-d7d2e0bee8cd tags:
We can also fit We can also fit
%% Cell type:code id:5499ea62-cf1b-4a13-8191-ebb73ea38704 tags: %% Cell type:code id:5499ea62-cf1b-4a13-8191-ebb73ea38704 tags:
``` python ``` python
ds.gap.polyfit(dim="Us", deg=1).polyfit_coefficients[0].data ds.gap.polyfit(dim="Us", deg=1).polyfit_coefficients[0].data
``` ```
%% Output %% Output
array(0.9997852) array(0.9997852)
%% Cell type:code id:0cb395cd-84d1-49b4-89dd-da7a2d09c8d0 tags: %% Cell type:code id:0cb395cd-84d1-49b4-89dd-da7a2d09c8d0 tags:
``` python ``` python
ds.to_netcdf("./data/1d_hubbard_example.nc") ds.to_netcdf("./data/1d_hubbard_example.nc")
``` ```
%% Cell type:code id:ce428241 tags: %% Cell type:code id:ce428241 tags:
``` python ``` python
```{code-cell} ipython3 ```{code-cell} ipython3
def compute_phase_diagram( def compute_phase_diagram(
Us, Us,
nk, nk,
nk_dense, nk_dense,
filling=2, filling=2,
): ):
gap = [] gap = []
vals = [] vals = []
for U in tqdm(Us): for U in tqdm(Us):
# onsite interactions # onsite interactions
guess = utils.generate_guess(frozenset(h_int), len(list(h_0.values())[0])) guess = utils.generate_guess(frozenset(h_int), len(list(h_0.values())[0]))
full_model = Model(h_0, h_int, filling) full_model = Model(h_0, h_int, filling)
mf_sol = solver(full_model, guess, nk=nk) mf_sol = solver(full_model, guess, nk=nk)
hkfunc = transforms.tb_to_kfunc(add_tb(h_0, mf_sol)) hkfunc = transforms.tb_to_kfunc(add_tb(h_0, mf_sol))
ks_dense = np.linspace(0, 2 * np.pi, nk_dense, endpoint=False) ks_dense = np.linspace(0, 2 * np.pi, nk_dense, endpoint=False)
hkarray = np.array([hkfunc(kx) for kx in ks_dense]) hkarray = np.array([hkfunc(kx) for kx in ks_dense])
_vals = np.linalg.eigvalsh(hkarray) _vals = np.linalg.eigvalsh(hkarray)
_gap = (utils.compute_gap(add_tb(h_0, mf_sol), fermi_energy=0, nk=nk_dense)) _gap = (utils.compute_gap(add_tb(h_0, mf_sol), fermi_energy=0, nk=nk_dense))
gap.append(_gap) gap.append(_gap)
vals.append(_vals) vals.append(_vals)
return np.asarray(gap, dtype=float), np.asarray(vals) return np.asarray(gap, dtype=float), np.asarray(vals)
import xarray as xr import xarray as xr
ds = xr.Dataset( ds = xr.Dataset(
data_vars=dict(vals=(["Us", "ks", "n"], vals), gap=(["Us"], gap)), data_vars=dict(vals=(["Us", "ks", "n"], vals), gap=(["Us"], gap)),
coords=dict( coords=dict(
Us=Us, Us=Us,
ks=np.linspace(0, 2 * np.pi, nk_dense), ks=np.linspace(0, 2 * np.pi, nk_dense),
n=np.arange(vals.shape[-1]) n=np.arange(vals.shape[-1])
), ),
) )
# Interaction strengths # Interaction strengths
Us = np.linspace(0.5, 10, 20, endpoint=True) Us = np.linspace(0.5, 10, 20, endpoint=True)
nk, nk_dense = 40, 100 nk, nk_dense = 40, 100
gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense) gap, vals = compute_phase_diagram(Us=Us, nk=nk, nk_dense=nk_dense)
ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5) ds.vals.plot.scatter(x="ks", hue="Us", ec=None, s=5)
plt.axhline(0, ls="--", c="k") plt.axhline(0, ls="--", c="k")
plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"]) plt.xticks([0, np.pi, 2 * np.pi], ["$0$", "$\pi$", "$2\pi$"])
plt.xlim(0, 2 * np.pi) plt.xlim(0, 2 * np.pi)
plt.ylabel("$E - E_F$") plt.ylabel("$E - E_F$")
plt.xlabel("$k / a$") plt.xlabel("$k / a$")
plt.show() plt.show()
``` ```
The Hartree-Fock dispersion should follow (see [these notes](https://www.cond-mat.de/events/correl11/manuscript/Lechermann.pdf)) The Hartree-Fock dispersion should follow (see [these notes](https://www.cond-mat.de/events/correl11/manuscript/Lechermann.pdf))
$$ $$
\epsilon_{HF}^{\sigma}(\mathbf{k}) = \epsilon(\mathbf{k}) + U \left(\frac{n}{2} + \sigma m\right) \epsilon_{HF}^{\sigma}(\mathbf{k}) = \epsilon(\mathbf{k}) + U \left(\frac{n}{2} + \sigma m\right)
$$ $$
where $m=(\langle n_{i\uparrow} \rangle - \langle n_{i\downarrow} \rangle) / 2$ is the magnetization per atom and $n = \sum_i \langle n_i \rangle$ is the total number of atoms per cell. Thus, for the antiferromagnetic groundstate, $m=1/2$ and $n=2$. The gap thus should be $\Delta=U$. And we can confirm it indeed follows the expected trend. where $m=(\langle n_{i\uparrow} \rangle - \langle n_{i\downarrow} \rangle) / 2$ is the magnetization per atom and $n = \sum_i \langle n_i \rangle$ is the total number of atoms per cell. Thus, for the antiferromagnetic groundstate, $m=1/2$ and $n=2$. The gap thus should be $\Delta=U$. And we can confirm it indeed follows the expected trend.
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment