template<> void Op_component<CreCreDesComp>::build_iterators(SpinBlock& b) { if (b.get_sites().size () == 0) return; // blank construction (used in unset_initialised() Block copy construction, for use with STL) const double screen_tol = dmrginp.oneindex_screen_tol(); vector< int > screened_cdd_ix = (dmrginp.hamiltonian() == BCS) ? screened_cddcomp_indices(b.get_complementary_sites(), b.get_sites(), v_1, *b.get_twoInt(), v_cc, v_cccc, v_cccd, screen_tol) : screened_cddcomp_indices(b.get_complementary_sites(), b.get_sites(), v_1, *b.get_twoInt(), screen_tol); m_op.set_indices(screened_cdd_ix, dmrginp.last_site()); std::vector<int> orbs(1); for (int i = 0; i < m_op.local_nnz(); ++i) { orbs[0] = m_op.get_local_indices()[i]; m_op.get_local_element(i).resize(1); m_op.get_local_element(i)[0]=boost::shared_ptr<CreCreDesComp>(new CreCreDesComp); SparseMatrix& op = *m_op.get_local_element(i)[0]; op.set_orbs() = orbs; op.set_initialised() = true; op.set_fermion() = true; //op.set_deltaQuantum() = SpinQuantum(1, SpinOf(orbs[0]), SymmetryOfSpatialOrb(orbs[0]) ); if (dmrginp.hamiltonian() == BCS) { op.resize_deltaQuantum(4); SpinQuantum qorb = getSpinQuantum(orbs[0]); op.set_deltaQuantum(0) = qorb; op.set_deltaQuantum(1) = SpinQuantum(3, qorb.get_s(), qorb.get_symm()); op.set_deltaQuantum(2) = SpinQuantum(-1, qorb.get_s(), qorb.get_symm()); op.set_deltaQuantum(3) = SpinQuantum(-3, qorb.get_s(), qorb.get_symm()); } else { op.set_deltaQuantum(1, getSpinQuantum(orbs[0])); } } }
template<> void Op_component<CreCreComp>::build_iterators(SpinBlock& b) { if (b.get_sites().size () == 0) return; // blank construction (used in unset_initialised() Block copy construction, for use with STL) const double screen_tol = dmrginp.twoindex_screen_tol(); vector< pair<int, int> > screened_dd_ix = (dmrginp.hamiltonian() == BCS) ? screened_dd_indices(b.get_complementary_sites(), b.get_sites(), *b.get_twoInt(), v_cc, v_cccc, v_cccd, screen_tol) : screened_dd_indices(b.get_complementary_sites(), b.get_sites(), *b.get_twoInt(), screen_tol); m_op.set_pair_indices(screened_dd_ix, dmrginp.last_site()); std::vector<int> orbs(2); for (int i = 0; i < m_op.local_nnz(); ++i) { orbs = m_op.unmap_local_index(i); std::vector<boost::shared_ptr<CreCreComp> >& vec = m_op.get_local_element(i); SpinQuantum spin1 = getSpinQuantum(orbs[0]); SpinQuantum spin2 = getSpinQuantum(orbs[1]); std::vector<SpinQuantum> spinvec = spin1+spin2; vec.resize(spinvec.size()); for (int j=0; j<spinvec.size(); j++) { vec[j]=boost::shared_ptr<CreCreComp>(new CreCreComp); SparseMatrix& op = *vec[j]; op.set_orbs() = orbs; op.set_initialised() = true; op.set_fermion() = false; op.set_deltaQuantum(1, spinvec[j]); } } }
template<> std::vector<std::vector<int> > Op_component<CreDesDesComp>::get_array() const { std::vector<int> orbs(1); std::vector< std::vector<int> > ret_val(m_op.local_nnz()); for (int i=0; i<m_op.local_nnz(); i++) { orbs[0] = m_op.get_local_indices()[i]; ret_val[i] = orbs; } return ret_val; }
template<> void Op_component<Des>::build_iterators(SpinBlock& b) { if (b.get_sites().size () == 0) return; // blank construction (used in unset_initialised() Block copy construction, for use with STL) const double screen_tol = dmrginp.oneindex_screen_tol(); std::vector<int> screened_d_ix = screened_d_indices(b.get_sites(), b.get_complementary_sites(), v_1, *b.get_twoInt(), screen_tol); m_op.set_indices(screened_d_ix, dmrginp.last_site()); std::vector<int> orbs(1); for (int i = 0; i < m_op.local_nnz(); ++i) { orbs[0] = m_op.get_local_indices()[i]; m_op.get_local_element(i).resize(1); m_op.get_local_element(i)[0]=boost::shared_ptr<Des>(new Des); SparseMatrix& op = *m_op.get_local_element(i)[0]; op.set_orbs() = orbs; op.set_initialised() = true; op.set_fermion() = true; op.set_deltaQuantum(1, -getSpinQuantum(orbs[0]));//SpinQuantum(1, 1, SymmetryOfSpatialOrb(orbs[0])); op.set_quantum_ladder()["(D)"] = { op.get_deltaQuantum(0) }; } }
// Compute expansion of orbitals around cen, return clm[norbs][l,m][nrad] real_expansion_t expand_orbitals_real(const arma::mat & C, const BasisSet & bas, const coords_t & cen, bool verbose, size_t Nrad, int lmax, int lquad) { // Returned expansion real_expansion_t ret; Timer t; // Form angular grid std::vector<angular_grid_t> grid=form_angular_grid(lquad); // Compute values of spherical harmonics and complex conjugate them std::vector< std::vector< double > > Ylm=compute_solid_harmonics(grid,lmax); if(verbose) { printf("Formed angular grid and computed solid harmonics in %s.\n",t.elapsed().c_str()); t.set(); } #ifdef CHECKORTHO // Check orthogonality of solid harmonics size_t nfail=0, nsucc=0; for(int l1=0;l1<=lmax;l1++) for(int m1=-l1;m1<=l1;m1++) for(int l2=0;l2<=l1;l2++) for(int m2=-l2;m2<=l2;m2++) { // Perform quadrature over the sphere double res=0.0; for(size_t ip=0;ip<grid.size();ip++) res+=grid[ip].w*Ylm[ip][lmind(l2,m2)]*Ylm[ip][lmind(l1,m1)]; if( (l1==l2) && (m1==m2) ) res-=1.0; if (fabs(res)>ORTHTOL) { printf("(%i,%i) - (%i,%i) -> %e\n",l1,m1,l2,m2,res); nfail++; } else nsucc++; } if(verbose) printf("Checked the orthonormality of solid harmonics: %u succ, %u fail.\n",(unsigned int) nsucc,(unsigned int) nfail); #endif // Form radial grid ret.grid=form_radial_grid(Nrad); // Coefficients of expansion ret.clm.resize(C.n_cols); for(size_t iorb=0;iorb<C.n_cols;iorb++) { ret.clm[iorb].resize(Ylm[0].size()); for(size_t lm=0;lm<Ylm[0].size();lm++) { ret.clm[iorb][lm].resize(ret.grid.size()); for(size_t irad=0;irad<ret.grid.size();irad++) ret.clm[iorb][lm][irad]=0.0; } } // Loop over radii #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) #endif for(size_t irad=0;irad<ret.grid.size();irad++) { // Loop over angular grid for(size_t iang=0;iang<grid.size();iang++) { // Compute coordinates of grid point coords_t gp=grid[iang].r*ret.grid[irad].r+cen; // Evaluate values of orbitals at grid point arma::vec orbs=compute_orbitals(C,bas,gp); // Do quadrature step for(size_t lm=0;lm<Ylm[iang].size();lm++) for(size_t iorb=0;iorb<orbs.n_elem;iorb++) ret.clm[iorb][lm][irad]+=orbs(iorb)*grid[iang].w*Ylm[iang][lm]; } } if(verbose) printf("Computed solid harmonics expansion of orbitals in %s.\n",t.elapsed().c_str()); return ret; }
std::vector<Csf> Csf::distributeNonSpinAdapted (const int n, const int sp, const IrrepVector &sym, const int left, const int right, const int edge, int integralIndex) { std::vector<Csf> s; int na = 0; int nb = 0; na = (n + sp) / 2; nb = (n - sp) / 2; // let's count how many left and right orbitals there actually are int actualOrbs = right - left; int actualNA, actualNB; actualNA = actualNB = 0; for (int i=left; i<right; ++i) { if((SpinOf(i) == 1)) ++actualNA; else ++actualNB; } // cannot form this combination if (na > actualNA || nb > actualNB || na < 0 || nb < 0) { return s; } // now make orbital occupancies std::vector<int> alphaSeed (actualNA); std::vector<int> betaSeed (actualNB); for (int i = 0; i < na; ++i) alphaSeed [i] = -1; for (int i = 0; i < nb; ++i) betaSeed [i] = -1; // okay now make some permutations (at most GUESS_PERMUTATIONS) std::vector< std::vector<int> > alphaList; alphaList.push_back (alphaSeed); std::vector< std::vector<int> > betaList; betaList.push_back (betaSeed); int numberOfGuesses = dmrginp.guess_permutations(); while (next_permutation (alphaSeed.begin (), alphaSeed.end ()) && numberOfGuesses--) alphaList.push_back (alphaSeed); numberOfGuesses = dmrginp.guess_permutations();; while (next_permutation (betaSeed.begin (), betaSeed.end ()) && numberOfGuesses--) betaList.push_back (betaSeed); // okay - we have all the permutations. // make list of available alpha and beta orbitals in energy ordering. std::vector<int> orbitalAlphaList; std::vector<int> orbitalBetaList; multimap <double, int> alphaMap; multimap <double, int> betaMap; int alphaIndex = 0; int betaIndex = 0; // scan orbitals from left to right, pick out orbitals which are occupied in the hartree-fock reference for (int i=left; i<right; ++i) { if (dmrginp.hf_occupancy()[i]) { if ((SpinOf(i) == 1)) // 0 to take into account case of nospin { orbitalAlphaList.push_back(alphaIndex); ++alphaIndex; } else { orbitalBetaList.push_back(betaIndex); ++betaIndex; } } else if ((SpinOf(i) == 1)) // not HF orb, but alpha orb { alphaMap.insert(pair<double, int>(v_1[integralIndex](i, i), alphaIndex)); ++alphaIndex; } else // beta orb { betaMap.insert(pair<double, int>(v_1[integralIndex](i, i), betaIndex)); ++betaIndex; } } for (multimap<double, int>::iterator m=alphaMap.begin (); m!=alphaMap.end (); ++m) orbitalAlphaList.push_back(m->second); for (multimap<double, int>::iterator m=betaMap.begin (); m!=betaMap.end (); ++m) orbitalBetaList.push_back(m->second); // Now convert permutation lists to energy ordered form for (int i=0; i<alphaList.size (); ++i) ConvertList (alphaList[i], orbitalAlphaList); for (int i=0; i<betaList.size (); ++i) ConvertList (betaList[i], orbitalBetaList); // Now catenate to make Slaters for (int i=0; i<alphaList.size(); ++i) for (int j=0; j<betaList.size(); ++j) { std::vector<bool> lbuffer(left, 0); std::vector<bool> rbuffer(edge - right, 0); std::vector<bool> orbs(right - left); int alphaI = 0; int betaI = 0; for (int orbI=0; orbI<right-left; ++orbI) { if (SpinOf(orbI + left) == 1) { if (alphaList[i][alphaI]) orbs[orbI] = 1; ++alphaI; } else { if (betaList[j][betaI]) orbs[orbI] = 1; ++betaI; } } std::vector<bool> tmp = lbuffer; for (std::vector<bool>::iterator it = orbs.begin(); it!=orbs.end(); ++it) tmp.push_back(*it); for (std::vector<bool>::iterator it = rbuffer.begin(); it!=rbuffer.end(); ++it) tmp.push_back(*it); Slater new_det = Slater (Orbstring (tmp)); map<Slater, double> m; m[new_det] = 1.0; if(sym.getirrep() == AbelianSymmetryOf(new_det).getirrep()) s.push_back (Csf(m,n,SpinSpace(sp), sp, IrrepVector(sym.getirrep(),0))); } return s; }
std::vector< SpinAdapted::Csf > SpinAdapted::Csf::distribute (const int n, const int sp, const IrrepVector &sym, const int left, const int right, const int edge, int integralIndex) { std::vector< Csf > s; int na = 0; int nb = 0; na = (n + sp) / 2; nb = (n - sp) / 2; if(dmrginp.hamiltonian() == HEISENBERG && nb != 0) return s; // let's count how many left and right orbitals there actually are int actualOrbs = dmrginp.spatial_to_spin()[right] - dmrginp.spatial_to_spin()[left]; int actualNA, actualNB; actualNA = actualOrbs/2; actualNB = actualOrbs/2; // cannot form this combination if (na > actualNA || nb > actualNB || na < 0 || nb < 0) { return s; } // now make orbital occupancies std::vector<int> abSeed (right-left); for (int i = 0; i < max(na, nb); ++i) abSeed [i] = -1; // okay now make some permutations (at most GUESS_PERMUTATIONS) std::vector< std::vector<int> > abList; abList.push_back (abSeed); int numberOfGuesses = dmrginp.guess_permutations(); bool doAgain = true; int numtries = 0; while(doAgain && numtries <500) { while (next_permutation (abSeed.begin (), abSeed.end ()) && numberOfGuesses--) abList.push_back (abSeed); // make list of available alpha and beta orbitals in energy ordering. std::vector<int> orbitalList; multimap <double, int> orbMap; int alphaIndex = 0; // scan orbitals from left to right, pick out orbitals which have smallest v_1(i, i) integrals for (int i=left; i<right; ++i) { if (dmrginp.hf_occupancy()[dmrginp.spatial_to_spin()[i]]) { orbitalList.push_back(alphaIndex); alphaIndex++; continue; } orbMap.insert(pair<double, int>(v_1[integralIndex](2*i, 2*i), alphaIndex)); ++alphaIndex; } for (multimap<double, int>::iterator m=orbMap.begin (); m!=orbMap.end (); ++m) orbitalList.push_back(m->second); // Now convert permutation lists to energy ordered form for (int i=0; i<abList.size (); ++i) ConvertList (abList[i], orbitalList); Slater last_det; // Now catenate to make Slaters for (int i=0; i<abList.size(); ++i) { std::vector<bool> lbuffer(dmrginp.spatial_to_spin()[left], 0); std::vector<bool> rbuffer(dmrginp.spatial_to_spin()[edge] - dmrginp.spatial_to_spin()[right], 0); std::vector<bool> orbs(dmrginp.spatial_to_spin()[right] - dmrginp.spatial_to_spin()[left], 0); int alphaI = 0; int betaI = 0; for (int orbI=0; orbI<(right-left); orbI++) { if (abList[i][alphaI]) { orbs[dmrginp.spatial_to_spin()[orbI]] = 1; if (betaI < min(na, nb)) { orbs[ dmrginp.spatial_to_spin()[orbI]+1] = 1; ++betaI; } } ++alphaI; } std::vector<bool> tmp = lbuffer; for (std::vector<bool>::iterator it = orbs.begin(); it!=orbs.end(); ++it) tmp.push_back(*it); for (std::vector<bool>::iterator it = rbuffer.begin(); it!=rbuffer.end(); ++it) tmp.push_back(*it); Slater new_det = Slater (Orbstring (tmp)); map<Slater, double> m; m[new_det] = 1.0; last_det = new_det; if(sym.getirrep() == AbelianSymmetryOf(new_det).getirrep()) s.push_back ( Csf(m, n, SpinSpace(sp), sp, IrrepVector(sym.getirrep(), 0)) ); } if (s.size() == 0) { numtries++; doAgain = true; abList.clear(); numberOfGuesses = dmrginp.guess_permutations(); } else doAgain = false; } return s; }