.. _SecGW: Lattice GW ========== .. contents:: :local: :depth: 2 .. _BZ_def: As in the discussion of the :ref:`SecChain`, we will consider the Hubbard model, but we will assume here a translationally invariant system with periodic boundary conditions. The translational invariance implies that all observables and propagators are diagonal in momentum space. Hence, all quantities can be labeled by the reciprocal lattice vector :math:`\vec k` within the first Brillouin zone (BZ). This reduces the computational and storage complexity from :math:`\mathcal{O}(N_k^2)` for the real space formalism introduced in :ref:`SecChain` to :math:`\mathcal{O}(N_k)`. Moreover, the Dyson equation is diagonal in momentum space and can be efficiently parallelized using a distributed-memory parallelization based on MPI. .. _S4S6_1: Synopsis -------- We will consider a 1D chain described by the Hubbard model, see Eq. :eq:`eq:hubbmodel1`. The single particle part of the Hamiltonian can be diagonalized as .. math:: \hat{H}_0 = \sum_{\vec k,\sigma} \epsilon(\vec k) c_{\vec{k}\sigma}^{\dagger} c_{\vec{k}\sigma}, where we have introduced the free-electron dispersion :math:`\epsilon(\vec k)=-2 J \cos(\vec k_x)`. The system is excited via an electromagnetic excitation, which in translationally invariant systems is conveniently introduced using the Peierls substitution. The latter involves the vector potential :math:`\vec A(\vec r,t)` as a phase factor in the hopping .. math:: J\rightarrow J \exp\Bigg[-\frac{i q}{\hbar} \int_{\vec R_i}^{\vec R_j} d\vec r \vec A(\vec r,t)\Bigg], leading to a time-dependent single-particle dispersion .. math:: \epsilon(\vec k,t)=\epsilon(\vec k- q \vec A(t)/\hbar). In this example, we treat the dynamics within the :math:`GW` approximation. The numerical evaluation of the respective self-energy expressions is implemented in the C++ module ``gw_selfen_impl.cpp``. In momentum space, the correlation part of the :math:`GW` self-energy can be written as .. math:: :label: Eq:Sigmak \Sigma_{\vec k}(t,t^\prime)=\frac{i}{N_k} \sum_{\vec q} G_{\vec k-\vec q}(t,t^\prime) \delta W_{\vec q}(t,t^\prime), where we have introduced the Fourier transform of the propagator :math:`X_{\vec q}(t,t^\prime)=(1/N_k)\sum_{i} \exp(i (\vec r_i-\vec r_j) \vec q) X_{ij}(t,t^\prime)`, see also the previous :ref:`SecChain` discussion for the definition of the propagators. In line with the previous notation, we have introduced the dynamical part of the effective interaction :math:`\delta W_{\vec q}` via :math:`W_{\vec q}(t,t^\prime)=U\delta_\mathcal{C}(t,t^\prime)+\delta W_{\vec q}(t,t^\prime)`. The retarded part of the interaction is obtained as a solution of the Dyson-like equation .. math:: :label: Eq:Wk W_{\vec k}(t,t')=U\delta_\mathcal{C}(t,t^\prime)+ U [ \Pi_{\vec k} \ast W_{\vec k} ](t,t^\prime), the Fourier transform of the polarization is given by .. math:: :label: Eq:Pol \Pi_{\vec k}(t,t')= \frac{-i}{N_k} \sum_{\vec q} G_{\vec k+\vec q}(t,t') G_{\vec q}(t',t). .. _S4S6_2: MPI parallelization ------------------- The main advantage of the translational invariance is that the propagators and corresponding Dyson equations are diagonal in momentum space. This leads to a significant speed-up of calculations since the most complex operation, the solutions of the VIE, can be performed in parallel. Moreover, the main bottleneck to reach longer propagation times is the memory restriction imposed by the hardware. The usage of the MPI parallelization scheme over momentum points alleviates this problem because memory can be distributed among different nodes. The Dyson equation is diagonal in the momentum space and it is convenient to introduce a class called ``kpoint`` that includes all propagators and corresponding methods for a given momentum point :math:`\vec q`. In terms of data, the ``kpoint`` class includes single and two particle propagators for a given momentum point :math:`\vec q`, namely :math:`G_{\vec q}` and :math:`W_{\vec q}`, as well as the self-energy :math:`\Sigma_{\vec q}` and the polarization :math:`\Pi_{\vec q}`. The routines include wrappers around VIE2 solvers to solve the single-particle and two-particle Dyson equations. While the Dyson equation is diagonal in momentum space, the evaluation of the self-energy diagrams mixes information between different momentum points and requires communication between different ranks. The communication between different ranks is performed using the ``cntr::distributed_timestep_array`` as described in the MPI section of the manual. Users should be careful that the simple example code presented there includes a global object of type ``cntr::herm_matrix_timestep_view``, which only allocates memory if a given momentum is owned by that rank. In the following implementation we will rather work with a local copy of this object on every rank. The latter produces only a minimal overhead in the memory usage and simplifies the implementation. The strategy to compute the :math:`GW` self-energy :math:`\mathcal{T}[\Sigma_{\vec{k}}]_n` at time step :math:`n` thus consists of two steps: 1. At time :math:`t_n`, communicate the latest time slice of the Green's functions :math:`\mathcal{T}[G_{\vec k}]_n` and retarded interactions :math:`\mathcal{T}[W_{\vec k}]_n` for all momentum points among all MPI ranks. 2. Evaluate the self-energy diagram :math:`\mathcal{T}[\Sigma_{\vec k_{\text{rank}}}]_n` in Eq. :eq:`Eq:Sigmak` for a subset of momentum points :math:`\vec k_{\text{rank}}` present on a given rank using the routine ``cntr::Bubble2``. Step 1 is implemented as .. code-block:: cpp void gather_gk_timestep(int tstp,int Nk_rank,DIST_TIMESTEP &gk_all_timesteps,std::vector &corrK_rank,std::vector &kindex_rank){ gk_all_timesteps.reset_tstp(tstp); for(int k=0;k` ``SolverOrder``. The selfconsistency iterations include the communication of all fermionic and bosonic propagators between different ranks using the routine ``gather_gk_timestep`` (introduced above) and the determination of the local propagators using a routine ``get_loc`` .. code-block:: cpp for(int iter=0;iter<=MatsMaxIter;iter++){ // update propagators via MPI diag::gather_gk_timestep(tstp,Nk_rank,gk_all_timesteps,corrK_rank,kindex_rank); diag::gather_wk_timestep(tstp,Nk_rank,wk_all_timesteps,corrK_rank,kindex_rank); diag::set_density_k(tstp,Norb,Nk,gk_all_timesteps,lattice,density_k,kindex_rank,rho_loc); diag::get_loc(tstp,Ntau,Norb,Nk,lattice,Gloc,gk_all_timesteps); diag::get_loc(tstp,Ntau,Norb,Nk,lattice,Wloc,wk_all_timesteps); } As on each MPI rank, the momentum-dependent single-particle density matrix :math:`\rho(\vec k)` is known for the whole BZ, the evaluation of the HF contribution is done as in :ref:`SecChain`. The self-energies :math:`\Sigma_{k_{\text{rank}}}` for the momentum points :math:`k_{\text{rank}}=0,\ldots,N_{\text{rank}}-1` on each rank are obtained by the routine ``sigma_GW`` (introduced above). .. code-block:: cpp // update mean field and self-energy for(int k=0;k