void SpinAdapted::Slater::outerProd(const Slater& s, Slater& output) const { vector<bool> occ(Slater().size()); for (int i=0; i<Slater().size(); i++) { if (s.alpha.get_occ_rep()[i] == 1 && alpha.get_occ_rep()[i]==1) { cout <<"cannot get outerprod of slater determinants\ndet1: "<<s<<"\ndet2: "<<*this<<endl; throw 20; } occ[i] = s.alpha.get_occ_rep()[i] + alpha.get_occ_rep()[i]; } Orbstring o(occ, s.alpha.getSign()*alpha.getSign()); Slater temp(o); output = temp; }
void SpinAdapted::Csf::applySminus(Csf& output) { map<Slater, double>::iterator itout, it = det_rep.begin(); map<Slater, double> detsout; for ( ; it!= det_rep.end(); it++) for (int i=0; i<Slater().size(); i+=2) { Slater s = (*it).first; s.d(i).c(i+1); if ( !s.isempty()) { itout = detsout.find(s); if (itout == detsout.end()) detsout[s] = (*it).second; else detsout[s] += (*it).second; } } output.set_det_rep(detsout, S, irrep); output.set_S(S); output.set_Sz(Sz-2); output.set_n(n); output.normalize(); }
Csf SpinAdapted::CSFUTIL::applyTensorOp(const TensorOp& newop, int spinL) { //for (int k=0; k<newop.Szops[newop.Szops.size()-1-newop.Spin].size(); k++) { map<Slater, double> m; SpinQuantum sq(newop.optypes.size(), SpinSpace(newop.Spin), IrrepSpace(newop.irrep)); for (int k=0; k<newop.Szops[spinL].size(); k++) { if (fabs(newop.Szops[spinL][k]) > 1e-10) { std::vector<bool> occ_rep(Slater().size(), 0); Slater s(occ_rep,1); for (int k2=newop.opindices[k].size()-1; k2>=0; k2--) { s.c(newop.opindices[k][k2]); } if (s.isempty()) { continue; } map<Slater, double>::iterator itout = m.find(s); if (itout == m.end()) { int sign = s.alpha.getSign(); s.setSign(1); m[s] = sign*newop.Szops[spinL][k]; } else m[s] += s.alpha.getSign()*newop.Szops[spinL][k]; } } int irreprow = spinL/(newop.Spin+1); int sz = -2*(spinL%(newop.Spin+1)) + newop.Spin; Csf csf = Csf(m,sq.particleNumber, sq.totalSpin, sz, IrrepVector(sq.get_symm().getirrep(),irreprow)) ; if (!csf.isempty() && fabs(csf.norm()) > 1e-14) csf.normalize(); return csf; }
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; }
//this version of the code is used when DMRG is no spin adapted std::vector<SpinAdapted::Csf > SpinAdapted::CSFUTIL::spinfockstrings(const std::vector<int>& orbs) { std::vector<Csf > singleSiteCsf; std::vector<int> numcsfs; std::vector< std::vector<Csf> > singleSiteLadder; int numCsfSoFar = 0; for (int i=0; i<orbs.size(); i++) { std::vector< Csf> thisSiteCsf; int I = orbs[i]; IrrepSpace Irrep = SymmetryOfSpatialOrb(orbs[i]); SpinQuantum sQ(1, SpinSpace(1), Irrep); int irrepsize = Symmetry::sizeofIrrep(Irrep.getirrep()); std::vector<Csf> ladderentry; std::map<Csf, std::vector<Csf> > laddermap; std::vector<bool> occ_rep1(Slater().size(),0), occ_rep2(Slater().size(),0), occ_rep3(Slater().size(), 0), occ_rep4(Slater().size(), 0); occ_rep2[dmrginp.spatial_to_spin()[I]] = 1; occ_rep3[dmrginp.spatial_to_spin()[I]+1] = 1; occ_rep4[dmrginp.spatial_to_spin()[I]] = 1;occ_rep4[dmrginp.spatial_to_spin()[I]+1] = 1; Slater s1(occ_rep1, 1), s2(occ_rep2, 1), s3(occ_rep3, 1), s4(occ_rep4, 1); map<Slater, double > m1, m2, m3, m4; m1[s1]= 1.0; m2[s2] = 1.0; m3[s3]= 1.0; m4[s4] = 1.0; thisSiteCsf.push_back( Csf(m1, 0, SpinSpace(0), 0, IrrepVector(0,0))); //0,0,0 thisSiteCsf.push_back( Csf(m2, 1, SpinSpace(1), 1, IrrepVector(Irrep.getirrep(), irrepsize-1))); //1,1,L thisSiteCsf.push_back( Csf(m3, 1, SpinSpace(-1), -1, IrrepVector(Irrep.getirrep(), irrepsize-1))); //1,1,L thisSiteCsf.push_back( Csf(m4, 2, SpinSpace(0), 0, IrrepVector(0, 0))); //2,0,0 numcsfs.push_back(thisSiteCsf.size()); for (int i=0; i<thisSiteCsf.size(); i++) singleSiteCsf.push_back( thisSiteCsf[i]); } std::vector<Csf> prevoutput, output; for (int i=0; i<numcsfs[0]; i++) output.push_back(singleSiteCsf[i]); int csfindex = numcsfs[0]; for (int i2=1; i2<orbs.size(); i2++) { for (int i=0; i<output.size(); i++) { prevoutput.push_back(output[i]); } output.clear(); for (int j=0; j<prevoutput.size(); j++) { for (int k=0; k<numcsfs[i2]; k++) { CSFUTIL::TensorProduct(prevoutput[j], singleSiteCsf[csfindex+k], output); } } prevoutput.clear(); csfindex += numcsfs[i2]; } std::vector<int> sortvec(output.size()); for (int i=0; i<output.size(); i++) sortvec[i] = i; std::sort(sortvec.begin(), sortvec.end(), sorter<Csf>(output)); std::sort(output.begin(), output.end()); return output; }
std::vector<SpinAdapted::Csf > SpinAdapted::CSFUTIL::spinfockstrings(const std::vector<int>& orbs, std::vector< std::vector<Csf> >& ladders) { std::vector<Csf > singleSiteCsf; std::vector<int> numcsfs; std::vector< std::vector<Csf> > singleSiteLadder; int numCsfSoFar = 0; for (int i=0; i<orbs.size(); i++) { std::vector< Csf> thisSiteCsf; int I = orbs[i]; std::vector<TensorOp> tensorops(1, TensorOp(I, 1)); IrrepSpace Irrep = SymmetryOfSpatialOrb(orbs[i]); SpinQuantum sQ(1, SpinSpace(1), Irrep); int irrepsize = Symmetry::sizeofIrrep(Irrep.getirrep()); std::vector<Csf> ladderentry; std::map<Csf, std::vector<Csf> > laddermap; std::vector<bool> occ_rep1(Slater().size(),0), occ_rep2(Slater().size(),0); occ_rep2[dmrginp.spatial_to_spin()[I]+2*irrepsize-2] = 1; Slater s1(occ_rep1, 1), s2(occ_rep2, 1); map<Slater, double > m1, m2; m1[s1]= 1.0; m2[s2] = 1.0; if ( (dmrginp.calc_type() != RESPONSELCC && dmrginp.calc_type() != RESPONSEAAAV && dmrginp.calc_type() != RESPONSEAAAC) && find(dmrginp.get_openorbs().begin(), dmrginp.get_openorbs().end(), I) != dmrginp.get_openorbs().end() ) { thisSiteCsf.push_back( Csf(m1, 0, SpinSpace(0), 0, IrrepVector(0,0))); //0,0,0 ladderentry.push_back(Csf(m1, 0, SpinSpace(0), 0, IrrepVector(0,0))); singleSiteLadder.push_back(ladderentry); numcsfs.push_back(thisSiteCsf.size()); for (int i=0; i<thisSiteCsf.size(); i++) singleSiteCsf.push_back( thisSiteCsf[i]); continue; } else if ( (dmrginp.calc_type() != RESPONSELCC && dmrginp.calc_type() != RESPONSEAAAV && dmrginp.calc_type() != RESPONSEAAAC)&& find(dmrginp.get_closedorbs().begin(), dmrginp.get_closedorbs().end(), I) != dmrginp.get_closedorbs().end()) { std::vector<bool> occ_rep(Slater().size(),0); occ_rep[dmrginp.spatial_to_spin()[I]+2*irrepsize-2] = 1; occ_rep[dmrginp.spatial_to_spin()[I]+2*irrepsize-1] = 1; Slater s(occ_rep, 1); map<Slater, double > m; m[s]= 1.0; thisSiteCsf.push_back( Csf(m, 2, SpinSpace(0), 0, IrrepVector(0,0))); //2,0,0 ladderentry.push_back(Csf(m, 2, SpinSpace(0), 0, IrrepVector(0,0))); singleSiteLadder.push_back(ladderentry); numcsfs.push_back(thisSiteCsf.size()); for (int i=0; i<thisSiteCsf.size(); i++) singleSiteCsf.push_back( thisSiteCsf[i]); continue; } else if(dmrginp.hamiltonian() == HEISENBERG) { thisSiteCsf.push_back( Csf(m2, 1, SpinSpace(1), 1, IrrepVector(Irrep.getirrep(), irrepsize-1))); //1,1,L for (int i=tensorops[0].Szops.size(); i> 0; i--) ladderentry.push_back(applyTensorOp(tensorops[0], i-1)); singleSiteLadder.push_back(ladderentry); numcsfs.push_back(thisSiteCsf.size()); for (int i=0; i<thisSiteCsf.size(); i++) singleSiteCsf.push_back( thisSiteCsf[i]); continue; } thisSiteCsf.push_back( Csf(m1, 0, SpinSpace(0), 0, IrrepVector(0,0))); //0,0,0 thisSiteCsf.push_back( Csf(m2, 1, SpinSpace(1), 1, IrrepVector(Irrep.getirrep(), irrepsize-1))); //1,1,L ladderentry.push_back(Csf(m1, 0, SpinSpace(0), 0, IrrepVector(0,0))); singleSiteLadder.push_back(ladderentry); ladderentry.clear(); for (int i=tensorops[0].Szops.size(); i> 0; i--) ladderentry.push_back(applyTensorOp(tensorops[0], i-1)); singleSiteLadder.push_back(ladderentry); //laddermap[singleSiteCsf.back()] = ladderentry; for (int nele = 2; nele < 2*irrepsize+1; nele++) { std::vector<SpinQuantum> quanta; std::vector<TensorOp> newtensorops; for (int i=0; i<tensorops.size(); i++) { quanta = SpinQuantum(nele-1, SpinSpace(tensorops[i].Spin), IrrepSpace(tensorops[i].irrep)) + sQ; for (int j=0; j<quanta.size(); j++) { TensorOp newop = TensorOp(I,1).product(tensorops[i], quanta[j].totalSpin.getirrep(), quanta[j].get_symm().getirrep()); Csf csf = applyTensorOp(newop, newop.Szops.size()-1-newop.Spin); if (!csf.isempty() && csf.norm() >1e-10) { csf.normalize(); if (find(thisSiteCsf.begin(), thisSiteCsf.end(), csf) == thisSiteCsf.end()) { thisSiteCsf.push_back( csf); newtensorops.push_back(newop); std::vector<Csf> ladderentry; for (int k=newop.Szops.size(); k>0 ; k--) ladderentry.push_back(applyTensorOp(newop, k-1)); singleSiteLadder.push_back(ladderentry); //laddermap[csf] = ladderentry; } } } } tensorops = newtensorops; } numcsfs.push_back(thisSiteCsf.size()); for (int i=0; i<thisSiteCsf.size(); i++) singleSiteCsf.push_back( thisSiteCsf[i]); } std::vector<Csf> prevoutput, output; std::vector< std::vector<Csf> > prevladder, ladder; for (int i=0; i<numcsfs[0]; i++) { output.push_back(singleSiteCsf[i]); ladder.push_back(singleSiteLadder[i]); } int csfindex = numcsfs[0]; for (int i2=1; i2<orbs.size(); i2++) { for (int i=0; i<output.size(); i++) { prevoutput.push_back(output[i]); prevladder.push_back(ladder[i]); } output.clear(); ladder.clear(); for (int j=0; j<prevoutput.size(); j++) { for (int k=0; k<numcsfs[i2]; k++) { CSFUTIL::TensorProduct(prevoutput[j], prevladder[j], singleSiteCsf[csfindex+k], singleSiteLadder[csfindex+k], output, ladder); } } prevoutput.clear(); prevladder.clear(); csfindex += numcsfs[i2]; } std::vector<int> sortvec(output.size()); for (int i=0; i<output.size(); i++) sortvec[i] = i; std::sort(sortvec.begin(), sortvec.end(), sorter<Csf>(output)); std::sort(output.begin(), output.end()); for (int i=0; i<output.size(); i++) ladders.push_back(ladder[sortvec[i]]); return output; }