From 2a8a7cc18ed4b49c2a38cbbaae33b4f4c4bb4d42 Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 16:06:55 +0800 Subject: [PATCH 1/8] add batched refactorization in rgf kernel --- dpnegf/negf/recursive_green_cal.py | 323 ++++++++++++++++------------- 1 file changed, 178 insertions(+), 145 deletions(-) diff --git a/dpnegf/negf/recursive_green_cal.py b/dpnegf/negf/recursive_green_cal.py index bb66388..03719e2 100644 --- a/dpnegf/negf/recursive_green_cal.py +++ b/dpnegf/negf/recursive_green_cal.py @@ -1,13 +1,18 @@ import torch.linalg as tLA import torch -def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, +def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, sd, su, sl, s_in=0, s_out=0, eta=1e-5, need_lesser=False, need_greater=False, need_gr_lc=False): """The recursive Green's function algorithm is taken from M. P. Anantram, M. S. Lundstrom and D. E. Nikonov, Proceedings of the IEEE, 96, 1511 - 1550 (2008) DOI: 10.1109/JPROC.2008.927355 + Batched form: every tensor carries a leading energy-batch dim B. Diagonal + blocks have shape ``[B, n_q, n_q]`` and the energy argument is ``[B]``. + Scalar callers go through :func:`recursive_gf`, which broadcasts to B=1 + and squeezes the leading dim back out. + In order to get the electron correlation function output, the parameters s_in has to be set. For the hole correlation function, the parameter s_out has to be set. @@ -15,22 +20,24 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, Parameters ---------- - energy : torch.Tensor (dtype=torch.float) - Energy array - mat_d_list : list of torch.Tensor (dtype=torch.float) - List of diagonal blocks - mat_u_list : list of torch.Tensor (dtype=torch.float) - List of upper-diagonal blocks - mat_l_list : list of torch.Tensor (dtype=torch.float) - List of lower-diagonal blocks + energy : torch.Tensor (dtype=torch.complex) + Energy array of shape ``[B]``. + mat_d_list : list of torch.Tensor (dtype=torch.complex) + List of diagonal blocks, each of shape ``[B, n_q, n_q]``. + mat_u_list : list of torch.Tensor (dtype=torch.complex) + List of upper-diagonal blocks, each of shape ``[B, n_q, n_{q+1}]``. + mat_l_list : list of torch.Tensor (dtype=torch.complex) + List of lower-diagonal blocks, each of shape ``[B, n_{q+1}, n_q]``. s_in : - (Default value = 0) + (Default value = 0). When ``need_lesser`` is True, a list of + ``[B, n_q, n_q]`` tensors. s_out : - (Default value = 0) + (Default value = 0). When ``need_greater`` is True, a list of + ``[B, n_q, n_q]`` tensors. eta : (Default value = 0.000001j) need_lesser : bool, optional - Whether to calculate the lesser Green's function, by default False. + Whether to calculate the lesser Green's function, by default False. Lesser Green's function is used for electron density and current density calculation. need_greater : bool, optional Whether to calculate the greater Green's function, by default False. @@ -40,89 +47,66 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, gr_lc is used for lead spectral function A_L/ A_R = G^r * Gamma_L/R * G^a calculation. Although set need_gr_lc to True would not increase the computational cost of the recursive Green's function algorithm, it would increase the memory cost. If the memory cost is a concern, it is recommended to set need_gr_lc to False. + Returns ------- - g_trans : torch.Tensor (dtype=torch.complex) - [0, N-1] block of the retarded Green's function responsible for transmission - gr_lc: torch.Tensor (dtype=torch.complex) - Last column [:, N-1] blocks of the retarded Green's function responsible for transmission - grd : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the retarded Green's function - grl : torch.Tensor (dtype=torch.complex) - Lower diagonal blocks of the retarded Green's function - gru : torch.Tensor (dtype=torch.complex) - Upper diagonal blocks of the retarded Green's function - gr_left : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the Left-conencted retarded Green's function - gnd : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the lesser Green's function - gnl : torch.Tensor (dtype=torch.complex) - Lower diagonal blocks of the lesser Green's function - gnu : torch.Tensor (dtype=torch.complex) - Upper diagonal blocks of the lesser Green's function - gin_left : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the Left-conencted lesser Green's function - gpd : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the greater Green's function - gpl : torch.Tensor (dtype=torch.complex) - Lower diagonal blocks of the greater Green's function - gpu : torch.Tensor (dtype=torch.complex) - Upper diagonal blocks of the greater Green's function - gip_left : torch.Tensor (dtype=torch.complex) - Diagonal blocks of the Left-conencted greater Green's function + All returned blocks carry a leading batch dim ``B``. """ - # ------------------------------------------------------------------- - # ---------- convert input arrays to the matrix data type ----------- - # ----------------- in case they are not matrices ------------------- - # ------------------------------------------------------------------- if need_lesser: assert isinstance(s_in, list), "Lesser Green's function calculation requires s_in to be a list of coupling matrices" if need_greater: assert isinstance(s_out, list), "Greater Green's function calculation requires s_out to be a list of coupling matrices" - for jj, item in enumerate(mat_d_list): - mat_d_list[jj] = mat_d_list[jj] - (energy+1j*eta) * sd[jj] - for jj, item in enumerate(mat_l_list): - mat_l_list[jj] = mat_l_list[jj] - (energy+1j*eta) * sl[jj] - for jj, item in enumerate(mat_u_list): - mat_u_list[jj] = mat_u_list[jj] - (energy+1j*eta) * su[jj] - # computes matrix sizes - num_of_matrices = len(mat_d_list) # Number of diagonal blocks. - mat_shapes = [item.shape for item in mat_d_list] # This gives the sizes of the diagonal matrices. + # energy enters as a [B]-shaped (or broadcastable) complex tensor; reshape + # so it multiplies into [B, n, n] block tensors along the batch dim. + e_bcast = (energy + 1j * eta).view(-1, 1, 1) + + for jj in range(len(mat_d_list)): + mat_d_list[jj] = mat_d_list[jj] - e_bcast * sd[jj] + for jj in range(len(mat_l_list)): + mat_l_list[jj] = mat_l_list[jj] - e_bcast * sl[jj] + for jj in range(len(mat_u_list)): + mat_u_list[jj] = mat_u_list[jj] - e_bcast * su[jj] + num_of_matrices = len(mat_d_list) + mat_shapes = [item.shape for item in mat_d_list] # [B, n_q, n_q] + ref = mat_d_list[0] + B = ref.shape[0] + + def _batched_eye(n): + return torch.eye(n, dtype=ref.dtype, device=ref.device).expand(B, n, n) # ------------------------------------------------------------------- # -------------- compute retarded Green's function ------------------ # ------------------------------------------------------------------- # Firstly calculate the left-connected retarded Green's function gr_left = [None for _ in range(num_of_matrices)] - gr_left[0] = tLA.solve(-mat_d_list[0], torch.eye(mat_shapes[0][0], dtype=mat_d_list[0].dtype)) # Initialising the retarded left connected. + gr_left[0] = tLA.solve(-mat_d_list[0], _batched_eye(mat_shapes[0][-1])) for q in range(num_of_matrices - 1): # Recursive algorithm (B2) - gr_left[q + 1] = tLA.solve(-mat_d_list[q + 1] - mat_l_list[q] @ gr_left[q] @ mat_u_list[q], - torch.eye(mat_shapes[q + 1][0], dtype=mat_d_list[0].dtype)) # The left connected recursion. - # ------------------------------------------------------------------- - - grl = [None for _ in range(num_of_matrices-1)] - gru = [None for _ in range(num_of_matrices-1)] - grd = [i.clone() for i in gr_left] # Our glorious benefactor. + gr_left[q + 1] = tLA.solve( + -mat_d_list[q + 1] - mat_l_list[q] @ gr_left[q] @ mat_u_list[q], + _batched_eye(mat_shapes[q + 1][-1]), + ) + + grl = [None for _ in range(num_of_matrices - 1)] + gru = [None for _ in range(num_of_matrices - 1)] + grd = [i.clone() for i in gr_left] g_trans = gr_left[len(gr_left) - 1].clone() if need_gr_lc: gr_lc = [gr_left[len(gr_left) - 1].clone()] else: gr_lc = None for q in range(num_of_matrices - 2, -1, -1): # Recursive algorithm - grl[q] = grd[q + 1] @ mat_l_list[q] @ gr_left[q] # (B5) We get the off-diagonal blocks for free. - gru[q] = gr_left[q] @ mat_u_list[q] @ grd[q + 1] # (B6) because we need .Tthem.T for the next calc: - grd[q] = gr_left[q] + gr_left[q] @ mat_u_list[q] @ grl[q] # (B4) I suppose I could also use the lower. - g_trans = gr_left[q] @ mat_u_list[q] @ g_trans # iteratively calculate the (0, N-1) block of the retarded Green's function responsible for transmission + grl[q] = grd[q + 1] @ mat_l_list[q] @ gr_left[q] # (B5) + gru[q] = gr_left[q] @ mat_u_list[q] @ grd[q + 1] # (B6) + grd[q] = gr_left[q] + gr_left[q] @ mat_u_list[q] @ grl[q] # (B4) + g_trans = gr_left[q] @ mat_u_list[q] @ g_trans if need_gr_lc: - gr_lc.append(g_trans) # The last coloumn of the retarded Green's function: (:, N-1) block of the retarded Green's function + gr_lc.append(g_trans) if need_gr_lc: gr_lc.reverse() - - # ------------------------------------------------------------------- # ------ compute the electron correlation function ( Lesser Green Function ) if needed -------- # ------------------------------------------------------------------- @@ -131,31 +115,25 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, assert isinstance(s_in, list), "need_lesser=True requires s_in to be a list of coupling matrices" gin_left = [None for _ in range(num_of_matrices)] # Keldysh formula: G^< = G^r * Sigma^< * G^a ====> (-i * G^<) = G^r * (-i * Sigma^<) * G^a - gin_left[0] = gr_left[0] @ s_in[0] @ gr_left[0].conj().T + gin_left[0] = gr_left[0] @ s_in[0] @ gr_left[0].mH for q in range(num_of_matrices - 1): - # sla2: coupling with the left layer - # s_in[q + 1]: coupling directly with the q+1 layer from lead sla2 = mat_l_list[q] @ gin_left[q] @ mat_u_list[q] prom = s_in[q + 1] + sla2 - gin_left[q + 1] = gr_left[q + 1] @ prom @ gr_left[q + 1].conj().T - - # --------------------------------------------------------------- + gin_left[q + 1] = gr_left[q + 1] @ prom @ gr_left[q + 1].mH - gnl = [None for _ in range(num_of_matrices-1)] - gnu = [None for _ in range(num_of_matrices-1)] + gnl = [None for _ in range(num_of_matrices - 1)] + gnu = [None for _ in range(num_of_matrices - 1)] gnd = [i.clone() for i in gin_left] - for q in range(num_of_matrices - 2, -1, -1): # Recursive algorithm + for q in range(num_of_matrices - 2, -1, -1): gnl[q] = grd[q + 1] @ mat_l_list[q] @ gin_left[q] + \ - gnd[q + 1] @ mat_l_list[q] @ gr_left[q].conj().T # (B10) + gnd[q + 1] @ mat_l_list[q] @ gr_left[q].mH # (B10) gnd[q] = gin_left[q] + \ - gr_left[q] @ mat_u_list[q] @ gnd[q + 1] @ mat_l_list[q] @ \ - gr_left[q].conj().T + \ - ((gin_left[q] @ mat_u_list[q] @ gru[q].conj().T) + (gru[q] @ - mat_l_list[q] @ gin_left[q])) # (B11) - - gnu[q] = gnl[q].conj().T + gr_left[q] @ mat_u_list[q] @ gnd[q + 1] @ mat_l_list[q] @ gr_left[q].mH + \ + ((gin_left[q] @ mat_u_list[q] @ gru[q].mH) + + (gru[q] @ mat_l_list[q] @ gin_left[q])) # (B11) + gnu[q] = gnl[q].mH # ------------------------------------------------------------------- # -------- compute the hole correlation function if needed ---------- @@ -171,58 +149,54 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, prom = s_out[q + 1] + sla2 gip_left[q + 1] = gr_left[q + 1] @ prom @ gr_left[q + 1].conj() - # --------------------------------------------------------------- - - gpl = [None for _ in range(num_of_matrices-1)] - gpu = [None for _ in range(num_of_matrices-1)] + gpl = [None for _ in range(num_of_matrices - 1)] + gpu = [None for _ in range(num_of_matrices - 1)] gpd = [i.clone() for i in gip_left] - for q in range(num_of_matrices - 2, -1, -1): # Recursive algorithm + for q in range(num_of_matrices - 2, -1, -1): gpl[q] = grd[q + 1] @ mat_l_list[q] @ gip_left[q] + \ gpd[q + 1] @ mat_l_list[q].conj() @ gr_left[q].conj() gpd[q] = gip_left[q] + \ - gr_left[q] @ mat_u_list[q] @ gpd[q + 1] @ mat_l_list[q].conj() @ \ - gr_left[q].conj()+ \ - ((gip_left[q]@ mat_u_list[q].conj() @ grl[q].conj()) + (gru[q] @ - mat_l_list[q] @ gip_left[q])) - - gpu[q] = gpl[q].conj().T + gr_left[q] @ mat_u_list[q] @ gpd[q + 1] @ mat_l_list[q].conj() @ gr_left[q].conj() + \ + ((gip_left[q] @ mat_u_list[q].conj() @ grl[q].conj()) + + (gru[q] @ mat_l_list[q] @ gip_left[q])) + gpu[q] = gpl[q].mH # ------------------------------------------------------------------- # -- remove energy from the main diagonal of th Hamiltonian matrix -- # ------------------------------------------------------------------- - for jj, item in enumerate(mat_d_list): - mat_d_list[jj] = mat_d_list[jj] + (energy + 1j * eta) * sd[jj] - for jj, item in enumerate(mat_l_list): - mat_l_list[jj] = mat_l_list[jj] + (energy + 1j * eta) * sl[jj] - for jj, item in enumerate(mat_u_list): - mat_u_list[jj] = mat_u_list[jj] + (energy + 1j * eta) * su[jj] + for jj in range(len(mat_d_list)): + mat_d_list[jj] = mat_d_list[jj] + e_bcast * sd[jj] + for jj in range(len(mat_l_list)): + mat_l_list[jj] = mat_l_list[jj] + e_bcast * sl[jj] + for jj in range(len(mat_u_list)): + mat_u_list[jj] = mat_u_list[jj] + e_bcast * su[jj] # ------------------------------------------------------------------- # ---- choose a proper output depending on the list of arguments ---- # ------------------------------------------------------------------- if not need_lesser and not need_greater: - return g_trans,gr_lc, \ + return g_trans, gr_lc, \ grd, grl, gru, gr_left, \ None, None, None, None, \ None, None, None, None elif need_lesser and not need_greater: - return g_trans,gr_lc, \ + return g_trans, gr_lc, \ grd, grl, gru, gr_left, \ gnd, gnl, gnu, gin_left, \ None, None, None, None elif not need_lesser and need_greater: - return g_trans,gr_lc, \ + return g_trans, gr_lc, \ grd, grl, gru, gr_left, \ None, None, None, None, \ gpd, gpl, gpu, gip_left else: - return g_trans,gr_lc, \ + return g_trans, gr_lc, \ grd, grl, gru, gr_left, \ gnd, gnl, gnu, gin_left, \ gpd, gpl, gpu, gip_left @@ -230,23 +204,26 @@ def recursive_gf_cal(energy, mat_l_list, mat_d_list, mat_u_list, def recursive_gf(energy, hl, hd, hu, sd, su, sl, left_se, right_se, seP=None, E_ref=0.0, s_in=0, s_out=0, eta=1e-5, need_lesser=False, need_greater=False, need_gr_lc=False): - + """The recursive Green's function algorithm is taken from M. P. Anantram, M. S. Lundstrom and D. E. Nikonov, Proceedings of the IEEE, 96, 1511 - 1550 (2008) DOI: 10.1109/JPROC.2008.927355 - Obitan various green function for later calculations. + Obtain various Green's functions for later calculations. + + Accepts either a scalar/0-d ``energy`` (legacy callers) or a 1-D ``[B]`` + energy tensor. In the scalar case, all inputs are broadcast to B=1, the + batched kernel runs, and the leading batch dim is squeezed back out so + return shapes match the legacy contract. In the batched case, every + energy-dependent input (``left_se``, ``right_se``, ``s_in``, ``s_out``, + ``seP``) must already carry the leading ``[B, ...]`` dim, and the + k-dependent blocks (``hd``, ``sd``, ``hl``, ``hu``, ``sl``, ``su``) may + arrive 2-D and will be expanded to ``[B, ...]`` zero-copy. Parameters ---------- - energy : torch.Tensor (dtype=torch.float) - Energy array - mat_d_list : list of torch.Tensor (dtype=torch.float) - List of diagonal blocks - mat_u_list : list of torch.Tensor (dtype=torch.float) - List of upper-diagonal blocks - mat_l_list : list of torch.Tensor (dtype=torch.float) - List of lower-diagonal blocks + energy : torch.Tensor + Scalar (0-d) or 1-D ``[B]`` complex tensor. s_in : Coupling Matrix Gamma from leads to the device (Default value = 0) s_out : @@ -254,63 +231,119 @@ def recursive_gf(energy, hl, hd, hu, sd, su, sl, left_se, right_se, seP=None, E_ eta : (Default value = 0.000001j) need_lesser : bool, optional - Whether to calculate the lesser Green's function, by default False. + Whether to calculate the lesser Green's function, by default False. Lesser Green's function is used for electron density and current density calculation. need_greater : bool, optional Whether to calculate the greater Green's function, by default False. Greater Green's function is used for hole density and phase-breaking scattering case. need_gr_lc : bool, optional Whether to calculate the left-connected blocks of the retarded Green's function responsible for transmission, - by default False for memory saving. + by default False for memory saving. Returns ------- ans: tuple of torch.Tensor - The output of the recursive Green's function calculation + The output of the recursive Green's function calculation. Leading + batch dim is squeezed when the caller passed a scalar energy. """ shift_energy = energy + E_ref - # shift_energy = torch.scalar_tensor(shift_energy, dtype=torch.complex128) - - # if isinstance(hd,torch.Tensor): # hd, hl, hu are torch.nested.nested_tensor - # temp_mat_d_list = [hd[i] * 1. for i in range(hd.size(0))] - # temp_mat_l_list = [hl[i] * 1. for i in range(hl.size(0))] - # temp_mat_u_list = [hu[i] * 1. for i in range(hu.size(0))] - # else: - temp_mat_d_list = [hd[i] * 1. for i in range(len(hd))] - temp_mat_l_list = [hl[i] * 1. for i in range(len(hl))] - temp_mat_u_list = [hu[i] * 1. for i in range(len(hu))] + if not torch.is_tensor(shift_energy): + shift_energy = torch.as_tensor(shift_energy, dtype=torch.complex128) + # Legacy scalar callers pass either a 0-d tensor or a length-1 1-D tensor + # together with 2-D Hamiltonian / self-energy inputs. + # Batched callers pass a 1-D ``[B]`` energy together with 3-D ``[B, n, n]`` tensors. + # Use the rank of ``left_se`` (or ``right_se``) as the disambiguator so the + # wrapper can squeeze the batch dim back out for scalar callers. + # se_probe is used to determine whether the self-energy inputs are 2-D (scalar energy case) or 3-D (batched energy case). + se_probe = left_se if isinstance(left_se, torch.Tensor) else right_se + squeezed = isinstance(se_probe, torch.Tensor) and se_probe.ndim == 2 + # if squeezed = True, the wrapper will squeeze the leading batch dim from every output tensor; + # if False, the wrapper leaves the leading batch dim in place. + if shift_energy.ndim == 0: + shift_energy = shift_energy.reshape(1) + elif squeezed and shift_energy.ndim == 1 and shift_energy.shape[0] == 1: + pass # already shape [1]; kernel runs B=1, wrapper will squeeze + B = shift_energy.shape[0] + + def _to_batch(t): + if t.ndim == 2: + return t.unsqueeze(0).expand(B, -1, -1) + return t + + temp_mat_d_list = [_to_batch(hd[i]) * 1. for i in range(len(hd))] + temp_mat_l_list = [_to_batch(hl[i]) * 1. for i in range(len(hl))] + temp_mat_u_list = [_to_batch(hu[i]) * 1. for i in range(len(hu))] + sd_b = [_to_batch(sd[i]) for i in range(len(sd))] + sl_b = [_to_batch(sl[i]) for i in range(len(sl))] + su_b = [_to_batch(su[i]) for i in range(len(su))] + if seP is not None: + seP_b = [_to_batch(seP[i]) if torch.is_tensor(seP[i]) else seP[i] for i in range(len(seP))] for i in range(len(temp_mat_d_list)): - temp_mat_d_list[i] = temp_mat_d_list[i] + seP[i] + temp_mat_d_list[i] = temp_mat_d_list[i] + seP_b[i] + else: + seP_b = None if isinstance(left_se, torch.Tensor): - s01, s02 = temp_mat_d_list[0].shape - se01, se02 = left_se.shape + left_se_b = _to_batch(left_se) + s01, s02 = temp_mat_d_list[0].shape[-2], temp_mat_d_list[0].shape[-1] + se01, se02 = left_se_b.shape[-2], left_se_b.shape[-1] idx0, idy0 = min(s01, se01), min(s02, se02) - temp_mat_d_list[0][:idx0,:idy0] = temp_mat_d_list[0][:idx0,:idy0] + left_se[:idx0,:idy0] + temp_mat_d_list[0][:, :idx0, :idy0] = temp_mat_d_list[0][:, :idx0, :idy0] + left_se_b[:, :idx0, :idy0] + else: + left_se_b = left_se if isinstance(right_se, torch.Tensor): - s11, s12 = temp_mat_d_list[-1].shape - se11, se12 = right_se.shape + right_se_b = _to_batch(right_se) + s11, s12 = temp_mat_d_list[-1].shape[-2], temp_mat_d_list[-1].shape[-1] + se11, se12 = right_se_b.shape[-2], right_se_b.shape[-1] idx1, idy1 = min(s11, se11), min(s12, se12) - # right_se = right_se[-idx1:, -idy1:] - temp_mat_d_list[-1][-idx1:, -idy1:] = temp_mat_d_list[-1][-idx1:, -idy1:] + right_se[-idx1:, -idy1:] + temp_mat_d_list[-1][:, -idx1:, -idy1:] = temp_mat_d_list[-1][:, -idx1:, -idy1:] + right_se_b[:, -idx1:, -idy1:] + else: + right_se_b = right_se + + # s_in / s_out arrive as lists when the lesser/greater paths are active. + if isinstance(s_in, list): + s_in_b = [_to_batch(t) if torch.is_tensor(t) else t for t in s_in] + else: + s_in_b = s_in + if isinstance(s_out, list): + s_out_b = [_to_batch(t) if torch.is_tensor(t) else t for t in s_out] + else: + s_out_b = s_out - ans = recursive_gf_cal(shift_energy, temp_mat_l_list, temp_mat_d_list, temp_mat_u_list, sd, su, sl, - s_in=s_in, s_out=s_out, eta=eta, - need_lesser=need_lesser, - need_greater=need_greater, + ans = recursive_gf_cal(shift_energy, temp_mat_l_list, temp_mat_d_list, temp_mat_u_list, sd_b, su_b, sl_b, + s_in=s_in_b, s_out=s_out_b, eta=eta, + need_lesser=need_lesser, + need_greater=need_greater, need_gr_lc=need_gr_lc) if isinstance(left_se, torch.Tensor): - temp_mat_d_list[0][:idx0, :idy0] = temp_mat_d_list[0][:idx0, :idy0] - left_se[:idx0, :idy0] + temp_mat_d_list[0][:, :idx0, :idy0] = temp_mat_d_list[0][:, :idx0, :idy0] - left_se_b[:, :idx0, :idy0] if isinstance(right_se, torch.Tensor): - temp_mat_d_list[-1][-idx1:, -idy1:] = temp_mat_d_list[-1][-idx1:, -idy1:] - right_se[-idx1:, -idy1:] + temp_mat_d_list[-1][:, -idx1:, -idy1:] = temp_mat_d_list[-1][:, -idx1:, -idy1:] - right_se_b[:, -idx1:, -idy1:] if seP is not None: for i in range(len(temp_mat_d_list)): - temp_mat_d_list[i] = temp_mat_d_list[i] - seP[i] - - return ans \ No newline at end of file + temp_mat_d_list[i] = temp_mat_d_list[i] - seP_b[i] + + if squeezed: + ans = _squeeze_ans(ans) + + return ans + + +def _squeeze_ans(ans): + """Squeeze the leading batch dim from every tensor / list-of-tensors in the + RGF return tuple so scalar-energy callers see the original 2-D shapes.""" + def _sq(x): + if x is None: + return None + if torch.is_tensor(x): + return x.squeeze(0) + if isinstance(x, list): + return [t.squeeze(0) if torch.is_tensor(t) else t for t in x] + return x + return tuple(_sq(x) for x in ans) From 54497c9e0095847badee522e1f1b519c5deefe46 Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 16:07:10 +0800 Subject: [PATCH 2/8] add batched RGF unit test --- dpnegf/tests/test_recursive_gf_batched.py | 184 ++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 dpnegf/tests/test_recursive_gf_batched.py diff --git a/dpnegf/tests/test_recursive_gf_batched.py b/dpnegf/tests/test_recursive_gf_batched.py new file mode 100644 index 0000000..9d8cc64 --- /dev/null +++ b/dpnegf/tests/test_recursive_gf_batched.py @@ -0,0 +1,184 @@ +"""Correctness + GPU smoke tests for the batched recursive Green's function kernel. + +The kernel in ``dpnegf/negf/recursive_green_cal.py`` was rewritten to accept +a leading energy-batch dim. These tests pin the contract: + +1. Batched call over B energies == stack of B scalar calls (allclose 1e-10). +2. Same inputs moved to CUDA produce the same result (allclose 1e-8). + +The CUDA test is skipped on machines without a GPU. +""" + +import pytest +import torch + +from dpnegf.negf.recursive_green_cal import recursive_gf + + +def _make_btd_inputs(B, block_sizes, seed=0, device="cpu", dtype=torch.complex128): + """Build a synthetic block-tridiagonal Hamiltonian + overlap and lead self- + energies for B energies. Returns the lists in the shape ``recursive_gf`` + expects from a batched caller (k-blocks 2-D, energy-dep tensors leading-B).""" + g = torch.Generator(device="cpu").manual_seed(seed) + + def _randc(*shape): + return (torch.randn(*shape, generator=g, dtype=torch.float64) + + 1j * torch.randn(*shape, generator=g, dtype=torch.float64)).to(dtype).to(device) + + N = len(block_sizes) + + hd, sd = [], [] + for n in block_sizes: + h = _randc(n, n) + h = 0.5 * (h + h.mH) # hermitian diagonal block + hd.append(h) + s = torch.eye(n, dtype=dtype, device=device) + sd.append(s) + + hl, hu, sl, su = [], [], [], [] + for q in range(N - 1): + n_q, n_qp = block_sizes[q], block_sizes[q + 1] + u = _randc(n_q, n_qp) + hu.append(u) + hl.append(u.mH) # H_l = H_u^H so the full H is hermitian + su.append(torch.zeros(n_q, n_qp, dtype=dtype, device=device)) + sl.append(torch.zeros(n_qp, n_q, dtype=dtype, device=device)) + + n0, nN = block_sizes[0], block_sizes[-1] + left_se = _randc(B, n0, n0) + right_se = _randc(B, nN, nN) + # batched energy grid; small imaginary offset stays inside the eta envelope + energies = (torch.linspace(-1.0, 1.0, B, dtype=torch.float64, device=device) + + 1j * 1e-4).to(dtype) + + return hd, sd, hl, hu, sl, su, left_se, right_se, energies + + +def _stack_scalar(hd, sd, hl, hu, sl, su, left_se, right_se, energies, + need_lesser=False, s_in_batched=None): + """Drive the scalar path B times and stack the results along a new dim 0.""" + B = energies.shape[0] + per_e = [] + for b in range(B): + s_in_b = 0 + if need_lesser: + s_in_b = [s_in_batched[q][b] for q in range(len(s_in_batched))] + ans = recursive_gf( + energy=energies[b], + hl=hl, hd=hd, hu=hu, sd=sd, su=su, sl=sl, + left_se=left_se[b], right_se=right_se[b], + s_in=s_in_b, + eta=1e-5, + need_lesser=need_lesser, + need_gr_lc=True, + ) + per_e.append(ans) + + def _stack_field(idx): + first = per_e[0][idx] + if first is None: + return None + if torch.is_tensor(first): + return torch.stack([per_e[b][idx] for b in range(B)], dim=0) + # list of per-block tensors + return [torch.stack([per_e[b][idx][q] for b in range(B)], dim=0) + for q in range(len(first))] + + return tuple(_stack_field(i) for i in range(len(per_e[0]))) + + +def _assert_ans_close(stacked, batched, atol): + for s, b in zip(stacked, batched): + if s is None: + assert b is None + continue + if torch.is_tensor(s): + assert torch.allclose(s, b, atol=atol), \ + f"tensor mismatch: max abs diff {(s - b).abs().max().item():.3e}" + else: + for sq, bq in zip(s, b): + assert torch.allclose(sq, bq, atol=atol), \ + f"list-elem mismatch: max abs diff {(sq - bq).abs().max().item():.3e}" + + +def test_batched_matches_scalar_retarded(): + B = 16 + block_sizes = [8, 6, 8] + hd, sd, hl, hu, sl, su, left_se, right_se, energies = _make_btd_inputs(B, block_sizes) + + stacked = _stack_scalar(hd, sd, hl, hu, sl, su, left_se, right_se, energies, + need_lesser=False) + + batched = recursive_gf( + energy=energies, + hl=hl, hd=hd, hu=hu, sd=sd, su=su, sl=sl, + left_se=left_se, right_se=right_se, + s_in=0, eta=1e-5, + need_lesser=False, need_gr_lc=True, + ) + + _assert_ans_close(stacked, batched, atol=1e-10) + + +def test_batched_matches_scalar_lesser(): + B = 8 + block_sizes = [6, 6, 6] + hd, sd, hl, hu, sl, su, left_se, right_se, energies = _make_btd_inputs( + B, block_sizes, seed=1) + + rng = torch.Generator(device="cpu").manual_seed(2) + s_in_batched = [] + for n in block_sizes: + x = (torch.randn(B, n, n, generator=rng, dtype=torch.float64) + + 1j * torch.randn(B, n, n, generator=rng, dtype=torch.float64)).to(torch.complex128) + # Hermitize so s_in resembles a physical -i*(Sigma^< - Sigma^<^dag); + # the kernel doesn't enforce this but it keeps test inputs sane. + s_in_batched.append(0.5 * (x + x.mH)) + + stacked = _stack_scalar(hd, sd, hl, hu, sl, su, left_se, right_se, energies, + need_lesser=True, s_in_batched=s_in_batched) + + batched = recursive_gf( + energy=energies, + hl=hl, hd=hd, hu=hu, sd=sd, su=su, sl=sl, + left_se=left_se, right_se=right_se, + s_in=s_in_batched, eta=1e-5, + need_lesser=True, need_gr_lc=True, + ) + + _assert_ans_close(stacked, batched, atol=1e-10) + + +@pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA not available") +def test_batched_cuda_smoke(): + B = 16 + block_sizes = [8, 6, 8] + cpu_inputs = _make_btd_inputs(B, block_sizes, device="cpu") + cuda_inputs = _make_btd_inputs(B, block_sizes, device="cuda") + + cpu_ans = recursive_gf( + energy=cpu_inputs[-1], + hl=cpu_inputs[2], hd=cpu_inputs[0], hu=cpu_inputs[3], + sd=cpu_inputs[1], su=cpu_inputs[5], sl=cpu_inputs[4], + left_se=cpu_inputs[6], right_se=cpu_inputs[7], + s_in=0, eta=1e-5, need_lesser=False, need_gr_lc=True, + ) + cuda_ans = recursive_gf( + energy=cuda_inputs[-1], + hl=cuda_inputs[2], hd=cuda_inputs[0], hu=cuda_inputs[3], + sd=cuda_inputs[1], su=cuda_inputs[5], sl=cuda_inputs[4], + left_se=cuda_inputs[6], right_se=cuda_inputs[7], + s_in=0, eta=1e-5, need_lesser=False, need_gr_lc=True, + ) + + for c, g in zip(cpu_ans, cuda_ans): + if c is None: + assert g is None + continue + if torch.is_tensor(c): + assert g.device.type == "cuda" + assert torch.allclose(c, g.cpu(), atol=1e-8) + else: + for cq, gq in zip(c, g): + assert gq.device.type == "cuda" + assert torch.allclose(cq, gq.cpu(), atol=1e-8) From d4ffc8e7aad918c9e61b0b17e1d2190f97e6742d Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 21:32:03 +0800 Subject: [PATCH 3/8] =?UTF-8?q?.conj().T=20=E2=86=92=20.mH=20in=20sigmaLR2?= =?UTF-8?q?Gamma=20so=20lead.gamma=20works=20on=20both=20[n,n]=20and=20[B,?= =?UTF-8?q?n,n]=20self-energies.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dpnegf/negf/lead_property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnegf/negf/lead_property.py b/dpnegf/negf/lead_property.py index 5e8feec..9390bda 100644 --- a/dpnegf/negf/lead_property.py +++ b/dpnegf/negf/lead_property.py @@ -450,7 +450,7 @@ def sigmaLR2Gamma(self, se): The Gamma function, Gamma = 1j(se-se^dagger). ''' - return 1j * (se - se.conj().T) + return 1j * (se - se.mH) def fermi_dirac(self, x) -> torch.Tensor: return 1 / (1 + torch.exp((x - self.chemiPot_lead)/ self.kBT)) From f42120382841188294124dcf212804ca4a065ce9 Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 22:30:49 +0800 Subject: [PATCH 4/8] refactor device_property.py for batched-E calculaiton --- dpnegf/negf/device_property.py | 101 +++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/dpnegf/negf/device_property.py b/dpnegf/negf/device_property.py index 4dcc0a2..d4179c4 100644 --- a/dpnegf/negf/device_property.py +++ b/dpnegf/negf/device_property.py @@ -16,6 +16,20 @@ """ log = logging.getLogger(__name__) + +def _build_s_in_batched(hd, seinL, seinR, idx0, idy0, idx1, idy1): + '''Allocate per-block [B, n_q, n_q] zeros and inject the corner self-energy slices. + + Mirrors the scalar construction in cal_green_function (the seinL/seinR fed in + here are the already-scaled 1j*(seL - seL.mH) * f tensors of shape [B,n,n]). + ''' + B = seinL.shape[0] + s_in = [torch.zeros((B,) + tuple(blk.shape), dtype=torch.complex128) for blk in hd] + s_in[0][:, :idx0, :idy0] = s_in[0][:, :idx0, :idy0] + seinL[:, :idx0, :idy0] + s_in[-1][:, -idx1:, -idy1:] = s_in[-1][:, -idx1:, -idy1:] + seinR[:, -idx1:, -idy1:] + return s_in + + class DeviceProperty(object): '''Device object for NEGF calculation @@ -150,8 +164,12 @@ def cal_green_function(self, energy, kpoint, eta_device=0., block_tridiagonal=Tr A boolean parameter that indicates whether the last column blocks of the retarded Green's function are needed. ''' assert len(np.array(kpoint).reshape(-1)) == 3 - if not isinstance(energy, torch.Tensor): - energy = torch.tensor(energy, dtype=torch.complex128) + energy = torch.as_tensor(energy, dtype=torch.complex128) + if energy.ndim == 0: + energy = energy.reshape(1) + assert energy.ndim == 1, f"energy must be 0-d, scalar, or 1-D [B]; got shape {tuple(energy.shape)}" + B = energy.shape[0] + batched_mode = B > 1 self.block_tridiagonal = block_tridiagonal if self.kpoint is None or abs(self.kpoint - torch.tensor(kpoint)).sum() > 1e-5: @@ -200,21 +218,26 @@ def cal_green_function(self, energy, kpoint, eta_device=0., block_tridiagonal=Tr seL = self.lead_L.se seR = self.lead_R.se + if batched_mode: + assert seL.ndim == 3 and seR.ndim == 3, f"In batched mode, the self-energy should have shape [B,n,n], but got {seL.shape} and {seR.shape}" + else: + assert seL.ndim == 2 and seR.ndim == 2, f"In non-batched mode, the self-energy should have shape [n,n], but got {seL.shape} and {seR.shape}" + s01, s02 = self.hd[0].shape # The shape of the first H block - se01, se02 = seL.shape # The shape of the left self-energy + se01, se02 = seL.shape[-2], seL.shape[-1] # last two dims work for [n,n] and [B,n,n] s11, s12 = self.hd[-1].shape - se11, se12 = seR.shape + se11, se12 = seR.shape[-2], seR.shape[-1] idx0, idy0 = min(s01, se01), min(s02, se02) idx1, idy1 = min(s11, se11), min(s12, se12) if block_tridiagonal: # Based on the block tridiagonal algorithm, the shape of the self-energy should be - # equal to or larger than the corresponding Hamiltonian block + # equal to or lesser than the corresponding Hamiltonian block if se01 > s01 or se02 > s02: log.warning(f"The shape of left self-energy ({se01},{se02}) is larger than\ the first Hamiltonian block ({s01},{s02}).") raise ValueError("Left Lead Self Energy size is larger than the first Hamiltonian Block.") if se11 > s11 or se12 > s12: - log.warning(f"The shape of right self-energy ({se11},{se12}) is different from\ + log.warning(f"The shape of right self-energy ({se11},{se12}) is larger than\ the last Hamiltonian block ({s11},{s12}).") raise ValueError("Right Lead Self Energy size is larger than the last Hamiltonian Block.") @@ -222,11 +245,18 @@ def cal_green_function(self, energy, kpoint, eta_device=0., block_tridiagonal=Tr if need_lesser: # Fluctuation-Dissipation theorem; only build s_in when the lesser GF is consumed - seinL = 1j*(seL-seL.conj().T) * self.lead_L.fermi_dirac(energy+self.E_ref).reshape(-1) - seinR = 1j*(seR-seR.conj().T) * self.lead_R.fermi_dirac(energy+self.E_ref).reshape(-1) - s_in = [torch.zeros(i.shape).cdouble() for i in self.hd] - s_in[0][:idx0,:idy0] = s_in[0][:idx0,:idy0] + seinL[:idx0,:idy0] - s_in[-1][-idx1:,-idy1:] = s_in[-1][-idx1:,-idy1:] + seinR[-idx1:,-idy1:] + if batched_mode: + fL = self.lead_L.fermi_dirac(energy + self.E_ref).reshape(B, 1, 1) + fR = self.lead_R.fermi_dirac(energy + self.E_ref).reshape(B, 1, 1) + seinL = 1j * (seL - seL.mH) * fL + seinR = 1j * (seR - seR.mH) * fR + s_in = _build_s_in_batched(self.hd, seinL, seinR, idx0, idy0, idx1, idy1) + else: + seinL = 1j*(seL-seL.conj().T) * self.lead_L.fermi_dirac(energy+self.E_ref).reshape(-1) + seinR = 1j*(seR-seR.conj().T) * self.lead_R.fermi_dirac(energy+self.E_ref).reshape(-1) + s_in = [torch.zeros(i.shape).cdouble() for i in self.hd] + s_in[0][:idx0,:idy0] = s_in[0][:idx0,:idy0] + seinL[:idx0,:idy0] + s_in[-1][-idx1:,-idy1:] = s_in[-1][-idx1:,-idy1:] + seinR[-idx1:,-idy1:] else: s_in = 0 @@ -322,26 +352,36 @@ def _cal_current_nscf_(self, energy_grid, tc): def _cal_tc_(self): - '''calculate the transmission coefficient - + '''calculate the transmission coefficient + Returns ------- - tc is the transmission coefficient - + tc is the transmission coefficient + ''' - tx, ty = self.g_trans.shape - lx, ly = self.lead_L.se.shape - rx, ry = self.lead_R.se.shape + g_trans = self.g_trans + batched = g_trans.ndim == 3 + tx, ty = g_trans.shape[-2], g_trans.shape[-1] + gammaL_full = self.lead_L.gamma + gammaR_full = self.lead_R.gamma + lx = gammaL_full.shape[-2] + rx = gammaR_full.shape[-2] x0 = min(lx, tx) x1 = min(rx, ty) - gammaL = torch.zeros(size=(tx, tx), dtype=self.cdtype, device=self.device) - gammaL[:x0, :x0] += self.lead_L.gamma[:x0, :x0] - gammaR = torch.zeros(size=(ty, ty), dtype=self.cdtype, device=self.device) - gammaR[-x1:, -x1:] += self.lead_R.gamma[-x1:, -x1:] + gL_shape = (g_trans.shape[0], tx, tx) if batched else (tx, tx) + gR_shape = (g_trans.shape[0], ty, ty) if batched else (ty, ty) + gammaL = torch.zeros(size=gL_shape, dtype=self.cdtype, device=self.device) + gammaR = torch.zeros(size=gR_shape, dtype=self.cdtype, device=self.device) + if batched: + gammaL[:, :x0, :x0] = gammaL[:, :x0, :x0] + gammaL_full[:, :x0, :x0] + gammaR[:, -x1:, -x1:] = gammaR[:, -x1:, -x1:] + gammaR_full[:, -x1:, -x1:] + else: + gammaL[:x0, :x0] += gammaL_full[:x0, :x0] + gammaR[-x1:, -x1:] += gammaR_full[-x1:, -x1:] - tc = torch.mm(torch.mm(gammaL, self.g_trans), torch.mm(gammaR, self.g_trans.conj().T)).diag().real.sum(-1) + tc = (gammaL @ g_trans @ gammaR @ g_trans.mH).diagonal(dim1=-2, dim2=-1).real.sum(-1) return tc @@ -368,7 +408,7 @@ def _cal_dos_(self): temp = self.grd[jj] @ self.sd[jj] + self.grl[jj-1] @ self.su[jj-1] else: temp = self.grd[jj] @ self.sd[jj] + self.grl[jj-1] @ self.su[jj-1] + self.gru[jj] @ self.sl[jj] - dos -= temp.imag.diag().sum(-1) / pi + dos -= temp.imag.diagonal(dim1=-2, dim2=-1).sum(-1) / pi return dos * 2 def _cal_ldos_(self): @@ -391,27 +431,28 @@ def _cal_ldos_(self): temp = self.grd[jj] @ self.sd[jj] + self.grl[jj-1] @ self.su[jj-1] else: temp = self.grd[jj] @ self.sd[jj] + self.grl[jj-1] @ self.su[jj-1] + self.gru[jj] @ self.sl[jj] - ldos.append(-temp.imag.diag() / pi) # shape(Nd(diagonal elements)) + ldos.append(-temp.imag.diagonal(dim1=-2, dim2=-1) / pi) # [n_q] or [B, n_q] - ldos = torch.cat(ldos, dim=0).contiguous() + ldos = torch.cat(ldos, dim=-1).contiguous() norbs = [0]+self.norbs_per_atom accmap = np.cumsum(norbs) - ldos = torch.stack([ldos[accmap[i]:accmap[i+1]].sum() for i in range(len(accmap)-1)]) + ldos = torch.stack([ldos[..., accmap[i]:accmap[i+1]].sum(-1) for i in range(len(accmap)-1)], dim=-1) # return ldos*2 return ldos*2 def _cal_local_current_(self): - '''calculate the local current between different atoms + '''calculate the local current between different atoms At this stage, local current calculation only support non-block-triagonal format Hamiltonian - + Returns ------- the local current - + ''' + # TODO(batched-energy): vectorize then batch — currently expects scalar-E gnd[0] (2-D). # current only support non-block-triagonal format v_L = self.lead_L.voltage v_R = self.lead_R.voltage From 374f48a84cc53bc19487be8d28b25254493c3d8a Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 22:32:06 +0800 Subject: [PATCH 5/8] add batched Energy green's function calculaiton in NEGF.py --- dpnegf/runner/NEGF.py | 155 +++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 61 deletions(-) diff --git a/dpnegf/runner/NEGF.py b/dpnegf/runner/NEGF.py index 8a42698..dee3c4e 100644 --- a/dpnegf/runner/NEGF.py +++ b/dpnegf/runner/NEGF.py @@ -44,7 +44,7 @@ def __init__(self, unit: str, scf: bool, poisson_options: dict, stru_options: dict,eta_lead: float,eta_device: float, - block_tridiagonal: bool, plot_blocks: bool, + block_tridiagonal: bool, sgf_solver: str, e_fermi: float=None, use_saved_HS: bool=False, saved_HS_path: str=None, @@ -52,18 +52,20 @@ def __init__(self, se_info_display: bool=False, se_numba_jit: Optional[bool]=None, out_tc: bool=False,out_dos: bool=False,out_density: bool=False,out_potential: bool=False, out_current: bool=False,out_current_nscf: bool=False,out_ldos: bool=False,out_lcurrent: bool=False, - results_path: Optional[str]=None, + results_path: Optional[str]=None, plot_blocks: Optional[bool]=False, torch_device: Union[str, torch.device]=torch.device('cpu'), AtomicData_options: Optional[dict]=None, n_cpus: Optional[int]=None, + e_batch_size: Optional[int]=None, **kwargs): - - + + # self.model = model # No need to set model as property for memory saving self.results_path = results_path self.cdtype = torch.complex128 self.torch_device = torch_device self.n_cpus = n_cpus + self.e_batch_size = e_batch_size # get the parameters self.ele_T = ele_T @@ -642,13 +644,15 @@ def negf_compute(self,scf_require=False,Vbias=None): # in non-scf case, computing properties in uni_gird else: - if hasattr(self, "uni_grid"): - output_freq = int(len(self.uni_grid)/10) - if output_freq == 0: output_freq = 1 - for ie, e in enumerate(self.uni_grid): - if ie % output_freq == 0: - log.info(f" computing green's function at e = {float(e):>6.3f}") - if self.scf: + if hasattr(self, "uni_grid"): + if self.scf: + # SCF branch keeps per-E iteration: lead.voltage is mutated per energy, + # which makes per-E self_energy unavoidable. + output_freq = int(len(self.uni_grid)/10) + if output_freq == 0: output_freq = 1 + for ie, e in enumerate(self.uni_grid): + if ie % output_freq == 0: + log.info(f" computing green's function at e = {float(e):>6.3f}") if not self.poisson_options["with_Dirichlet_leads"]: for ll in self.stru_options.keys(): if ll.startswith("lead") and\ @@ -663,63 +667,87 @@ def negf_compute(self,scf_require=False,Vbias=None): # TODO: consider the case with heterogeneous Dirichlet leads # In this case, the Dirichlet conditions in leads and gate are set as electrochemical potential(Fermi level + voltage) assert getattr(self.deviceprop, "lead_L").voltage == self.stru_options["lead_L"]["voltage"] - assert getattr(self.deviceprop, "lead_R").voltage == self.stru_options["lead_R"]["voltage"] - + assert getattr(self.deviceprop, "lead_R").voltage == self.stru_options["lead_R"]["voltage"] + for ll in self.stru_options.keys(): if ll.startswith("lead"): getattr(self.deviceprop, ll).self_energy( - energy=e, - kpoint=k, + energy=e, + kpoint=k, eta_lead=self.eta_lead, method=self.sgf_solver, save_path=self.self_energy_save_path, se_info_display=self.se_info_display ) - # self.out[str(ll)+"_se"][str(e.numpy())] = getattr(self.deviceprop, ll).se - - else: - for ll in self.stru_options.keys(): - if ll.startswith("lead"): - getattr(self.deviceprop, ll).self_energy( - energy=e, - kpoint=k, - eta_lead=self.eta_lead, - method=self.sgf_solver, - save_path=self.self_energy_save_path, - se_info_display=self.se_info_display - ) - - self.deviceprop.cal_green_function( - energy=e, kpoint=k, - eta_device=self.eta_device, - block_tridiagonal=self.block_tridiagonal, - Vbias=Vbias, - need_lesser=False, - need_greater=False, - need_gr_lc=False, # set to False for memory saving, can be set to True for lead spectral function G^r * \Gamma * G^a + + self.deviceprop.cal_green_function( + energy=e, kpoint=k, + eta_device=self.eta_device, + block_tridiagonal=self.block_tridiagonal, + Vbias=Vbias, + need_lesser=False, + need_greater=False, + need_gr_lc=False, + ) + + if self.out_dos: + self.out.setdefault('DOS', {}).setdefault(str(k), []).append(self.compute_DOS(k)) + if self.out_tc or self.out_current_nscf: + self.out.setdefault('T_k', {}).setdefault(str(k), []).append(self.compute_TC(k)) + if self.out_ldos: + self.out.setdefault('LDOS', {}).setdefault(str(k), []).append(self.compute_LDOS(k)) + else: + # Non-SCF: solve a whole chunk of energies in one batched recursive_gf call. + chunk = self.e_batch_size if self.e_batch_size is not None else len(self.uni_grid) + for e_chunk in torch.split(self.uni_grid, chunk): + b = len(e_chunk) + log.info( + f"computing green's functions for chunk e=[{float(e_chunk[0]):>6.3f}..{float(e_chunk[-1]):>6.3f}], B={b}" ) - # self.out["gtrans"][str(e.numpy())] = gtrans - - - if self.out_dos: - # prop = self.out.setdefault("DOS", []) - # prop.append(self.compute_DOS(k)) - prop = self.out.setdefault('DOS', {}) - propk = prop.setdefault(str(k), []) - propk.append(self.compute_DOS(k)) - if self.out_tc or self.out_current_nscf: - # prop = self.out.setdefault("TC", []) - # prop.append(self.compute_TC(k)) - prop = self.out.setdefault('T_k', {}) - propk = prop.setdefault(str(k), []) - propk.append(self.compute_TC(k)) - if self.out_ldos: - # prop = self.out['LDOS'].setdefault(str(k), []) - # prop.append(self.compute_LDOS(k)) - prop = self.out.setdefault('LDOS', {}) - propk = prop.setdefault(str(k), []) - propk.append(self.compute_LDOS(k)) - + seL_list, seR_list = [], [] + for e in e_chunk: + for ll in self.stru_options.keys(): + if ll.startswith("lead"): + getattr(self.deviceprop, ll).self_energy( + energy=e, + kpoint=k, + eta_lead=self.eta_lead, + method=self.sgf_solver, + save_path=self.self_energy_save_path, + se_info_display=self.se_info_display + ) + seL_list.append(self.deviceprop.lead_L.se) + seR_list.append(self.deviceprop.lead_R.se) + + if b > 1: + self.deviceprop.lead_L.se = torch.stack(seL_list, dim=0) + self.deviceprop.lead_R.se = torch.stack(seR_list, dim=0) + # else: leave the per-E [n,n] in place — preserves scalar contract exactly. + + self.deviceprop.cal_green_function( + energy=e_chunk, kpoint=k, + eta_device=self.eta_device, + block_tridiagonal=self.block_tridiagonal, + Vbias=Vbias, + need_lesser=False, + need_greater=False, + need_gr_lc=False, # set to False for memory saving, can be set to True for lead spectral function G^r * \Gamma * G^a + ) + + if self.out_dos: + self.out.setdefault('DOS', {}).setdefault(str(k), []).append(self.compute_DOS(k).reshape(-1)) + if self.out_tc or self.out_current_nscf: + self.out.setdefault('T_k', {}).setdefault(str(k), []).append(self.compute_TC(k).reshape(-1)) + if self.out_ldos: + ldos_chunk = self.compute_LDOS(k) + if ldos_chunk.ndim == 1: # scalar-E chunk → [na] + ldos_chunk = ldos_chunk.unsqueeze(0) + self.out.setdefault('LDOS', {}).setdefault(str(k), []).append(ldos_chunk) + + # Restore lead.se to scalar [n,n] so downstream scalar callers + # (density modules, lcurrent loop, future SCF re-entry) see the expected shape. + self.deviceprop.lead_L.se = seL_list[-1] + self.deviceprop.lead_R.se = seR_list[-1] # over energy loop in uni_gird # The following code is for output properties before NEGF ends @@ -759,10 +787,15 @@ def negf_compute(self,scf_require=False,Vbias=None): raise ValueError("Unknown method for density calculation.") if self.out_potential: pass + # SCF branch appended per-E scalars (stack→[E]); non-SCF branch appended per-chunk [b] tensors (cat→[E]). + reduce_fn = torch.stack if self.scf else torch.cat if self.out_dos: - self.out["DOS"][str(k)] = torch.stack(self.out["DOS"][str(k)]) + self.out["DOS"][str(k)] = reduce_fn(self.out["DOS"][str(k)]) if self.out_tc or self.out_current_nscf: - self.out["T_k"][str(k)] = torch.stack(self.out["T_k"][str(k)]) + self.out["T_k"][str(k)] = reduce_fn(self.out["T_k"][str(k)]) + if self.out_ldos: + # Non-SCF: list of [b, na] → [E, na]. SCF: list of [na] → [E, na]. + self.out["LDOS"][str(k)] = reduce_fn(self.out["LDOS"][str(k)]) # if self.out_current_nscf: # self.out["BIAS_POTENTIAL_NSCF"], self.out["CURRENT_NSCF"] = self.compute_current_nscf(k, self.uni_grid, self.out["TC"]) # computing properties that are not functions of E (improvement can be made here in properties related to integration of energy window of fermi functions) From c6e7335373a9696fd8e78d63da6c23f72aeef718 Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 22:32:42 +0800 Subject: [PATCH 6/8] add e_batch_size and update related files --- dpnegf/negf/recursive_green_cal.py | 3 +- dpnegf/utils/argcheck.py | 1 + examples/CNT/run.ipynb | 82 +++++++++++++++--------------- 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/dpnegf/negf/recursive_green_cal.py b/dpnegf/negf/recursive_green_cal.py index 03719e2..be8f472 100644 --- a/dpnegf/negf/recursive_green_cal.py +++ b/dpnegf/negf/recursive_green_cal.py @@ -250,8 +250,7 @@ def recursive_gf(energy, hl, hd, hu, sd, su, sl, left_se, right_se, seP=None, E_ shift_energy = energy + E_ref if not torch.is_tensor(shift_energy): shift_energy = torch.as_tensor(shift_energy, dtype=torch.complex128) - # Legacy scalar callers pass either a 0-d tensor or a length-1 1-D tensor - # together with 2-D Hamiltonian / self-energy inputs. + # Legacy scalar callers pass either a 0-d tensor or a length-1 1-D tensor together with 2-D Hamiltonian / self-energy inputs. # Batched callers pass a 1-D ``[B]`` energy together with 3-D ``[B, n, n]`` tensors. # Use the rank of ``left_se`` (or ``right_se``) as the disambiguator so the # wrapper can squeeze the batch dim back out for scalar callers. diff --git a/dpnegf/utils/argcheck.py b/dpnegf/utils/argcheck.py index 202f1bc..6a660a9 100644 --- a/dpnegf/utils/argcheck.py +++ b/dpnegf/utils/argcheck.py @@ -1055,6 +1055,7 @@ def negf(): Argument("espacing", [int, float], optional=False, doc=doc_espacing), Argument("emin", [int, float], optional=False, doc=doc_emin), Argument("emax", [int, float], optional=False, doc=doc_emax), + Argument("e_batch_size", [int, float], optional=False, doc="the batch size for energy points in NEGF calculation"), Argument("e_fermi", [int, float], optional=True, default=None ,doc=doc_e_fermi), Argument("density_options", dict, optional=True, default={}, sub_fields=[], sub_variants=[density_options()], doc=doc_density_options), Argument("eta_lead", [int, float], optional=True, default=1e-5, doc=doc_eta_lead), diff --git a/examples/CNT/run.ipynb b/examples/CNT/run.ipynb index c266283..3e827bd 100644 --- a/examples/CNT/run.ipynb +++ b/examples/CNT/run.ipynb @@ -5,7 +5,16 @@ "execution_count": 1, "id": "8c5c64a9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/mamba/envs/dpnegf-dev/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], "source": [ "import os\n", "import torch\n", @@ -23,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 9, "id": "0f64a6b8", "metadata": {}, "outputs": [ @@ -31,11 +40,12 @@ "name": "stderr", "output_type": "stream", "text": [ + "rm: cannot remove 'output': Directory not empty\n", "DPNEGF INFO ================================================================================\n", "DPNEGF INFO Version Info \n", "DPNEGF INFO --------------------------------------------------------------------------------\n", - "DPNEGF INFO DPNEGF : 0.1.1.dev97+bccd946\n", - "DPNEGF INFO DeePTB : 2.1.2.dev53+5b97981\n", + "DPNEGF INFO DPNEGF : 0.0.1.dev293+d4ffc8e\n", + "DPNEGF INFO DeePTB : 2.2.1.dev62+g155e85e76.d20260602\n", "DPNEGF INFO ================================================================================\n", "\n", "DPNEGF WARNING The model option atomic_radius in nnsk is not defined in input model_options, set to v1.\n" @@ -65,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 11, "id": "830d67a4", "metadata": {}, "outputs": [ @@ -80,7 +90,7 @@ "DPNEGF INFO k-points: [[0. 0. 0.]]\n", "DPNEGF INFO k-points weights: [1.]\n", "DPNEGF INFO --------------------------------\n", - "DPNEGF WARNING AtomicData_options is extracted from input file. This may be not consistent with the model options. Please be careful and check the cutoffs.\n", + "DPNEGF WARNING AtomicData_options is extracted from NEGF input file. This may be not consistent with the model options. Please be careful and check the cutoffs.\n", "DPNEGF INFO The AtomicData_options is:\n", " {\n", " \"r_max\": 4.6\n", @@ -88,8 +98,6 @@ "DPNEGF INFO The structure is sorted lexicographically in this version!\n", "DPNEGF INFO Lead principal layers translational equivalence error (on average): 1.732035e-10 (threshold: 1.000000e-05)\n", "DPNEGF INFO Lead principal layers translational equivalence error (on average): 1.732051e-10 (threshold: 1.000000e-05)\n", - "/opt/mamba/envs/dpnegf-dev/lib/python3.10/site-packages/torch/nested/__init__.py:107: UserWarning: The PyTorch API of nested tensors is in prototype stage and will change in the near future. (Triggered internally at ../aten/src/ATen/NestedTensorImpl.cpp:178.)\n", - " return torch._nested_tensor_from_tensor_list(ts, dtype, None, device, None)\n", "DPNEGF INFO The coupling width of lead_L is 112.\n", "DPNEGF INFO The coupling width of lead_R is 112.\n", "DPNEGF INFO The Hamiltonian is block tridiagonalized into 18 subblocks.\n", @@ -108,53 +116,42 @@ "DPNEGF INFO Getting eigenvalues from the model.\n", "DPNEGF INFO Calculating Fermi energy in the case of spin-degeneracy.\n", "DPNEGF INFO Fermi energy converged after 4 iterations.\n", - "DPNEGF INFO q_cal: 224.0, total_electrons: 224.0, diff q: 0.0\n", - "DPNEGF INFO Estimated E_fermi: -4.476735791109641 based on the valence electrons setting nel_atom : {'C': 4.0} .\n", + "DPNEGF INFO q_cal: 224.00000000003706, total_electrons: 224.0, diff q: 3.7061909097246826e-11\n", + "DPNEGF INFO Estimated E_fermi: -4.510708691306822 based on the valence electrons setting nel_atom : {'C': 4.0} .\n", "DPNEGF INFO -----Calculating Fermi level for lead_R-----\n", "DPNEGF INFO KPOINTS kmesh sampling: 6 kpoints\n", "DPNEGF INFO Getting eigenvalues from the model.\n", "DPNEGF INFO Calculating Fermi energy in the case of spin-degeneracy.\n", "DPNEGF INFO Fermi energy converged after 4 iterations.\n", - "DPNEGF INFO q_cal: 224.0, total_electrons: 224.0, diff q: 0.0\n", - "DPNEGF INFO Estimated E_fermi: -4.476750334642966 based on the valence electrons setting nel_atom : {'C': 4.0} .\n", + "DPNEGF INFO q_cal: 224.000000000037, total_electrons: 224.0, diff q: 3.700506567838602e-11\n", + "DPNEGF INFO Estimated E_fermi: -4.510722161956541 based on the valence electrons setting nel_atom : {'C': 4.0} .\n", "DPNEGF INFO -------------------------------------------------\n", "DPNEGF INFO Zero bias case detected.\n", - "DPNEGF INFO Fermi level for lead_L: -4.476735791109641\n", - "DPNEGF INFO Fermi level for lead_R: -4.476750334642966\n", - "DPNEGF INFO Electrochemical potential for lead_L: -4.476735791109641\n", - "DPNEGF INFO Electrochemical potential for lead_R: -4.476750334642966\n", - "DPNEGF INFO Reference energy E_ref: -4.476735791109641\n", + "DPNEGF INFO Fermi level for lead_L: -4.510708691306822\n", + "DPNEGF INFO Fermi level for lead_R: -4.510722161956541\n", + "DPNEGF INFO Electrochemical potential for lead_L: -4.510708691306822\n", + "DPNEGF INFO Electrochemical potential for lead_R: -4.510722161956541\n", + "DPNEGF INFO Reference energy E_ref: -4.510708691306822\n", "DPNEGF INFO =================================================\n", "\n", + "DPNEGF INFO ------Self-energy calculation------\n", + "DPNEGF INFO Calculating self-energy and saving to output/self_energy\n", + "DPNEGF INFO Estimated safe n_jobs=16 based on available memory.\n", + "DPNEGF INFO Auto-detected safe n_jobs=16 based on available memory\n", "DPNEGF INFO Merging 120 tmp self energy files into output/self_energy/self_energy_leadL.h5\n", "DPNEGF INFO Merge complete.\n", "DPNEGF INFO Merging 120 tmp self energy files into output/self_energy/self_energy_leadR.h5\n", "DPNEGF INFO Merge complete.\n", - "DPNEGF INFO Properties computation at k = [0.0000,0.0000,0.0000]\n", - "DPNEGF INFO computing green's function at e = -3.000\n", - "DPNEGF INFO computing green's function at e = -2.395\n", - "DPNEGF INFO computing green's function at e = -1.790\n", - "DPNEGF INFO computing green's function at e = -1.185\n", - "DPNEGF INFO computing green's function at e = -0.580\n", - "DPNEGF INFO computing green's function at e = 0.025\n", - "DPNEGF INFO computing green's function at e = 0.630\n", - "DPNEGF INFO computing green's function at e = 1.235\n", - "DPNEGF INFO computing green's function at e = 1.840\n", - "DPNEGF INFO computing green's function at e = 2.445\n", + "DPNEGF INFO -----------------------------------\n", + "\n", + "DPNEGF INFO Properties computation at k = (0.0000, 0.0000, 0.0000)\n", + "DPNEGF INFO computing green's functions for chunk e=[-3.000..-0.529], B=50\n", + "DPNEGF INFO computing green's functions for chunk e=[-0.479.. 1.992], B=50\n", + "DPNEGF INFO computing green's functions for chunk e=[ 2.042.. 3.000], B=20\n", "DPNEGF WARNING Fiori method is under test in this version.\n", "DPNEGF WARNING Free charge output has some problems.\n", "DPNEGF WARNING The Fermi energy of the left and right leads should be equal in nscf current calculation.\n" ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ @@ -163,6 +160,7 @@ " AtomicData_options=negf_json['AtomicData_options'],\n", " structure=structure,\n", " results_path=output, \n", + " e_batch_size=50,\n", " **negf_json['task_options']\n", ")\n", " \n", @@ -179,7 +177,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/tmp/ipykernel_18951/1724458665.py:1: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", + "/tmp/ipykernel_170135/1724458665.py:1: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n", " negf_out = torch.load('./output/negf.out.pth')\n" ] } @@ -217,7 +215,7 @@ "outputs": [ { "data": { - "image/png": "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feU89pXz2FfO82RfSZ/b0ud4QxjsACgrKwMApKSkeLklRERE5KqysjJERUU1+LggNhUOBQGLxYLc3FxERkZCEAS3nbe0tBQpKSm4cuUKdDqd284biNhXrmF/OY995Tz2lfPYV87zZF+JooiysjIkJydDoWi4MoeZHQAKhQLt27f32Pl1Oh1/GJzEvnIN+8t57Cvnsa+cx75ynqf6qrGMjoQFykRERBTQGOwQERFRQGOw40EajQYvv/wyNBqNt5vi89hXrmF/OY995Tz2lfPYV87zhb5igTIREREFNGZ2iIiIKKAx2CEiIqKAxmCHiIiIAhqDHSIiIgpoDHZayZ133okOHTpAq9Wibdu2mDlzJnJzc73dLJ908eJFzJ07F2lpaQgNDUV6ejpefvllGAwGbzfNJ73++usYOnQowsLCEB0d7e3m+JSlS5eiY8eO0Gq1GDx4MPbu3evtJvmk7du3Y8qUKUhOToYgCPjyyy+93SSftWTJEgwcOBCRkZFISEjA1KlTcerUKW83yye9/fbb6NOnj7yYYEZGBtatW+eVtjDYaSWjR4/Gp59+ilOnTuF///sfzp07h3vvvdfbzfJJJ0+ehMViwb/+9S8cO3YMf/3rX/HOO+/g+eef93bTfJLBYMDPfvYzPPbYY95uik9ZtWoVFi5ciJdffhkHDhxA3759kZWVhYKCAm83zedUVFSgb9++WLp0qbeb4vO2bduG+fPnY/fu3cjOzobRaERmZiYqKiq83TSf0759e/z+97/H/v378eOPP2LMmDG46667cOzYsdZvjEhe8dVXX4mCIIgGg8HbTfELb7zxhpiWlubtZvi0ZcuWiVFRUd5uhs8YNGiQOH/+fPm22WwWk5OTxSVLlnixVb4PgPjFF194uxl+o6CgQAQgbtu2zdtN8QsxMTHie++91+qvy8yOFxQVFWHFihUYOnSo27e7D1QlJSWIjY31djPITxgMBuzfvx9jx46V71MoFBg7dix27drlxZZRoCkpKQEA/n5qgtlsxieffIKKigpkZGS0+usz2GlFzz77LMLDwxEXF4fLly/jq6++8naT/MLZs2fx97//HY8++qi3m0J+orCwEGazGYmJiXb3JyYmIi8vz0utokBjsVjwxBNPYNiwYejVq5e3m+OTjhw5goiICGg0Gvzyl7/EF198gR49erR6OxjstMBzzz0HQRAa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", + "image/png": "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H34YgYGBDsu6fft2dO3a1W7b7cqoVqvx5JNPYsmSJbBtoF+5ciVMJhMef/xxcZtWq0Xnzp2xffv2GtQkETnFLUvKEpHXSUpKElQqleDv72/39e6774rHABBef/118XFhYaEAQPj1118FQRCEt99+W0hISLC77sWLFwUAwokTJwRBEIT7779f6NKli90xL7/8snDPPffYbXvttdcEAMLNmzcFQRCEPXv2CCqVSrhy5YogCIKQlZUlqNVqYevWrVW+ppEjRwrPPPOM3TYpZTx27JgAQNiyZYt4TN++fYUnnnii0nOMHj1aeOqpp6osAxG5Bm9KE1G9GTBgAD777DO7baGhoXaPO3bsKH7v7++PoKAgZGdnAwAOHjyILVu2ICAgoNK1z5w5g7vvvhsAKrXanDhxAt27d7fbdt9991V63L59e3z11Vd45ZVX8M033yAmJgb9+vWr8vXcunULPj4+dtuklLFNmzbo1asXvvzyS/Tv3x+nT5/G9u3bMXv27Ern+Pr6ori4uMoyEJFrMBARUb3x9/fHXXfdVe0xGo3G7rFCoYDZbAZg6WczYsQIvP/++5XOi4yMtHuemvjzn/+MhQsX4pVXXsHixYvx9NNPQ6FQVHl8kyZNcPPmTbttUss4YcIEPP/881i4cCEWL16Mli1b4v777690Tk5ODlq2bFmj10NE0rEPERF5jHvvvRfp6elo0aIF7rrrLruv6kJQ69atsX//frtt1pFctp544glcuHAB8+fPx9GjR5GUlFRtebp06YKjR4/WqIyPPvoolEolli1bhq+//hrPPPOMw/B15MgRdOnSpdpyEFHtMRARUb3R6/XIzMy0+7IdIXY7kydPRk5ODh5//HHs27cPZ86cwYYNG/D000/DZDJVed6kSZNw/PhxvPzyyzh58iRWrFghjvKyDSGNGjXCQw89hOnTpyMhIaHSsPiKEhMTkZ6ebtdKJLWMAQEBeOyxxzBjxgxcvXoVTz31VKXrnz9/HpcvX0Z8fLzEGiKimmIgIqJ6s379ekRGRtp99enTR/L5UVFR2LFjB0wmExISEtChQwdMnToVISEhUCqr/nUWGxuL77//Hj/++CM6duyIzz77TBxlptPp7I6dMGECSktL8cwzz9y2PB06dMC9996LFStW1KiMEyZMwM2bN5GYmIioqKhK1//222+RkJCAmJiY25aFiGqHEzMSkVd69913sWjRIly8eNFu+//+9z+8+OKLuHLliqQJHX/55RdMnz4dR44cqTaUOau0tBStWrXCsmXL0Lt3b5ddl4gcY6dqIvIK//rXv9C9e3c0btwYO3bswAcffIApU6aI+4uLi3H16lW89957mDRpkuTZrYcNG4ZTp07h8uXLiI6Odll5MzIy8OqrrzIMEdUTthARkVd48cUXsXz5cuTk5KB58+YYP348ZsyYIS6J8dZbb+Hdd99Fv3798NNPPzkcNk9E8sVARERERF6PnaqJiIjI6zEQERERkddjICIiIiKvx0BEREREXo+BiIiIiLweAxERERF5PQYiIiIi8noMREREROT1GIiIiIjI6/0/2XZ5NYoIbkQAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -243,7 +241,7 @@ "outputs": [ { "data": { - "image/png": "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Zct8K9hK8vPzUa9ePfTv3x///ve/NYqQKBDHqBARVUG5ubkBx+bNmweTyYR777034HOfffYZLl++jJEjR1ZGeESyseuHiKgKeuutt7Br1y706NEDYWFhWL9+PdavX4+nnnrKb0bVzz//jF9//RVvvPEG2rZti27dumkYNVEgdv0QEVVBqampSE5OxsGDB5GTk4MGDRrg8ccfxyuvvIKwsKL3qKNGjcKyZctwxx13YMmSJWjZsqWGURMFYqJCREREusUxKkRERKRbTFSIiIhIt0J6MK3X68W5c+cQHR1d4gJGREREpD+iKCI7Oxv16tUrc6+qkE5Uzp07p+p+IERERFR5Tp8+HbD79/VCOlGRlg0/ffq0qvuCAIDb7caGDRuQmJgIi8Wi6rWrGraVfGwr+dhW8rGt5GNbKROs9srKykJCQoKs7T9COlGRuntiYmKCkqjYbDbExMTwZi4D20o+tpV8bCv52Fbysa2UCXZ7yRm2wcG0REREpFtMVIiIiEi3mKgQERGRbjFRISIiIt1iokJERES6xUSFiIiIdIuJChEREekWExUiIiLSLSYqREREpFuaJioejwfTpk1D48aNERkZiSZNmuCNN96AKIpahkVEREQ6oekS+nPmzMHChQvx0UcfoUWLFti5cydGjx6NatWqYcKECVqGRkRERDqgaaLy448/YuDAgejXrx8AoFGjRvjkk0+wfft2LcMiIiIindC06+fuu+/Gxo0bceTIEQDA3r178f3336NPnz5ahqW63DyP1iEQERGFJE0rKlOmTEFWVhaaN28Os9kMj8eDmTNn4rHHHivxfJfLBZfL5XuclZUFoGB3R7fbrWps0vUqet3dpzIw/N87MK77zRjfo4kaoemOWm1lBGwr+dhW8rGt5GNbKROs9lJyPUHUcOTqihUr8OKLL+Ltt99GixYtsGfPHkycOBFz585FUlJSwPkzZsxAcnJywPGUlBTYbLbKCFmxLecF/PeEGc1ivBjfwqt1OERERJpzOp0YPnw4MjMzERMTU+q5miYqCQkJmDJlCsaNG+c79uabb2LZsmU4dOhQwPklVVQSEhKQlpZW5gtVyu12IzU1Fb169YLFYin3dRZu+QNzv/0dTePtWD/hHhUj1A+12soI2Fbysa3kY1vJx7ZSJljtlZWVhbi4OFmJiqZdP06nEyaT/zAZs9kMr7fkyoPV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5xMFDX+6iAzIXmxlWlEUNY4mNPkG0rLbhyiomKgQGZA0mNbjFeHK92ocTWgqWkOF3T5EwcREhciApMG0AAfUltflwopKfHSExpEQVW1MVIgMKMxsQnhYwY8/B9SWDxd7I6ocTFSIDMq3jD4rKuXCfX6IKgcTFSKDkgbUOpiolAsXeyOqHLpIVBYsWIBGjRohIiICHTt2xPbt27UOiajKK5qizK6f8vBVVKLZ9UMUTJonKitXrsTkyZMxffp0/PLLL2jTpg169+6NS5cuaR0aUZVmlxIVbkxYLmnZXJWWqDKEaR3A3Llz8eSTT2L06NEAgEWLFuGrr77Cf/7zH0yZMkXj6IiqLqmicjYjF2euOjWOJlB+fj7SXQXxhYW5tQ7HjygCVxwco0JUGTRNVPLy8rBr1y5MnTrVd8xkMqFnz5746aefAs53uVxwuVy+x1lZWQAAt9sNt1vdX2TS9dS+blXEtpJPT20VaSkoqE7//ACmf35A42huJAzJv2zVOohSxVhNmn8/9XRf6R3bSplgtZeS62maqKSlpcHj8aB27dp+x2vXro1Dhw4FnD9r1iwkJycHHN+wYQNsNltQYkxNTQ3KdasitpV8emirevkCIswmeLjeW7m1rili44avtQ7DRw/3VahgWymjdns5nfKruJp3/SgxdepUTJ482fc4KysLCQkJSExMRExMjKrP5Xa7kZqail69esFisah67aqGbSWfntqqL4AZmkZQOj21ld6xreRjWykTrPaSekTk0DRRiYuLg9lsxsWLF/2OX7x4EXXq1Ak432q1wmoN7A+2WCxBu+GCee2qhm0lH9tKPraVfGwr+dhWyqjdXkqupemsn/DwcLRr1w4bN270HfN6vdi4cSM6d+6sYWRERESkB5p3/UyePBlJSUm466670KFDB8ybNw8Oh8M3C4iIiIiMS/NEZdiwYbh8+TJee+01XLhwAXfccQe+/vrrgAG2REREZDyaJyoAMH78eIwfP17rMIiIiEhnNF+ZloiIiOhGmKgQERGRbjFRISIiIt1iokJERES6xUSFiIiIdIuJChEREekWExUiIiLSLSYqREREpFtMVIiIiEi3dLEybXmJoghA2XbRcrndbjidTmRlZXGHzTKwreRjW8nHtpKPbSUf20qZYLWX9Hdb+jtempBOVLKzswEACQkJGkdCRERESmVnZ6NatWqlniOIctIZnfJ6vTh37hyio6MhCIKq187KykJCQgJOnz6NmJgYVa9d1bCt5GNbyce2ko9tJR/bSplgtZcoisjOzka9evVgMpU+CiWkKyomkwn169cP6nPExMTwZpaJbSUf20o+tpV8bCv52FbKBKO9yqqkSDiYloiIiHSLiQoRERHpFhOVG7BarZg+fTqsVqvWoege20o+tpV8bCv52Fbysa2U0UN7hfRgWiIiIqraWFEhIiIi3WKiQkRERLrFRIWIiIh0i4kKERER6RYTFRkGDBiABg0aICIiAnXr1sXjjz+Oc+fOaR2W7pw4cQJPPPEEGjdujMjISDRp0gTTp09HXl6e1qHp0syZM3H33XfDZrOhevXqWoejOwsWLECjRo0QERGBjh07Yvv27VqHpDvfffcd+vfvj3r16kEQBHz22Wdah6Rbs2bNQvv27REdHY1atWph0KBBOHz4sNZh6dLChQvRunVr3yJvnTt3xvr16zWLh4mKDD169MCqVatw+PBhfPrppzh27BgeeughrcPSnUOHDsHr9eL999/HgQMH8O6772LRokV4+eWXtQ5Nl/Ly8jB06FA888wzWoeiOytXrsTkyZMxffp0/PLLL2jTpg169+6NS5cuaR2arjgcDrRp0wYLFizQOhTd27JlC8aNG4dt27YhNTUVbrcbiYmJcDgcWoemO/Xr18fs2bOxa9cu7Ny5E/fddx8GDhyIAwcOaBOQSIqtW7dOFARBzMvL0zoU3XvrrbfExo0bax2Gri1evFisVq2a1mHoSocOHcRx48b5Hns8HrFevXrirFmzNIxK3wCIa9eu1TqMkHHp0iURgLhlyxatQwkJsbGx4ocffqjJc7OiolB6ejqWL1+Ou+++m1uEy5CZmYkaNWpoHQaFkLy8POzatQs9e/b0HTOZTOjZsyd++uknDSOjqiQzMxMA+PupDB6PBytWrIDD4UDnzp01iYGJikwvvfQS7HY7atasiVOnTmHdunVah6R7v//+O+bPn4+xY8dqHQqFkLS0NHg8HtSuXdvveO3atXHhwgWNoqKqxOv1YuLEibjnnnvQsmVLrcPRpX379iEqKgpWqxVPP/001q5di9tvv12TWAybqEyZMgWCIJT6cejQId/5L774Inbv3o0NGzbAbDZj5MiREA2yqK/StgKAs2fP4oEHHsDQoUPx5JNPahR55StPWxFR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", + "image/png": "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27bFK6+8gu+++w5bt27F2bNnsWjRooC1Q46mTZsCAGrXrl3iKE2vXr3KvUajRo3gdrtx4sQJn+PHjh0r8fyHHnoIRqMRn3zyCZYvXw6TyeQX5IjUwqBCFATSb83Ff9vPz8/He++9V+FrXrlyxeex2WxGq1atIIqi7LUhStntdr8Q1LRpU0RFRXmndq5du+Y3qiFNeZQ2/WM0GpGYmIh169b57GK5ePEiUlNT0b17d++0TCAMGzbM+4N49erVuP/++31qjWRlZaGgoMDna9q2bQuDwVDmFFYwJCUlITo6Gm+++WaJ/67lbcmWrgHA7/327rvvlnh+XFwc+vXrh2XLlmH58uW47777/KYJidQSmmUiiVR25513IjY2FsnJyZg4cSIEQcDSpUvLnaYoS2JiIurWrYu77roLderUwa+//op//vOfGDBgAKKiogLY+iJHjx7FvffeiwcffBCtWrVCWFgY1qxZg4sXL+Khhx4CAHz00Ud47733MHToUDRt2hTZ2dn44IMPEB0djf79+5d67TfeeANpaWno3r07nnnmGYSFheH999+Hw+EosYZMZdSuXRu9e/fGvHnzkJ2d7Tda8H//93+YMGEChg8fjltuuQUFBQVYunQpjEajd7tvWQoKCrBs2bISPzd06FBFBdiio6OxcOFCPProo7jtttvw0EMPIT4+HqdOncJXX32Fu+66C//85z/LvEanTp0wbNgwzJ8/H1euXEHXrl2xZcsWHD16FAD81kMBnumfBx54AADw+uuvy24vUbAxqBAFQa1atfDll1/iueeewyuvvILY2FiMGjUK9957r/e3XaWefPJJLF++HPPmzUNOTg4aNGiAiRMn4pVXXglw64skJCTg4YcfxsaNG7F06VKEhYWhZcuWWLVqlfcHeM+ePbF9+3asWLECFy9eRExMDDp37ozly5f7LeYsrnXr1ti6dSumTZuG2bNnw+12o0uXLli2bBm6dOkS8NcyYsQIfPvtt4iKivILUO3bt0dSUhK++OILnD17FlarFe3bt8f69evRtWvXcq/tcDjw6KOPlvi5EydOKK4UO3LkSNSvXx9z5szB22+/DYfDgZtuugk9evQocYdZST7++GPUrVsXn3zyCdasWYM+ffpg5cqVaNGiRYn3IBo4cCBiY2PhdrsxaNAgRe0lCiaW0Cci0om9e/eiY8eOWLZsmbeC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", "text/plain": [ "
" ] @@ -278,7 +276,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.16" + "version": "3.10.19" } }, "nbformat": 4, From aa13cd80dbb0c1ac3acc4a19430ba4d5b1c9155b Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 22:33:14 +0800 Subject: [PATCH 7/8] add unit test for batched Energy device property calculation --- dpnegf/tests/test_device_property_batched.py | 247 +++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 dpnegf/tests/test_device_property_batched.py diff --git a/dpnegf/tests/test_device_property_batched.py b/dpnegf/tests/test_device_property_batched.py new file mode 100644 index 0000000..f241358 --- /dev/null +++ b/dpnegf/tests/test_device_property_batched.py @@ -0,0 +1,247 @@ +"""Batched-energy contract for DeviceProperty. + +The recursive Green's function kernel was widened to take a leading energy-batch +dim; this test pins that DeviceProperty.cal_green_function, _cal_tc_, +_cal_dos_, and _cal_ldos_ produce the same numbers whether the caller drives B +scalar energies in a loop or feeds a 1-D [B] energy tensor in one shot. + +It also pins the runner-style chunking behavior (split [E] into chunks of size +e_batch_size, cat the per-chunk outputs back together). +""" + +import pytest +import torch + +from dpnegf.negf.device_property import DeviceProperty + +from .test_recursive_gf_batched import _make_btd_inputs + + +class _FakeHamiltonian: + """Minimal hamiltonian: cal_green_function calls get_hs_device(...) to + fill self.hd/sd/hl/su/sl/hu; we just hand back pre-built BTD blocks.""" + + def __init__(self, hd, sd, hl, hu, sl, su, device_norbs): + self._packed = (hd, sd, hl, su, sl, hu) + self.device_norbs = device_norbs + + def get_hs_device(self, kpoint, V, block_tridiagonal): + return self._packed + + +class _FakeLead: + """Per-E scalar se store + a Fermi-Dirac at chemiPot=0, kBT=0.025 (~300K).""" + + def __init__(self): + self.se = None + self.chemiPot_lead = 0.0 + self.kBT = 0.025 + + def fermi_dirac(self, x): + return 1.0 / (1.0 + torch.exp((x - self.chemiPot_lead) / self.kBT)) + + @property + def gamma(self): + # Mirrors LeadProperty.gamma after the .mH fix — shape-agnostic. + return 1j * (self.se - self.se.mH) + + +def _make_deviceprop(block_sizes, hd, sd, hl, hu, sl, su): + """Construct a DeviceProperty with the fakes wired in.""" + n_total = sum(block_sizes) + norbs_per_atom = [1] * n_total # one orbital per "atom" so ldos == per-orb DOS + ham = _FakeHamiltonian(hd, sd, hl, hu, sl, su, device_norbs=norbs_per_atom) + + dev = DeviceProperty.__new__(DeviceProperty) + dev.greenfuncs = 0 + dev.hamiltonian = ham + dev.structure = None + dev.results_path = "/tmp" + dev.cdtype = torch.complex128 + dev.device = "cpu" + dev.kBT = 0.025 + dev.e_T = 300.0 + dev.chemiPot = None + dev.E_ref = 0.0 + dev.kpoint = None + dev.newK_flag = None + dev.newV_flag = None + dev.lead_L = _FakeLead() + dev.lead_R = _FakeLead() + return dev + + +def _block_sizes_match_se(left_se_2d, right_se_2d, block_sizes): + # cal_green_function asserts se shape <= corresponding hd block; with the BTD + # builder, block_sizes[0] == left_se size and block_sizes[-1] == right_se size. + assert left_se_2d.shape == (block_sizes[0], block_sizes[0]) + assert right_se_2d.shape == (block_sizes[-1], block_sizes[-1]) + + +def _run_scalar(dev, energies_1d, left_se_batched, right_se_batched, need_lesser): + """Drive cal_green_function B times with scalar energies; collect tc/dos/ldos.""" + tc_list, dos_list, ldos_list, gnd0_list = [], [], [], [] + for b in range(energies_1d.shape[0]): + dev.lead_L.se = left_se_batched[b] + dev.lead_R.se = right_se_batched[b] + dev.cal_green_function( + energy=energies_1d[b], + kpoint=[0.0, 0.0, 0.0], + eta_device=0.0, + block_tridiagonal=True, + need_lesser=need_lesser, + need_gr_lc=False, + ) + tc_list.append(dev._cal_tc_()) + dos_list.append(dev._cal_dos_()) + ldos_list.append(dev._cal_ldos_()) + if need_lesser: + gnd0_list.append(dev.greenfuncs["gnd"][0]) + return ( + torch.stack(tc_list), + torch.stack(dos_list), + torch.stack(ldos_list), + torch.stack(gnd0_list) if need_lesser else None, + ) + + +def _run_batched(dev, energies_1d, left_se_batched, right_se_batched, need_lesser): + """Drive cal_green_function once with a 1-D [B] energy.""" + dev.lead_L.se = left_se_batched + dev.lead_R.se = right_se_batched + dev.cal_green_function( + energy=energies_1d, + kpoint=[0.0, 0.0, 0.0], + eta_device=0.0, + block_tridiagonal=True, + need_lesser=need_lesser, + need_gr_lc=False, + ) + tc_B = dev._cal_tc_() + dos_B = dev._cal_dos_() + ldos_B = dev._cal_ldos_() + gnd0_B = dev.greenfuncs["gnd"][0] if need_lesser else None + return tc_B, dos_B, ldos_B, gnd0_B + + +@pytest.mark.parametrize("need_lesser", [False, True]) +def test_batched_matches_scalar(need_lesser): + B = 7 + block_sizes = [4, 4, 4] + hd, sd, hl, hu, sl, su, left_se_B, right_se_B, energies_cplx = _make_btd_inputs( + B, block_sizes, seed=11 + ) + # The runner feeds real-valued energies (the kernel adds 1j*eta itself); strip + # the seed's tiny imaginary offset to keep this path realistic. + energies = energies_cplx.real.to(torch.complex128) + + # Hermitize lead self-energies so .mH-based gamma is a real broadening function. + left_se_B = 0.5 * (left_se_B + left_se_B.mH) + 1j * 0.1 * torch.eye( + block_sizes[0], dtype=torch.complex128 + ) + right_se_B = 0.5 * (right_se_B + right_se_B.mH) + 1j * 0.1 * torch.eye( + block_sizes[-1], dtype=torch.complex128 + ) + _block_sizes_match_se(left_se_B[0], right_se_B[0], block_sizes) + + dev = _make_deviceprop(block_sizes, hd, sd, hl, hu, sl, su) + + tc_e, dos_e, ldos_e, gnd0_e = _run_scalar( + dev, energies, left_se_B, right_se_B, need_lesser + ) + + # Reset cached state so the batched call goes through the same init path. + dev.kpoint = None + dev.newK_flag = None + dev.newV_flag = None + if hasattr(dev, "V"): + del dev.V + if hasattr(dev, "hd"): + del dev.hd, dev.sd, dev.hl, dev.su, dev.sl, dev.hu + + tc_B, dos_B, ldos_B, gnd0_B = _run_batched( + dev, energies, left_se_B, right_se_B, need_lesser + ) + + assert tc_B.shape == (B,) + assert dos_B.shape == (B,) + assert ldos_B.shape == (B, sum(block_sizes)) + assert torch.allclose(tc_B, tc_e, atol=1e-10, rtol=0) + assert torch.allclose(dos_B, dos_e, atol=1e-10, rtol=0) + assert torch.allclose(ldos_B, ldos_e, atol=1e-10, rtol=0) + if need_lesser: + assert gnd0_B.shape == (B, block_sizes[0], block_sizes[0]) + assert torch.allclose(gnd0_B, gnd0_e, atol=1e-10, rtol=0) + + +def test_chunked_matches_unchunked(): + """Runner-style chunking: split [E] into chunks of e_batch_size, cat back.""" + B = 7 + block_sizes = [4, 4, 4] + hd, sd, hl, hu, sl, su, left_se_B, right_se_B, energies_cplx = _make_btd_inputs( + B, block_sizes, seed=13 + ) + energies = energies_cplx.real.to(torch.complex128) + left_se_B = 0.5 * (left_se_B + left_se_B.mH) + 1j * 0.1 * torch.eye( + block_sizes[0], dtype=torch.complex128 + ) + right_se_B = 0.5 * (right_se_B + right_se_B.mH) + 1j * 0.1 * torch.eye( + block_sizes[-1], dtype=torch.complex128 + ) + + dev = _make_deviceprop(block_sizes, hd, sd, hl, hu, sl, su) + + # Unchunked baseline: single B=7 batched call. + tc_full, dos_full, ldos_full, _ = _run_batched( + dev, energies, left_se_B, right_se_B, need_lesser=False + ) + + # Chunked: e_batch_size=3 → splits of [3,3,1]. + e_batch_size = 3 + tc_chunks, dos_chunks, ldos_chunks = [], [], [] + for chunk_idx, e_chunk in enumerate(torch.split(energies, e_batch_size)): + b = len(e_chunk) + i0 = chunk_idx * e_batch_size + seL_chunk = left_se_B[i0:i0 + b] + seR_chunk = right_se_B[i0:i0 + b] + + # Reset cached state between chunks so each goes through full init. + dev.kpoint = None + dev.newK_flag = None + dev.newV_flag = None + if hasattr(dev, "V"): + del dev.V + if hasattr(dev, "hd"): + del dev.hd, dev.sd, dev.hl, dev.su, dev.sl, dev.hu + + # Runner restores lead.se to [n,n] after the last chunk, but mid-loop it + # stacks; we replicate that here. + if b > 1: + dev.lead_L.se = seL_chunk + dev.lead_R.se = seR_chunk + else: + dev.lead_L.se = seL_chunk[0] + dev.lead_R.se = seR_chunk[0] + + dev.cal_green_function( + energy=e_chunk, + kpoint=[0.0, 0.0, 0.0], + eta_device=0.0, + block_tridiagonal=True, + need_lesser=False, + need_gr_lc=False, + ) + tc_chunks.append(dev._cal_tc_().reshape(-1)) + dos_chunks.append(dev._cal_dos_().reshape(-1)) + ldos_one = dev._cal_ldos_() + if ldos_one.ndim == 1: + ldos_one = ldos_one.unsqueeze(0) + ldos_chunks.append(ldos_one) + + tc_cat = torch.cat(tc_chunks) + dos_cat = torch.cat(dos_chunks) + ldos_cat = torch.cat(ldos_chunks) + + assert torch.allclose(tc_cat, tc_full, atol=1e-10, rtol=0) + assert torch.allclose(dos_cat, dos_full, atol=1e-10, rtol=0) + assert torch.allclose(ldos_cat, ldos_full, atol=1e-10, rtol=0) From 79e852d963979b2c3a94f89062e216c8a8f332ac Mon Sep 17 00:00:00 2001 From: AsymmetryChou <181240085@smail.nju.edu.cn> Date: Thu, 11 Jun 2026 23:05:24 +0800 Subject: [PATCH 8/8] update e_batch_size argument to be optional --- dpnegf/utils/argcheck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnegf/utils/argcheck.py b/dpnegf/utils/argcheck.py index 6a660a9..6cf38e0 100644 --- a/dpnegf/utils/argcheck.py +++ b/dpnegf/utils/argcheck.py @@ -1055,7 +1055,7 @@ def negf(): Argument("espacing", [int, float], optional=False, doc=doc_espacing), Argument("emin", [int, float], optional=False, doc=doc_emin), Argument("emax", [int, float], optional=False, doc=doc_emax), - Argument("e_batch_size", [int, float], optional=False, doc="the batch size for energy points in NEGF calculation"), + Argument("e_batch_size", [int, float], optional=True, default=None, doc="the batch size for energy points in NEGF calculation"), Argument("e_fermi", [int, float], optional=True, default=None ,doc=doc_e_fermi), Argument("density_options", dict, optional=True, default={}, sub_fields=[], sub_variants=[density_options()], doc=doc_density_options), Argument("eta_lead", [int, float], optional=True, default=1e-5, doc=doc_eta_lead),