25 auto n_k = res.
P_k.extent(0);
26 auto n_sigma = res.P_k.extent(1);
27 for (
auto isig : range(n_sigma)) {
28 auto decomp = range(U.extent(0)) | stdv::transform([&](
auto &&m) {
return U(m, isig).extent(0); }) | tl::to<std::vector>();
29 for (
auto ik : range(n_k)) {
32 res.P_k(ik, isig, sli,
r_all) = dagger(U(a, isig)) * matrix_const_view<dcomplex>{this->
P_k(ik, isig, sli,
r_all)};
54 auto atomic_shells = atom_indices | stdv::transform([&](
auto i) {
return obe.
C_space.
atomic_shells()[i]; }) | tl::to<std::vector>();
58 for (
auto &&[iatom, atom] : enumerate(atom_indices)) {
63 auto n_atoms = atom_partition.size();
66 auto irreps_per_atom = nda::array<std::vector<long>, 2>(n_atoms, n_sigma);
67 for (
auto &&[ipart, partition] : enumerate(atom_partition)) {
68 if (partition.size() == 1) {
71 irreps_per_atom(ipart,
r_all) = std::vector{
72 stdr::fold_left(partition | stdv::transform([&](
auto idx) {
return obe.
C_space.
atomic_shells()[idx].dim; }), 0, std::plus<>())};
76 auto new_C_space =
local_space{spin_kind, atomic_shells, irreps_per_atom, rot_from_dft_to_local_basis, rot_from_sph_to_dft_basis};
80 auto [n_k, n_sig, n_M, n_nu] = obe.
P.
P_k.shape();
82 auto P_k_list = atom_decomp | stdv::transform([&](
auto dim) {
return nda::zeros<dcomplex>(n_k, n_sig, dim, n_nu); }) | tl::to<std::vector>();
87 auto new_P_k_list = atom_indices | stdv::transform([&](
auto i) {
return P_k_list[i]; }) | tl::to<std::vector>();
89 auto new_atom_decomp = new_C_space.atomic_decomposition() | tl::to<std::vector>();
91 auto P_k = nda::zeros<dcomplex>(n_k, n_sig, n_M, n_nu);
99 if (!obe.
ibz_symm_ops)
return {.H = obe.
H, .C_space = new_C_space, .P = new_P, .ibz_symm_ops = {}};
102 auto new_ibz_symm_ops = ibz_symm_ops;
103 for (
auto &&[isym, sym_op] : enumerate(new_ibz_symm_ops.ops)) {
104 sym_op.mats = atom_indices | stdv::transform([&](
auto i) {
return ibz_symm_ops.ops[isym].mats[i]; }) | tl::to<std::vector>();
105 sym_op.permutation = atom_indices | stdv::transform([&](
auto i) {
return ibz_symm_ops.ops[isym].permutation[i]; }) | tl::to<std::vector>();
107 return {.H = obe.
H, .C_space = new_C_space, .P = new_P, .ibz_symm_ops = new_ibz_symm_ops};
115 auto results_per_atom = nda::array<nda::matrix<dcomplex>, 2>{n_atoms, n_sigma};
120 for (
auto sigma : range(n_sigma)) {
121 auto hloc0 = nda::zeros<dcomplex>(M_a, M_a);
122 for (
auto ik : range(obe.
H.
n_k())) {
123 auto P = obe.
P.
P(sigma, ik)(R_atom,
r_all);
124 hloc0 += obe.
H.
k_weights(ik) * P * obe.
H.
H(sigma, ik) * dagger(P);
126 results_per_atom(atom_idx, sigma) = hloc0;
129 if (
auto const &S = obe.
ibz_symm_ops; S) results_per_atom = S->symmetrize(results_per_atom);
131 for (
auto atom_idx : range(n_atoms)) {
133 results_per_atom(atom_idx,
r_all) = results_per_atom(inequiv,
r_all);
136 auto result = nda::array<nda::matrix<dcomplex>, 2>{1, n_sigma};
137 for (
auto sigma : range(n_sigma)) {
140 result(0, sigma)(r_atom, r_atom) = results_per_atom(atm, sigma);
154 nda::array<dcomplex, 3> detail::G0_C_k_sigma(one_body_elements_on_grid
const &obe,
double mu,
long k_idx,
long sigma,
155 std::vector<dcomplex>
const &omegas,
bool mu_derivative) {
158 auto n_nu = obe.H.N_nu(sigma, k_idx);
159 auto R_nu = nda::range(n_nu);
160 auto M = obe.C_space.dim();
163 auto n_omega = omegas.size();
164 auto Dinv = nda::matrix<dcomplex>(n_omega, n_nu);
165 auto Hk = obe.H.H(sigma, k_idx);
166 constexpr auto sqr = [](
auto x) {
return x * x; };
169 if (not mu_derivative) {
170 for (
auto [n, om] : enumerate(omegas))
171 for (auto nu : R_nu) Dinv(n, nu) = 1 / (om + mu -
Hk(nu, nu));
173 for (
auto [n, om] : enumerate(omegas))
174 for (auto nu : R_nu) Dinv(n, nu) = -1 / sqr(om + mu -
Hk(nu, nu));
178 auto PP = nda::zeros<dcomplex>(n_nu, M, M);
179 auto P = obe.P.P(sigma, k_idx);
180 for (
auto m : range(M))
181 for (auto mp : range(M))
182 for (auto nu : R_nu) PP(nu, m, mp) = P(m, nu) * conj(P(mp, nu));
186 auto Y = nda::zeros<dcomplex>(n_omega, M, M);
187 auto M_asmat =
cmat_vt{nda::group_indices_view(PP, nda::idx_group<0>, nda::idx_group<1, 2>)};
188 auto Y_asmat =
cmat_vt{nda::group_indices_view(Y, nda::idx_group<0>, nda::idx_group<1, 2>)};
189 nda::blas::gemm(1, Dinv, M_asmat, 0, Y_asmat);
Describe the atomic orbitals within downfolded space.
spin_kind_e spin_kind() const
nda::array< nda::matrix< dcomplex >, 1 > const & rotation_from_spherical_to_dft_basis() const
List of rotation matrices from spherical harmonics to dft specific orbital basis.
long n_sigma() const
Dimension of the σ index.
nda::array< nda::matrix< dcomplex >, 2 > const & rotation_from_dft_to_local_basis() const
List of all (a, sigma) local rotation matices that rotate the data.
nda::array< std::vector< long >, 2 > const & atoms_block_decomposition() const
List of all blocks spanning 𝓒 space -> atoms_block_decomposition.
auto atomic_decomposition() const
Generates [dimension of the atomic shell].
long dim() const
Dimension of the correlated space.
std::vector< atomic_orbs > const & atomic_shells() const
List of all atomic shells spanning the 𝓒 space.
long n_atoms() const
The number of atoms.
long first_shell_of_its_equiv_cls(long idx) const
Given the index idx of an atomic shell, return the index of the first atomic shell of its equivalence...
nda::array< nda::matrix< dcomplex >, 2 > impurity_levels(one_body_elements_on_grid const &obe)
Compute the local impurity levels from the single-particle dispersion.
std::vector< T > flatten(const std::vector< std::vector< T > > &nested)
one_body_elements_on_grid rotate_local_basis(nda::array< nda::matrix< dcomplex >, 2 > const &U, one_body_elements_on_grid const &x)
Rotates the local basis of the downfolding projector.
one_body_elements_on_grid permute_local_space(std::vector< std::vector< long > > const &atom_partition, one_body_elements_on_grid const &obe)
static constexpr auto r_all
nda::matrix_view< dcomplex > cmat_vt
generator< std::pair< long, nda::range > > enumerated_sub_slices(auto sub_div)
nda::array< double, 1 > k_weights
k_weights[k_idx]
long n_k() const
Number of k points in the grid.
nda::matrix_const_view< dcomplex > H(long sigma, long k_idx) const
H^σ(k)_ν, returned as a MATRIX in (ν, ν)
The projector that downfolds the one-body dispersion (ν) onto local orbitals (m).
nda::matrix_const_view< dcomplex > P(long sigma, long k_idx) const
P^σ(k)_mν, returned as a matrix in (m ν)
nda::array< dcomplex, 4 > P_k
Pk[alpha][k_idx, σ', m_alpha, nu].
nda::array< long, 2 > n_bands_per_k
n_bands_per_k [k_idx, σ'] = # of nu
downfolding_projector rotate_local_basis(nda::array< nda::matrix< dcomplex >, 2 > const &U) const
Rotates the local basis of the downfolding projector.
A one-body elements struct where all of the underlying data exists on a fixed momentum grid.
C2PY_IGNORE std::optional< ibz_symmetry_ops > ibz_symm_ops
IBZ symmetrizer after a k-sum.